:::callout{intent="info" title="Added in `v1.38`"}
:::

The Weaviate [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server is an implementation of the open standard that enables Large Language Models (LLMs) to interact securely with your Weaviate instance.

Instead of pasting context manually, MCP allows compatible clients (like Claude Desktop or IDEs) to directly "see" and interact with your database. Weaviate implements this as a Streamable HTTP server that runs on the same port as the main Weaviate REST API. It exposes tools to inspect schemas, search data (vector/hybrid), and modify objects, governed by Weaviate's authentication and authorization.

***

## Using the Weaviate MCP server

The Weaviate MCP server runs at `/v1/mcp` on the REST API port if enabled (`http://localhost:8080/v1/mcp` on a default self-hosted instance, `https://<your-cluster-host>/v1/mcp` on Weaviate Cloud) and supports authentication via Bearer tokens (API Keys).
To get started:

1. On a self-hosted instance, enable the MCP server (and optionally write access) with [environment variables](#environment-variables). On Weaviate Cloud it is already enabled (see [Weaviate Cloud](#weaviate-cloud) for the write-access switch).
2. [Ensure your API key has the right permissions](#permissions) if using RBAC.
3. [Connect your MCP client](#connect-your-mcp-client) using the REST API host and port.

You can also optionally [customize tool descriptions](#custom-tool-descriptions) to tailor the LLM's understanding of your workflow.

#### Connect your MCP client

::::tabs{sync="platform"}
:::tab{title="Claude Code"}
Run the following command in your terminal to add the server ([Claude Code MCP docs](https://docs.anthropic.com/en/docs/claude-code/mcp)):

```bash
claude mcp add-json weaviate-local '{"type":"http","url":"http://localhost:8080/v1/mcp","headers":{"Authorization":"Bearer YOUR_API_KEY"}}'
```

_If anonymous access is enabled, you can omit the `headers` field._
:::

:::tab{title="Claude Desktop"}
[Claude Desktop](https://claude.ai/download) does not natively support Streamable HTTP transport. Use [`mcp-proxy`](https://github.com/sparfenyuk/mcp-proxy) to bridge between Claude Desktop's `stdio` transport and the Weaviate MCP server.

**Config Location:**

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "weaviate-local": {
      "command": "mcp-proxy",
      "args": [
        "http://localhost:8080/v1/mcp",
        "--headers",
        "Authorization",
        "Bearer YOUR_API_KEY",
        "--transport",
        "streamablehttp"
      ]
    }
  }
}
```

_Note: Replace `YOUR_API_KEY` with your actual Weaviate API key. If anonymous access is enabled, you can omit the `--headers` arguments._
:::

:::tab{title="Cursor"}
Add the following to your `.cursor/mcp.json` file ([Cursor MCP docs](https://docs.cursor.com/context/model-context-protocol)). Cursor supports Streamable HTTP connections directly.

```json
{
  "mcpServers": {
    "weaviate-local": {
      "type": "streamable-http",
      "url": "http://localhost:8080/v1/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```
:::

:::tab{title="VS Code"}
**Prerequisites:** VS Code 1.102+ with GitHub Copilot enabled ([VS Code MCP docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)).

Create or edit the `mcp.json` file in your workspace `.vscode` folder:

```json
{
  "servers": {
    "weaviate-local": {
      "type": "streamable-http",
      "url": "http://localhost:8080/v1/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```
:::

:::tab{title="Other"}
Most MCP clients support Streamable HTTP. Use the following connection details:

- **URL:** `http://localhost:8080/v1/mcp`
- **Transport:** Streamable HTTP
- **Auth Header:** `Authorization: Bearer <your-api-key>`

Standard JSON configuration format:

```json
{
  "mcpServers": {
    "weaviate-local": {
      "url": "http://localhost:8080/v1/mcp",
      "type": "streamable-http"
    }
  }
}
```
:::
::::

***

## Configuration

The MCP server is built into Weaviate. On a self-hosted instance it is **disabled by default** for security. On Weaviate Cloud it is **always enabled** (see [Weaviate Cloud](#weaviate-cloud)). It is served at the `/v1/mcp` endpoint on the same port as the REST API (default `8080`).

### Weaviate Cloud

On Weaviate Cloud, the MCP server is always enabled. There is no console setting to turn it off. What you control is write access, with a single switch in the cluster's advanced configuration: `Enable MCP Read-Only`. The switch is **off by default** on all Weaviate Cloud clusters, so `weaviate-objects-upsert` is available out of the box. Turning it on restricts the server to its read tools. No environment variables are involved and no restart is needed: a saved change applies after a short delay, from under a minute to a few minutes.

To change the switch on an existing cluster:

1. Open the cluster details page in the [Weaviate Cloud console](https://console.weaviate.cloud/) and click `Show advanced options`.
2. Under `Advanced configuration`, set `Enable MCP Read-Only`.
3. Click `Save Configuration`.

On Shared Cloud clusters, the switch is also available on the cluster creation form under `Advanced configuration` (see [Create a cluster](../manage-clusters/create.md#shared-cloud-clusters)).

The switch is cluster-wide, while a `viewer` API key is per-credential: to keep one agent read-only without restricting the whole cluster, connect it with an API key that has the read-only `viewer` role (see [Permissions](#permissions)).

:::callout{intent="warning" title="Connecting to a Weaviate Cloud cluster"}
Use your cluster's REST endpoint with `/v1/mcp` appended and a cluster [API key](../manage-clusters/authentication.md) as the Bearer token. If the cluster vectorizes with [Weaviate Embeddings](../model-provider-integrations/weaviate-embeddings.md) (`text2vec-weaviate`), the client must also send the `X-Weaviate-Cluster-Url` header set to the cluster URL:

```json
{
  "mcpServers": {
    "weaviate-cloud": {
      "type": "streamable-http",
      "url": "https://<your-cluster-host>/v1/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY",
        "X-Weaviate-Cluster-Url": "https://<your-cluster-host>"
      }
    }
  }
}
```
:::

### Environment variables

On a self-hosted instance, set the following [environment variables](../database-configuration/overview.md) in your Weaviate configuration (e.g., `docker-compose.yml`):

| Environment Variable                                                                                       | Default | Runtime-configurable | Description                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------------------------------------------------------------------------------- | ------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`MCP_SERVER_ENABLED`](../database-configuration/overview.md#MCP_SERVER_ENABLED)                           | `false` | from `v1.38`         | **Required.** Set to `true` to start the MCP server.                                                                                                                                                                                                                                                                                                                                                              |
| [`MCP_SERVER_WRITE_ACCESS_ENABLED`](../database-configuration/overview.md#MCP_SERVER_WRITE_ACCESS_ENABLED) | `false` | from `v1.38`         | When `true`, enables write tools (`weaviate-objects-upsert`). Default is read-only.                                                                                                                                                                                                                                                                                                                               |
| [`MCP_SERVER_CONFIG_PATH`](../database-configuration/overview.md#MCP_SERVER_CONFIG_PATH)                   | `""`    | No                   | Path to a YAML file for customizing tool descriptions (useful for prompt engineering the LLM's understanding of your specific data). If not provided or file malformed, the default descriptions from the [source code](https://github.com/weaviate/weaviate/tree/main/adapters/handlers/mcp) will be used. Tool descriptions are baked into the tool schemas at registration, so this flag remains startup-only. |

### Permissions

If you use [RBAC](../authorization-and-authentication/weaviate-configuration-rbac.md) with fine-grained permissions instead of root access, the role assigned to your API key must include the appropriate MCP permissions. Without them, most tool calls are rejected.

:::accordion{title="Per-tool permissions"}
| Tool                              | MCP permissions required   | Additional permissions                                      |
| --------------------------------- | -------------------------- | ----------------------------------------------------------- |
| `weaviate-collections-get-config` | `read_mcp`                 | `read_collections`                                          |
| `weaviate-tenants-list`           | `read_mcp`                 | `read_tenants`                                              |
| `weaviate-query-hybrid`           | `read_mcp`                 | `read_data`, plus `read_collections` when `filters` is used |
| `weaviate-objects-upsert`         | `create_mcp`, `update_mcp` | `create_data`, `update_data`                                |
:::

For a read-only key, assign the predefined `viewer` role, the assignable read-only role for database users: it includes `read_mcp` together with read access to collections, data, and tenants. On Weaviate Cloud, the `admin` role includes all three MCP permissions. Pick the role when you [create the API key](../manage-clusters/authentication.md).

Permissions are enforced when a tool is called, not when tools are listed. `tools/list` shows every tool to every authenticated key (only the write-access flag hides `weaviate-objects-upsert`). A call the key is not allowed to make returns HTTP `200` with a tool result whose `isError` is `true` and whose text contains `insufficient permissions to read_mcp []` (or `create_mcp`, `read_data`, and so on). It is neither an HTTP `403` nor a JSON-RPC error.

### Custom tool descriptions

You can override the default descriptions provided to the LLM by mounting a YAML or JSON file at `MCP_SERVER_CONFIG_PATH`.

:::code-group{sync="config-format"}
```yaml title="YAML"
# mcp-config.yaml
tools:
  weaviate-query-hybrid:
    description: "Perform a vector or keyword search on a collection."
    arguments:
      query: "The natural language search query to find relevant objects."
      alpha: "0.0 = pure keyword (BM25), 1.0 = pure vector. Defaults to 0.75."
```

```json title="JSON"
{
  "tools": {
    "weaviate-query-hybrid": {
      "description": "Perform a vector or keyword search on a collection.",
      "arguments": {
        "query": "The natural language search query to find relevant objects.",
        "alpha": "0.0 = pure keyword (BM25), 1.0 = pure vector. Defaults to 0.75."
      }
    }
  }
}
```
:::

***

## Tools

The server exposes different tools depending on your configuration. These are all the available tools:

- `weaviate-collections-get-config`
- `weaviate-tenants-list`
- `weaviate-query-hybrid`
- `weaviate-objects-upsert`

For every tool, `collection_name` is matched after uppercasing only its first character: `article` resolves to the collection `Article`, but `ARTICLE` does not.

### `weaviate-collections-get-config`

Retrieves the schema configuration for collections.

**Arguments:**

- `collection_name` (string, optional): Specific collection to retrieve. If omitted, returns all.

**Returns:** JSON object containing class names, properties, and vectorizer settings.

### `weaviate-tenants-list`

Lists tenants for multi-tenant collections.

**Arguments:**

- `collection_name` (string, required): The collection to inspect.

**Returns:** List of tenants with their `activityStatus`. The status is reported with the legacy names: `HOT` is [`ACTIVE`](../how-to-manage-collections/tenant-states.md#active), `COLD` is [`INACTIVE`](../how-to-manage-collections/tenant-states.md#inactive), and `FROZEN` is [`OFFLOADED`](../how-to-manage-collections/tenant-states.md#offloaded) (a tenant offloaded to cloud storage). `FREEZING` and `UNFREEZING` are the transitional `OFFLOADING` and `ONLOADING` states. Calling the tool on a collection without multi-tenancy returns an error.

### `weaviate-query-hybrid`

Performs a hybrid search combining vector similarity and keyword matching (BM25).

**Arguments:**

- `query` (string, required): The natural language search text.
- `collection_name` (string, required): The collection to search.
- `tenant_name` (string, optional): Tenant to search within for multi-tenant collections.
- `alpha` (float, optional): Weighting between the two searches. `0.0` = pure keyword search, `1.0` = pure vector search. Defaults to `0.75`.
- `limit` (int, optional): Maximum number of results. Defaults to `100`. A value of `0` returns no results.
- `target_vectors` (array, optional): Named vectors to use for vector search.
- `target_properties` (array, optional): Properties to search with BM25. If omitted, searches all text properties.
- `return_properties` (array, optional): Properties to include in results. If omitted, every property is returned in full, long text included, so set this to keep responses small.
- `return_metadata` (array, optional): Metadata fields to return (e.g., `id`, `vector`, `distance`, `score`, `creationTimeUnix`, `lastUpdateTimeUnix`). Values are case-insensitive, and unknown values are ignored.
- `filters` (object, optional): A [where filter](../apis/graphql-filters.md) applied before scoring.

A leaf filter is an object with `path` (an array of property names), `operator`, and a typed value field. The typed value field is one of `valueText`, `valueInt`, `valueNumber`, `valueBoolean`, `valueDate`, the corresponding `value*Array` field for a `Contains*` operator, or `valueGeoRange` for `WithinGeoRange`. Combine leaves with `{"operator": "And" | "Or", "operands": [ ... ]}`, nested to any depth. The supported operators are `And`, `Or`, `Not`, `Equal`, `NotEqual`, `Like`, `GreaterThan`, `GreaterThanEqual`, `LessThan`, `LessThanEqual`, `ContainsAny`, `ContainsAll`, `ContainsNone`, `WithinGeoRange`, and `IsNull`. See [Concepts: Filtering](../concepts/filtering.md) for how filters interact with search.

**Returns:** Ranked objects. Each result carries the object's properties at the top level, its `id`, and an `_additional` object with the requested metadata.

### `weaviate-objects-upsert`

:::callout{intent="info" title="MCP write access"}
This tool is only available if `MCP_SERVER_WRITE_ACCESS_ENABLED=true`. On Weaviate Cloud it is available by default and the `Enable MCP Read-Only` switch removes it.
:::

Batch inserts or updates objects. An update **replaces** the stored object rather than merging into it: properties you leave out are dropped, and a property set to `null` is removed. If the update supplies no `vectors`, the object is re-vectorized on a collection with a vectorizer, and on a collection without one the stored vector is dropped. To change a single property, send the complete object.

:::callout{intent="warning" title="Upserts can change the schema"}
With [auto-schema](../reference-configuration/collections.md#auto-schema) enabled (the default, including on Weaviate Cloud), an object with an unknown property adds that property to the collection, and a `collection_name` that does not exist creates a new collection with default settings. A mistyped collection name therefore creates a collection instead of failing. If the MCP server must not change your schema, turn auto-schema off (`AUTOSCHEMA_ENABLED=false`. On Weaviate Cloud, the `Enable auto schema generation` switch in the cluster's `Advanced configuration`).
:::

**Arguments:**

- `collection_name` (string, required): The collection to upsert into.
- `tenant_name` (string, optional): Tenant for multi-tenant collections.
- `objects` (array, required): List of objects containing `properties` and optional `uuid` or `vectors`. `vectors` maps vector names to arrays, and there is no singular `vector` field. If `uuid` is omitted, one is generated. If any `uuid` is invalid, the whole call is rejected and nothing is written.

**Returns:** Array of results containing UUIDs or error messages per object, in input order. Partial success is normal: one object can fail while the rest are written.

***

## Errors and limits

- **Authentication:** when anonymous access is disabled, a missing or invalid API key is rejected by the REST layer with HTTP `401` and a JSON body before the request reaches the MCP server: for example, `{"code": 401, "message": "unauthorized: invalid api key"}` for an invalid key, or a `message` of `anonymous access not enabled. Please authenticate through one of the available methods: [API-keys, OIDC]` for a missing one. This applies to `initialize` and `tools/list` as well as to tool calls.
- **Authorization:** a permission failure is a tool result, not an HTTP error: HTTP `200` with `isError: true` and the RBAC message as text (see [Permissions](#permissions)).
- **Server or write access disabled:** a request to `/v1/mcp` on an instance where the MCP server is disabled returns HTTP `503` with a JSON error body. Where only write access is disabled, `weaviate-objects-upsert` is absent from the `tools/list` response, and calling it returns a tool result with `isError: true` and the text `MCP write access is disabled: ...`.
- **Request duration:** on Weaviate Cloud, a request that takes longer than about 60 seconds from its first byte to the response is cut off by the server's write timeout and surfaces as a plain-text HTTP `503` from the ingress (`upstream connect error or disconnect/reset before headers ...`), not as a JSON-RPC error. Nothing from a cut-off upsert is written. Weaviate does not enforce a request-size limit on `/v1/mcp`, so size `weaviate-objects-upsert` batches by how long they take to upload and process, not by bytes, and keep each call well under a minute.

***

## Monitoring

From `v1.38`, the MCP server emits six Prometheus metrics under the `weaviate_mcp_*` prefix on the existing [Prometheus endpoint](../monitoring-and-logging/monitoring.md). Use them to track tool traffic, latency, auth failures, and the live state of the write-access flag.

See [Monitoring → MCP server](../monitoring-and-logging/monitoring.md#mcp-server) for the full label catalogue and the rest of Weaviate's Prometheus surface.

***

## Further resources

- [Vibe coding - Best practices](index.md)
- [Weaviate Docs MCP server](mcp-docs-mcp-server.md)

## Questions and feedback

Have a question or feedback? Here's how to reach us.

::::card-grid
:::card{title="Community Forum" href="https://forum.weaviate.io/c/support" icon="messages-square"}
Ask questions and connect with other developers on our **Community forum**.
:::

:::card{title="Support" href="/guides/support-overview" icon="life-buoy"}
Weaviate Cloud user or customer? Find the right channel on the **Support page**.
:::
::::

## Related pages

- [Agents](./agents-index.md)
- [AI-assisted Weaviate code generation](./ai-assisted-vibe-coding-index.md)
- [APIs](./apis-index.md)
- [Authorization and authentication](./authorization-and-authentication-index.md)
- [Benchmarks](./benchmarks-index.md)
- [Best practices](./best-practices-index.md)
- [Client libraries](./clients-index.md)
- [Client Libraries / SDKs](./client-libraries-index.md)
- [Cloud](./cloud-index.md)
- [Cloud account management](./cloud-account-management-index.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
