Deploying Claude Connectors to Production: Host Your MCP Server on Cloudflare, Vercel, or Any Platform (August 2026)

Deploy your Claude Connector MCP server to production.
TL;DR: Deploy a Claude Connector behind a stable public HTTPS /mcp endpoint using Streamable HTTP. Prefer stateless request handling, but test the MCP revisions your hosts actually negotiate because 2025-era clients use initialize while MCP 2026-07-28 uses server/discover and no protocol session. Configure Claude-compatible OAuth, ship server and MCP App resources atomically, test the staged endpoint, monitor each protocol boundary, and keep a fast rollback.
A local MCP server becomes a production Claude Connector when Anthropic’s infrastructure can reach it, authenticate users, discover its tools, call them under load, and fetch any MCP App UI resources. Hosting is only one part of that path. DNS, protocol compatibility, OAuth discovery, deployment topology, metadata caching, and observability decide whether the connector stays reliable.
This guide covers Cloudflare Workers, Vercel, long-running app hosts, containers, and VPS deployments. The same production contract applies to each platform, so pick the runtime after you know what the connector needs.
The Production Contract
A production Claude Connector needs:
- A stable public HTTPS URL such as
https://connector.example.com/mcp. - A Streamable HTTP handler that supports the MCP behavior your target clients negotiate.
- Public OAuth discovery and user-scoped authorization for private data or actions.
- Deterministic tool, prompt, resource, and MCP App metadata.
- A scaling model that matches the protocol era and application state.
- Bounded tool execution, result sizes, and upstream calls.
- Logs, metrics, traces, health checks, alerts, and a tested rollback.
Claude currently supports Streamable HTTP and legacy HTTP+SSE, with HTTP+SSE being deprecated. Use Streamable HTTP for new deployments. A stdio server is useful when a local client starts the process, but it cannot be registered as a hosted remote connector URL.
Account for Both MCP Protocol Eras
MCP 2026-07-28 changed the production model. Do not deploy new infrastructure around the assumption that every client opens an initialize session.
| Behavior | 2025 era | 2026-07-28 era |
|---|---|---|
| Opening exchange | initialize | server/discover when discovery is needed |
| Client and capability data | Connection scoped | Request _meta envelope |
| HTTP protocol state | May use Mcp-Session-Id | No protocol session ID |
| Application workflow state | Often mixed with session state | Explicit tool arguments and durable handles |
| Cancellation | notifications/cancelled | Close the request stream |
| Change delivery | List-changed notifications | subscriptions/listen |
The current MCP TypeScript SDK v2 calls these the legacy and modern eras. Its createMcpHandler creates a fresh server for each request and, by default, also accepts compatible stateless 2025 traffic. That makes one endpoint usable by clients migrating at different times.
Do not assume Claude has negotiated the newest era just because the specification exists. Log the negotiated version when your SDK exposes it, test the versions your server advertises, and keep compatibility until your production client data says it is safe to remove.
What Proxies Must Preserve
Let an MCP SDK validate transport details. Configure the proxy to forward the data it needs:
MCP-Protocol-Versionon HTTP requests.Mcp-MethodandMcp-Namefor modern requests.Mcp-Session-Idfor negotiated legacy sessions when you still serve them.Accept: application/json, text/event-streamwithout coercion.- SSE response streaming without buffering when the handler uses it.
- W3C
traceparent,tracestate, andbaggagemetadata when you use distributed tracing.
MCP 2026-07-28 requires method and name headers so gateways can route and rate-limit without parsing the JSON-RPC body. The server rejects a request when those headers disagree with the body, so a proxy must not synthesize stale values.
Keep Application State Explicit
Protocol statelessness does not prevent multi-step workflows. Return a durable handle and accept it in the next tool call:
{
"content": [{ "type": "text", "text": "Report queued as job_8f31." }],
"structuredContent": {
"jobId": "job_8f31",
"status": "queued"
}
}
A later get_report_status call receives jobId. Any healthy server replica can load the job from durable storage, so deploys and load balancing do not depend on process memory.
Choose a Hosting Model
Start with workload behavior rather than a platform logo.
| Requirement | Suitable deployment shape |
|---|---|
| Short request-scoped API tools | Edge Worker or serverless function |
| Existing web product and preview workflow | Product platform function or container |
| Background jobs or queues | App host plus durable queue and worker |
| Native binaries or heavy processing | Container platform or VPS |
| Legacy sessionful MCP traffic | Long-lived process with affinity or a routed legacy lane |
| High availability across replicas | Stateless handler plus shared application storage |
Cold starts, execution limits, response buffering, and preview access controls matter more than the provider name. Measure the first call after idle, the longest valid tool, and a streamed response before choosing a plan.
Deploy on Cloudflare Workers
Cloudflare’s July 2026 remote MCP guide recommends its stateless createMcpHandler() path for new Workers. The older McpAgent path is now the legacy option for deployments that still depend on Durable Object session state, pushed requests, or replay.
Workers fit connectors that validate input, call APIs or storage, and return bounded results. Put long jobs in a queue and return a job handle instead of keeping a Worker request open.
For a sunpeak project on a web-standard edge runtime, mount the stateless handler behind your router:
import { createHandler } from 'sunpeak/mcp';
const mcp = createHandler({
tools,
resources,
stateless: true,
serverUrl: 'https://connector.example.com/mcp',
});
export default {
async fetch(request: Request) {
const url = new URL(request.url);
if (url.pathname === '/health') {
return Response.json({ status: 'ok' });
}
if (url.pathname !== '/mcp') {
return new Response('Not found', { status: 404 });
}
return mcp(request);
},
};
createHandler handles every request passed to it, so keep path matching in the Worker router. Set secrets with Wrangler and deploy:
pnpm exec wrangler secret put OAUTH_CLIENT_SECRET
pnpm exec wrangler deploy
Check Worker CPU time, subrequest limits, bundle compatibility, and streaming behavior. Use a custom domain for production so the connector URL remains stable if you move accounts or deployment projects.
Deploy on Vercel
Vercel fits teams that already ship product APIs there and want preview deployments, managed HTTPS, and one deployment history. Mount the MCP handler on a stable function route such as /mcp, use a Node or edge runtime that your MCP SDK supports, and keep request processing within the selected runtime’s limits.
For previews, check three boundaries:
- Deployment protection must allow the MCP client, or the client receives a login page instead of JSON-RPC.
- OAuth metadata must use the preview MCP URL exactly, including its path.
- Preview and production environments need separate secrets, callback configuration, data, and alerts.
Deploy a preview first, run protocol and OAuth smoke tests against its full URL, then promote the same artifact:
vercel deploy
vercel deploy --prod
Do not build MCP App resources again during promotion. A second build can generate different versioned resource URIs, which means the tested preview artifact and production artifact are no longer identical.
Deploy on Railway, Render, Fly.io, or a Container Platform
A long-running app host is a good fit for Node, Python, Go, or Rust servers, background workers, native packages, and existing application stacks. It is also the easiest place to keep a temporary sessionful compatibility lane while clients migrate.
For a sunpeak app, the normal production commands are:
pnpm build
pnpm start -- --json-logs
The production server listens on 0.0.0.0:8000, serves MCP at /mcp, and exposes /health. It registers the compiled tools and bundled resources from dist/ and calls the optional auth() function on requests.
A minimal container is:
FROM node:22-alpine
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
EXPOSE 8000
CMD ["pnpm", "start", "--", "--json-logs"]
Use a readiness probe on /health, send SIGTERM during replacement, and give in-flight requests time to finish. Disable scale-to-zero for user-facing connectors unless a measured cold start fits your connection and tool latency budget.
Deploy on a VPS
A VPS provides direct control over the runtime, network, disk, and process manager. It also makes your team responsible for TLS, operating system updates, process restarts, backups, firewall rules, and intrusion monitoring.
Run the MCP process on loopback and terminate HTTPS with Caddy or nginx:
connector.example.com {
reverse_proxy 127.0.0.1:8000
}
For nginx and an SSE-capable handler, disable response buffering:
location /mcp {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
}
Use systemd, a container supervisor, or another process manager to restart the service and collect logs. Test certificate renewal and host reboot before treating the server as production ready.
Build sunpeak Resources and Tools as One Artifact
sunpeak 0.20.77 compiles an MCP App project with:
pnpm build
The resulting dist/ contains self-contained HTML resources, resource metadata, compiled tool handlers, and an optional compiled server entry:
dist/
├── ticket-list/
│ ├── ticket-list.html
│ └── ticket-list.json
├── tools/
│ └── search-tickets.js
└── server.js
Deploy that directory and its server code together. An MCP App tool advertises a ui:// resource URI, the host reads that resource, and the app expects a compatible structuredContent shape. If any one of those pieces comes from a different release, the tool can succeed while the UI fails.
sunpeak production builds add cache-busting resource URIs. Keep the previous artifact available so a rollback restores its server, tool metadata, and matching resource bundles as one unit.
Know What --stateless Means in Current sunpeak
sunpeak 0.20.77 uses the 2025-era MCP wire protocol. Its stateless: true handler creates a fresh server for each POST and removes in-memory session tracking, which is the right topology for Workers and functions. It does not make that endpoint speak the MCP 2026-07-28 wire format.
Use the current sunpeak behavior when deploying sunpeak apps, and use an MCP SDK v2 dual-era handler when you need native 2026-07-28 support today. Test the endpoint rather than inferring protocol behavior from a stateless option name.
Configure Claude-Compatible OAuth
An authless connector is appropriate only when every exposed operation is public and safe for anonymous use. Private reads and all user actions need user-scoped authorization.
When an unauthenticated client reaches /mcp, return 401 Unauthorized with a WWW-Authenticate pointer to Protected Resource Metadata:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://connector.example.com/.well-known/oauth-protected-resource/mcp", scope="tickets.read"
Claude supports:
- Dynamic Client Registration, or DCR.
- Client ID Metadata Documents, or CIMD.
- Anthropic-held client credentials for approved directory connectors.
- Organization-supplied OAuth credentials for custom connectors.
- No authentication for fully public servers.
For high-volume directory connectors, Anthropic recommends CIMD or Anthropic-held credentials because DCR registers a new client on each fresh connection. CIMD metadata must advertise client_id_metadata_document_supported: true and support the none token endpoint authentication method for Claude’s public client.
Register this hosted callback:
https://claude.ai/api/mcp/auth_callback
Claude Code uses http://localhost/callback and http://127.0.0.1/callback with a variable port. Accept both loopback hosts while ignoring the port for redirect matching.
Before release, verify:
- The Protected Resource Metadata
resourceexactly matches the MCP URL, including/mcp. - The first
authorization_serversentry is the issuer Claude should use. - The auth server advertises PKCE S256.
- The token endpoint accepts
application/x-www-form-urlencoded. - The DCR endpoint, if used, accepts
application/json. - Access tokens are bound to the MCP resource audience.
- Refresh token rotation returns the replacement token in the same response.
- Expired refresh tokens return
invalid_grant. - Scope and tenant checks run in each tool handler.
Never put a token or API key in the connector URL. Query strings leak into browser history, proxy logs, analytics, and support captures.
Make the Endpoint Reachable From Claude
Hosted Claude surfaces connect from Anthropic’s cloud, even when the user opens Claude Desktop. Current Anthropic documentation lists 160.79.104.0/21 as its outbound range for connector traffic.
Check public DNS from outside your own network:
dig +short connector.example.com A
curl -i https://connector.example.com/mcp
curl -sI https://connector.example.com/mcp
Claude requires at least one public IPv4 A record, and every resolved address must be globally routable. A mix of public and private answers still fails. IPv6-only, split-horizon, VPN-only, loopback, link-local, private, and carrier-grade NAT addresses do not work for hosted connectors.
A 401, 405, or JSON-RPC error from curl proves the endpoint answered. A timeout, 502, edge-generated 403 or 429, or redirect to another host identifies a network or proxy failure.
Register the final canonical URL. When /mcp redirects to a different host, the standard HTTP client drops the Authorization header, so the target sees an unauthenticated request and Claude reports an auth error.
Separate Staging and Production
Give staging its own:
- MCP hostname and OAuth resource URL.
- OAuth client registration or CIMD identity.
- secrets, database, queues, and storage.
- test users and scrubbed fixture data.
- alerts and log retention policy.
Do not point a staging connector at production user data just because the tools are read-only. Tool results can still expose private content to test prompts, screenshots, logs, and model context.
Build once, deploy the immutable artifact to staging, run smoke tests, then promote the same artifact. Keep environment-specific values outside the bundle unless the MCP App genuinely needs a public runtime setting.
Test the Deployment in Layers
Run local checks first:
pnpm test
pnpm build
For an existing server that does not use sunpeak, add the test harness:
npx sunpeak test init --server http://localhost:8000/mcp
Then inspect the staged production endpoint:
npx sunpeak inspect --server https://staging-connector.example.com/mcp
Verify:
- Discovery or compatible initialization succeeds.
- The scoped tool catalog matches the test user.
- Every tool accepts valid input and returns actionable execution errors for invalid input.
- The first unauthenticated protected request returns the expected OAuth challenge.
- Token refresh, insufficient scope, revocation, and tenant boundaries work.
- MCP App resources render their success, empty, error, cancelled, and large-result states.
- The production Content Security Policy allows only required origins.
- Logs and traces contain the reference data needed to debug the call without private payloads.
Finish with one narrow real-Claude smoke test. Use the exact staging URL, refresh the connector metadata, trigger one read tool, render one UI, and exercise one permission or error case. The local inspector should carry the broad host, theme, width, and fixture matrix because it is faster and deterministic.
Release Without Breaking Cached Metadata
Treat tool contracts and UI resources as a versioned API.
- Keep published tool names stable.
- Add optional inputs before making them required.
- Add a new tool when behavior changes enough that the old description becomes false.
- Keep model-visible
contentuseful when the host cannot render the app. - Publish a new
ui://URI when the resource or bridge contract changes. - Keep handlers backward compatible with the previous resource during a rolling deploy.
- Deploy metadata, handlers, schemas, and resources atomically.
Use canary or blue-green deployment when the platform supports it. Send a small share of traffic to the new release, compare protocol errors, tool latency, auth failures, and resource read failures, then promote. Roll back the whole artifact when those rates move outside the release threshold.
Schema migrations need the same care. Expand the database first, deploy code that handles old and new rows, migrate data, then remove the old shape in a later release.
Monitor Every Production Boundary
Record low-cardinality metrics for:
- DNS and HTTPS reachability from outside your network.
- Protocol negotiation and unsupported-version errors.
- OAuth discovery, authorization, token, refresh, and insufficient-scope failures.
tools/list,resources/read, andtools/callsuccess and latency.- Per-tool upstream status, timeout, cancellation, and result size.
- MCP App resource reads and frontend support references.
- Cold starts, process restarts, queue age, and saturation.
Propagate W3C trace context through the MCP request and downstream APIs when your SDK supports it. Add a short support ID to user-facing execution errors so one report can find the matching trace.
Do not log bearer tokens, authorization codes, cookies, full tool arguments, private result bodies, or MCP App DOM snapshots. Hash or map user and tenant identifiers when raw IDs are not needed for operations.
Alert on symptoms users feel: sustained connection failures, rising OAuth errors, slow tools, queue backlog, failed resource reads, and rollback-triggering release regressions. A healthy /health response does not prove that OAuth discovery or a real tool works.
Production Checklist
Network and Protocol
- The canonical
/mcpURL uses HTTPS and has only globally routable DNS answers. - No cross-host redirect sits in front of
/mcp. - WAF and rate-limit rules allow Anthropic traffic to MCP and OAuth routes.
- The SDK and proxy preserve and validate negotiated MCP headers.
- Streaming is unbuffered when the handler returns SSE.
- Modern, compatible legacy, and unsupported-version behavior are tested.
Auth and Data
- The first unauthenticated request returns
401withresource_metadata. - Protected Resource Metadata matches the full connector URL.
- DCR, CIMD, or configured credentials work from a clean connection.
- PKCE S256, token audience, scope, refresh, revocation, user, and tenant checks pass.
- Secrets live in the platform secret manager.
- Logs and staging data do not expose private records.
Tools and MCP Apps
- Tool names, descriptions, schemas, annotations, and results agree.
- Tool execution and upstream timeouts are bounded.
- Large results are paginated or fetched on demand.
- UI resources use versioned URIs and a narrow CSP.
- The deployed UI handles loading, empty, error, cancellation, and narrow widths.
- The previous full artifact is available for rollback.
Release and Operations
- CI runs protocol, E2E, visual, build, and security checks.
- The immutable staging artifact is promoted without rebuilding.
- Post-deploy smoke tests cover discovery, auth, one tool, one UI, and one error.
- Dashboards and alerts cover real protocol and tool boundaries.
- Rollback steps and owners are documented and tested.
A production Claude Connector is a public, versioned API used by an AI host. Choose a runtime that fits the work, support the protocol behavior your clients negotiate, keep user authorization explicit, and deploy each server and MCP App resource set as one tested artifact. The sunpeak MCP App Inspector and testing framework let you exercise that artifact before Claude users do.
Get Started
npx sunpeak newFurther Reading
- Anthropic building guide - current Claude Connector limits and transport support
- Anthropic authentication guide - DCR, CIMD, callback URLs, and refresh
- Anthropic troubleshooting guide - public DNS, WAF, redirects, and OAuth
- MCP TypeScript SDK protocol versions - modern and legacy deployment behavior
- MCP 2026-07-28 release candidate - stateless transport and trace context
- Cloudflare remote MCP server guide - current stateless Worker path
- Vercel MCP documentation - deploying and connecting remote servers
- sunpeak deployment guide - builds, handlers, scaling, logs, and health checks
- Claude Connector deployment debugging - production failure workflow
- Claude Connector OAuth authentication - discovery and token lifecycle
- Claude Connector Directory submission - production review requirements
- How to deploy an MCP App - shared ChatGPT and Claude release workflow
- Testing Claude Connectors - local, CI, and real-host coverage
- MCP App observability - traces, support IDs, redaction, and alerts
Frequently Asked Questions
Where should I host my Claude Connector MCP server?
Choose based on execution and state. Cloudflare Workers or another edge runtime fits short stateless tools. Vercel fits teams already using its functions and deployment workflow. Railway, Render, Fly.io, a container platform, or a VPS fits long-running processes, native dependencies, background jobs, or legacy MCP sessions. Every option must expose a stable public HTTPS endpoint and preserve the headers and response behavior required by Streamable HTTP.
Does a production Claude Connector need a public HTTPS URL?
Yes. Hosted Claude surfaces reach remote MCP servers from Anthropic infrastructure, even when the user runs Claude Desktop. The hostname needs public DNS with at least one globally routable IPv4 A record, and every resolved address must be public. Private, loopback, link-local, carrier-grade NAT, split-horizon, and IPv6-only hosts are rejected before the request reaches your app.
Should a deployed Claude Connector be stateful or stateless?
Prefer stateless request handling for new serverless or horizontally scaled deployments. MCP 2026-07-28 removed protocol sessions, while 2025-era clients can still use initialize and may use Mcp-Session-Id. If your target hosts include both eras, use an SDK handler that serves modern requests and compatible stateless legacy requests, or keep a documented legacy lane with session affinity until those clients migrate.
What OAuth callback URL does a Claude Connector use?
Register https://claude.ai/api/mcp/auth_callback for hosted Claude surfaces, including Claude.ai, Desktop, mobile, and Cowork. Claude Code uses loopback redirects on localhost and 127.0.0.1 with an ephemeral port. Claude supports DCR, Client ID Metadata Documents, Anthropic-held credentials for approved directory connectors, and organization-supplied credentials for custom connectors.
How do I deploy a sunpeak Claude Connector?
Run pnpm build to compile self-contained MCP App resources, tool handlers, and the optional server entry into dist. For a long-lived Node server, run pnpm start and expose port 8000 behind HTTPS. For edge or function runtimes, mount createHandler from sunpeak/mcp with stateless: true. sunpeak 0.20.77 uses the 2025-era MCP wire protocol, so its stateless option removes in-memory transport sessions but does not enable the 2026-07-28 wire format.
How do I test a deployed Claude Connector before release?
Run unit, protocol, E2E, visual, and build checks locally, then point npx sunpeak inspect at the staged HTTPS /mcp endpoint. Test discovery, tool calls, OAuth challenges, UI resources, errors, and production configuration. Finish with one narrow custom-connector test in Claude using a staging account, then repeat the same smoke test after production deploy.
How do I deploy MCP App UI changes without breaking cached resources?
Publish tool metadata, resource metadata, HTML, JavaScript, CSS, and server handlers as one release. Use a new versioned ui:// resource URI when the bundle or bridge contract changes, keep the previous artifact available during rollback, and make new tool inputs optional when possible. sunpeak production builds generate cache-busting resource URIs for built resources.
What should I monitor for a production Claude Connector?
Monitor public reachability, protocol negotiation, OAuth discovery and refresh, tools/list and tools/call errors, per-tool latency, upstream failures, result size, MCP App resource reads, and process restarts. Propagate a request or W3C trace ID through the MCP request and downstream calls, but do not log access tokens, authorization codes, private tool input, or full tool output.