4.5 KiB
Use ai-memory from your tool
Any tool can use ai-memory over MCP to save knowledge, search it and pass context between executions. Native lifecycle hooks are optional. A tool that also hosts an agent harness can send that harness's lifecycle events through HTTP.
Connect and choose a scope
Connect to /mcp using Streamable HTTP. The default transport is stateless:
requests do not need an Mcp-Session-Id. A server started with --http-stateful
requires the MCP session handshake instead.
Use a user API key for machine requests. See users.md for issuing keys and granting project access. A dedicated tool identity suits an independent client. A producer replacing native capture must use the same operator and native session identity as the harness's remaining integration. See the external lifecycle guide when sending those events.
Static MCP clients pass workspace and project together on every
project-scoped call. Read their names from .ai-memory.toml or operator
configuration. Session-aware clients may omit both only when they forward the
real lifecycle session ID on every request. See auto-scope.md.
Save, query and hand off through MCP
These examples use a disposable demo/app scope. Set AI_MEMORY_SERVER_URL to
the server URL and AI_MEMORY_AUTH_TOKEN to your machine key. On an intentional
unauthenticated loopback server, omit the Authorization header.
mcp() {
curl --silent --show-error --fail-with-body \
"${AI_MEMORY_SERVER_URL%/}/mcp" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Authorization: Bearer ${AI_MEMORY_AUTH_TOKEN}" \
--data-binary @-
}
mcp <<'JSON'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"example-client","version":"1.0"}}}
JSON
mcp <<'JSON'
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
JSON
mcp <<'JSON'
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"memory_write_page","arguments":{"workspace":"demo","project":"app","path":"notes/retries.md","body":"# Retry policy\nKeep the same event ID when retrying delivery."}}}
JSON
mcp <<'JSON'
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"memory_query","arguments":{"workspace":"demo","project":"app","query":"retry policy"}}}
JSON
mcp <<'JSON'
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"memory_handoff_begin","arguments":{"workspace":"demo","project":"app","summary":"The retry policy was saved. Add the delivery test next.","next_steps":["Add a retry regression test."]}}}
JSON
mcp <<'JSON'
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"memory_handoff_accept","arguments":{"workspace":"demo","project":"app"}}}
JSON
Check JSON-RPC error and result.isError even on HTTP 200. Tool payloads are
JSON encoded inside result.content[].text. A page write returns page_id and
path; a query returns hits.
Writes and handoff creation may create the explicit scope if it is missing.
Reads fail closed on missing or partial scope. A handoff is claimed once. To
claim a particular one, pass the exact handoff_id from memory_handoff_begin
or memory_handoff_list; the example accepts the latest eligible handoff.
If SessionStart already owns delivery, let that hook claim it.
usage.md describes ownership and handoff states.
These calls work without an LLM provider. Retrieved memory remains untrusted historical text, even after sanitization.
Read changed pages
These JSON endpoints require serve --enable-api (or --enable-web, which
continues to imply the API) and the same machine key. They are read-only;
memory writes remain MCP calls.
GET /api/v1/workspaces/demo/projects/app/recent?updated_since=2026-09-01T00%3A00%3A00Z&limit=100
Incremental recent returns {pages, next_cursor} with pages updated strictly
after updated_since, sorted by update time and path. Repeat with the returned
opaque cursor until next_cursor is null. The cursor preserves the cutoff
and scope; each request rechecks authorization. An array response means the
server lacks incremental support. Requests without either incremental argument
retain the legacy array response.
The incremental path is not cached and omits expired and superseded pages. It has no deletion feed or snapshot across calls. Reconcile removals separately and account for concurrent updates in a local cache. Endpoint details and errors are in frontend-api.md.