Skip to content

MCP Integration

The mempill-mcp package is a FastMCP server that exposes the mempill engine over the MCP stdio transport. It lets any MCP-compatible agent (Claude Desktop, Claude Code, custom) read and write mempill claims without embedding the Python wheel directly.

The server registers four tools, implemented in mempill-mcp/src/mempill_mcp/tools.py:

Tool Signature Description
ingest_claim (subject, predicate, value, provenance, ...) Write a belief claim
query_memory (subject, predicate, as_of_tx_time?) Read the canonical belief
reconcile (subject_lines) Trigger conflict reconciliation
audit (limit?, claim_ref?, from_tx_time?) Read the immutable audit ledger

These map directly to engine.ingest_claim, engine.query_memory, engine.reconcile, and engine.query_audit. The agent_id is injected from the environment — the MCP client never needs to pass it.

subject str Entity (e.g. "user:alice")
predicate str Property (e.g. "city")
value any JSON-serialisable value
provenance str | dict "External:UserAsserted" | "External:ExternalFirstHand" |
"RecallReEntry" | "ModelDerived" | raw wire dict
cardinality str = "Functional" "Functional" | "SetValued" | "Unknown"
confidence_value float = 0.9 Value confidence [0, 1]
confidence_valid_time float = 0.9 Temporal confidence [0, 1]
criticality str = "Low" "Low" | "Medium" | "High" | "Critical"
valid_time dict | None {"start"?: ISO-8601, "end"?: ISO-8601}
derived_from list[str] | None Source claim UUIDs

When disposition is non-committed (Contested, QueuedForAdjudication, etc.), the response includes a human-readable status_reason field explaining why.

subject str
predicate str
as_of_tx_time str | None ISO-8601 UTC for point-in-time query

Returns {"belief": {...}}. Contested beliefs also include status_reason.

subject_lines list[list[str]] Each inner list is [subject, predicate]

Example: [["user:alice", "city"], ["user:bob", "location"]]

limit int = 50
claim_ref str | None UUID of a specific claim to filter
from_tx_time str | None ISO-8601 UTC lower bound
Variable Required Default Meaning
MEMPILL_AGENT_ID Yes Agent identity for all writes in this session. Must be set before launch — the server fails fast with a clear error if missing.
MEMPILL_DB_PATH No in-memory Absolute path to the SQLite database file. If omitted the server uses an ephemeral in-memory engine (data lost on exit).

MEMPILL_AGENT_ID is the single-writer key: all claims written in a session belong to this agent. Use a stable, meaningful identifier (e.g. "claude-desktop-alice").

The mempill wheel is on PyPI; mempill-mcp is installed from source. Set up both into a venv:

Terminal window
# 1. Install the published mempill wheel
pip install mempill
# 2. Install the MCP adapter from source
cd mempill/mempill-mcp
pip install .
# 3. Test the server
MEMPILL_AGENT_ID=test python -m mempill_mcp
# Should start and wait for MCP stdio input; Ctrl-C to exit.

The easiest approach is to use the mempill-demo repository, which ships a pre-built venv with all dependencies. See Examples for the demo.

Claude Desktop reads mcpServers from its config file. Copy the block below, replace the absolute paths, and restart Claude Desktop (full quit — menu bar → Quit, not just close):

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

claude_desktop_config.json
{
"mcpServers": {
"mempill": {
"command": "/ABSOLUTE/PATH/TO/mempill-demo/.venv/bin/python",
"args": ["-m", "mempill_mcp"],
"env": {
"MEMPILL_AGENT_ID": "my-agent",
"MEMPILL_DB_PATH": "/ABSOLUTE/PATH/TO/mempill-demo/demo.db"
}
}
}
}

Important notes:

  • Use the python binary from the project venv that has mempill and mempill-mcp installed. Launching mempill-mcp as a bare command requires both packages to be on the system Python, which is unlikely. The venv python is the reliable path.
  • Claude Desktop does not expand $HOME or shell variables in this file — use literal absolute paths.
  • The MEMPILL_DB_PATH path is shared across all Claude Desktop sessions for this agent. Use distinct paths per agent identity if you need per-agent isolation.

This config is sourced from mempill-demo/mcp/claude_desktop_config.json.example.

Claude Code reads .mcp.json from the project root. This file is gitignored in mempill-demo. Claude Code supports ${VAR:-default} expansion in the env block:

.mcp.json (at project root)
{
"mcpServers": {
"mempill": {
"type": "stdio",
"command": "/ABSOLUTE/PATH/TO/mempill-demo/.venv/bin/python",
"args": ["-m", "mempill_mcp"],
"env": {
"MEMPILL_AGENT_ID": "${MEMPILL_AGENT_ID:-demo-agent}",
"MEMPILL_DB_PATH": "${MEMPILL_DB_PATH}"
}
}
}
}

If MEMPILL_DB_PATH is unset in the shell environment, the server opens an in-memory (ephemeral) engine.

This config is sourced from mempill-demo/mcp/.mcp.json.example.

The server opens the mempill engine once in a FastMCP lifespan context manager and yields {"engine": engine, "agent_id": agent_id} to all tool functions. This means:

  • Engine startup cost (migrations, WAL setup) happens once per server process, not per call.
  • All four tools share the same engine instance and agent identity.
  • SQLite WAL mode is active — concurrent reads from other processes do not block.
  • When MEMPILL_DB_PATH is set, the database file persists after the server exits.

mempill-demo/mcp/verify_stdio.py is a small script that sends a tool-list request over stdio and validates the response. Run it against the installed server:

Terminal window
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
| MEMPILL_AGENT_ID=test .venv/bin/python -m mempill_mcp

You should see a JSON response listing all four tools.

When query_memory returns a Contested belief, the response includes:

{
"belief": {
"status": "Contested",
"primary": null,
"alternatives": [
{"fact": {"value": "Berlin"}},
{"fact": {"value": "Munich"}}
]
},
"status_reason": "This claim conflicts with one or more existing beliefs..."
}

A well-behaved MCP agent should surface this to the user rather than silently picking one value. See Concepts: Contested and Dispositions.