Canonical page: https://docs.singlebase.io/mcp-guide

# MCP

**Your project's data, ready for agent tools.**

Connect an agent runtime to Singlebase with your project's MCP endpoint and an
agent key. The tools use the same gateway permissions and data operations as
your application's API calls.

## Overview

MCP gives AI agents named tools for discovering collections, finding documents,
changing records, and answering questions from project knowledge.

**Key features:**

- Six tools, with descriptions and examples an agent can use immediately.
- Tool lists and collection choices tailored to the agent key's permissions.
- The same ownership, automations, limits and usage tracking as the JSON API.
- A project switch, disabled by default, and a platform-wide availability switch.
- Stateless HTTP requests with an agent key on every call.

**Use cases:** Coding assistants inspecting an application's data model, support
agents answering policy questions, ingestion workers adding documents, and
operations agents updating records within their assigned collections.

**How it works:**

1. Create an [agent key](/agents.md) with the collections and feature permissions it needs.
2. Enable MCP for the project in the console.
3. Connect your MCP client with the project endpoint and agent key.
4. Let the client discover its tools. Calls go through the normal Singlebase gateway.

## Requirements

You need a project endpoint key, an `agk_…` agent key, and MCP enabled for the
project. Save `settings.mcp.enabled: true` through the console's project settings.
The platform must also have MCP available; a global shutdown prevents projects
from enabling it. MCP is for machines and agent runtimes. It has no user login,
OAuth flow, or session setup.

## Endpoint and authentication

```http
POST https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>
Authorization: Bearer agk_<AGENT_KEY>
Content-Type: application/json
Accept: application/json, text/event-stream
```

`X-API-KEY: agk_<AGENT_KEY>` is also accepted. Authenticate every request.
Root, server and web keys, user bearer tokens, and signed requests are refused.
The trailing-slash URL also works. GET returns 405; responses do not contain an
`Mcp-Session-Id` or open a server message stream.

The endpoint supports MCP Streamable HTTP with JSON responses and protocol
revisions `2025-03-26`, `2025-06-18`, and `2025-11-25`. Clients negotiate a revision
with `initialize` and can send it in `MCP-Protocol-Version` on subsequent calls.

## Connect a client

### Claude Code

```bash
claude mcp add --transport http singlebase \
  'https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>' \
  --header 'Authorization: Bearer agk_<AGENT_KEY>'
```

See the [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp)
for configuration scopes and credential options.

### Cursor

Add a remote server to your MCP configuration:

```json
{
  "mcpServers": {
    "singlebase": {
      "url": "https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>",
      "headers": {"Authorization": "Bearer ${env:SINGLEBASE_AGENT_KEY}"}
    }
  }
}
```

Set `SINGLEBASE_AGENT_KEY` in the environment available to Cursor. See
[Cursor's MCP configuration](https://cursor.com/docs/mcp) for configuration locations.

### Claude Desktop and stdio clients

For a client configuration that launches local commands, use the
[`mcp-remote` bridge](https://github.com/punkpeye/mcp-remote). It forwards requests
to the HTTP endpoint and sends the configured agent-key header:

```json
{
  "mcpServers": {
    "singlebase": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>",
        "--header", "Authorization:${SINGLEBASE_AUTH_HEADER}"
      ],
      "env": {"SINGLEBASE_AUTH_HEADER": "Bearer agk_<AGENT_KEY>"}
    }
  }
}
```

This requires Node.js and the bridge. The gateway itself does not use OAuth.
Keep the configuration containing the key private.

### Raw HTTP

Initialize the connection using your actual endpoint and key:

```bash
curl 'https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>' \
  -H 'Authorization: Bearer agk_<AGENT_KEY>' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
```

The response names the server `singlebase`, advertises tools, and provides
instructions describing this key's collections, permissions and filter syntax.
Normal MCP clients send `notifications/initialized` next; it receives an empty
HTTP 202 response. No server session is created.

List this key's tools:

```bash
curl 'https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>' \
  -H 'X-API-KEY: agk_<AGENT_KEY>' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

Call a tool:

```bash
curl 'https://v1.api.singlebase.io/mcp/<ENDPOINT_KEY>' \
  -H 'X-API-KEY: agk_<AGENT_KEY>' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search_documents","arguments":{"collection":"orders","limit":5}}}'
```

## Tools

| Tool | Purpose | Permission |
| --- | --- | --- |
| `list_collections` | Discover collection descriptions, fields, indexes and permissions | Any collection permission |
| `search_documents` | Return documents using filters or full-text search | `read`; text search also needs `search` |
| `insert_documents` | Add one or more documents | `write` |
| `update_documents` | Update documents by ID or filter | `write` |
| `delete_documents` | Archive documents by ID, IDs or filter | `delete` |
| `ask_documents` | Get a written answer with sources from project documents | `ai.chat` and an available knowledge source |

Only available tools are listed. Schemas describe exact collection enums for
each permission, including their console descriptions. Read tools advertise
`readOnlyHint`; update advertises `idempotentHint`, and delete advertises
`destructiveHint`. These annotations guide the client; gateway checks enforce access.

### list_collections

Call with `{}`. The result includes the collections assigned to this key, their
descriptions, field types, indexes and the key's permissions. Field information
combines the declared schema with a one-document sample when the key has read
access. Sample values are not returned.

```json
{"name":"list_collections","arguments":{}}
```

### search_documents

Returns matching documents. Use a filter alone for a query, or add `search` for
full-text search with the same filter.

Required: `collection`. Optional: `search`, `filter`, `fields` (an array of field
names), `sort`, `limit` (1–100, default 20), `page` (starting at 1), `_user_id`.
The search argument names the collections where this key can use full-text search.

```json
{"name":"search_documents","arguments":{"collection":"orders","filter":{"total:$gte":100},"fields":["_id","total"],"limit":10}}
```

Filters use the normal [query syntax](/queries.md). Put ownership selectors at
the argument root; `_user_id` inside a filter is refused.

### insert_documents

Required: `collection` and `data` (an object or list of objects). Optional:
root `_user_id`, to assign an owner. Documents are unowned when an agent key
does not specify ownership. Collection create automations run normally.

```json
{"name":"insert_documents","arguments":{"collection":"notes","_user_id":"user-123","data":[{"text":"Follow up"},{"text":"Send receipt"}]}}
```

### update_documents

Required: `collection` and `data`. Identify documents using `_id` in the data,
or pass `filter` to apply the changes to matching documents. App automations
follow the normal update path.

```json
{"name":"update_documents","arguments":{"collection":"orders","data":{"_id":"ord_123","status":"shipped"}}}
```

### delete_documents

Required: `collection` and exactly one of `id`, `ids`, or `filter`. This uses
`data.delete`, with the normal archive retention. It does not permanently purge
documents.

```json
{"name":"delete_documents","arguments":{"collection":"notes","ids":["note_123","note_456"]}}
```

### ask_documents

Answers a question in plain language from project documents, citing its
sources. Use this for a written answer; use `search_documents` when you need
the matching records themselves.

Required: `question` and at least one of `collections` or `docsets`.
`collections` accepts 1–10 readable collection names; `docsets` accepts 1–5
enabled agent-accessible docset IDs shown in the tool schema. Calls use
`llm.ask` in `kb` mode. Readable collections with `search` use text retrieval;
without it, the answer uses up to 20 documents from the collection. Docsets use
their configured retrieval and ACL rules.

```json
{"name":"ask_documents","arguments":{"question":"What is our refund policy?","docsets":["docset-123"]}}
```

## Permissions

Agent keys decide which tools and collections appear. A read-only key lists
discovery and search. Write enables insert and update; delete enables deletion;
`ai.chat` enables answering when a readable collection or allowed docset exists.
Changing the key takes effect on the next request. A name invented by a model
does not grant access: out-of-scope collections return `AGENT_SCOPE_DENIED`.
Docsets with user/admin ACLs and disabled docsets are unavailable to agents.

MCP cannot use a full server key or sign in as a user. See [Agents](/agents.md)
for key management, expiry and ownership rules.

## Results and errors

A successful call returns a tool result inside the JSON-RPC `result`:

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "structuredContent": {"data": [{"_id": "ord_123", "total": 150}], "pagination": {"total_items": 1}},
    "content": [{"type":"text","text":"{\"data\":[{\"_id\":\"ord_123\",\"total\":150}],\"pagination\":{\"total_items\":1}}"}],
    "isError": false
  }
}
```

`structuredContent.data` holds the full gateway result. Pagination is included
when available; ask results retain their answer and sources. The text fallback
is compact JSON capped around 20 KB, followed by a note if truncated. The full
structured result remains available.

Gateway and argument failures return `isError: true` with the error code and
message in text and an error object in structured content. Unknown tools, bad
JSON-RPC, and malformed JSON produce protocol errors instead.

| HTTP status | Meaning |
| --- | --- |
| `401` | Invalid/disabled agent key, another credential type, or `AGENT_KEY_EXPIRED` |
| `403` | `MCP_DISABLED_FOR_PROJECT`, or an unauthorized supplied Origin |
| `405` | Method other than POST while the service is enabled |
| `503` | `MCP_DISABLED`, maintenance, offline service, or database unavailable |

## Limits

Each tool call counts as its mapped gateway operation, using the same rate
limits and usage recording as an API call with that agent key. AI work uses
the normal model metering. Call metrics include `surface: "mcp"`. MCP has no
separate tool quota. JSON requests are limited to 10 MB; the 20 KB text limit
affects only the fallback, not the structured result. JSON-RPC batches are not
supported.
