Skip to main content
Proxy MCP puts BundleUp in front of a provider’s own remote MCP server. The provider defines the tools. BundleUp handles what the provider doesn’t: storing and refreshing users’ tokens, keeping one user’s connection away from another’s, rate limiting, and logging. Proxy MCP doesn’t define, rename, filter or normalize tools. It’s a pass-through.

Endpoint

There’s no per-provider path. The connection decides which provider’s MCP server a message goes to. Any path or query string you add is ignored.

What happens to each message

Every MCP message (initialize, tools/list, tools/call, resources/read, notifications) takes the same path:
  1. Authenticate the workspace. Missing or unknown API key → 401.
  2. Resolve the connection. It must belong to the same workspace as the API key. Otherwise → 400 connection_invalid.
  3. Rate limit. Over 100 messages in 60 seconds on this connection → 429 with Retry-After: 60. Nothing is sent upstream.
  4. 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.
  5. Check MCP support. If the provider has no MCP server → 400 mcp_not_supported.
  6. Forward. The body is sent unchanged to the provider’s MCP server, with Authorization set to the user’s token.
  7. 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/list goes to the provider, and its response comes back verbatim: names, descriptions, input and output schemas, annotations and pagination cursors.
  • Calls. tools/call goes 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.
The provider owns the tool definitions, so tool names and arguments can change without a BundleUp release. Treat the tool list as a live contract.

Sessions and streaming

The proxy is stateless. Session state lives on the provider’s server.
  • The provider’s Mcp-Session-Id from initialize is 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 ignores BU-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:
These are plain HTTP responses with a JSON body, not JSON-RPC errors. Most MCP clients report them as connection or transport errors rather than tool errors.
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.