MCP server
Khiip ships a Model Context Protocol server
(khiip-mcp-server) that exposes the substrate’s core operations as MCP tools.
Claude Desktop, Cursor, or any other MCP-aware client can connect over stdio and
capture/recall through Khiip without writing any HTTP code.
Tools
| Tool | Maps to |
|---|---|
capture_url(url, force_new=False) | POST /api/v1/captures |
recall(query, limit=10) | GET /api/v1/recall |
list_captures(source=None, limit=50, offset=0) | GET /api/v1/captures |
get_capture(capture_id, format="json") | GET /api/v1/captures/{id} |
refetch_capture(capture_id, dimension="extraction") | POST /api/v1/captures/{id}/refetch |
daemon_status() | GET /health + GET /api/v1/meta |
How it works
The MCP server is a thin HTTP proxy that connects to your running Khiip daemon at
127.0.0.1:8478 (configurable via the KHIIP_DAEMON_URL env var or
[daemon] host/port in ~/.config/khiip/config.toml). It reads the Bearer auth
token from ~/.config/khiip/auth.toml — the same file the CLI and Obsidian plugin
use. The daemon must be running before MCP tool calls land.
Claude Desktop config
On macOS, edit ~/Library/Application Support/Claude/claude_desktop_config.json
(analogous paths on other platforms):
{ "mcpServers": { "khiip": { "command": "khiip-mcp-server" } }}If khiip-mcp-server isn’t on Claude Desktop’s PATH (common when you installed
with pip install -e inside a venv), point at the full path:
{ "mcpServers": { "khiip": { "command": "/Users/you/projects/khiip/.venv/bin/khiip-mcp-server" } }}Verify the wiring
# Start the daemon in one terminalkhiipd serve
# In another terminal, send an initialize ping to the MCP serverpython -c "import asynciofrom mcp.client.session import ClientSessionfrom mcp.client.stdio import stdio_client, StdioServerParameters
async def main(): params = StdioServerParameters(command='khiip-mcp-server', args=[]) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools = await session.list_tools() for t in tools.tools: print(t.name)
asyncio.run(main())"You should see all six tool names listed.