返回提交历史
Modified
g4f/mcp/server.py
+45
-39
XFEstudio/gpt4free
fix(mcp): redirect standard output to stderr in stdio mode to protect JSON-RPC framing
b4768cc1
代码差异
1 个文件
+45
-39
@@ -195,50 +195,56 @@ class MCPServer:
195
195
196
196
async def run(self):
197
197
"""Run the MCP server with stdio transport"""
198
# Write server info to stderr for debugging
199
sys.stderr.write(
200
f"Starting {self.server_info['name']} v{self.server_info['version']}\n"
201
)
202
sys.stderr.flush()
203
204
while True:
205
try:
206
# Read line from stdin
207
line = await asyncio.get_event_loop().run_in_executor(
208
None, sys.stdin.readline
209
)
210
211
if not line:
212
break
198
real_stdout = sys.stdout
199
sys.stdout = sys.stderr
213
200
214
# Parse JSON-RPC request
215
request_data = json.loads(line)
216
request = MCPRequest(
217
jsonrpc=request_data.get("jsonrpc", "2.0"),
218
id=request_data.get("id"),
219
method=request_data.get("method"),
220
params=request_data.get("params"),
221
)
201
try:
202
# Write server info to stderr for debugging
203
sys.stderr.write(
204
f"Starting {self.server_info['name']} v{self.server_info['version']}\n"
205
)
206
sys.stderr.flush()
222
207
223
# Handle request
224
response = await self.handle_request(request)
208
while True:
209
try:
210
# Read line from stdin
211
line = await asyncio.get_event_loop().run_in_executor(
212
None, sys.stdin.readline
213
)
225
214
226
# Write response to stdout
227
response_dict = {"jsonrpc": response.jsonrpc, "id": response.id}
228
if response.result is not None:
229
response_dict["result"] = response.result
230
if response.error is not None:
231
response_dict["error"] = response.error
215
if not line:
216
break
232
217
233
sys.stdout.write(json.dumps(response_dict) + "\n")
234
sys.stdout.flush()
218
# Parse JSON-RPC request
219
request_data = json.loads(line)
220
request = MCPRequest(
221
jsonrpc=request_data.get("jsonrpc", "2.0"),
222
id=request_data.get("id"),
223
method=request_data.get("method"),
224
params=request_data.get("params"),
225
)
235
226
236
except json.JSONDecodeError as e:
237
sys.stderr.write(f"JSON decode error: {e}\n")
238
sys.stderr.flush()
239
except Exception as e:
240
sys.stderr.write(f"Error: {e}\n")
241
sys.stderr.flush()
227
# Handle request
228
response = await self.handle_request(request)
229
230
# Write response to protocol stdout
231
response_dict = {"jsonrpc": response.jsonrpc, "id": response.id}
232
if response.result is not None:
233
response_dict["result"] = response.result
234
if response.error is not None:
235
response_dict["error"] = response.error
236
237
real_stdout.write(json.dumps(response_dict) + "\n")
238
real_stdout.flush()
239
240
except json.JSONDecodeError as e:
241
sys.stderr.write(f"JSON decode error: {e}\n")
242
sys.stderr.flush()
243
except Exception as e:
244
sys.stderr.write(f"Error: {e}\n")
245
sys.stderr.flush()
246
finally:
247
sys.stdout = real_stdout
242
248
243
249
async def run_http(
244
250
self, host: str = "0.0.0.0", port: int = 8765, origin: Optional[str] = None