mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
Add HTTP transport mode for MCP server with --http flag
Co-authored-by: hlohaus <983577+hlohaus@users.noreply.github.com>
This commit is contained in:
parent
0a72ce961c
commit
a15618a80e
6 changed files with 266 additions and 10 deletions
|
|
@ -22,6 +22,8 @@ pip install -e .
|
|||
|
||||
### Running the MCP Server
|
||||
|
||||
**Stdio Mode (Default)**
|
||||
|
||||
Start the MCP server using:
|
||||
|
||||
```bash
|
||||
|
|
@ -36,11 +38,31 @@ g4f mcp
|
|||
|
||||
The server communicates over stdin/stdout using JSON-RPC 2.0 protocol.
|
||||
|
||||
**HTTP Mode**
|
||||
|
||||
Start the MCP server with HTTP transport:
|
||||
|
||||
```bash
|
||||
g4f mcp --http --port 8765
|
||||
```
|
||||
|
||||
This starts an HTTP server with the following endpoints:
|
||||
- `POST http://localhost:8765/mcp` - MCP JSON-RPC endpoint
|
||||
- `GET http://localhost:8765/health` - Health check endpoint
|
||||
|
||||
HTTP mode is useful for:
|
||||
- Web-based integrations
|
||||
- Testing with curl or HTTP clients
|
||||
- Remote access (configure host with `--host`)
|
||||
|
||||
Options:
|
||||
- `--http`: Enable HTTP transport instead of stdio
|
||||
- `--host HOST`: Host to bind to (default: 0.0.0.0)
|
||||
- `--port PORT`: Port to bind to (default: 8765)
|
||||
|
||||
### Configuration for AI Assistants
|
||||
|
||||
To use this MCP server with an AI assistant like Claude Desktop, add the following to your MCP configuration:
|
||||
|
||||
**For Claude Desktop** (`claude_desktop_config.json`):
|
||||
**For Claude Desktop (Stdio)** - `claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -53,6 +75,17 @@ To use this MCP server with an AI assistant like Claude Desktop, add the followi
|
|||
}
|
||||
```
|
||||
|
||||
**For HTTP-based clients**:
|
||||
|
||||
Make POST requests to `http://localhost:8765/mcp` with JSON-RPC payloads.
|
||||
|
||||
Example with curl:
|
||||
```bash
|
||||
curl -X POST http://localhost:8765/mcp \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
|
||||
```
|
||||
|
||||
**For VS Code with Cline**:
|
||||
|
||||
```json
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
"""MCP Server implementation using stdio transport
|
||||
"""MCP Server implementation with stdio and HTTP transports
|
||||
|
||||
This module implements a Model Context Protocol (MCP) server that communicates
|
||||
over standard input/output using JSON-RPC 2.0. The server exposes tools for:
|
||||
over standard input/output using JSON-RPC 2.0, or via HTTP POST endpoints.
|
||||
The server exposes tools for:
|
||||
- Web search
|
||||
- Web scraping
|
||||
- Image generation
|
||||
|
|
@ -190,12 +191,115 @@ class MCPServer:
|
|||
except Exception as e:
|
||||
sys.stderr.write(f"Error: {e}\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
async def run_http(self, host: str = "0.0.0.0", port: int = 8765):
|
||||
"""Run the MCP server with HTTP transport
|
||||
|
||||
Args:
|
||||
host: Host to bind the HTTP server to
|
||||
port: Port to bind the HTTP server to
|
||||
"""
|
||||
try:
|
||||
from aiohttp import web
|
||||
except ImportError:
|
||||
sys.stderr.write("Error: aiohttp is required for HTTP transport\n")
|
||||
sys.stderr.write("Install it with: pip install aiohttp\n")
|
||||
sys.exit(1)
|
||||
|
||||
async def handle_mcp_request(request: web.Request) -> web.Response:
|
||||
"""Handle MCP JSON-RPC request over HTTP POST"""
|
||||
try:
|
||||
# Parse JSON-RPC request from POST body
|
||||
request_data = await request.json()
|
||||
|
||||
mcp_request = MCPRequest(
|
||||
jsonrpc=request_data.get("jsonrpc", "2.0"),
|
||||
id=request_data.get("id"),
|
||||
method=request_data.get("method"),
|
||||
params=request_data.get("params")
|
||||
)
|
||||
|
||||
# Handle request
|
||||
response = await self.handle_request(mcp_request)
|
||||
|
||||
# Build response dict
|
||||
response_dict = {
|
||||
"jsonrpc": response.jsonrpc,
|
||||
"id": response.id
|
||||
}
|
||||
if response.result is not None:
|
||||
response_dict["result"] = response.result
|
||||
if response.error is not None:
|
||||
response_dict["error"] = response.error
|
||||
|
||||
return web.json_response(response_dict)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
return web.json_response({
|
||||
"jsonrpc": "2.0",
|
||||
"id": None,
|
||||
"error": {
|
||||
"code": -32700,
|
||||
"message": f"Parse error: {str(e)}"
|
||||
}
|
||||
}, status=400)
|
||||
except Exception as e:
|
||||
return web.json_response({
|
||||
"jsonrpc": "2.0",
|
||||
"id": None,
|
||||
"error": {
|
||||
"code": -32603,
|
||||
"message": f"Internal error: {str(e)}"
|
||||
}
|
||||
}, status=500)
|
||||
|
||||
async def handle_health(request: web.Request) -> web.Response:
|
||||
"""Health check endpoint"""
|
||||
return web.json_response({
|
||||
"status": "ok",
|
||||
"server": self.server_info
|
||||
})
|
||||
|
||||
# Create aiohttp application
|
||||
app = web.Application()
|
||||
app.router.add_post('/mcp', handle_mcp_request)
|
||||
app.router.add_get('/health', handle_health)
|
||||
|
||||
# Start server
|
||||
sys.stderr.write(f"Starting {self.server_info['name']} v{self.server_info['version']} (HTTP mode)\n")
|
||||
sys.stderr.write(f"Listening on http://{host}:{port}\n")
|
||||
sys.stderr.write(f"MCP endpoint: http://{host}:{port}/mcp\n")
|
||||
sys.stderr.write(f"Health check: http://{host}:{port}/health\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
runner = web.AppRunner(app)
|
||||
await runner.setup()
|
||||
site = web.TCPSite(runner, host, port)
|
||||
await site.start()
|
||||
|
||||
# Keep server running
|
||||
try:
|
||||
await asyncio.Event().wait()
|
||||
except KeyboardInterrupt:
|
||||
sys.stderr.write("\nShutting down HTTP server...\n")
|
||||
sys.stderr.flush()
|
||||
finally:
|
||||
await runner.cleanup()
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for MCP server"""
|
||||
def main(http: bool = False, host: str = "0.0.0.0", port: int = 8765):
|
||||
"""Main entry point for MCP server
|
||||
|
||||
Args:
|
||||
http: If True, use HTTP transport instead of stdio
|
||||
host: Host to bind HTTP server to (only used when http=True)
|
||||
port: Port to bind HTTP server to (only used when http=True)
|
||||
"""
|
||||
server = MCPServer()
|
||||
asyncio.run(server.run())
|
||||
if http:
|
||||
asyncio.run(server.run_http(host, port))
|
||||
else:
|
||||
asyncio.run(server.run())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue