robit-man/hydra-mcp-server
If you are the rightful owner of hydra-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The Hydra MCP Server is a self-contained Model Context Protocol server designed for the Hydra NKN graph environment, providing a JSON-RPC 2.0 interface over WebSocket and HTTP endpoints.
Hydra MCP Server
A self-contained Model Context Protocol (MCP) server tailored for the Hydra NKN graph environment. It exposes a compliant JSON-RPC 2.0 interface over WebSocket and a set of convenience HTTP endpoints used by the Hydra graph workspace (including when transported via NKN relay).
Single-file service:
mcp_service.py— no database; auto-bootstraps its few dependencies.
Table of contents
Features
-
Implements core MCP handlers aligned with the current draft:
initialize(akaroot.initialize),resources.list/get,tools.list/call,messages.create
-
Dual interface:
- WebSocket (
/mcp/ws) speaking JSON-RPC 2.0 - HTTP helpers:
/mcp/status,/mcp/resources,/mcp/tools,/mcp/query,/mcp/tool
- WebSocket (
-
Curated resources and tools that enrich downstream LLM prompts
-
Optional API key protection for both HTTP and WebSocket
-
Zero DB footprint; single FastAPI app; automatic dependency install (FastAPI, Uvicorn, Pydantic)
-
CORS enabled (allow-all) for simple embedding in the graph workspace
Protocol/capability constants:
-
PROTOCOL_VERSION:2024-05-31 -
CAPABILITIES:resources: {list, get}(no subscribe)tools: {list, call}messages: {create}
Architecture overview
- Single file:
mcp_service.py - FastAPI app with REST endpoints and a WebSocket route (
/mcp/ws) - Resource catalog (markdown bodies) and tool registry (declared input schema) are in-memory
- Optional router snapshot loader reads
router_config.json(two directories above the script) to expose Hydra/NKN relay assignments via a tool
Quick start
# 1) Run directly (auto-installs pip deps if missing)
python3 mcp_service.py
# 2) Optional environment variables (see Configuration)
export MCP_PORT=9003
export MCP_BIND=0.0.0.0
export MCP_LOG_LEVEL=info
export MCP_API_KEY="change-me"
# 3) Test health
curl -s http://127.0.0.1:9003/healthz
The service will listen on
MCP_BIND:MCP_PORT(default0.0.0.0:9003).
Configuration
Environment variables:
| Variable | Default | Description |
|---|---|---|
MCP_BIND | 0.0.0.0 | Bind address for HTTP/WS server |
MCP_PORT | 9003 | Listen port |
MCP_LOG_LEVEL | info | Uvicorn log level (debug, info, warning, error) |
MCP_API_KEY | (empty) | If set, enables API-key auth for all HTTP endpoints (except /healthz) and for WebSocket |
Dependency bootstrap On first run, the script installs/updates:
fastapiuvicorn[standard]pydantic
Security
When MCP_API_KEY is set, requests must include one of:
- Header:
X-Api-Key: <key> - Header:
Authorization: Bearer <key>
WebSocket connections apply the same header validation and will be closed with code 4401 on failure.
/healthz remains public.
CORS is permissive (allow-all) by default to simplify embedding in local graph tooling.
HTTP API
Base URL: http://<bind>:<port>
GET /healthz
Lightweight liveness probe.
Response
{ "ok": true, "ts": 1720000000000 }
GET /mcp/status
Server capabilities, resources, tools.
Auth: required if MCP_API_KEY set.
Response model
{
"server": { "name": "...", "version": "0.1.0", "homepage": "...", "description": "..." },
"protocolVersion": "2024-05-31",
"capabilities": { "resources": {...}, "tools": {...}, "messages": {...}, "corpus": {"list": false} },
"resources": [{ "uri": "...", "name": "...", "description": "...", "mimeType": "text/markdown", "tags": ["..."] }],
"tools": [{ "name": "...", "description": "...", "inputSchema": {...} }],
"ts": 1720000000000
}
Example
curl -H "X-Api-Key: $MCP_API_KEY" http://127.0.0.1:9003/mcp/status
GET /mcp/resources
Returns the full resource catalog (with bodies).
Auth: required if MCP_API_KEY set.
Response
{
"resources": [
{
"uri": "resource://hydra/overview",
"name": "Hydra Workspace Overview",
"description": "...",
"mime_type": "text/markdown",
"tags": ["hydra","graph"],
"media_type": null,
"body": "# Hydra Graph Overview\n..."
}
],
"ts": 1720000000000
}
GET /mcp/tools
Lists tools and their input schemas.
Auth: required if MCP_API_KEY set.
Response
{ "tools": [ { "name": "hydra.graph.describe", "description": "...", "inputSchema": {...} } ], "ts": 1720000000000 }
POST /mcp/query
Builds a prompt package (system/prompt/context) from an input query, optional resource filters, and optional tool executions.
Auth: required if MCP_API_KEY set.
Request body
{
"query": "User question or instruction",
"resourceFilters": ["nkn","llm"], // optional: tags to include
"toolFilters": ["hydra.graph.describe"], // optional: tool names to invoke (no args)
"augmentSystem": "Additional system text",// optional: appended to default system template
"client": { "graphId": "...", "nodeId": "..." }, // optional opaque metadata
"emitSystem": true, // default true
"emitContext": true // default true
}
Response body
{
"ok": true,
"system": "Default system prompt (plus any augmentSystem)...", // null if emitSystem=false
"prompt": "User query\n---\nContext:\n<compiled markdown>",
"context": "<compiled markdown or null>",
"resources": [{ "uri":"...", "name":"...", "description":"...", "mimeType":"...", "tags":[...] }],
"toolResults": [
{
"name": "hydra.graph.describe",
"content": [{ "type": "text", "text": "..." }],
"meta": { "resourceCount": 3 }
}
],
"server": { ... },
"ts": 1720000000000
}
Example
curl -X POST -H "Content-Type: application/json" -H "X-Api-Key: $MCP_API_KEY" \
-d '{"query":"Summarize the topology.","resourceFilters":["nkn"],"toolFilters":["hydra.nkn.status"]}' \
http://127.0.0.1:9003/mcp/query
POST /mcp/tool
Directly invokes a tool with arguments and returns its result.
Auth: required if MCP_API_KEY set.
Request
{ "name": "hydra.context.search", "arguments": { "query": "LLM", "limit": 3 } }
Response
{
"ok": true,
"result": {
"name": "hydra.context.search",
"content": [{ "type": "text", "text": "Search results for 'LLM':\n• ..." }],
"meta": { "matchCount": 2 }
},
"error": null,
"ts": 1720000000000
}
Errors return ok:false with error text.
WebSocket (MCP over JSON-RPC 2.0)
- URL:
ws://<bind>:<port>/mcp/ws - JSON-RPC 2.0 messages with
id,method, andparams - On success, replies with
{"jsonrpc":"2.0","id":<id>,"result":...} - On error, replies with
{"jsonrpc":"2.0","id":<id>,"error":{"code":<int>,"message":"..."}}
Connection & authentication
Send headers on connect if MCP_API_KEY is set:
X-Api-Key: <key>orAuthorization: Bearer <key>
Unauthorized sockets are closed with 4401.
Supported methods
initialize(aliasroot.initialize) Marks the connection initialized and returns server metadata.
Request
{
"jsonrpc":"2.0",
"id":1,
"method":"initialize",
"params":{
"clientInfo":{"name":"my-client","version":"0.0.1"},
"capabilities":{}
}
}
Result
{
"jsonrpc":"2.0",
"id":1,
"result":{
"protocolVersion":"2024-05-31",
"capabilities": { "resources":{...},"tools":{...},"messages":{"create":true},"corpus":{"list":false} },
"serverInfo": { "name":"Hydra MCP Server","version":"0.1.0","homepage":"...","description":"..." },
"resources":[{...}],
"tools":[{...}]
}
}
Also emits notifications (no id):
notifications/resources.list_changednotifications/tools.list_changed
-
resources.list(aliasresources/list) Returns available resources; accepts optional{"tags":["nkn","llm"]}. -
resources.get(aliasresources/get) Fetches a specific resource byuri.
-
Error codes:
-32602: Resource not found
-
tools.list(aliastools/list) Returns tool descriptors. -
tools.call(aliastools/call) Executes a tool with arguments:
Request
{"jsonrpc":"2.0","id":2,"method":"tools.call","params":{"name":"hydra.context.search","arguments":{"query":"topology","limit":5}}}
Result
{"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"..."}],"meta":{"matchCount":1}}}
-
Error codes:
-32001: Tool raised an exception
messages.create(aliasmessages/create) Server composes a simple system message and an assistant message that includes the user’s most recentrole:"user"text and an appended context block built from selected resources.
Params shape
{
"messages":[{"role":"user","content":[{"type":"text","text":"Explain the topology"}]}],
"resourceFilters":["nkn"]
}
Result
{
"jsonrpc":"2.0",
"id":3,
"result":{
"messages":[
{"role":"system","content":[{"type":"text","text":"You are operating inside the Hydra NKN orchestration graph..."}]},
{"role":"assistant","content":[{"type":"text","text":"<user text>\n\n---\nContext:\n<compiled markdown>"}]}
]
}
}
General error codes:
-32000: Server not initialized (callinitializefirst)-32601: Unknown method
Built-in resources
Resources are markdown documents bundled in the catalog:
-
resource://hydra/overview— Hydra Workspace Overview High-level description of Hydra’s NKN orchestration graph and nodes. -
resource://hydra/nkn-topology— NKN Relay Topology Operational guidance for multi-relay deployments and assignments. -
resource://hydra/llm-integration— LLM Integration Guidance How to wire MCP system/prompt/context into downstream LLM nodes.
Each resource object includes:
uri,name,description,mimeType,tags, optionalmediaType, and fullbody.
Built-in tools
All tools return a content array (e.g., [{ "type":"text", "text":"..." }]) and may include a meta object.
hydra.graph.describeSummarizes available resources, optionally filtered.
"input_schema": {
"type":"object",
"properties":{
"tags":{"type":"array","items":{"type":"string"}},
"focus":{"type":"string"}
}
}
hydra.nkn.statusReports relay assignments and HTTP targets fromrouter_config.json.
"input_schema": {
"type":"object",
"properties":{ "includeTargets": {"type":"boolean","default":true} }
}
hydra.context.searchKeyword search across resource bodies; returns snippets.
"input_schema": {
"type":"object",
"properties":{
"query":{"type":"string"},
"limit":{"type":"integer","minimum":1,"maximum":10,"default":5}
},
"required":["query"]
}
Router snapshot (router_config.json)
The tool hydra.nkn.status reads a router snapshot from:
<repo root>/router_config.json
# (Specifically: two directories above mcp_service.py)
Expected top-level keys:
targets— map of HTTP service names to URLsservice_assignments— map of service → relay identifiernodes— list of relay nodes (names/ids and seed hex)
Example
{
"targets": {
"tts": "https://relay-c.local:8124",
"asr": "https://relay-b.local:8123",
"llm": "https://relay-c.local:8080",
"mcp": "https://relay-a.local:9003"
},
"service_assignments": {
"tts": "relay-c",
"asr": "relay-b",
"llm": "relay-c",
"mcp": "relay-a"
},
"nodes": [
{ "name": "relay-a", "seed_hex": "abcd..." },
{ "name": "relay-b", "seed_hex": "1234..." },
{ "name": "relay-c", "seed_hex": "7890..." }
]
}
If the file is absent or malformed, the tool returns a minimal snapshot.
Integration notes (Hydra graph)
-
Use
POST /mcp/queryto assemble:system→ feed to LLM system promptprompt→ feed to LLM user prompt (already includes an appended context block whenemitContext=true)context→ optional markdown for audit or downstream summarization
-
When multiple MCP nodes feed one LLM, concatenate system prompts deterministically (e.g., by priority or timestamp) to avoid conflicts.
-
The WebSocket MCP path is suitable for clients that already speak JSON-RPC 2.0 and MCP method names.
Extending the server
-
Add a resource: append a
Resource(...)toRESOURCE_CATALOG -
Add a tool:
- Register a
ToolSpecinTOOL_REGISTRY - Implement the behavior in
tool_call(name, arguments) - Ensure it returns
{ "content": [...], "meta": {...optional} }
- Register a
-
Search behavior: tweak
search_resources()(currently simple substring with snippet extraction)
Deployment notes
-
Default HTTP:
uvicorninsidemain(); to run with an external process manager:# Example: uvicorn (note the app import path) uvicorn mcp_service:app --host 0.0.0.0 --port 9003 --log-level info -
Reverse proxy / TLS: terminate TLS at a proxy (nginx, caddy) or front via NKN relay
-
CORS: currently
allow_origins=["*"]; restrict as needed for production -
Systemd (sketch):
[Unit] Description=Hydra MCP Server After=network.target [Service] WorkingDirectory=/opt/hydra Environment=MCP_BIND=0.0.0.0 Environment=MCP_PORT=9003 Environment=MCP_API_KEY=change-me ExecStart=/usr/bin/python3 /opt/hydra/mcp_service.py Restart=always [Install] WantedBy=multi-user.target
Troubleshooting
- 401 Unauthorized / WS close 4401
Ensure
X-Api-KeyorAuthorization: Bearer <key>matchesMCP_API_KEY. Server not initialized(-32000) Callinitializefirst on the WebSocket connection.Unknown method(-32601) Check method name and alias; see Supported methods.- No router info in
hydra.nkn.statusVerifyrouter_config.jsonexists two directories abovemcp_service.pyand is valid JSON. - CORS issues Default allows all; if modified, ensure your origin is listed.