From a00b6a0ba2db1ef4f05e2ecab7e54d8b559fddbb Mon Sep 17 00:00:00 2001 From: latte Date: Sat, 14 Feb 2026 18:18:34 +0100 Subject: [PATCH] update --- src/aegis_gitea_mcp/mcp_protocol.py | 9 ++++++++- src/aegis_gitea_mcp/server.py | 4 ++-- tests/test_integration.py | 4 ++-- tests/test_server.py | 18 +++++++++++++++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/aegis_gitea_mcp/mcp_protocol.py b/src/aegis_gitea_mcp/mcp_protocol.py index 27af399..6bc5a1e 100644 --- a/src/aegis_gitea_mcp/mcp_protocol.py +++ b/src/aegis_gitea_mcp/mcp_protocol.py @@ -12,9 +12,16 @@ class MCPTool(BaseModel): name: str = Field(..., description="Unique tool identifier") description: str = Field(..., description="Human-readable tool description") - input_schema: dict[str, Any] = Field(..., description="JSON schema describing input arguments") + input_schema: dict[str, Any] = Field( + ..., + alias="inputSchema", + serialization_alias="inputSchema", + description="JSON schema describing input arguments", + ) write_operation: bool = Field(default=False, description="Whether tool mutates data") + model_config = ConfigDict(populate_by_name=True) + class MCPToolCallRequest(BaseModel): """Request to invoke an MCP tool.""" diff --git a/src/aegis_gitea_mcp/server.py b/src/aegis_gitea_mcp/server.py index 6e136c9..4d078e5 100644 --- a/src/aegis_gitea_mcp/server.py +++ b/src/aegis_gitea_mcp/server.py @@ -328,7 +328,7 @@ async def automation_run_job(request: AutomationJobRequest) -> JSONResponse: async def list_tools() -> JSONResponse: """List all available MCP tools.""" response = MCPListToolsResponse(tools=AVAILABLE_TOOLS) - return JSONResponse(content=response.model_dump()) + return JSONResponse(content=response.model_dump(by_alias=True)) async def _execute_tool_call( @@ -519,7 +519,7 @@ async def sse_message_handler(request: Request) -> JSONResponse: content={ "jsonrpc": "2.0", "id": message_id, - "result": response.model_dump(), + "result": response.model_dump(by_alias=True), } ) diff --git a/tests/test_integration.py b/tests/test_integration.py index 8d6db3d..f9333f7 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -183,9 +183,9 @@ def test_all_mcp_tools_discoverable(client): for tool in tools: assert "name" in tool assert "description" in tool - assert "input_schema" in tool + assert "inputSchema" in tool assert tool["description"] # Not empty - assert "type" in tool["input_schema"] + assert "type" in tool["inputSchema"] def test_error_responses_include_helpful_messages(client): diff --git a/tests/test_server.py b/tests/test_server.py index 59e806c..cfa763f 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -126,7 +126,7 @@ def test_list_tools_with_valid_key(client, mock_env): tool = data["tools"][0] assert "name" in tool assert "description" in tool - assert "input_schema" in tool + assert "inputSchema" in tool def test_list_tools_with_query_param(client): @@ -149,6 +149,22 @@ def test_list_tools_no_auth_when_disabled(client_no_auth): assert "tools" in data +def test_sse_tools_list_returns_camel_case_schema(client): + """SSE tools/list returns MCP-compatible camelCase inputSchema.""" + response = client.post( + f"/mcp/sse?api_key={'a' * 64}", + json={"jsonrpc": "2.0", "id": "1", "method": "tools/list"}, + ) + + assert response.status_code == 200 + data = response.json() + assert "result" in data + assert "tools" in data["result"] + tool = data["result"]["tools"][0] + assert "inputSchema" in tool + assert "type" in tool["inputSchema"] + + def test_call_tool_without_auth(client): """Test that /mcp/tool/call requires authentication.""" response = client.post("/mcp/tool/call", json={"tool": "list_repositories", "arguments": {}})