Skip to content

Claude Agent SDK

This guide shows how to give Claude persistent memory by connecting it to the xmemory MCP server. Two approaches are covered:

  • Agent SDK — the Claude Agent SDK connects to the xmemory MCP server; the agent gets write and read (and more) as ready-made tools.
  • Messages API connector — the Claude Messages API connects to the MCP server directly, with no SDK.

API key: To use xmemory APIs or integrations, you need an API key. Get one from the xmemory console. Copy and securely store the key. Never share your API key publicly.


Terminal window
pip install claude-agent-sdk anthropic xmemory-ai pyyaml

Set XMEM_API_KEY (your xmemory key — create one in the console) in your environment; every example below reads it. Both approaches call Claude, so set ANTHROPIC_API_KEY too. (For TypeScript, the Agent SDK package is @anthropic-ai/claude-agent-sdk.)


xmemory stores data in typed instances. Describe what you want to remember in plain language and xmemory designs the schema for you — natural-language generation is the primary path (you can also hand it an existing schema, e.g. a Pydantic model’s JSON schema).

This is a one-time setup script. Save the returned instance ID (e.g. in an environment variable) and reuse it in your agent.

Fastest path: the CLI creates an instance in three commands (xmemcli xmd generate → validate → instance create). The Python script below is the equivalent if you’d rather stay in code.

import os
import yaml
from xmemory import XmemoryClient, SchemaType
API_KEY = os.environ["XMEM_API_KEY"]
# Connect and pick a cluster
client = XmemoryClient(api_key=API_KEY)
cluster_id = client.admin.list_clusters()[0].id
# Describe what to remember in plain language — xmemory designs the schema
schema = client.admin.generate_schema(
cluster_id,
"Track contacts with name, email, company, and notes.",
)
# Create the instance from that schema
inst = client.admin.create_instance(
cluster_id=cluster_id,
name="contacts",
schema_text=yaml.dump(schema.data_schema, allow_unicode=True),
schema_type=SchemaType.YML,
)
print(f"Created instance: {inst.id}")
# → store this in XMEM_INSTANCE_ID and reuse it on subsequent runs

The instance ID is a UUID string. Keep it — you’ll use it to get an instance handle on subsequent runs.


This headless flow sends your account API key directly as the Bearer token on the /instance/<instance_id> shortcut path — no OAuth exchange needed. The instance is bound by the URL path. See the MCP guide for the other connection options.

Register the xmemory MCP server under mcp_servers (keyed by server name) with type: "http". MCP tools must be allow-listed via allowed_tools using the mcp__<server>__<tool> pattern, or Claude can see them but not call them.

import asyncio
import os
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
API_KEY = os.environ["XMEM_API_KEY"]
INSTANCE_ID = os.environ["XMEM_INSTANCE_ID"] # from Part 1
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"xmemory": {
"type": "http",
"url": f"https://mcp.xmemory.ai/instance/{INSTANCE_ID}",
"headers": {"Authorization": f"Bearer {API_KEY}"},
}
},
allowed_tools=["mcp__xmemory__write_async", "mcp__xmemory__read"],
)
async for message in query(
prompt="Remember that Alice Johnson works at Acme Corp, her email is alice@acme.com.",
options=options,
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
if __name__ == "__main__":
asyncio.run(main())

The TypeScript SDK takes the same shape under mcpServers / allowedTools:

import { query } from "@anthropic-ai/claude-agent-sdk";
const INSTANCE_ID = process.env.XMEM_INSTANCE_ID!;
const API_KEY = process.env.XMEM_API_KEY!;
for await (const message of query({
prompt: "Remember that Alice Johnson works at Acme Corp, her email is alice@acme.com.",
options: {
mcpServers: {
xmemory: {
type: "http",
url: `https://mcp.xmemory.ai/instance/${INSTANCE_ID}`,
headers: { Authorization: `Bearer ${API_KEY}` },
},
},
allowedTools: ["mcp__xmemory__write_async", "mcp__xmemory__read"],
},
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}

write_async returns immediately — recall it in a later turn (a subsequent query reflects it). Avoid read in the same turn as an async write.


The Messages API can connect to a remote MCP server itself — Claude calls the tools server-side. Pass the server under mcp_servers with type: "url", set authorization_token to your raw xmemory API key (the connector adds the Bearer prefix), and reference the server from tools with an mcp_toolset entry. The connector is in beta — pass the mcp-client-2025-11-20 beta flag.

import os
import anthropic
API_KEY = os.environ["XMEM_API_KEY"]
INSTANCE_ID = os.environ["XMEM_INSTANCE_ID"] # from Part 1
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
response = client.beta.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
betas=["mcp-client-2025-11-20"],
mcp_servers=[
{
"type": "url",
"url": f"https://mcp.xmemory.ai/instance/{INSTANCE_ID}",
"name": "xmemory",
"authorization_token": API_KEY,
}
],
tools=[{"type": "mcp_toolset", "mcp_server_name": "xmemory"}],
messages=[{"role": "user", "content": "What do you know about Alice?"}],
)
print(response)

Available MCP tools (instance connection type)

Section titled “Available MCP tools (instance connection type)”

The instance connection exposes 9 default tools — 6 bound (get_instance_id, get_instance_schema, write, write_async, write_status, read) and the 3-tool schema-evolution suggestion engine (review_suggestions, decide_suggestions, apply_pending_decisions) — plus an opt-in Schema management group (5 more). See the MCP — Tools reference for full parameter and return-shape details.