# MCP for agents: synthetic records with no key, consented records with your API key.

Canonical URL: https://finchnode.com/products/mcp

> Two Streamable HTTP MCP endpoints: a keyless synthetic demo and your consented records.

FinchNode serves two Model Context Protocol endpoints over Streamable HTTP. The public demo endpoint needs no account and serves the named synthetic scenarios. The authenticated endpoint takes the same app-scoped keys as /api/v1 and reads through the same service, so consent is enforced identically on every tool.

## What it is

Built for: Developers connecting a server-side or desktop MCP client to patient-authorized records, or any MCP client to the synthetic demo.

Base URL: https://api.finchnode.com/demo/mcp (public demo, no key) and https://api.finchnode.com/api/mcp (authenticated, API key)

Authentication: The public demo endpoint (https://api.finchnode.com/demo/mcp) takes no account or key and serves synthetic data only. The authenticated endpoint (https://api.finchnode.com/api/mcp) takes the same app-scoped keys as /api/v1: Authorization: Bearer ck_test_... for sandbox keys or Authorization: Bearer ck_live_... for live keys.

Create a free account to get sandbox keys: https://finchnode.com/signup

**At a glance**

- **Status:** Available
- **Auth:** None for the demo endpoint; API key for the authenticated endpoint
- **Contract:** MCP (Streamable HTTP); tools mirror the OpenAPI 3.1 REST API
- **Public demo MCP endpoint (no key, synthetic):** `https://api.finchnode.com/demo/mcp`
- **Authenticated MCP endpoint (API key):** `https://api.finchnode.com/api/mcp`

**Documents for this product**

- [Markdown version of this page](https://finchnode.com/products/mcp.md)
- [OpenAPI 3.1 document](https://finchnode.com/openapi.yaml)
- [Public demo OpenAPI 3.1 document](https://finchnode.com/demo-openapi.json)

## Try it in 30 seconds

**List the demo MCP tools**

```bash
curl -X POST https://api.finchnode.com/demo/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

No account or key. For the authenticated endpoint, send the same request to https://api.finchnode.com/api/mcp with your API key as a Bearer token, as How it works shows below.

Expected response: A JSON-RPC result whose tools array lists the 14 demo tools, starting with list_demo_scenarios.

Synthetic data only. Not for clinical use.

## For coding agents

Three ways in for a coding agent: connect the MCP endpoints below, load the OpenAPI document (https://finchnode.com/openapi.yaml), or fetch this page as markdown (https://finchnode.com/products/mcp.md). https://finchnode.com/llms.txt lists every product’s markdown twin.

**Public demo MCP endpoint (no key, synthetic)**

- **MCP endpoint:** `https://api.finchnode.com/demo/mcp`
- **Transport:** Streamable HTTP (JSON-RPC over POST)
- **Auth:** None
- **Clients:** ChatGPT, Codex, Claude, and other MCP clients, with no key
- **MCP Registry name:** com.finchnode/health-records-demo

**Tools at https://api.finchnode.com/demo/mcp**

- list_demo_scenarios
- get_demo_health_record
- get_demo_record
- get_demo_fhir_bundle
- search_demo_fhir
- simulate_demo_connect
- get_demo_demographics
- get_demo_medications
- get_demo_conditions
- get_demo_labs
- get_demo_vitals
- get_demo_allergies
- get_demo_immunizations
- get_demo_encounters

**Claude Code: Public demo MCP endpoint (no key, synthetic)**

```bash
claude mcp add --transport http finchnode-demo https://api.finchnode.com/demo/mcp
```

**Codex CLI: Public demo MCP endpoint (no key, synthetic)**

```bash
codex mcp add finchnode-demo --url https://api.finchnode.com/demo/mcp
```

**Cursor (.cursor/mcp.json): Public demo MCP endpoint (no key, synthetic)**

```json
{
  "mcpServers": {
    "finchnode-demo": {
      "url": "https://api.finchnode.com/demo/mcp"
    }
  }
}
```

**Claude.ai: Public demo MCP endpoint (no key, synthetic)**

- Where your plan offers custom connectors: on a Free, Pro, or Max plan, open Customize > Connectors, click Add custom connector, enter https://api.finchnode.com/demo/mcp as the remote MCP server URL, and click Add. If the dialog asks how people connect, choose No sign-in: the demo takes no key. Turn the connector on for a chat from the + button, under Connectors.
- Where your plan offers custom connectors: on a Team or Enterprise plan, an Owner adds https://api.finchnode.com/demo/mcp under Organization settings > Connectors (Add, then Custom, then Web if asked), and each member clicks Connect on it under Customize > Connectors.

**ChatGPT: Public demo MCP endpoint (no key, synthetic)**

- Where your plan offers custom connectors: turn on Developer mode under Settings > Security and login, then open ChatGPT Plugins (chatgpt.com/plugins), select the plus button, and create a developer-mode app for the remote MCP server https://api.finchnode.com/demo/mcp with no authentication.
- Where your plan offers custom connectors: in a conversation, choose Developer mode from the Plus menu and select the app you created for https://api.finchnode.com/demo/mcp.

**Authenticated MCP endpoint (API key)**

- **MCP endpoint:** `https://api.finchnode.com/api/mcp`
- **Transport:** Streamable HTTP (JSON-RPC over POST)
- **Auth:** Authorization: Bearer ck_test_... (sandbox keys) or Authorization: Bearer ck_live_... (live keys)
- **Clients:** Server-side and desktop MCP clients only; the endpoint is not CORS-enabled
- **MCP Registry name:** com.finchnode/health-records

**Tools at https://api.finchnode.com/api/mcp**

- get_app
- list_users
- get_health_record
- get_category_records
- get_record_changes
- get_consent_receipt
- create_connect_session
- get_connect_session
- cancel_connect_session
- simulate_connect_session
- trigger_sandbox_event
- start_conformance_run
- get_conformance_run
- advance_conformance_run

**Set FINCHNODE_API_KEY once in the shell that runs these commands or starts your agent client (replace ck_test_... with your sandbox key; it is the only key value to substitute)**

```bash
export FINCHNODE_API_KEY=ck_test_...
```

**Claude Code: Authenticated MCP endpoint (API key)**

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

Claude Code writes this server to the project's .mcp.json, which is meant to be checked into version control and shared with the project, and expands ${FINCHNODE_API_KEY} when it connects, so the file never holds the key: set FINCHNODE_API_KEY in the shell that runs Claude Code.

**Codex CLI: Authenticated MCP endpoint (API key)**

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

**Cursor (.cursor/mcp.json): Authenticated MCP endpoint (API key)**

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

**Machine-readable resources**

- [llms.txt: every FinchNode product and guide for agents](https://finchnode.com/llms.txt)
- [This page as markdown](https://finchnode.com/products/mcp.md)
- [OpenAPI 3.1 document](https://finchnode.com/openapi.yaml)
- [Public demo OpenAPI 3.1 document](https://finchnode.com/demo-openapi.json)

## How it works

1. **Choose a demo scenario**

   Call list_demo_scenarios first. get_demo_health_record, get_demo_record, get_demo_fhir_bundle, and simulate_demo_connect take an optional scenario id from that list and default to baseline-adult. The per-category tools, such as get_demo_labs, take no scenario and always serve baseline-adult. search_demo_fhir takes patient_id, one of the scenario subjects, instead.

   ```bash
   curl -X POST https://api.finchnode.com/demo/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_demo_scenarios","arguments":{}}}'
   ```

2. **Read a synthetic record and its error paths**

   get_demo_health_record returns the platform-shaped record. Behavior scenarios answer with the production codes as tool results marked isError, with _meta["com.finchnode/error"] = { code, status, retryAfterSeconds, scenario } and no structuredContent; successful results match strict output schemas.

   ```bash
   curl -X POST https://api.finchnode.com/demo/mcp -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_demo_health_record","arguments":{"scenario":"consent-revoked"}}}'
   ```

3. **Connect the authenticated endpoint**

   Point a server-side or desktop MCP client at the authenticated endpoint with your key. It is not CORS-enabled, and it shares rate limits and usage telemetry with /api/v1.

   ```bash
   curl -X POST https://api.finchnode.com/api/mcp -H "Authorization: Bearer $FINCHNODE_API_KEY" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
   ```

4. **Read consented records**

   get_health_record returns a consent-filtered snapshot. If it exceeds 256 KiB, whole categories are dropped and named in meta.truncatedSections, so page those with get_category_records. A category the user has not authorized fails closed, and consent_scope_exceeded comes back as a tool error rather than a transport failure.

   ```bash
   curl -X POST https://api.finchnode.com/api/mcp -H "Authorization: Bearer $FINCHNODE_API_KEY" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_health_record","arguments":{"user":"u_7f3aa1c2d9e4b801","categories":["medications"]}}}'
   ```

## Reference

Both MCP endpoints take JSON-RPC over Streamable HTTP POST: https://api.finchnode.com/demo/mcp (no key) and https://api.finchnode.com/api/mcp (API key). The authenticated tools are a thin adapter over the service /api/v1 uses, so consent is enforced in one place for both; the endpoint table lists the /api/v1 routes behind the record, consent, and Connect tools.

Endpoints

| Method | Path | OpenAPI operationId |
| --- | --- | --- |
| GET | https://api.finchnode.com/api/v1/app | getCurrentApp |
| GET | https://api.finchnode.com/api/v1/users | listUsers |
| GET | https://api.finchnode.com/api/v1/users/{subject}/records | getUserRecord |
| GET | https://api.finchnode.com/api/v1/users/{subject}/records/{category} | listCategoryRecords |
| GET | https://api.finchnode.com/api/v1/users/{subject}/records/{category}/changes | listRecordChanges |
| GET | https://api.finchnode.com/api/v1/consents/{receiptId} | getConsentReceipt |
| POST | https://api.finchnode.com/api/v1/connect/sessions | createConnectSession |
| GET | https://api.finchnode.com/api/v1/connect/sessions/{sessionId} | getConnectSession |
| POST | https://api.finchnode.com/api/v1/connect/sessions/{sessionId}/cancel | cancelConnectSession |

MCP tools

| Tool | Endpoint |
| --- | --- |
| list_demo_scenarios | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_health_record | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_record | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_fhir_bundle | https://api.finchnode.com/demo/mcp (no key) |
| search_demo_fhir | https://api.finchnode.com/demo/mcp (no key) |
| simulate_demo_connect | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_demographics | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_medications | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_conditions | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_labs | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_vitals | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_allergies | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_immunizations | https://api.finchnode.com/demo/mcp (no key) |
| get_demo_encounters | https://api.finchnode.com/demo/mcp (no key) |
| get_app | https://api.finchnode.com/api/mcp (API key) |
| list_users | https://api.finchnode.com/api/mcp (API key) |
| get_health_record | https://api.finchnode.com/api/mcp (API key) |
| get_category_records | https://api.finchnode.com/api/mcp (API key) |
| get_record_changes | https://api.finchnode.com/api/mcp (API key) |
| get_consent_receipt | https://api.finchnode.com/api/mcp (API key) |
| create_connect_session | https://api.finchnode.com/api/mcp (API key) |
| get_connect_session | https://api.finchnode.com/api/mcp (API key) |
| cancel_connect_session | https://api.finchnode.com/api/mcp (API key) |
| simulate_connect_session | https://api.finchnode.com/api/mcp (sandbox keys) |
| trigger_sandbox_event | https://api.finchnode.com/api/mcp (sandbox keys) |
| start_conformance_run | https://api.finchnode.com/api/mcp (sandbox keys) |
| get_conformance_run | https://api.finchnode.com/api/mcp (sandbox keys) |
| advance_conformance_run | https://api.finchnode.com/api/mcp (sandbox keys) |

## What it does not do

- The authenticated endpoint is not CORS-enabled: responses can contain PHI and a browser origin cannot hold a live key safely, so it is for server-side and desktop MCP clients.
- An app-scoped key reaches every subject the app holds receipts for, and list_users enumerates them. Treat it accordingly when handing it to an agent.
- The authenticated endpoint is not eligible for the Claude or ChatGPT connector directories, which require OAuth 2.1; it authenticates with API keys.
- The demo endpoint serves synthetic data only. It never reaches production records, real patient accounts, credentials, or vendor sandboxes, and it is not for clinical use.
- 5xx detail never reaches the caller: only the status-derived message is returned, and no subject label, receipt id, or record value appears in an error.

## Frequently asked questions

### Which MCP endpoint should I connect?

Use https://api.finchnode.com/demo/mcp to prototype with synthetic data and no key. Use https://api.finchnode.com/api/mcp with a sandbox key (ck_test_...) to reach your sandbox connections, or a live key (ck_live_...) for production connections.

### Does the MCP endpoint enforce consent like the REST API?

Yes. The authenticated endpoint is a thin adapter over the service /api/v1 uses, so a category the user has not authorized fails closed on every tool, and consent_scope_exceeded comes back as a tool error the agent can recover from.

### How are demo errors reported to an agent?

Behavior scenarios return tool results with isError set and _meta["com.finchnode/error"] carrying code, status, retryAfterSeconds, and scenario, so an agent can branch on the code without parsing prose. An error result carries no structuredContent.

### What are the MCP Registry names?

com.finchnode/health-records-demo for the demo endpoint, which declares no headers, and com.finchnode/health-records for the authenticated endpoint, which declares a required Authorization header, so a client asks for a key at install time.

## Related

- [Public Demo API](https://finchnode.com/products/demo-api.md)
- [Records API](https://finchnode.com/products/records-api.md)
- [Hosted Connect](https://finchnode.com/products/hosted-connect.md)
- [Fetch patient data with a FHIR API: Patient, labs, conditions, and medications.](https://finchnode.com/blog/fhir-api-tutorial-patient-data.md)
- [FHIR API error handling: retries, rate limits, and partial results.](https://finchnode.com/blog/fhir-api-errors-retries-rate-limits.md)
