All posts

How Claude Connectors Work: Architecture, Lifecycle, and Limits (June 2026)

Abe Wheeler
Claude Connectors Claude Connector Framework Claude Connector Testing Claude Apps MCP Apps MCP App Framework
How Claude Connectors work under the hood: architecture, lifecycle, and limits.

How Claude Connectors work under the hood: architecture, lifecycle, and limits.

TL;DR: Claude Connectors are MCP integrations that let Claude call tools, read resources, and render interactive MCP Apps from remote servers. The core loop is discovery, tool selection, JSON-RPC over Streamable HTTP, tool execution, and result handling. The June 2026 details that matter most are the split between hosted Claude limits and Claude Code limits, the newer MCP Apps metadata shape (_meta.ui.resourceUri), richer tool annotations, OAuth callback and token refresh behavior, and the fact that custom connectors are reached from Anthropic’s cloud, not from the user’s laptop.

If you already know what Claude Connectors are, this post explains what happens under the hood. That matters when a connector works locally but fails in Claude, when a tool is called with the wrong arguments, when an interactive view does not render, or when a production connector times out after working in a small demo.

Claude’s connector system now covers more than “Claude can call my MCP server.” The current Claude connector overview describes connectors as a way to connect Claude to tools, data, and UI through MCP. That means a production connector needs to be designed as a protocol server, an auth boundary, a tool contract, and sometimes an MCP App host surface.

What Changed Since the First Version of This Post

The connector ecosystem moved quickly after early remote MCP support. A few details are worth updating before we talk about the lifecycle:

  • The current MCP spec uses Streamable HTTP as the remote transport. Legacy HTTP+SSE is a compatibility path, not the target for new work.
  • Claude’s current custom connector docs list separate hosted Claude and Claude Code limits. Hosted Claude surfaces document about 150,000 characters for tool results and a 300 second timeout. Claude Code documents a 25,000 token tool result size, configurable through MAX_MCP_OUTPUT_TOKENS, and a configurable MCP_TOOL_TIMEOUT.
  • MCP Apps are now the standard way to describe interactive UI. A tool points to a UI resource with _meta.ui.resourceUri, and hosts render that resource in a sandboxed iframe.
  • Tool annotations now deserve more than readOnlyHint and destructiveHint. idempotentHint and openWorldHint affect how hosts explain and approve actions.
  • Custom connectors are reached from Anthropic’s cloud infrastructure. A server on a private network, behind a VPN, or blocked by a firewall will fail unless you expose or allowlist it.

Those details change how you should design connector tools, not just how you deploy them.

The Architecture

A Claude Connector has three layers.

First, there is your MCP server. It exposes capabilities through the Model Context Protocol: tools, resources, prompts, and optional MCP Apps metadata. In practice, most connector work starts with tools, because tools are what Claude calls to search, fetch, create, update, or trigger work.

Second, there is the connector configuration in Claude. For a custom connector, a user or organization adds your remote MCP server URL in Claude’s connector settings. Claude then connects to that server from Anthropic’s infrastructure. For Team and Enterprise plans, an owner has to add the connector for the organization before individual users connect their accounts.

Third, there is the optional UI layer. A connector can stay text-only, but it can also expose MCP Apps. MCP Apps use web UI resources, usually bundled HTML, JavaScript, and CSS, rendered by the host. In Claude, that lets a connector show charts, dashboards, boards, forms, previews, or review surfaces directly in the conversation.

That architecture is why connector bugs often sit at boundaries. A tool schema issue looks like a model problem. An OAuth callback issue looks like a connector install problem. A CSP issue looks like a React rendering problem. You need to debug each layer separately.

The Request Lifecycle

Here is the normal request lifecycle for a remote Claude Connector:

  1. Claude initializes the connection. It sends an MCP initialize request, negotiates the protocol version, and reads the server capabilities. Your server replies with supported capabilities such as tools, resources, or prompts.

  2. Claude discovers tools and resources. It can request tools/list and resources/list so it knows what your connector can do. Tool names, titles, descriptions, input schemas, output schemas, annotations, and _meta fields all influence how the host presents and uses the connector.

  3. The user sends a message. Claude decides whether any enabled connector tools match the user’s intent. A good tool description narrows this decision. A vague tool description makes Claude guess.

  4. Claude prepares a tool call. It builds arguments that match your inputSchema, then sends a JSON-RPC tools/call request to your server over Streamable HTTP.

  5. Your handler validates and executes. The handler should validate arguments, authorize the user, call your database or API, enforce timeouts, and shape the result for the model and, if needed, the UI.

  6. Your server returns a tool result. The result includes content, optional structuredContent, optional _meta, and optional isError.

  7. Claude uses the result. For text or image content, Claude can summarize, cite, or reason over the data. For structured data with an MCP App resource, Claude can render an interactive UI and pass the data into the app.

  8. The conversation continues. The user might ask a follow-up, click inside an MCP App, or approve a write action. The connector may receive more tools/call requests as the task continues.

The whole flow is simple when the tool is read-only and the data is small. It gets harder when you add OAuth, large result sets, app-only UI actions, write permissions, and host differences.

Transport: Streamable HTTP

Remote connectors should use Streamable HTTP. The transport is still JSON-RPC, but the server is reached over a single HTTP endpoint, usually something like:

https://api.example.com/mcp

The MCP transport spec defines two standard transports, stdio and Streamable HTTP. For remote connectors, Streamable HTTP is the one that matters.

Your endpoint receives POST requests for JSON-RPC messages. It can also support GET for an SSE stream if the server needs server-to-client notifications. If you do not support an SSE stream, returning 405 Method Not Allowed for GET is valid.

The most common production mistakes are ordinary HTTP mistakes:

  • The server URL is not publicly reachable from Anthropic’s infrastructure.
  • The endpoint requires headers Claude cannot provide.
  • The server accepts application/json in development but rejects a real request shape in production.
  • A proxy buffers or strips streaming responses.
  • A platform timeout is shorter than Claude’s tool timeout.

You can keep old HTTP+SSE endpoints if you need older clients, but new Claude Connector work should target Streamable HTTP. If you still have an SSE connector, use the Streamable HTTP migration guide.

Discovery: Capabilities, Tools, and Resources

Discovery is where Claude learns what your connector can do. The server’s initialize response advertises capabilities. A tools/list response provides tool definitions.

A tool definition should include:

  • name, the stable programmatic name.
  • title, the human-readable display name.
  • description, the model-facing description of when and how to use the tool.
  • inputSchema, the JSON Schema for arguments.
  • outputSchema, when you return structuredContent.
  • annotations, such as readOnlyHint, destructiveHint, idempotentHint, and openWorldHint.
  • _meta, for host and app metadata such as UI resource links.

Tool descriptions should be specific enough that Claude knows when not to call the tool. “Search tickets by status, owner, and created date” is better than “Search data.” If two tools overlap, make the distinction obvious in the descriptions and schemas.

For MCP Apps, the current standard pattern is to attach UI metadata to the tool:

{
  name: 'show_ticket_board',
  title: 'Show ticket board',
  description: 'Render a board of support tickets grouped by status.',
  inputSchema: {
    type: 'object',
    properties: {
      teamId: { type: 'string' },
    },
    required: ['teamId'],
  },
  outputSchema: {
    type: 'object',
    properties: {
      tickets: { type: 'array' },
    },
    required: ['tickets'],
  },
  annotations: {
    readOnlyHint: true,
  },
  _meta: {
    ui: {
      resourceUri: 'ui://tickets/board.html',
      visibility: ['model', 'app'],
    },
  },
}

The older ChatGPT-specific _meta["openai/outputTemplate"] key still appears in some Apps SDK examples as a compatibility alias, but _meta.ui.resourceUri is the cross-host shape to use first.

Authentication: OAuth and Identity

Not every connector needs authentication. A connector that serves public data can be authless. A connector that reads or writes user-specific data needs OAuth.

For hosted Claude surfaces, register this redirect URI:

https://claude.ai/api/mcp/auth_callback

Claude Code is different because it is a native client. It uses a loopback redirect on localhost with an ephemeral port. If your connector supports both hosted Claude and Claude Code, handle both redirect patterns in your authorization server.

Claude’s connector auth docs also call out token refresh behavior. Claude can refresh reactively after a 401 response and proactively near expiry. Your token endpoint should accept application/x-www-form-urlencoded, return standard OAuth error codes such as invalid_grant, and rotate refresh tokens for public-client connections when required by your auth model.

OAuth does not replace authorization inside your server. The connector still needs to check:

  • Which user owns the OAuth token.
  • Which tenant, workspace, repo, project, or account the user can access.
  • Whether a tool is read-only or write-capable.
  • Whether a write action needs a local approval step in your own system.

Claude can help explain and confirm actions, but your server is the enforcement point.

Tool Results: What the Model Sees and What the UI Gets

The MCP CallToolResult shape is the contract between your server and the host:

return {
  content: [
    {
      type: 'text',
      text: 'Found 12 open tickets for the billing team.',
    },
  ],
  structuredContent: {
    tickets: [
      { id: 'TK-1234', title: 'Invoice failed to load', status: 'open' },
      { id: 'TK-1235', title: 'Card declined incorrectly', status: 'open' },
    ],
  },
  _meta: {
    internalRequestId: 'req_01JZ9...',
  },
};

Use content for unstructured output the model can read. Use structuredContent for JSON that should match your outputSchema. Use _meta for data the component needs but the model should not see. OpenAI’s Apps SDK reference makes the same distinction for ChatGPT Apps: structuredContent and content appear in the transcript, while _meta is delivered only to the component.

That split is useful for privacy and token control. For example, a ticket board can show full rows in the UI while the model only receives a short summary and IDs. Keep secrets, raw access tokens, internal trace payloads, and oversized records out of content and structuredContent.

For tool-level failures, return a tool result with isError: true when the model can recover:

return {
  isError: true,
  content: [
    {
      type: 'text',
      text: 'The status must be one of open, pending, or closed.',
    },
  ],
};

Reserve protocol-level JSON-RPC errors for protocol failures, missing tools, unsupported methods, malformed requests, and other cases where the host or server cannot complete the MCP operation.

Interactive UI with MCP Apps

Claude Connectors can render interactive UI through MCP Apps. The MCP Apps overview describes the pattern as two MCP primitives working together: a tool declares a UI resource, and a resource returns an interactive HTML interface.

The flow looks like this:

  1. Your tool definition includes _meta.ui.resourceUri.
  2. The host can preload or fetch that ui:// resource.
  3. The resource returns bundled HTML, JavaScript, and CSS.
  4. The host renders it inside a sandboxed iframe.
  5. The app talks to the host over a JSON-RPC protocol on postMessage.
  6. The app can receive tool data, request tool calls, update model context, and respond to host context such as theme, locale, display mode, and container size.

This is different from returning a normal web link. The UI stays in the conversation, it is isolated by the host, and the app can call MCP tools through the host instead of exposing a separate browser API.

For connector authors, the important design point is tool visibility. Some tools should be visible to both the model and the app. Some should be app-only:

_meta: {
  ui: {
    resourceUri: 'ui://tickets/board.html',
    visibility: ['app'],
  },
}

App-only tools are useful for pagination, refresh buttons, draft form state, and UI actions that would clutter the model’s tool list. Keep model-facing tools focused on user intent. Keep app-only tools focused on UI mechanics.

Tool Annotations and Permission UX

Tool annotations are hints that help hosts explain and gate tool calls. They are not a security boundary.

Use the four core annotations deliberately:

  • readOnlyHint: true for tools that only read or compute data.
  • destructiveHint: true for tools that may delete or overwrite data.
  • idempotentHint: true for tools where repeating the same call has no additional effect.
  • openWorldHint: true for tools that contact outside systems, publish content, send messages, or otherwise affect the world outside the user’s local context.

Examples:

{
  name: 'list_tickets',
  annotations: {
    readOnlyHint: true,
  },
}
{
  name: 'delete_ticket',
  annotations: {
    destructiveHint: true,
    openWorldHint: true,
  },
}

The host may use these hints to decide how much confirmation UI to show. Your server still needs to check the OAuth token, user permissions, workspace rules, and tool arguments. Never assume an annotation will stop a bad call.

Limits You Need to Design Around

The old version of this post stated a single 25,000 token limit. That is too broad now.

Claude’s current custom connector docs list these constraints:

  • Claude.ai and Claude Desktop max tool result size: about 150,000 characters.
  • Claude.ai and Claude Desktop timeout: 300 seconds, or 5 minutes.
  • Claude Code max tool result size: 25,000 tokens, configurable with MAX_MCP_OUTPUT_TOKENS.
  • Claude Code timeout: configurable with MCP_TOOL_TIMEOUT.

Design to the strictest host you care about. If your connector should work across Claude.ai, Claude Desktop, Claude Code, and other MCP hosts, do not treat the highest limit as your real budget.

Practical patterns:

  • Return summaries and IDs from search tools, then fetch full records with detail tools.
  • Paginate every collection tool, even if the first version only returns a small dataset.
  • Add limit, cursor, sort, and filter fields to schemas before users need them.
  • Keep UI-only hydration data in _meta only when the host supports that path.
  • Add upstream HTTP timeouts shorter than the host’s timeout.
  • Cache repeated reads when the underlying data does not need to be live.
  • Make long-running work asynchronous: one tool starts a job, another checks status.

Also implement your own rate limits. Claude does not publish a single connector call rate limit you can design around, and a user can trigger many tool calls in one conversation. Rate limit per user, tenant, connector installation, and upstream service where needed. Return clear recoverable errors so Claude can tell the user what to do next.

Network and Deployment Requirements

Custom connectors are remote MCP servers. Hosted Claude reaches them from Anthropic’s cloud infrastructure, not from the user’s local machine. This is true even when the user is running Claude Desktop or Cowork locally.

That means:

  • localhost does not work for a hosted custom connector.
  • A private corporate network does not work unless you expose or allowlist access.
  • A VPN-only endpoint will fail for most users.
  • Your server needs TLS, stable routing, and production logging.
  • If you use OAuth, callback URLs must match the Claude surface using the connector.

During development, use a tunnel only for real-host smoke tests. For day-to-day work, use a local inspector so you are not waiting on tunnels, host caches, real account state, or production OAuth setup.

Testing the Full Lifecycle Locally

You should test a Claude Connector at four layers:

  1. Protocol tests. Validate initialize, tools/list, tools/call, resource reads, errors, and auth challenges.

  2. Tool contract tests. Call each tool with valid, invalid, empty, large, and unauthorized inputs. Assert both success and isError results.

  3. UI runtime tests. Render MCP Apps in Claude-like and ChatGPT-like host contexts. Test theme, display mode, mobile width, app-only tools, and missing data.

  4. Real-host smoke tests. Add the connector to Claude and run a short checklist before release.

sunpeak helps with the middle two layers and can connect to any MCP server. The sunpeak inspector replicates ChatGPT and Claude host runtimes locally, lets you toggle host, theme, viewport, display mode, tool input, tool result, and simulations, and uses the same inspector runtime for Playwright E2E tests.

For an existing MCP server:

npx sunpeak inspect --server http://localhost:8000/mcp

For a sunpeak project:

pnpm dev

Use simulation fixtures for repeatable states: empty search results, large lists, OAuth failures, rate limits, destructive action confirmation paths, stale resources, and malformed tool output. Those are the states that break in production because they rarely happen during a happy-path demo.

Production Checklist

Before shipping a Claude Connector, check the full system:

  • The server supports Streamable HTTP at one stable MCP endpoint.
  • The endpoint is reachable from the public internet or from the approved Anthropic IP ranges for your setup.
  • initialize, tools/list, tools/call, and any resource reads pass MCP inspector checks.
  • Every tool has a narrow description, input schema, output schema when using structuredContent, and correct annotations.
  • Every write-capable tool validates user permissions on the server.
  • OAuth redirect URLs cover hosted Claude and Claude Code if you support both.
  • Token refresh handles standard OAuth errors and form-encoded token requests.
  • Search and list tools paginate.
  • Tool results stay below the strictest host limit you support.
  • Long-running work has app-level timeouts, upstream request timeouts, and async job fallback.
  • MCP Apps declare _meta.ui.resourceUri, CSP domains, and tool visibility deliberately.
  • App-only tools are hidden from the model.
  • Error results use isError: true when the model can recover.
  • Logs include connector installation, user or tenant ID, request ID, tool name, latency, auth outcome, and result size.
  • Local inspector tests and at least one real Claude smoke test pass before release.

The connector itself is only one part of the product surface. The model sees descriptions and schemas. The host sees metadata and auth. The user sees confirmation prompts, UI, and errors. A good connector is designed for all of them.

Get Started

Documentation →
npx sunpeak new

Further Reading

Frequently Asked Questions

How do Claude Connectors work?

Claude Connectors are MCP integrations that let Claude call tools, read resources, and render MCP Apps from a remote MCP server. Claude discovers your server capabilities, decides when a tool fits a user request, sends a JSON-RPC tools/call request over Streamable HTTP, and uses the result in the conversation. Interactive connectors can also surface MCP Apps, which are sandboxed HTML interfaces rendered directly in Claude.

What transport do Claude Connectors use?

Claude Connectors use remote MCP over Streamable HTTP. The current MCP transport model uses a single MCP endpoint, often /mcp, that accepts POST requests for JSON-RPC messages and can optionally accept GET requests for an SSE stream. Legacy HTTP+SSE is still supported in some clients for compatibility, but Streamable HTTP is the transport to build against.

What are the current Claude Connector response limits?

Claude.ai and Claude Desktop document a hosted tool result size of about 150,000 characters and a 300 second, or 5 minute, timeout. Claude Code documents a 25,000 token max tool result size, configurable with MAX_MCP_OUTPUT_TOKENS, and a configurable MCP_TOOL_TIMEOUT. Treat those as host-specific limits, not one universal MCP limit.

How does authentication work for Claude Connectors?

Claude Connectors support authless servers and OAuth-based servers. For hosted Claude surfaces, register https://claude.ai/api/mcp/auth_callback as the redirect URI. Claude stores connector credentials for hosted surfaces and refreshes tokens proactively near expiry or reactively after a 401 response. Claude Code uses a native loopback redirect flow instead of the hosted callback.

Can Claude Connectors render UI?

Yes. Claude supports MCP Apps, which let a connector surface interactive UI components directly in the conversation. A tool can point to a UI resource with _meta.ui.resourceUri, the host fetches the ui:// resource, and the HTML app runs in a sandboxed iframe with a controlled CSP and a postMessage bridge.

What fields matter most in a Claude Connector tool result?

The MCP CallToolResult includes content for unstructured text or media, structuredContent for JSON that should match the tool outputSchema when one is declared, _meta for component-only data that should not appear in the transcript, and isError for tool-level failures the model can see and recover from.

What tool annotations should a Claude Connector include?

Use readOnlyHint for tools that do not modify data, destructiveHint for tools that may delete or overwrite data, idempotentHint for calls that can repeat without extra effect, and openWorldHint for tools that contact outside systems or publish content. These are hints, so your server still needs real authorization and validation.

How do I test a Claude Connector locally?

Use the official MCP inspector for protocol validation and a host-runtime inspector for UI behavior. sunpeak provides a local inspector that can connect to any MCP server with sunpeak inspect --server URL, toggle Claude and ChatGPT runtimes, load deterministic simulation fixtures, and run Playwright tests against the same inspector in CI.