Spaces:
Paused
Paused
| """MCP Server implementation for the Hermes platform.""" | |
| from __future__ import annotations | |
| import json | |
| import logging | |
| from typing import Any | |
| from hermes.config.settings import get_settings | |
| from hermes.tools.base.registry import tool_registry | |
| logger = logging.getLogger(__name__) | |
| class MCPServer: | |
| """Model Context Protocol server implementation.""" | |
| def __init__(self) -> None: | |
| self.settings = get_settings() | |
| self._initialized = False | |
| async def initialize(self) -> None: | |
| """Initialize the MCP server.""" | |
| from hermes.tools.register import register_default_tools | |
| register_default_tools() | |
| self._initialized = True | |
| logger.info("MCP server initialized") | |
| async def handle_request(self, request: dict[str, Any]) -> dict[str, Any]: | |
| """Handle an MCP protocol request.""" | |
| method = request.get("method", "") | |
| params = request.get("params", {}) | |
| request_id = request.get("id") | |
| try: | |
| if method == "initialize": | |
| return await self._handle_initialize(params, request_id) | |
| elif method == "tools/list": | |
| return await self._handle_list_tools(request_id) | |
| elif method == "tools/call": | |
| return await self._handle_call_tool(params, request_id) | |
| elif method == "resources/list": | |
| return await self._handle_list_resources(request_id) | |
| elif method == "resources/read": | |
| return await self._handle_read_resource(params, request_id) | |
| else: | |
| return self._error_response(request_id, -32601, f"Method not found: {method}") | |
| except Exception as e: | |
| logger.error(f"MCP request error: {e}") | |
| return self._error_response(request_id, -32603, str(e)) | |
| async def _handle_initialize( | |
| self, params: dict[str, Any], request_id: str | None | |
| ) -> dict[str, Any]: | |
| """Handle initialization request.""" | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": { | |
| "protocolVersion": "2024-11-05", | |
| "capabilities": { | |
| "tools": {"listChanged": True}, | |
| "resources": {"listChanged": True}, | |
| }, | |
| "serverInfo": { | |
| "name": "hermes-mcp-server", | |
| "version": "1.0.0", | |
| }, | |
| }, | |
| } | |
| async def _handle_list_tools(self, request_id: str | None) -> dict[str, Any]: | |
| """Handle tools/list request.""" | |
| schemas = tool_registry.list_schemas() | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": {"tools": schemas}, | |
| } | |
| async def _handle_call_tool( | |
| self, params: dict[str, Any], request_id: str | None | |
| ) -> dict[str, Any]: | |
| """Handle tools/call request.""" | |
| tool_name = params.get("name", "") | |
| arguments = params.get("arguments", {}) | |
| tool = tool_registry.get(tool_name) | |
| if not tool: | |
| return self._error_response(request_id, -32602, f"Tool not found: {tool_name}") | |
| try: | |
| result = await tool.execute(**arguments) | |
| content = json.dumps(result, default=str) if isinstance(result, dict) else str(result) | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": { | |
| "content": [{"type": "text", "text": content}], | |
| "isError": False, | |
| }, | |
| } | |
| except Exception as e: | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": { | |
| "content": [{"type": "text", "text": str(e)}], | |
| "isError": True, | |
| }, | |
| } | |
| async def _handle_list_resources(self, request_id: str | None) -> dict[str, Any]: | |
| """Handle resources/list request.""" | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": { | |
| "resources": [ | |
| { | |
| "uri": "hermes://tools", | |
| "name": "Available Tools", | |
| "description": "List of all available tools", | |
| "mimeType": "application/json", | |
| }, | |
| { | |
| "uri": "hermes://status", | |
| "name": "Server Status", | |
| "description": "Current server status", | |
| "mimeType": "application/json", | |
| }, | |
| ] | |
| }, | |
| } | |
| async def _handle_read_resource( | |
| self, params: dict[str, Any], request_id: str | None | |
| ) -> dict[str, Any]: | |
| """Handle resources/read request.""" | |
| uri = params.get("uri", "") | |
| if uri == "hermes://tools": | |
| data = json.dumps(tool_registry.list_schemas(), indent=2) | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": { | |
| "contents": [ | |
| {"uri": uri, "mimeType": "application/json", "text": data} | |
| ] | |
| }, | |
| } | |
| elif uri == "hermes://status": | |
| data = json.dumps( | |
| {"status": "running", "tools": len(tool_registry.list_tools())}, | |
| indent=2, | |
| ) | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "result": { | |
| "contents": [ | |
| {"uri": uri, "mimeType": "application/json", "text": data} | |
| ] | |
| }, | |
| } | |
| return self._error_response(request_id, -32602, f"Resource not found: {uri}") | |
| def _error_response( | |
| self, request_id: str | None, code: int, message: str | |
| ) -> dict[str, Any]: | |
| """Create an error response.""" | |
| return { | |
| "jsonrpc": "2.0", | |
| "id": request_id, | |
| "error": {"code": code, "message": message}, | |
| } | |
| mcp_server = MCPServer() | |