Connect an AI Agent
Configure an MCP client, give it access to a patient via the four VFS tools, and walk through a real clinical question end-to-end.
Connect an AI Agent
In this tutorial you will connect a language model to Patient Memory using the Model Context Protocol (MCP). By the end, the agent will be able to browse a patient's conditions, read a condition story, and answer a clinical question that requires traversing relationships across the graph.
Time: ~20 minutes.
Prerequisites
- A patient already ingested. Complete Ingest and Query a Patient first.
- Node.js 18+.
- An Anthropic API key and a Patient Memory access token set in your environment:
export ANTHROPIC_API_KEY="your-anthropic-key"
export CLINIA_ACCESS_TOKEN="your-access-token" # obtained via OAuth client credentialsSee Manage Credentials to obtain a Patient Memory access token.
Replace <workspace-id> with your Patient Memory workspace ID in the code below.
Steps
Install dependencies
npm install @modelcontextprotocol/sdk @anthropic-ai/sdkConnect the MCP client
Patient Memory exposes an MCP endpoint at /mcp over HTTP with SSE streaming. Connect to it and confirm the four tools are available:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
const transport = new SSEClientTransport(new URL("https://<workspace-id>.w.clinia.cloud/mcp"), {
requestInit: {
headers: { Authorization: `Bearer ${process.env.CLINIA_ACCESS_TOKEN}` },
},
});
const mcp = new Client({ name: "clinical-agent", version: "1.0.0" });
await mcp.connect(transport);
const { tools } = await mcp.listTools();
console.log(tools.map((t) => t.name));
// → ["browse_patient", "read_patient", "search_patient", "get_patient_info"]The {id} segment in VFS paths is the VFS patient ID — the patient.id extracted from the ingested record. It may differ from the registry key used at ingest time. Use get_patient_info to look it up if needed.
Wire the tools to Claude
Pass the MCP tools directly to the Anthropic SDK and let Claude decide when to call them:
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
const mcpTools = tools.map((t) => ({
name: t.name,
description: t.description ?? "",
input_schema: t.inputSchema,
}));
async function runAgent(question: string): Promise<string> {
const messages: Anthropic.MessageParam[] = [{ role: "user", content: question }];
while (true) {
const response = await anthropic.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 4096,
tools: mcpTools,
messages,
});
if (response.stop_reason === "end_turn") {
return response.content
.filter((b) => b.type === "text")
.map((b) => b.text)
.join("");
}
const toolUses = response.content.filter((b) => b.type === "tool_use");
if (toolUses.length === 0) break;
const toolResults = await Promise.all(
toolUses.map(async (use) => {
if (use.type !== "tool_use") return null;
const result = await mcp.callTool({
name: use.name,
arguments: use.input as Record<string, unknown>,
});
return {
type: "tool_result" as const,
tool_use_id: use.id,
content: result.content
.filter((c) => c.type === "text")
.map((c) => c.text)
.join("\n"),
};
}),
);
messages.push({ role: "assistant", content: response.content });
messages.push({
role: "user",
content: toolResults.filter(Boolean) as Anthropic.ToolResultBlockParam[],
});
}
return "";
}Run a clinical question
const answer = await runAgent(
"For patient jeanne-tremblay: given the recent acute COPD exacerbation, " +
"is the current inhaler regimen appropriate and is bone health being monitored?",
);
console.log(answer);
await mcp.close();The agent typically calls tools in this sequence:
browse_patienton/patient/jeanne-72f-copd/conditions/activeto discover available conditionsread_patientonchronic_obstructive_lung_disease/_story.md— the COPD story includes the acute exacerbation, current inhaler regimen, and spirometry trends- Optionally
read_patientonosteopenia/_story.md— surfaces the ICS exposure as a contributing factor and the pending DEXA follow-up - Synthesises the answer from the graph data
The agent reaches this conclusion without any application code that knows about ICS-related bone loss. It discovers the relationship from the condition stories, which were assembled by the pipeline from the clinical knowledge base.
Next steps
- MCP Tools reference for full parameter documentation
- Virtual File System to understand the path schema your agent is navigating
- Read a condition story for a focused how-to on format and token budget choices
Ingest and Query a Patient
Full walkthrough: ingest a FHIR bundle and a CDA document, browse the virtual file system, and read a condition story end-to-end.
Synthetic Patient Dataset
Download and ingest Jeanne Tremblay, a fully synthetic FHIR R4 and CDA dataset for testing Patient Memory without real patient data.