@@ -60,7 +60,11 @@ def _capture_headers(self) -> None:
6060 if len (request_log ) > 10 :
6161 request_log .pop (0 )
6262
63- def do_POST (self ) -> None : # pylint: disable=invalid-name
63+ def do_POST (
64+ self ,
65+ ) -> (
66+ None
67+ ): # pylint: disable=invalid-name,too-many-locals,too-many-branches,too-many-statements
6468 """Handle POST requests (MCP protocol endpoints)."""
6569 self ._capture_headers ()
6670
@@ -73,14 +77,24 @@ def do_POST(self) -> None: # pylint: disable=invalid-name
7377 request_id = request_data .get ("id" , 1 )
7478 method = request_data .get ("method" , "unknown" )
7579 except (json .JSONDecodeError , UnicodeDecodeError ):
80+ request_data = {}
7681 request_id = 1
7782 method = "unknown"
7883
84+ # Log the RPC method in the request log
85+ if request_log :
86+ request_log [- 1 ]["rpc_method" ] = method
87+
7988 # Determine tool name based on authorization header to avoid collisions
8089 auth_header = self .headers .get ("Authorization" , "" )
8190
91+ # Initialize tool info defaults
92+ tool_name = "mock_tool_no_auth"
93+ tool_desc = "Mock tool with no authorization"
94+ error_mode = False
95+
8296 # Match based on token content
83- match auth_header :
97+ match True :
8498 case _ if "test-secret-token" in auth_header :
8599 tool_name = "mock_tool_file"
86100 tool_desc = "Mock tool with file-based auth"
@@ -90,58 +104,116 @@ def do_POST(self) -> None: # pylint: disable=invalid-name
90104 case _ if "my-client-token" in auth_header :
91105 tool_name = "mock_tool_client"
92106 tool_desc = "Mock tool with client-provided token"
107+ case _ if "error-mode" in auth_header :
108+ tool_name = "mock_tool_error"
109+ tool_desc = "Mock tool configured to return errors"
110+ error_mode = True
93111 case _:
94- # No auth header or unrecognized token
95- tool_name = "mock_tool_no_auth"
96- tool_desc = "Mock tool with no authorization"
97-
98- # Handle MCP protocol methods
99- if method == "initialize" :
100- # Return MCP initialize response
101- response = {
102- "jsonrpc" : "2.0" ,
103- "id" : request_id ,
104- "result" : {
105- "protocolVersion" : "2024-11-05" ,
106- "capabilities" : {
107- "tools" : {},
108- },
109- "serverInfo" : {
110- "name" : "mock-mcp-server" ,
111- "version" : "1.0.0" ,
112+ # Default case already set above
113+ pass
114+
115+ # Log the tool name in the request log
116+ if request_log :
117+ request_log [- 1 ]["tool_name" ] = tool_name
118+
119+ # Handle MCP protocol methods using match statement
120+ response : dict = {}
121+ match method :
122+ case "initialize" :
123+ # Return MCP initialize response
124+ response = {
125+ "jsonrpc" : "2.0" ,
126+ "id" : request_id ,
127+ "result" : {
128+ "protocolVersion" : "2024-11-05" ,
129+ "capabilities" : {
130+ "tools" : {},
131+ },
132+ "serverInfo" : {
133+ "name" : "mock-mcp-server" ,
134+ "version" : "1.0.0" ,
135+ },
112136 },
113- },
114- }
115- elif method == "tools/list" :
116- # Return list of tools with unique name
117- response = {
118- "jsonrpc" : "2.0" ,
119- "id" : request_id ,
120- "result" : {
121- "tools" : [
122- {
123- "name" : tool_name ,
124- "description" : tool_desc ,
125- "inputSchema" : {
126- "type" : "object" ,
127- "properties" : {
128- "message" : {
129- "type" : "string" ,
130- "description" : "Test message" ,
131- }
137+ }
138+
139+ case "tools/list" :
140+ # Return list of tools with unique name
141+ response = {
142+ "jsonrpc" : "2.0" ,
143+ "id" : request_id ,
144+ "result" : {
145+ "tools" : [
146+ {
147+ "name" : tool_name ,
148+ "description" : tool_desc ,
149+ "inputSchema" : {
150+ "type" : "object" ,
151+ "properties" : {
152+ "message" : {
153+ "type" : "string" ,
154+ "description" : "Test message" ,
155+ }
156+ },
132157 },
133- },
134- }
135- ]
136- },
137- }
138- else :
139- # Generic success response for other methods
140- response = {
141- "jsonrpc" : "2.0" ,
142- "id" : request_id ,
143- "result" : {"status" : "ok" },
144- }
158+ }
159+ ]
160+ },
161+ }
162+
163+ case "tools/call" :
164+ # Handle tool execution
165+ params = request_data .get ("params" , {})
166+ tool_called = params .get ("name" , "unknown" )
167+ arguments = params .get ("arguments" , {})
168+
169+ # Check if error mode is enabled
170+ if error_mode :
171+ # Return error response
172+ response = {
173+ "jsonrpc" : "2.0" ,
174+ "id" : request_id ,
175+ "result" : {
176+ "content" : [
177+ {
178+ "type" : "text" ,
179+ "text" : (
180+ f"Error: Tool '{ tool_called } ' "
181+ "execution failed - simulated error."
182+ ),
183+ }
184+ ],
185+ "isError" : True ,
186+ },
187+ }
188+ else :
189+ # Build result text
190+ result_text = (
191+ f"Mock tool '{ tool_called } ' executed successfully "
192+ f"with arguments: { arguments } ."
193+ )
194+
195+ # Return successful tool execution result
196+ response = {
197+ "jsonrpc" : "2.0" ,
198+ "id" : request_id ,
199+ "result" : {
200+ "content" : [
201+ {
202+ "type" : "text" ,
203+ "text" : result_text ,
204+ }
205+ ],
206+ "isError" : False ,
207+ },
208+ }
209+
210+ case _:
211+ # Generic success response for other methods
212+ response = {
213+ "jsonrpc" : "2.0" ,
214+ "id" : request_id ,
215+ "result" : {"status" : "ok" },
216+ }
145217
146218 self .send_response (200 )
147219 self .send_header ("Content-Type" , "application/json" )
@@ -160,6 +232,11 @@ def do_GET(self) -> None: # pylint: disable=invalid-name
160232 )
161233 case "/debug/requests" :
162234 self ._send_json_response (request_log )
235+ case "/debug/clear" :
236+ # Clear the request log and last captured headers
237+ request_log .clear ()
238+ last_headers .clear ()
239+ self ._send_json_response ({"status" : "cleared" , "request_count" : 0 })
163240 case "/" :
164241 self ._send_help_page ()
165242 case _:
@@ -273,10 +350,10 @@ def main() -> None:
273350 https_port = http_port + 1
274351
275352 # Create HTTP server
276- http_server = HTTPServer (("" , http_port ), MCPMockHandler )
353+ http_server = HTTPServer (("" , http_port ), MCPMockHandler ) # type: ignore[arg-type]
277354
278355 # Create HTTPS server with self-signed certificate
279- https_server = HTTPServer (("" , https_port ), MCPMockHandler )
356+ https_server = HTTPServer (("" , https_port ), MCPMockHandler ) # type: ignore[arg-type]
280357
281358 # Generate or load self-signed certificate
282359 script_dir = Path (__file__ ).parent
0 commit comments