mcp server done
This commit is contained in:
@@ -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__":
|
||||
|
||||
Reference in New Issue
Block a user