Connecting an MCP client¶
luplo ships a Model Context Protocol server on stdio. Any MCP-compatible client — Claude Code, Claude Desktop, Cursor, Zed, or something built on the MCP SDKs — can call luplo’s tools during a coding session.
This guide shows how to wire up the most common clients and how to sanity-check the connection. For the full tool surface see MCP tool reference.
The launch command¶
Every client spawns the luplo MCP server the same way:
uv run --directory /absolute/path/to/luplo python -m luplo.mcp
…with LUPLO_DB_URL in the environment so the server can reach
Postgres. What varies between clients is only the config file shape
that describes this command.
Tip
Use an absolute path for --directory. MCP hosts don’t execute from
your shell’s working directory.
Claude Code¶
Claude Code auto-detects .mcp.json in the workspace root.
cp .mcp.json.example .mcp.json
# edit the path and DB URL
{
"mcpServers": {
"luplo": {
"command": "uv",
"args": [
"run", "--directory", "/absolute/path/to/luplo",
"python", "-m", "luplo.mcp"
],
"env": {
"LUPLO_DB_URL": "postgresql://USER:PASSWORD@localhost/luplo"
}
}
}
}
Reopen the workspace. Claude Code will show luplo under MCP servers
and the tools become callable.
Claude Desktop¶
Merge the same mcpServers block into:
macOS —
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows —
%APPDATA%\Claude\claude_desktop_config.jsonLinux —
~/.config/Claude/claude_desktop_config.json
Restart Claude Desktop after editing.
Cursor¶
Cursor reads ~/.cursor/mcp.json (global) or .cursor/mcp.json (per
project). The schema is identical to Claude Code’s:
{
"mcpServers": {
"luplo": {
"command": "uv",
"args": [
"run", "--directory", "/absolute/path/to/luplo",
"python", "-m", "luplo.mcp"
],
"env": {
"LUPLO_DB_URL": "postgresql://USER:PASSWORD@localhost/luplo"
}
}
}
}
Restart Cursor (or open the project fresh).
Zed¶
Zed’s MCP support is evolving; consult the
Zed docs for the current config path. The command
shape is the same uv run --directory … python -m luplo.mcp.
Other clients¶
Any MCP client that speaks the stdio transport can host luplo. If you
are building a custom client, see the
MCP client SDKs. Pass the
same command, args, and env through the client’s server-config
shape.
Smoke test¶
Once connected, ask the client:
“What did we decide about auth in this project?”
A correctly wired client will call luplo_item_search with a query
derived from your question, return the matching decisions, and cite
the ids. If you get no results, either no decisions are saved yet or
the project id is wrong.
You can also verify manually from the CLI:
uv run lp items search "auth" --project myapp
If the CLI sees items and the MCP client doesn’t, the client is
pointing at a different DB (check LUPLO_DB_URL) or a different
project (check the project_id argument in the tool calls).
How clients should use luplo¶
From luplo’s perspective, a well-behaved MCP client:
Calls
luplo_briefat most once per session, only when the human asks for context — not on every prompt. See Philosophy on why there is no auto-injection.Calls
luplo_item_searchliberally — it is cheap, glossary-expanded, and returns match reasons.Calls
luplo_save_decisionsandluplo_item_upsertonly when the human explicitly says so (“save this decision”, “log that we decided…”). Never auto-extracts.
These are conventions, not enforcement. luplo has no way to stop a
client from spamming luplo_brief on every tool call — that’s a client
bug to fix there, not a feature to code around here.
Trouble¶
- Client can’t find the server.
Run the launch command by hand from your shell. If
uv runworks there, the host is either using a non-login shell (noPATH) or--directorypoints at the wrong place. Use absolute paths.- Tool call succeeds but returns empty.
Check the
project_id. luplo is per-project; an empty project responds with nothing. Seed vialp init.- Server crashes on start.
Inspect stderr via the client’s MCP logs. The most common cause is
LUPLO_DB_URLpointing at a DB that isn’t up or doesn’t have migrations applied — runalembic upgrade head.