mcp server done

This commit is contained in:
Danilo Reyes
2026-02-01 10:36:54 -06:00
parent ecf058aacf
commit 8946ade5e8
15 changed files with 214 additions and 190 deletions

View File

@@ -2,14 +2,12 @@
from __future__ import annotations
import json
import os
import sys
from collections.abc import Mapping
from typing import Any
from mcp_server.docs_sync import check_catalog_parity
from mcp_server.tools import invoke_tool, list_tools_payload
from mcp.server.fastmcp import FastMCP
from mcp_server import tools
def _is_local_only() -> bool:
@@ -20,73 +18,53 @@ def _guard_local() -> None:
if not _is_local_only():
return
if os.environ.get("SSH_CONNECTION"):
_write_response({"error": {"code": -32099, "message": "Remote access denied"}})
sys.stderr.write("Remote access denied. Unset SSH_CONNECTION or set MCP_ALLOW_REMOTE.\n")
sys.exit(1)
def _write_response(payload: dict[str, Any]) -> None:
sys.stdout.write(json.dumps(payload) + "\n")
sys.stdout.flush()
mcp = FastMCP("NixOS Repo MCP", json_response=True)
def handle_request(request: Mapping[str, Any]) -> dict[str, Any]:
"""Dispatch a JSON-RPC request to the appropriate MCP handler."""
method = request.get("method")
params = request.get("params") or {}
if method == "listTools":
return {"result": list_tools_payload()}
if method == "invokeTool":
name = params.get("name") or ""
args = params.get("args") or {}
try:
return {"result": invoke_tool(name, args)}
except Exception as exc: # noqa: BLE001
return {
"result": {
"status": "failed",
"output": f"Service unavailable: {exc}",
"actions": ["retry locally", "call listTools to verify availability"],
"docsAnchor": {},
}
}
if method == "syncDocs":
return {"result": check_catalog_parity()}
return {
"error": {
"code": -32601,
"message": (
f"Method '{method}' not found. Call listTools to discover supported methods."
),
}
}
@mcp.tool(name="show-constitution")
def show_constitution() -> dict[str, object]:
"""Display repository AI constitution for rule lookup."""
return tools.invoke_tool("show-constitution", {})
@mcp.tool(name="list-playbooks")
def list_playbooks() -> dict[str, object]:
"""List available playbooks under docs/playbooks."""
return tools.invoke_tool("list-playbooks", {})
@mcp.tool(name="show-reference")
def show_reference() -> dict[str, object]:
"""Show docs/reference/index.md for navigation guidance."""
return tools.invoke_tool("show-reference", {})
@mcp.tool(name="search-docs")
def search_docs(query: str) -> dict[str, object]:
"""Search docs for a query string."""
return tools.invoke_tool("search-docs", {"query": query})
@mcp.tool(name="list-mcp-tasks")
def list_mcp_tasks() -> dict[str, object]:
"""Show MCP feature task list from specs."""
return tools.invoke_tool("list-mcp-tasks", {})
@mcp.tool(name="sync-docs")
def sync_docs() -> dict[str, object]:
"""Compare tool catalog against documented anchors."""
return tools.invoke_tool("sync-docs", {})
def main() -> None:
"""Run the MCP server in stdio mode."""
_guard_local()
for line in sys.stdin:
if not line.strip():
continue
try:
request = json.loads(line)
except json.JSONDecodeError:
_write_response({"error": {"code": -32700, "message": "Parse error"}})
continue
try:
response = handle_request(request)
except Exception as exc: # noqa: BLE001
_write_response(
{
"result": {
"status": "failed",
"output": f"Service unavailable: {exc}",
"actions": ["retry locally", "call listTools to verify availability"],
"docsAnchor": {},
}
}
)
continue
_write_response(response)
mcp.run(transport="stdio")
if __name__ == "__main__":