fix: dispatch_mcp.py missing mcp.run() entry point

The FastMCP server never started listening on stdio because the file was
missing 'if __name__ == "__main__": mcp.run(transport="stdio")'. The
LiveKit agent's MCP client got 'Connection closed' during initialize,
which killed the entire toolset setup — ALL tools (weather, memory,
skills, dispatch) were unavailable. This is why Hope could hear you but
never called any tools.
This commit is contained in:
Shane
2026-08-22 19:53:27 -04:00
parent d08a4e1fcb
commit 98168f2876
2 changed files with 156 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
# Memory Server (Cognee MCP)
A persistent, centralized **AI memory** service you can attach to any agentic
harness (OpenCode, Hermes, Claude Desktop, custom agents). It runs on the Unraid
box at `192.168.86.2` as two Docker containers managed by a single compose file
(`/mnt/user/appdata/cognee/docker-compose.yml`):
| Container | Purpose | Port (host) |
|----------------------|-------------------------------------------|-------------|
| `shane-cognee` | Cognee API + graph/vector store | `8002` (REST) |
| `shane-cognee-mcp` | MCP frontend — **Streamable HTTP** | `8003` (`/mcp`) |
| `shane-cognee-mcp-sse` | MCP frontend — **SSE** (for clients that can't do Streamable HTTP) | `8004` (`/sse`) |
Both MCP frontends bridge to the same Cognee API; all memory state lives in the
API container, so the two frontends are interchangeable.
## Endpoints
- **Streamable HTTP (preferred for most clients):** `http://192.168.86.2:8003/mcp`
- **SSE (for OpenCode 1.18.21, Claude Desktop, etc.):** `http://192.168.86.2:8004/sse`
- **REST API (custom apps):** `http://192.168.86.2:8002` (docs at `/docs`)
## Connecting an agentic harness
Pick the transport your client supports. Use **SSE (8004)** if the client only
does SSE, otherwise **Streamable HTTP (8003)**.
### OpenCode
OpenCode 1.18.21 only supports SSE (`type: "remote"`). Already configured in
`~/.config/opencode/opencode.jsonc`:
```jsonc
"mcp": {
"cognee": {
"type": "remote",
"url": "http://192.168.86.2:8004/sse"
}
}
```
Verify with `opencode mcp list` — it should show `✓ cognee connected`.
### Hermes
Hermes speaks Streamable HTTP natively. Already configured in
`~/.hermes/config.yaml` under `mcp_servers`:
```yaml
mcp_servers:
cognee:
url: http://192.168.86.2:8003/mcp
transport: http
enabled: true
```
### Claude Desktop / other MCP-aware clients
Use the SSE endpoint. Example `claude_desktop_config.json`:
```json
{
"mcpServers": {
"cognee": {
"url": "http://192.168.86.2:8004/sse"
}
}
}
```
For clients that support Streamable HTTP, point them at
`http://192.168.86.2:8003/mcp` instead.
### Stdio bridge (legacy clients only)
If a client can only spawn a stdio MCP server, bridge with `mcp-remote`
(pointed at the **SSE** endpoint — this `mcp-remote` build is SSE-only):
```json
{
"mcpServers": {
"cognee": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://192.168.86.2:8004/sse"]
}
}
}
```
### Custom applications (REST)
Call the Cognee REST API directly at `http://192.168.86.2:8002`. See
`/docs` for the OpenAPI schema. The MCP tools below are thin wrappers over
these endpoints.
## Authentication
The current deployment has no API token (`ENABLE_BACKEND_ACCESS_CONTROL:
"false"`). If you later enable auth on the Cognee API, pass the token to the
MCP frontend via the `API_TOKEN` env var in the compose file and restart the
containers.
## LAN access / Host guard
`cognee-mcp` enforces a DNS-rebinding Host/Origin guard. The container is
configured to accept the Unraid LAN IP via the env var
`MCP_ALLOWED_HOSTS: "192.168.86.2:*"` (comma-separated, requires the `:*` glob).
If you connect from a client that reaches the server by a **different hostname
or IP** (e.g. a DNS name, or a different interface), add that pattern to
`MCP_ALLOWED_HOSTS` in `docker-compose.yml` and `docker compose up -d`, or you
will get `421 Misdirected Request`. Example for two hosts:
```yaml
MCP_ALLOWED_HOSTS: "192.168.86.2:*,cognee.lan:*"
```
To disable the guard entirely (LAN-only, not exposed to the internet), set
`MCP_DISABLE_DNS_REBINDING_PROTECTION: "true"`.
## Tools
The server exposes 5 MCP tools:
| Tool | Description |
|----------------|-------------|
| `remember` | Store data in memory. Without `session_id` → permanent memory (runs the full add + `cognify` pipeline: ingest, entity extraction, graph build). With `session_id` → fast session-cache memory only (no graph). |
| `recall` | Search memory with auto-routing and session awareness. Use this for "what do I know about X". |
| `forget` | Delete data from memory (by dataset/id). |
| `search_tools` | Find a tool by natural-language description (meta-tool for the agent). |
| `call_tool` | Invoke a tool by name with arguments (meta-tool). |
## Usage patterns
- **Persist something for good:** `remember` without `session_id`. This triggers
`cognify`, which can take a while (ingest + embed + graph). Don't call it in a
tight loop; batch related content into one call.
- **Scratch / per-conversation notes:** `remember` with a `session_id` for fast,
non-graph storage you don't need long-term.
- **Retrieve:** `recall` with a natural-language query. It auto-routes between
graph and vector search and is session-aware.
- **Remove:** `forget` when memory is stale.
- Keep payloads reasonable; the MCP frontend rejects uploads over 10 MB.
## Troubleshooting
- `421 Misdirected Request` → Host header not in `MCP_ALLOWED_HOSTS`. Add the
client's target hostname/IP (with `:*` glob) and recreate the container.
- Connection refused on `8003`/`8004` → container not healthy yet; check
`docker ps` on Unraid and the API container's health (`/health` on `8002`).
- `opencode mcp list` shows the server but not `connected` → check the URL uses
the SSE endpoint (`/sse`) for OpenCode, and that the Host pattern is allowed.
+4
View File
@@ -56,3 +56,7 @@ async def _run_worker(worker: "TaskWorker", task_id: str):
except Exception as e:
logger.exception("Task %s crashed: %s", task_id, e)
registry.fail(task_id, str(e))
if __name__ == "__main__":
mcp.run(transport="stdio")