hydra-mcp-server

robit-man/hydra-mcp-server

3.2

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.

Tools
3
Resources
0
Prompts
0

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 (aka root.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
  • 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 (default 0.0.0.0:9003).


Configuration

Environment variables:

VariableDefaultDescription
MCP_BIND0.0.0.0Bind address for HTTP/WS server
MCP_PORT9003Listen port
MCP_LOG_LEVELinfoUvicorn 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:

  • fastapi
  • uvicorn[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, and params
  • 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> or Authorization: Bearer <key>

Unauthorized sockets are closed with 4401.

Supported methods

  1. initialize (alias root.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_changed
  • notifications/tools.list_changed
  1. resources.list (alias resources/list) Returns available resources; accepts optional {"tags":["nkn","llm"]}.

  2. resources.get (alias resources/get) Fetches a specific resource by uri.

  • Error codes:

    • -32602: Resource not found
  1. tools.list (alias tools/list) Returns tool descriptors.

  2. tools.call (alias tools/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
  1. messages.create (alias messages/create) Server composes a simple system message and an assistant message that includes the user’s most recent role:"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 (call initialize first)
  • -32601: Unknown method

Built-in resources

Resources are markdown documents bundled in the catalog:

  1. resource://hydra/overview — Hydra Workspace Overview High-level description of Hydra’s NKN orchestration graph and nodes.

  2. resource://hydra/nkn-topology — NKN Relay Topology Operational guidance for multi-relay deployments and assignments.

  3. 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, optional mediaType, and full body.

Built-in tools

All tools return a content array (e.g., [{ "type":"text", "text":"..." }]) and may include a meta object.

  1. hydra.graph.describe Summarizes available resources, optionally filtered.
"input_schema": {
  "type":"object",
  "properties":{
    "tags":{"type":"array","items":{"type":"string"}},
    "focus":{"type":"string"}
  }
}
  1. hydra.nkn.status Reports relay assignments and HTTP targets from router_config.json.
"input_schema": {
  "type":"object",
  "properties":{ "includeTargets": {"type":"boolean","default":true} }
}
  1. hydra.context.search Keyword 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 URLs
  • service_assignments — map of service → relay identifier
  • nodes — 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/query to assemble:

    • system → feed to LLM system prompt
    • prompt → feed to LLM user prompt (already includes an appended context block when emitContext=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(...) to RESOURCE_CATALOG

  • Add a tool:

    1. Register a ToolSpec in TOOL_REGISTRY
    2. Implement the behavior in tool_call(name, arguments)
    3. Ensure it returns { "content": [...], "meta": {...optional} }
  • Search behavior: tweak search_resources() (currently simple substring with snippet extraction)


Deployment notes

  • Default HTTP: uvicorn inside main(); 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-Key or Authorization: Bearer <key> matches MCP_API_KEY.
  • Server not initialized (-32000) Call initialize first on the WebSocket connection.
  • Unknown method (-32601) Check method name and alias; see Supported methods.
  • No router info in hydra.nkn.status Verify router_config.json exists two directories above mcp_service.py and is valid JSON.
  • CORS issues Default allows all; if modified, ensure your origin is listed.