Endpoint
What happens to each message
Every MCP message (initialize, tools/list, tools/call, resources/read, notifications) takes the same path:
- Authenticate the workspace. Missing or unknown API key →
401. - Resolve the connection. It must belong to the same workspace as the API key. Otherwise →
400 connection_invalid. - Rate limit. Over 100 messages in 60 seconds on this connection →
429withRetry-After: 60. Nothing is sent upstream. - Make sure the token is usable. If it’s expired or expires within 60 seconds, it’s refreshed first. If it’s only due for an early refresh, that happens in the background.
- Check MCP support. If the provider has no MCP server →
400 mcp_not_supported. - Forward. The body is sent unchanged to the provider’s MCP server, with
Authorizationset to the user’s token. - Return and log. The provider’s response comes back unmodified. A log entry is written afterwards without adding latency.
What happens to headers
The request body is never read, parsed or rewritten.
Tools
BundleUp keeps no tool registry. There’s nothing to sync or configure.- Discovery.
tools/listgoes to the provider, and its response comes back verbatim: names, descriptions, input and output schemas, annotations and pagination cursors. - Calls.
tools/callgoes to the provider verbatim. Arguments aren’t validated or changed by BundleUp. - Scope. A connection sees and can call whatever its OAuth grant allows. Narrow the scopes on the integration and the provider returns fewer tools, or rejects calls.
- Beyond tools.
resources/*,prompts/*,completion/*,logging/*and server notifications work if the provider supports them. - No namespacing. Tool names aren’t prefixed. If you register two connections as two servers, their tool names can collide; your client has to tell them apart.
Sessions and streaming
The proxy is stateless. Session state lives on the provider’s server.- The provider’s
Mcp-Session-Idfrominitializeis returned to your client. Send it back on later messages and they reach the same upstream session. - Streamable HTTP responses (
text/event-stream) are passed straight through, event by event. DELETE(session teardown) is forwarded like any other method.
A long-lived stream is authorized once, when it opens. If the access token expires while the stream is open, the provider closes it. Reconnect, and BundleUp attaches a fresh token.
No retries
Proxy MCP doesn’t retry, and ignoresBU-Max-Retries. A failed upstream message is returned on the first attempt, and your MCP client decides what to do next.
Errors
Errors from BundleUp, before anything reaches the provider:
Anything the provider returns, including its own
401, 403 or JSON-RPC error objects, is passed through with its original status and body. When a tool call fails upstream, your agent sees the provider’s error.
Logging
Each message is logged with its status, duration, upstream URL and method, and the connection, integration and API key that made it. Bodies are never logged, so tool arguments and results stay out of BundleUp’s records.No OAuth discovery
Proxy MCP authenticates with static headers. It doesn’t implement the MCP authorization spec: there’s no/.well-known/oauth-protected-resource, no dynamic client registration and no consent step at connect time. Users connect their accounts through BundleUp’s authorization flow beforehand.
Clients that can only authenticate through OAuth discovery can’t connect to mcp.bundleup.io. Use a client that supports static headers or a single bearer token, or bridge with mcp-remote.
