{"_id":"@critique-mcp/mcp-gateway-wrapper","_rev":"2-bcf4592a6ee52a12bb4645a5e05d063e","name":"@critique-mcp/mcp-gateway-wrapper","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@critique-mcp/mcp-gateway-wrapper","version":"0.1.0","keywords":["mcp","gateway","critique","stdio","proxy"],"author":{"name":"Critique"},"license":"MIT","_id":"@critique-mcp/mcp-gateway-wrapper@0.1.0","maintainers":[{"name":"bradthebeeble","email":"asaf.atzmon@gmail.com"}],"homepage":"https://github.com/bradthebeeble/critique#readme","bugs":{"url":"https://github.com/bradthebeeble/critique/issues"},"bin":{"mcp-gateway-wrapper":"index.js"},"dist":{"shasum":"0a85fcbb739209aacd18e771d58daf280356226a","tarball":"https://registry.npmjs.org/@critique-mcp/mcp-gateway-wrapper/-/mcp-gateway-wrapper-0.1.0.tgz","fileCount":4,"integrity":"sha512-nDEOi8bxN47btNL+qn08XPd4dqqHoVUof4JBXVO6LcF8Gq378F6xSu7DGxk0P00HFRo9YM2FxbxeyG1nDo5JXg==","signatures":[{"sig":"MEQCIByLUTxFdRmpOplX9MxIxAqg1B41+1t+t8E0Ggc1yu1lAiBBe6N4V6rx/3xzWaJILIPtp7pbfcoY9Pcfe3/9isqrwQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23134},"main":"index.js","engines":{"node":">=18.0.0"},"gitHead":"ed19d5862b50e7ea4a75247795cba4907fd8d7c4","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"bradthebeeble","email":"asaf.atzmon@gmail.com"},"repository":{"url":"git+https://github.com/bradthebeeble/critique.git","type":"git","directory":"services/mcp-gateway-wrapper"},"_npmVersion":"10.8.2","description":"Local stdio wrapper for Critique MCP Gateway with API key validation","directories":{},"_nodeVersion":"20.19.5","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mcp-gateway-wrapper_0.1.0_1767295240828_0.40504279119203557","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@critique-mcp/mcp-gateway-wrapper","version":"0.1.1","description":"Local stdio wrapper for Critique MCP Gateway with API key validation","main":"index.js","bin":{"mcp-gateway-wrapper":"index.js"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":["mcp","gateway","critique","stdio","proxy"],"author":{"name":"Critique"},"license":"MIT","engines":{"node":">=18.0.0"},"repository":{"type":"git","url":"git+https://github.com/bradthebeeble/critique.git","directory":"services/mcp-gateway-wrapper"},"publishConfig":{"access":"public"},"_id":"@critique-mcp/mcp-gateway-wrapper@0.1.1","gitHead":"ed19d5862b50e7ea4a75247795cba4907fd8d7c4","bugs":{"url":"https://github.com/bradthebeeble/critique/issues"},"homepage":"https://github.com/bradthebeeble/critique#readme","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-gJV87tilV0bAwvPM3Ru3SAWPZiLUWqgIYvEhAWHTPTVgtf9r/dfk3gwIk4OxuMq8McVbJqURr3wy91K9m8buxQ==","shasum":"1f18511b71595f36336880d1e3f1baf4996aba70","tarball":"https://registry.npmjs.org/@critique-mcp/mcp-gateway-wrapper/-/mcp-gateway-wrapper-0.1.1.tgz","fileCount":4,"unpackedSize":39061,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCkRrIqVNZKZA9TXb1I1+X9nst3Jl+NhnM/HxtI9s+gTwIgWyk/R1ReL05//M/OTvPhadMXWXYR/0UJxzNdlSlJ5pA="}]},"_npmUser":{"name":"bradthebeeble","email":"asaf.atzmon@gmail.com"},"directories":{},"maintainers":[{"name":"bradthebeeble","email":"asaf.atzmon@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-gateway-wrapper_0.1.1_1767357721046_0.12226028340211026"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-01T19:20:40.735Z","modified":"2026-01-02T12:42:01.386Z","0.1.0":"2026-01-01T19:20:40.979Z","0.1.1":"2026-01-02T12:42:01.181Z"},"bugs":{"url":"https://github.com/bradthebeeble/critique/issues"},"author":{"name":"Critique"},"license":"MIT","homepage":"https://github.com/bradthebeeble/critique#readme","keywords":["mcp","gateway","critique","stdio","proxy"],"repository":{"type":"git","url":"git+https://github.com/bradthebeeble/critique.git","directory":"services/mcp-gateway-wrapper"},"description":"Local stdio wrapper for Critique MCP Gateway with API key validation","maintainers":[{"name":"bradthebeeble","email":"asaf.atzmon@gmail.com"}],"readme":"# @critique-mcp/mcp-gateway-wrapper\n\nLocal stdio wrapper for Critique MCP Gateway that validates API keys on `initialize` calls and proxies MCP protocol to remote HTTP/SSE gateways with API key injection.\n\n## Overview\n\nThis wrapper runs locally on your machine and acts as a bridge between MCP clients (like Cursor, Claude Desktop) and remote Critique MCP Gateways. It provides:\n\n- **API Key Validation**: Validates your API key on `initialize` calls before establishing a session\n- **API Key Injection**: Automatically injects your API key into all MCP messages for gateway validation\n- **Protocol Translation**: Converts stdio MCP protocol (what clients expect) to HTTP/SSE (what remote gateways use)\n\n## Installation\n\n### Using npx (Recommended)\n\nNo installation needed! Use `npx` to run the wrapper directly:\n\n```bash\nnpx -y @critique-mcp/mcp-gateway-wrapper <gateway-url>\n```\n\n### Global Installation\n\n```bash\nnpm install -g @critique-mcp/mcp-gateway-wrapper\n```\n\nThen use it directly:\n\n```bash\nmcp-gateway-wrapper <gateway-url>\n```\n\n## Configuration\n\n### MCP Client Configuration\n\nConfigure the wrapper in your MCP client settings (e.g., `~/.cursor/mcp.json` or `~/Library/Application Support/Claude/claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"critique-gateway\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@critique-mcp/mcp-gateway-wrapper\",\n        \"http://gateways.critique.io/gateway/{client-id}/mcp\"\n      ],\n      \"env\": {\n        \"CLIENT_API_KEY\": \"client-api-key-{client-id}\",\n        \"CRITIQUE_API_URL\": \"http://localhost:8000\"\n      }\n    }\n  }\n}\n```\n\n### Environment Variables\n\n- **`CLIENT_API_KEY`** (required): Your API key for authentication. This is provided by Critique when you register your client.\n\n- **`CRITIQUE_API_URL`** (optional): The URL of the critique-api service. Defaults to `http://localhost:8000`.\n\n  - For local development: `http://localhost:8000`\n  - For production: Use your production critique-api URL\n\n### Command Line Arguments\n\n- **`<gateway-url>`** (required): The URL of your remote MCP Gateway endpoint.\n\n  Example: `http://gateways.critique.io/gateway/d2b7c8db-de3c-43eb-a10a-aafed3d54b64/mcp`\n\n## How It Works\n\n### Architecture\n\n```\nMCP Client (stdio)\n    ↓\nLocal Wrapper (@critique-mcp/mcp-gateway-wrapper)\n    ↓\n    ├─→ Validate API Key (critique-api)\n    └─→ Forward with API Key (Remote Gateway)\n```\n\n### Initialize Validation\n\nWhen the MCP client sends an `initialize` call:\n\n1. **Wrapper intercepts** the `initialize` call\n2. **Validates API key** by calling `POST {CRITIQUE_API_URL}/api/v1/validation/initialize` with `X-API-Key` header\n3. **If validation fails**: Returns MCP error to client, does not forward to gateway\n4. **If validation succeeds**: Forwards `initialize` to gateway with API key injected\n\n### API Key Injection\n\nFor all MCP messages (including `initialize` and `tools/call`):\n\n- API key is automatically added to the `X-API-Key` header when forwarding to the gateway\n- Gateway interceptor extracts the API key for validation on tool calls\n\n### Defense in Depth\n\nThe wrapper provides two layers of security:\n\n1. **First Gate**: Wrapper validates `initialize` call (blocks unauthorized sessions)\n2. **Second Gate**: Gateway interceptor validates every `tools/call` message (blocks unauthorized tool calls)\n\nEven if a user modifies the wrapper to bypass initialize validation, the gateway interceptor still validates every tool call.\n\n## Error Handling\n\n### Missing API Key\n\nIf `CLIENT_API_KEY` is not set:\n\n```\nError: CLIENT_API_KEY environment variable is required\n```\n\n**Solution**: Set the `CLIENT_API_KEY` environment variable in your MCP client configuration.\n\n### Missing Gateway URL\n\nIf gateway URL is not provided:\n\n```\nError: Gateway URL is required\nUsage: mcp-gateway-wrapper <gateway-url>\n```\n\n**Solution**: Provide the gateway URL as a command line argument.\n\n### Validation Failures\n\nIf API key validation fails, the wrapper returns an MCP error:\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": <request-id>,\n  \"error\": {\n    \"code\": -32000,\n    \"message\": \"Validation failed: invalid_key\",\n    \"data\": {\n      \"reason\": \"invalid_key\"\n    }\n  }\n}\n```\n\n**Common reasons**:\n- `invalid_key`: API key is invalid or doesn't match stored hash\n- `unregistered`: Client is not registered in the database\n- `suspended`: Client status is suspended\n- `timeout`: Validation endpoint did not respond in time\n- `network_error`: Cannot connect to critique-api\n\n**Solutions**:\n- Verify your API key is correct\n- Check that your client is registered and active\n- Ensure critique-api is running and accessible\n- Check network connectivity\n\n### Gateway Connection Failures\n\nIf the wrapper cannot connect to the gateway:\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": <request-id>,\n  \"error\": {\n    \"code\": -32603,\n    \"message\": \"Request failed: <error-details>\"\n  }\n}\n```\n\n**Solutions**:\n- Verify the gateway URL is correct\n- Check network connectivity to the gateway\n- Ensure the gateway is running and accessible\n\n## Security Considerations\n\n- **API Key Storage**: API key is read from environment variables (not command line arguments) to avoid exposure in process lists\n- **API Key Injection**: API key is injected into HTTP headers (not logged or exposed in error messages)\n- **Fail-Closed Policy**: If validation fails or critique-api is unavailable, the wrapper blocks the `initialize` call\n- **Defense in Depth**: Multiple validation layers ensure security even if one layer is bypassed\n\n## Known Limitations\n\n### Cursor MCP Client Issue with Null IDs\n\n**Issue**: Cursor's MCP client sends `initialize` requests with `id: null` (which in JSON-RPC 2.0 indicates a notification that doesn't expect a response). However, MCP protocol requires `initialize` to always receive a response. When the wrapper sends a response with a generated ID (since `null` is not valid in responses), Cursor logs an error: \"Received a response for an unknown message ID\".\n\n**Status**: This is a known limitation in Cursor's MCP client implementation. The wrapper is working correctly according to MCP protocol - the issue is with how Cursor handles `initialize` requests with null IDs.\n\n**Workaround**: Despite the error message, the connection may still work. If you encounter issues, please report this to Cursor's support team.\n\n**Technical Details**:\n- Cursor sends: `{\"jsonrpc\":\"2.0\",\"id\":null,\"method\":\"initialize\",...}`\n- Wrapper must send response (MCP requirement)\n- Wrapper generates ID (e.g., `\"cursor-1\"`) since `null` is invalid in responses\n- Cursor rejects response because ID doesn't match original `null`\n\n## Troubleshooting\n\n### Wrapper Not Found\n\nIf `npx` cannot find the package:\n\n```bash\n# Clear npx cache\nnpx clear-npx-cache\n\n# Or use specific version\nnpx -y @critique-mcp/mcp-gateway-wrapper@0.1.0 <gateway-url>\n```\n\n### Validation Endpoint Not Responding\n\nIf you see timeout errors:\n\n1. Check that critique-api is running: `curl http://localhost:8000/health`\n2. Verify `CRITIQUE_API_URL` is correct\n3. Check firewall/network settings\n\n### Gateway Not Responding\n\nIf gateway requests fail:\n\n1. Verify the gateway URL is correct\n2. Check that the gateway pod is running (if using Kubernetes)\n3. Verify network connectivity to the gateway\n\n## Development\n\n### Local Development\n\nTo test the wrapper locally:\n\n```bash\n# Set environment variables\nexport CLIENT_API_KEY=\"your-api-key\"\nexport CRITIQUE_API_URL=\"http://localhost:8000\"\n\n# Run the wrapper\nnode index.js http://localhost:8080/mcp\n```\n\n### Testing with MCP Client\n\n1. Configure the wrapper in your MCP client settings\n2. Restart your MCP client\n3. Check client logs for any errors\n4. Verify that tool calls work correctly\n\n## License\n\nMIT\n\n## Support\n\nFor issues and questions, please open an issue in the Critique repository.\n","readmeFilename":"README.md"}