MCP Server (Model Context Protocol)
Expose uteke memories as tools to AI coding agents — Claude Code, Claude Desktop, Cursor, Copilot, and any MCP-compatible client.
Quick Start
Option A: Stdio Transport (recommended for local agents)
No daemon needed — uteke-mcp communicates over stdin/stdout:
// Claude Code — .mcp.json or ~/.claude/settings.json
{
"mcpServers": {
"uteke": {
"command": "uteke-mcp"
}
}
}Option B: HTTP Transport (for remote/shared access)
Requires uteke-serve running. Uses Streamable HTTP transport:
{
"mcpServers": {
"uteke": {
"url": "http://127.0.0.1:8767/mcp"
}
}
}Client Configuration
Claude Code
Create or edit .mcp.json in your project root, or ~/.claude/settings.json for global access:
// Stdio (recommended)
{
"mcpServers": {
"uteke": {
"command": "uteke-mcp"
}
}
}// HTTP (requires uteke-serve)
{
"mcpServers": {
"uteke": {
"url": "http://127.0.0.1:8767/mcp"
}
}
}Claude Desktop
Create or edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"uteke": {
"command": "uteke-mcp"
}
}
}Cursor
Create or edit .cursor/mcp.json in your project root:
{
"mcpServers": {
"uteke": {
"command": "uteke-mcp"
}
}
}Hermes
Register uteke as an MCP server with the Hermes native client:
# Stdio transport
hermes mcp add uteke --command uteke-mcp
# HTTP transport (requires uteke-serve running)
hermes mcp add uteke --url http://127.0.0.1:8767/mcpMCP is Tool-Based (Not Automatic)
The MCP server exposes uteke as tools — the agent decides when to call uteke_recall, uteke_remember, etc. This means:
- ✅ On-demand: The agent calls memory tools only when needed (e.g., "recall project context before coding")
- ✅ Agent-controlled: The agent decides what to store and when to query
- ❌ No auto recall: Memories are NOT automatically injected every turn
- ❌ No auto extract: Facts are NOT automatically extracted from conversations
If you need automatic recall (memories injected every LLM call without the agent asking), use Mode C (shell hook) instead:
uteke init --agent hermes # Installs pre_llm_call hookWhich Integration Mode to Use?
| Need | Use This | How |
|---|---|---|
| On-demand memory, coding agents | MCP (this page) | uteke-mcp or POST /mcp |
| Automatic recall every turn | Mode C (shell hook) | uteke init --agent hermes |
| Automatic recall + auto extract | ❌ Deprecated (removed 2026-06-29) | |
| Multi-agent shared rooms | MCP + Mode C combo | Mode C for auto recall, MCP for room operations |
Tip: MCP and Mode C work great together. Use Mode C for automatic recall on every LLM call, and MCP for explicit tool-based operations like
uteke_doc_create,uteke_graph, oruteke_room_recall.
Available Tools
Both transports expose the same 49 tools (MCP protocol version 2025-06-18):
| Tool | Description |
|---|---|
uteke_remember | Store a memory (supports type, room, author, tags) |
uteke_recall | Semantic search (supports tags filter, min_score, strategy: fusion/vector/fts5/hybrid/graph — default fusion since 0.16.0, and the explain flag showing why each result ranked where it did, #1160). pack: true returns a budgeted context pack {selected, skipped, budget_used, budget_chars} (#1281) — deterministic, LLM-free, rank-order preserving; pair with budget_chars and exclude_ids (IDs already injected this turn) |
uteke_search | Text search with optional tag filter |
uteke_list | List memories (supports pagination via offset, or include_meta: true for the {memories, total, has_more, next_offset} envelope, #1188) |
uteke_get | Fetch a single memory's full record by id — no truncation (accepts UUID or unambiguous prefix) |
uteke_update | Partial update — only provided fields change; content changes re-embed; accepts namespace to move a memory (#1181) |
uteke_supersede | Mark a memory superseded by a newer one — wires the edge pair, soft-deprecates the old row; recall flags stale results (⚠ superseded by …) |
uteke_provenance | Full provenance report for a memory (#1172): author/source fields, trust tier, source hash at write vs live-recomputed content hash, and the timeline event chain with actor + evidence |
uteke_contradictions | List the contradiction resolution ledger (#1172): superseded-but-not-restored memories with winner, reason, and timestamp |
uteke_contradictions_undo | Undo a contradiction resolution (#1172): restore the retired memory, remove the supersession edge pair, record supersession_undone events |
uteke_timeline | Read the audit-grade timeline for a memory (#1280, schema v20): id, optional limit. Includes deprecated events (with reason) and forgot tombstones of hard-forgotten memories — history is never deleted |
uteke_forget | Delete a memory (accepts UUID or unambiguous prefix) |
uteke_stats | Memory store statistics |
uteke_context | AI-optimized context output for prompts |
uteke_dream | Maintenance pipeline (lint → backlinks → dedup → orphans → compact → verify). Dry-run by default — pass dry_run: false to apply; scope namespace or confirm_large for whole-store / >100-change runs |
uteke_verify | Report SQLite row count vs vector index size with a match flag (#1272) — live audit without restarting uteke-serve (write-token surface) |
uteke_repair | Rebuild the vector index from stored embeddings (#1272) — fixes the stale-index failure mode where rows exist in SQLite+FTS5 but go missing under fusion/hybrid recall |
uteke_doc_create | Create a document (wiki/knowledge base entry) |
uteke_doc_get | Retrieve a document by ID |
uteke_doc_list | List all documents |
uteke_doc_search | Search documents |
uteke_doc_delete | Delete a document |
uteke_doc_update | Partial document update with chunk rebuild (#589) |
uteke_doc_move | Move document to new parent (#438) |
uteke_graph | Get nodes + edges JSON for visualization |
uteke_graph_add_edge | Create a typed edge between two memories (#542) |
uteke_graph_remove_edge | Remove an edge between two memories (#542) |
uteke_room_recall | Semantic recall within a room |
uteke_room_memories | List memories in a room (#569) |
uteke_room_create | Create a room |
uteke_room_delete | Delete a room |
uteke_room_rename | Rename a room; rewrites the registry row and every reference in one transaction (#1202) |
uteke_room_update | Update a room's title/description (#1202) |
uteke_room_memory_move | Move a memory to another room, preserving link provenance (#1202) |
uteke_room_list | List all rooms |
uteke_namespace_rename | Rename a namespace (#1181); when the target exists this is a merge, returns {from, to, moved, target_existed} |
uteke_namespace_delete | Delete a namespace with an explicit strategy for its memories (#1181): refuse (default, 409 while referenced), merge into target, or deprecate (soft-delete, restorable) |
uteke_room_stats | Room statistics |
uteke_room_summary | Room topic summary (tag clustering, no LLM) |
uteke_room_summary_document | Generate summary document from room (→ POST /room/summary-document) |
uteke_room_add_document | Link an existing document to a room (#859) |
uteke_room_remove_document | Unlink a document from a room (#859) |
uteke_room_list_documents | List documents linked to a room (#859) |
uteke_doc_list_rooms | List rooms that reference a document (#859) |
uteke_tags_list | List all tags with counts (#566) |
uteke_tags_rename | Rename a tag across all memories (#566) |
uteke_tags_delete | Delete a tag from all memories (#566) |
uteke_pin | Pin a memory (prevent decay) (#566) |
uteke_unpin | Unpin a memory (#566) |
Transport Comparison
| Stdio | HTTP | |
|---|---|---|
| Binary | uteke-mcp | uteke-serve |
| Daemon needed | No | Yes |
| Remote access | No | Yes |
| Authentication | None needed (a local process you start yourself) | Static bearer token (UTEKE_AUTH_TOKEN) |
| Protocol | JSON-RPC over stdin/stdout | Streamable HTTP (POST /mcp) |
| Best for | Local agents, single machine | Shared/team, remote access |
Tip: HTTP transport is recommended when
uteke-serveis already running — it avoids subprocess overhead and works across machines. Stdio transport is simpler for local, single-agent setups where no daemon is desired.
Remote Access (VPS / Server / Domain)
Connect from a local agent to a remote uteke-serve
When uteke-serve runs on a VPS or remote server, your local MCP client connects over HTTP:
# On the server — start uteke-serve with auth enabled
UTEKE_AUTH_TOKEN=your-secret uteke-serve --host 0.0.0.0 --port 8767Note: In production, use environment variables for tokens — never commit secrets to config files. Some clients support env var substitution (e.g.,
$UTEKE_AUTH_TOKEN).
// Claude Code — .mcp.json
{
"mcpServers": {
"uteke": {
"url": "https://uteke.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer your-secret"
}
}
}
}// Claude Desktop
{
"mcpServers": {
"uteke": {
"url": "https://uteke.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer your-secret"
}
}
}
}// Cursor
{
"mcpServers": {
"uteke": {
"url": "https://uteke.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer your-secret"
}
}
}
}Keeping the token out of the client config
uteke-serve authenticates with a static bearer token. It does not implement OAuth sign-in, so an MCP client cannot start a browser login against it and no token is refreshed automatically. What you can do instead:
- Same machine: use the stdio transport.
uteke-mcpruns as a local process your client starts itself, so there is no network listener, no token and noAuthorizationheader to store (Option A above). - Another machine: keep the secret out of git. Put the token in an environment variable and reference it from the client config if your client supports expanding environment variables (check its documentation for the exact syntax), or keep the client config file out of version control. Prefer
UTEKE_READ_ONLY_TOKENfor clients that only need to recall. - Rotate by restarting. Change
UTEKE_AUTH_TOKEN, restartuteke-serve, and update the clients; old tokens stop working immediately.
OAuth-based sign-in for MCP clients is not part of the self-hosted server.
Read-only tokens
A client authenticated with UTEKE_READ_ONLY_TOKEN can call these tools over POST /mcp: uteke_recall, uteke_search, uteke_list, uteke_get, uteke_provenance, uteke_timeline, uteke_contradictions, uteke_stats, uteke_doc_get, uteke_doc_list, uteke_doc_search, uteke_doc_list_rooms, uteke_graph, uteke_room_list, uteke_room_recall, uteke_room_memories, uteke_room_stats, uteke_room_summary, uteke_room_summary_document (alias uteke_room_document), uteke_room_list_documents and uteke_tags_list.
Every other tool is refused with a tool error (isError: true, text Read-only token cannot use <tool>) and nothing is written. tools/list still lists every tool. The stdio transport (uteke-mcp) has no tokens and is unaffected.
Docker on a VPS
docker run -d --name uteke \
-p 8767:8767 \
-e UTEKE_AUTH_TOKEN=your-secret \
-v uteke-data:/data \
ghcr.io/codecoradev/uteke:latestPoint your MCP client at http://YOUR_VPS_IP:8767/mcp (or use a domain with TLS — see below).
Domain + TLS (Recommended for Production)
For HTTPS with a domain, use a reverse proxy (Caddy, Nginx, or Cloudflare Tunnel) in front of uteke-serve:
# uteke-serve still on localhost — the proxy handles TLS
UTEKE_AUTH_TOKEN=your-secret uteke-serve --host 127.0.0.1 --port 8767See TLS & Reverse Proxy for full setup guides (Caddy, Nginx, Cloudflare Tunnel).
Important: Network Security
| Setting | Value | Why |
|---|---|---|
--host | 127.0.0.1 (local) or 0.0.0.0 (remote) | Bind to localhost unless you need remote access |
UTEKE_AUTH_TOKEN | Set a strong token | Required for remote access — without it, anyone can read/write your memories |
| TLS | Use reverse proxy + HTTPS | Encrypts traffic in transit — strongly recommended for remote setups |
| Firewall | Allow only port 8767/tcp | Restrict access at the network level |
Namespace Isolation
Deprecated. Namespaces will be removed in a future 0.x release; prefer rooms, tags and author. Writes to a non-default namespace (
uteke_remember,uteke_updatemoves,uteke_room_create) return a deprecation warning. See Namespaces are deprecated.
The MCP server uses the default namespace by default. Each agent can use its own isolated namespace by passing a namespace argument to any tool call. Memories in one namespace are never visible to another.
This is the MCP equivalent of the CLI's --namespace flag — see Multi-Agent Isolation for details.
JSON-RPC 2.0 Compliance (#573/#576)
The MCP server implements strict JSON-RPC 2.0 compliance (v0.6.7):
- Tagged union responses: The
resultfield uses a tagged union ({"type": "result", "content": [...]}) per the MCP spec, not a bare array. - No notification response: JSON-RPC notifications (requests without
id) receive no response body, as required by the spec. This fixes Claude Code connectivity issues where unexpected responses on notifications caused handshake failures. - Claude Code compatible: Tested and verified with Claude Code, Claude Desktop, Cursor, and Hermes MCP client.
Memory-Provider Integration (#575/#577)
For automatic recall (memories injected every LLM call without the agent asking), use the --memory-provider flag with uteke init:
# pi (pi.dev)
uteke init --agent pi --memory-provider
# Claude Code
uteke init --agent claude --memory-provider
# Cursor
uteke init --agent cursor --memory-providerThis installs uteke as the agent's default memory provider — relevant memories are recalled and injected automatically every turn. No MCP server needed; talks to the uteke binary directly.
Note: The
--memory-providerflag is only deprecated for Hermes (removed 2026-06-29). For pi, Claude Code, and Cursor, it is the recommended integration mode.
Docker
When running uteke in Docker, both transports are available:
- HTTP: Start the container normally — the MCP endpoint is at
http://localhost:8767/mcpvia port mapping. - Stdio: Use
--entrypoint uteke-mcpto run the MCP binary directly inside the container.
See Docker guide — MCP for full Docker-specific configuration and examples.
Troubleshooting
| Problem | Solution |
|---|---|
uteke-mcp: command not found | Run install.sh or cargo install -p uteke-mcp to install the binary |
Permission denied | chmod +x $(which uteke-mcp) or ensure the binary is on your PATH |
Connection refused (HTTP) | Ensure uteke-serve is running: uteke-serve |
| Client can't see tools | Verify the MCP config JSON is valid and the client has been restarted |
| Slow first query | The embedding model (~200MB) downloads on first use — subsequent calls are ~45ms |
See also: Architecture — MCP Transport