vgtc-api / src /hermes /mcp /server.py
vora-sonnet's picture
Upload folder using huggingface_hub
0d3f7cc verified
Raw
History Blame Contribute Delete
6.4 kB
"""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()