# MCP Server

URL: https://docs.clinia.com/api/mcp/server

> Connecting to the MCP server, the arguments every tool shares, and how tools report errors.

The MCP server exposes four tools at `/mcp`:

| Tool                                                  | Returns                                        |
| ----------------------------------------------------- | ---------------------------------------------- |
| [`browse_patient`](https://docs.clinia.com/api/mcp/tools/browse-patient)     | A directory listing, or a file's content       |
| [`read_patient`](https://docs.clinia.com/api/mcp/tools/read-patient)         | A file's content in a chosen format and length |
| [`search_patient`](https://docs.clinia.com/api/mcp/tools/search-patient)     | Paths whose content matches a keyword query    |
| [`get_patient_info`](https://docs.clinia.com/api/mcp/tools/get-patient-info) | Patient demographics as JSON                   |

Every tool returns a single text content block.

## Connect [#connect]

Use the [Model Context Protocol](https://modelcontextprotocol.io) SDK to connect over streamable HTTP (with SSE support in clients/transports). Every call needs a token with the `read` scope, passed as `Authorization: Bearer <token>`. The transport is stateless: there is no client-level session to track. [Connect an AI Agent](https://docs.clinia.com/docs/context-assembly/connect-an-ai-agent) shows the client setup end to end.

## Shared arguments [#shared-arguments]

Every tool takes these two arguments:

| Argument     | Type   | Required | Description                                                                                                                    |
| ------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `patient_id` | string | Yes      | The `patientId` you assigned when [creating the patient](https://docs.clinia.com/api/rest/put-patients-patientId), as in REST routes.                 |
| `session_id` | string | No       | A [session](https://docs.clinia.com/docs/learned-memory/sessions) to record the call on. See [Record calls on a session](#record-calls-on-a-session). |

### Paths [#paths]

`browse_patient` and `read_patient` also take a `path`, relative to the patient: `/` for the root, `/conditions/active` for a folder. [VFS Paths](https://docs.clinia.com/api/vfs-paths) lists every path the tree can hold.

A path may start with `/patient/{id}/`, the form `search_patient` returns. That prefix is dropped, so the patient is always the one `patient_id` names.

### Record calls on a session [#record-calls-on-a-session]

With a `session_id`, the call and its text result are appended to that session as a tool call and its result. The session is created on first use, so a new id must follow the [rules for identifiers you assign](https://docs.clinia.com/api/identifiers#identifiers-you-assign).

Recording is best effort: an id no session can be created under records nothing, and the tool still returns its result.

## Typical agent flow [#typical-agent-flow]

1. `browse_patient` on `/` to discover what the patient's record holds.
2. `browse_patient` deeper into a domain (conditions, medications, labs, timeline).
3. `read_patient` on specific files for detailed context.
4. `search_patient` when the agent knows a term but not the path.
5. `get_patient_info` for demographics.

## Errors [#errors]

A tool fails the call when what it was asked for does not exist: the result has `isError: true`, and its text says what is missing.

- A `patient_id` with no patient, or no ingested data yet, fails every tool with a not-ready message naming the ingest routes to call first:

  ```
  Patient "abc" not found or no data ingested yet. POST to /v1/patients/abc/ingestions/fhir/r4, /v1/patients/abc/ingestions/fhir/r5, or /v1/patients/abc/ingestions/cda/r2 first, then poll the receipt it returns.
  ```

- `browse_patient` or `read_patient` on a path that does not exist fails with `path not found: {path}`.

A search that matches nothing is not a failure. It returns `No results for "{query}".`
