-
Notifications
You must be signed in to change notification settings - Fork 6
Proxy to Kapa MCP #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy to Kapa MCP #153
Conversation
Previously, deprecation warnings were only in server logs and HTTP headers, which LLMs cannot see. This change adds the deprecation notice directly to all tool response content so that LLMs are informed about the endpoint shutdown in February 2026 and the migration path to https://redpanda.mcp.kapa.ai Also removes redundant HTTP deprecation headers (Deprecation, Sunset, Link) since they don't provide value for LLM clients. Server-side logging is retained for monitoring purposes.
✅ Deploy Preview for redpanda-documentation ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
| const API_BASE = 'https://api.kapa.ai' | ||
| // Fetch Netlify env vars | ||
| // Hardcoded upstream | ||
| const KAPA_MCP_SERVER_URL = 'https://redpanda.mcp.kapa.ai' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be 'https://docs.redpanda.com/mcp' or that's exactly what proxies that url?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the proxy
| const CONNECT_TIMEOUT_MS = 8_000 | ||
| const CALL_TIMEOUT_MS = 22_000 | ||
| const MAX_QUERY_CHARS = 2_000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
those values look weird with _ . is this an api field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for readability. JS supports this syntax instead of 22000
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL !
| ) | ||
| } catch (retryErr) { | ||
| const retryMsg = | ||
| retryErr instanceof Error ? retryErr.message : String(retryErr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we log this error? where would logs even go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to the Netlify logs. we could log it yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added logs
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| limit: 60, // limit each key to 60 requests per windowMs (tune as needed) | ||
| keyGenerator: computeLimiterKey, // use our custom key generator | ||
| standardHeaders: true, // send RateLimit-* headers if supported | ||
| legacyHeaders: true, // also send X-RateLimit-* headers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have you checked if we need to tweak any of these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are our own limits. No need to change them
| const method = c.req.method | ||
| if (method === 'GET') { | ||
| // Let SSE stream open/reconnect without limiter interference | ||
| return next() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GETs are not rate limited. Is this intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're just for keeping the SSE stream going. Allows heartbeats that we don't want to limit.
| if ( | ||
| request.method !== 'POST' && | ||
| request.method !== 'GET' && | ||
| request.method !== 'DELETE' | ||
| ) { | ||
| return new Response('Method not allowed', { | ||
| status: 405, | ||
| headers: { Allow: 'POST, GET, DELETE' }, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i dont understand why we allow DELETE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used for cleaning up the session.

This PR introduces an MCP-to-MCP proxy that routes Redpanda documentation search requests through Kapa’s Hosted MCP server.
The Redpanda MCP server remains the single integration point. Native Redpanda tools can be added alongside the proxied search tool without breaking clients.