Skip to content

feat: MCP HTTP transport for remote MCP server#26

Open
linhdmn wants to merge 4 commits intomainfrom
feature/mcp-http
Open

feat: MCP HTTP transport for remote MCP server#26
linhdmn wants to merge 4 commits intomainfrom
feature/mcp-http

Conversation

@linhdmn
Copy link
Copy Markdown
Member

@linhdmn linhdmn commented Apr 24, 2026

Summary

  • Add mcp-http CLI command for HTTP-based MCP server (remote clients)
  • Implement Streamable HTTP transport per MCP spec
  • HTTP POST endpoint for JSON-RPC requests
  • Server-Sent Events (SSE) for streaming responses
  • Bearer token authentication
  • CORS headers for browser-based clients
  • Support multiple concurrent MCP clients
  • Default port 9699

Changes

  • src/mcp/server.rs - Added HTTP transport with SSE streaming
  • src/cli/mod.rs - Added McpHttp CLI variant
  • src/config/project.rs - Added DatabaseConfig struct (PostgreSQL support prepared but not yet functional)
  • src/db/schema.rs - Added init_db_with_config function

Test plan

  • Health check endpoint works
  • MCP initialize works with authentication
  • tools/list returns 35 tools
  • Tool calls work (mcp_status, search_code, etc.)
  • Authentication rejects unauthorized requests

@linhdmn
Copy link
Copy Markdown
Member Author

linhdmn commented Apr 24, 2026

Review Fixes Applied

Addressed the feedback from the code review:

Changes Made

  1. Clarified tool result handling (src/mcp/server.rs:1024-1026)

    • Added comment explaining when as_str() succeeds vs. when wrap_response() is needed
  2. Documented unused PostgreSQL fields (src/config/project.rs:78-83)

    • Marked pool_size and ssl_enabled as "Reserved for future PostgreSQL support - currently unused"

Not Addressed (by design)

  • SSE auth handler: The logic is actually consistent - returns true when no auth is required (token is None). This is correct behavior.
  • Rate limiting: Deferred as a production hardening concern
  • Cargo.toml: Dependencies (axum, tower-http) were already present in the PR

Testing

  • Build: cargo build --release
  • Unit tests for modified modules: cargo test --lib config::project (4/4 passed) ✓
  • Pre-commit hooks (fmt + clippy): passed ✓

@linhdmn
Copy link
Copy Markdown
Member Author

linhdmn commented Apr 24, 2026

Local Testing Results ✓

Tested the MCP HTTP server locally with curl:

Endpoints Verified

Endpoint Test Result
GET /health No auth {"status": "ok"}
POST /mcp initialize No auth Returns protocol version, capabilities
POST /mcp tools/list No auth Returns 35 tools
POST /mcp tools/call No auth mcp_status returns 8900 elements
POST /mcp with wrong token Auth required {"error": "Unauthorized"}
POST /mcp with correct token Auth enabled Passes auth, executes tool
GET /mcp/stream SSE Returns endpoint event

Test Commands

# Start server
cargo run --release -- mcp-http --auth my-secret-token

# Test health
curl http://localhost:9699/health

# Test with auth
curl -X POST http://localhost:9699/mcp \
  -H "Authorization: Bearer my-secret-token" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"mcp_status","arguments":{}}}'

All endpoints working as expected.

linhdmn added 3 commits April 24, 2026 18:00
Add mcp-http CLI command that starts LeanKG MCP server with
Streamable HTTP transport per MCP spec.

Features:
- POST /mcp endpoint for JSON-RPC requests
- GET /mcp/stream endpoint for SSE streaming
- GET /health endpoint for health checks
- Bearer token authentication (--auth flag)
- CORS headers for browser-based clients
- Default port 9699 (configurable via --port or MCP_HTTP_PORT env var)
- Watch mode support (--watch flag)

This enables LeanKG to serve multiple concurrent MCP clients
remotely, complementing the existing stdio transport for local use.
- Add DatabaseConfig struct to project.rs with backend, path, pool_size, ssl_enabled
- Add #[serde(default)] to ProjectConfig to handle missing database field
- Add init_db_with_config function to schema.rs (SQLite-only, PG returns error)
- Update HLD changelog to note PostgreSQL support pending cozo update

Note: PostgreSQL support requires cozo to add PG storage backend.
Currently only SQLite is supported via cozo 0.2.
- Add comment explaining when tool results use as_str() vs wrap_response()
- Mark pool_size and ssl_enabled as reserved for future PostgreSQL support
- Remove unused SseEventType enum from HTTP transport
- Use subtle::ConstantTimeEq for bearer token comparison to prevent
  timing attacks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant