Skip to content

Conversation

pablotp
Copy link
Contributor

@pablotp pablotp commented Sep 16, 2025

Description

Adds optional API key authentication to secure MCP proxy endpoints.

Changes

  • Added AuthenticationMiddleware class that validates requests using X-API-Key header
  • Added --apiKey CLI option and MCP_PROXY_API_KEY environment variable support
  • Integrated authentication into HTTP server with proper 401 responses for unauthorized requests
  • Exempted /ping and OPTIONS requests from authentication requirements

Implementation Details

  • Authentication is disabled by default for backward compatibility
  • When enabled, all endpoints except /ping and CORS preflight require valid API key
  • Uses X-API-Key header for simplicity and broad client support
  • Headers are case-insensitive per HTTP specification

Testing

  • Added 11 unit tests for authentication middleware - all passing
  • Added 9 integration tests for authenticated request scenarios - all passing
  • Manual verification performed
Manual verification commands
 npx tsx src/bin/mcp-proxy.ts --debug --apiKey "test-secret-key" tsx src/fixtures/simple-stdio-server.ts

Test commands:

  1. Test without API key (should return 401):
  curl -X POST http://localhost:8080/mcp \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"test","id":1}' \
    -w "\nStatus: %{http_code}\n"
  1. Test with wrong API key (should return 401):
  curl -X POST http://localhost:8080/mcp \
    -H "X-API-Key: wrong-key" \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"test","id":1}' \
    -w "\nStatus: %{http_code}\n"
  1. Test with correct API key (should pass authentication):
  curl -X POST http://localhost:8080/mcp \
    -H "X-API-Key: test-secret-key" \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}},"id":1}' \
    -w "\nStatus: %{http_code}\n"
  1. Test /ping endpoint without auth (should return 200):
  curl http://localhost:8080/ping -w "\nStatus: %{http_code}\n"
  1. Test OPTIONS request without auth (should return 204):
  curl -X OPTIONS http://localhost:8080/mcp -w "\nStatus: %{http_code}\n"
  1. Test case-insensitive header (should pass authentication):
  curl -X POST http://localhost:8080/mcp \
    -H "X-Api-Key: test-secret-key" \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"test","id":1}' \
    -w "\nStatus: %{http_code}\n"

Breaking Changes

None. Authentication is opt-in.

@pablotp pablotp force-pushed the add-authentication branch 2 times, most recently from 775195f to c6f5a1c Compare September 16, 2025 11:00
@pablotp pablotp marked this pull request as ready for review September 16, 2025 11:03
@punkpeye
Copy link
Owner

This is great!

@punkpeye punkpeye merged commit dc8583a into punkpeye:main Sep 16, 2025
2 checks passed
@punkpeye
Copy link
Owner

Great. Thanks!

@pablotp
Copy link
Contributor Author

pablotp commented Sep 16, 2025

Thanks for the prompt review and release!!
🤝

@punkpeye
Copy link
Owner

Of course. Appreciate high quality contribution!

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.

2 participants