# MCP server

> Give an AI agent the same consented access your server has, through FinchNode's MCP endpoint.

FinchNode runs two MCP servers over Streamable HTTP:

| Server | URL | Key |
| --- | --- | --- |
| Demo | `https://api.finchnode.com/demo/mcp` | None. Synthetic records only. |
| Authenticated | `https://api.finchnode.com/api/mcp` | A `ck_test_` key as a bearer token. Use a `ck_live_` key only in an agent your server runs. |

Start with the demo to see the tools. Move to the authenticated server when your agent needs your app's patients.

> **Records are patient data**
> Every record tool returns health information to the model. Before an agent sends records to a model provider, check that your agreements with that provider cover health data.

## Add it to your client

Claude Code:

```bash
claude mcp add --transport http finchnode-demo https://api.finchnode.com/demo/mcp
claude mcp add --scope project --transport http finchnode https://api.finchnode.com/api/mcp \
  --header 'Authorization: Bearer ${FINCHNODE_API_KEY}'
```
Codex CLI:

```bash
codex mcp add finchnode-demo --url https://api.finchnode.com/demo/mcp
codex mcp add finchnode --url https://api.finchnode.com/api/mcp --bearer-token-env-var FINCHNODE_API_KEY
```
Cursor:

```json
{
  "mcpServers": {
    "finchnode": {
      "url": "https://api.finchnode.com/api/mcp",
      "headers": { "Authorization": "Bearer ${env:FINCHNODE_API_KEY}" }
    }
  }
}
```

In Claude Code, the single quotes keep `${FINCHNODE_API_KEY}` literal, so the shared `.mcp.json` never holds the key. In Cursor, put the JSON in `.cursor/mcp.json` in your project. Set `FINCHNODE_API_KEY` in the shell that runs your client.

Claude.ai and ChatGPT can add the demo server as a custom connector where your plan allows it. Use no authentication. Don't add the authenticated server there: those connectors can't send your key.

## Pick a tool

The authenticated server has fourteen tools, each a thin layer over a REST operation. See [MCP tools](/docs/api/mcp-tools) for the list. Consent is checked in the same place as REST, so an unshared category fails on every tool.

## Expect these differences from REST

- **Server and desktop clients only.** A browser can't hold a key safely.
- **Big snapshots leave out sections.** If `get_health_record` would run past about 256 KiB, it leaves out whole sections and lists them in `meta.truncatedSections`. Read those categories with `get_category_records`.
- **Tool errors.** Sandbox and conformance tools return `FinchNode request failed (<code>): <message>`, with `code`, `status`, and `retryAfterSeconds` in `_meta["com.finchnode/error"]`. Record tools return the message and code as text.
- **Request errors.** A bad key or the per-address limit fails the whole request with a JSON-RPC error and HTTP `401` or `429`.
- **Shared limits.** MCP and REST share your key's [rate limit](/docs/resources/rate-limits).

> **An app key sees every patient**
> An app key reads every subject your app holds receipts for, and `list_users` lists them. Delegated agent credentials narrow access to one patient, but they work with the REST API only. Give an MCP agent a sandbox key while you build. See [Delegated agent credentials](/docs/ai-agents/agent-credentials).
