= MCP server :nav-title: MCP Server :description: Let AI agents such as Claude use your data over MCP: publish collections, aggregations, streams and GraphQL apps, and the agent works within your permissions. :keywords: MCP server, Model Context Protocol, AI agent backend, connect Claude to database, agent tools, AI app backend :group: Build :order: 70 Every service can present itself to an AI agent over the **Model Context Protocol**. You choose which collections, aggregations, change streams and GraphQL applications the agent may use, and describe each one so it knows what the thing is for. Nothing is exposed until you publish it. image::/assets/docs-images/mcp.png[The MCP Server page: the published resources with a description each, and the tools below] NOTE: MCP is in **beta**. The endpoint and the published catalogue are stable enough to build against; expect the page itself to keep gaining features. == Your first agent, in ten minutes Three steps, from a service to Claude answering a question about your data. Nothing here needs code. . **Publish a collection.** Under **Published resources**, **Add collection**, pick one, and write what it holds — a sentence an agent reads to decide whether this is the data it wants. Say `orders`: "Customer orders, one document per order, with status and total." Or skip this: the next step publishes a test collection. . **Quick test setup.** Under **Tools → Quick test setup**, click **Do all**. It creates the user `agent`, a permission for it on `/mcp` and on the test collection `/todos`, publishes `/todos` with a JSON schema, and issues an API key, shown once. To let `agent` read `orders` too, add a permission for the role `agent` on `/orders` on the xref:managing-permissions.adoc[Permissions] page. **Test credentials** is now filled in with the key: load it, and the collections are there. . **Connect Claude.** In Claude, **Settings → Connectors → Add custom connector**, paste the endpoint from **How to connect an agent**, and when Claude asks you to sign in, sign in as `agent` with the password shown in Quick test setup. In Cursor, VS Code or Claude Code, use the snippet under **How to connect an agent** instead: the key is already in it. Then ask: *"How many orders are still open?"* The agent reads the catalogue, finds `orders`, reads it with the permissions of `agent`, and answers. Everything it can do from here is what that user, with that role, can do over REST. == Published resources The page opens with the **Published resources** panel: the collections, aggregations, change streams and GraphQL apps an agent can find, and read or write within the permissions you defined. It starts empty. To publish something, click the **Add** button for its type at the bottom of the panel — **Add collection**, **Add aggregation**, **Add change stream**, **Add GraphQL app** — and a form opens in its place: . **Which one** — pick from what is not published yet, of that type. . **What it is for** — the description the agent reads to decide whether this is the resource it wants. . **Publish**. The description is the part that matters. An agent picks a resource by reading it, so write what the thing holds or computes, not what it is called: [cols="1,3"] |=== | Type | What to write | Collection | What it holds, so an agent knows when to read it. | Aggregation | What it computes, and what its parameters mean. | Change stream | What changes it reports. | GraphQL app | What this API is for. |=== To unpublish, remove the entry. The agent stops seeing it on its next catalogue read. Publishing and permissions are two separate switches. A published resource the agent's role cannot read is not in its catalogue; a readable resource that is not published is not there either. === Parameters of a parametric aggregation An aggregation whose pipeline uses `$var` takes parameters, and the page lists them under the entry, one row each, driven by the pipeline itself: add a variable to the stages and the row appears. Give each one a type and a description. Left undescribed, an agent is told the parameter exists and nothing more, which in practice means it guesses. == Tools Under the panel, four folded panels: click a title to open it. === Quick test setup Creates a test user, its permission, a test collection and an API key, so you can connect an agent right away. Normally you define roles for agents, let your users issue API keys with those roles, write the permissions and publish resources; this panel makes a test version of each, and shows with a checkbox which ones already exist: [cols="1,2,1"] |=== | Item | What it is | Button | Test user `agent` | A user of the service with the role `agent`. The password is generated and shown; the service never returns it, so after a page reload it is unknown here. | **Create**, or **Reset password** when the user exists | Test permission `agentTest` | The role `agent` may use `/mcp` and read `/todos`. | **Create**, or **Rewrite** | Test collection `/todos` | Created empty if missing, given the JSON schema `todo` (`title`, `done`, `priority`, `due`) and published with a description and an example query. | **Publish** | API key for `agent` | Turns API keys on if needed, lets the role `agent` issue keys, revokes the keys `agent` already holds, and issues one as `agent`. Needs the password: when it is not known here, it is reset first. The key is shown once, and goes into the snippets under How to connect an agent. | **Issue**, or **Reissue** |=== **Do all** runs the unchecked items in order. Everything it writes is what you would create yourself on the xref:managing-users.adoc[Users], xref:managing-permissions.adoc[Permissions], xref:schemas.adoc[Schemas] and xref:api-keys.adoc[API Keys] pages, under those names, and can be changed there. A permission applies within 20 seconds. To just try, the root user created with the service works too, and sees everything. === Test credentials Enter an API key or a user's password and load the catalogue of MCP resources that credential gets. Credentials carry a role, and the role's permissions decide which resources the agent can see and write: the same service shows different things to different users, because permissions apply to MCP exactly as they apply to REST. Test with the credential the agent will actually use. A password test shows what the *user* sees; a key carries only the roles it was issued with, so its agent may see less. Two things the listing does not show on its own: * The listing is only the first half. What an agent then *reads* is narrowed again by the permission's `readFilter` and `projectResponse`, which apply to MCP reads as they do to REST ones. * A GraphQL app's schema is already per-caller here: a field its `@visible` directive hides from those roles is absent from what you see. === How to connect an agent The panel gives you the endpoint and the four facts every client needs: [cols="1,3"] |=== | | Value | Endpoint | `https://f3a9c1.eu-central-1-free-1.restheart.com/mcp` | Transport | Streamable HTTP | Configuration | MCP 2025-06-18 | Headers | `Authorization: Bearer ` and `Content-Type: application/json` |=== The panel also has ready-made steps for the three common clients: * **Claude** — Settings → Connectors, in the desktop app or on claude.ai. Add → Add custom connector, and paste the endpoint. Claude then opens your service's login page: sign in as a **user of the service**, with that user's own username and password. Not your RESTHeart Cloud account, which signs you into the console and is unknown to the service. The agent reads what that user may read. * **Cursor** — add it from Cursor's own settings and paste the endpoint. In the `Authorization` header put `Bearer` and an API key (`rhak_…`) a user of the service issued for the agent. The panel shows the `.cursor/mcp.json` it expects, with the key from Quick test setup already in it. * **VS Code** — run "MCP: Add Server" from the Command Palette and paste the endpoint, with the same `Authorization` header. The panel shows the `.vscode/mcp.json`. For anything else — Zed, Windsurf, Claude Code, an agent you wrote yourself — the four facts above are all the configuration there is. ==== Give the agent its own credential An agent reads with the permissions of whoever it authenticates as. Before one can connect, two things have to be in place: . **An API key.** A user of your service issues one for the agent, and the key carries a role you chose for that user on the API Keys page: see xref:api-keys.adoc[API Keys for Agents] for how to turn that on and how a key is issued. Not your own account, and not the service administrator: an agent that authenticates as an administrator can read everything the administrator can. . **Permissions for that role**, written on the Permissions page like any other. One to reach the endpoint, with predicate `path-prefix('/mcp')`, and one for each collection or resource the agent may read, exactly as for a REST `GET` on it: the same `readFilter` and `projectResponse` apply. A resource the role cannot read is not in its catalogue, published or not. A client that signs the user in through the browser, like Claude, needs no key: the user signs in as themselves and their roles apply. The second point still holds for those roles. === The OAuth login page Clients like Claude use OAuth authentication: when a user adds your service as a connector, Claude opens a login page where they enter their credentials for your service. Clients that use an API key, like Cursor and VS Code, never see it. The default page is `https://f3a9c1.eu-central-1-free-1.restheart.com/oauth/login`. Under **OAuth Login Page** you can set a custom one, so the user sees your application's login: it receives the OAuth parameters as a query string and must POST them, plus the user's credentials, to `https://f3a9c1.eu-central-1-free-1.restheart.com/authorize`. The URL must be absolute, `https://` or `http://`. The same panel lists the **allowed redirect URIs**: the `redirect_uri` values `/authorize` accepts, `*` as a wildcard. It starts as the default list, which is what Claude and the desktop clients need. If you customise it, keep the `claude.ai` entry, or Claude can no longer connect: your list replaces the default rather than extending it. == Related pages * https://github.com/SoftInstigate/restheart/tree/master/examples/market-game[The market game^] — the full tutorial: three AI agents trading through a service's MCP server, with one collection, six rules and no code * xref:api-keys.adoc[API Keys for Agents] — the credential an agent uses, and how a user issues one * xref:managing-permissions.adoc[Managing Permissions (ACL)] — what an agent may read, including `readFilter` and `projectResponse` * xref:schemas.adoc[JSON Schemas] — what the test collection's schema is made of * xref:aggregations.adoc[Aggregation Pipelines] — where `$var` parameters come from * xref:graphql.adoc[GraphQL Applications] — and the `@visible` directive