> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcphub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP HTTP Endpoints

> Connect to your MCP servers using the unified HTTP endpoint.

MCPHub provides a unified streamable HTTP interface for all your MCP servers. This allows you to send requests to any configured MCP server and receive responses in real-time.

**Security note**: MCP endpoints require authentication by default to avoid exposing connected tools and data. If you intentionally want public MCP access, disable **Enable Bearer Authentication** in the Keys settings. **Skip Authentication** only affects dashboard login. By default MCPHub reads Bearer credentials from the `Authorization` header, but this is configurable via **Bearer Auth Header Name** if upstream passthrough headers would otherwise conflict.

### Unified Endpoint

This endpoint provides access to all enabled MCP servers.

* **Endpoint**: `http://localhost:3000/mcp`
* **Method**: `POST`

### Group-Specific Endpoint

For targeted access to specific server groups, use the group-based HTTP endpoint.

* **Endpoint**: `http://localhost:3000/mcp/{group}`
* **Method**: `POST`
* **Parameters**:
  * `{group}`: The ID or name of the group.

### Server-Specific Endpoint

For direct access to individual servers, use the server-specific HTTP endpoint.

* **Endpoint**: `http://localhost:3000/mcp/{server}`
* **Method**: `POST`
* **Parameters**:
  * `{server}`: The name of the server.

> **Note**: If a server name and group name are the same, the group will take precedence.

## Protocol compatibility

The same `/mcp` URL serves legacy `2025-11-25` and modern `2026-07-28`
clients. Group and server URLs use the same protocol handling. Changing the URL
from `/sse` to `/mcp` does not by itself upgrade the client's protocol revision.

| Behavior | Legacy HTTP+SSE (`/sse`) | HTTP `2025-11-25` (`/mcp`) | HTTP `2026-07-28` (`/mcp`) |
| - | - | - | - |
| Status | Deprecated; still supported | Supported for compatibility | Supported; migration work continues |
| Startup | `initialize` over the SSE transport | `initialize` over Streamable HTTP | No `initialize` handshake; SDK discovery |
| Downstream session | SSE connection and session message endpoint | `Mcp-Session-Id` | No downstream transport session |
| Routing headers | Legacy transport behavior | Legacy transport behavior | `Mcp-Method`; `Mcp-Name` for named calls and resource reads |
| Stateful tools | Existing session lifecycle | Existing session lifecycle | Bearer auth plus explicit state ID or OpenAI conversation metadata |
| MCP Apps capabilities | Declared during initialization | Declared during initialization | Declared in each request's `params._meta` |
| List cache hints | Existing legacy response shape | Existing legacy response shape | Remaining upstream TTL, capped at 5 seconds; `private`; otherwise zero |
| Resource-read cache hints | Existing upstream hints preserved | Existing upstream hints preserved | Valid remaining upstream TTL, restricted to `private`; otherwise zero |

MCP Apps passthrough also depends on the route and visible upstream servers;
`$smart` routes remain ordinary MCP routes. See [MCP Apps](/features/mcp-apps).
Upstream MCP connections currently retain legacy protocol negotiation; a modern
downstream request does not upgrade an upstream server.

## Migrating a client

1. Replace the legacy SSE client transport with an HTTP transport, and change
   `/sse` to `/mcp`, preserving any group, server or user route scope. Keep the
   same bearer credentials. A legacy HTTP client can make this transport change
   while retaining its initialization and session lifecycle.
2. To adopt `2026-07-28`, use a client that supports modern HTTP discovery and
   the per-request metadata envelope. The SDK v2 HTTP client supplies the
   protocol and routing headers. A custom client must send the normal JSON-RPC
   body with `params._meta["io.modelcontextprotocol/protocolVersion"]` set to
   `2026-07-28` and declare client capabilities under
   `params._meta["io.modelcontextprotocol/clientCapabilities"]`. Send matching
   `MCP-Protocol-Version` and `Mcp-Method` headers; `tools/call` and `prompts/get`
   require `Mcp-Name` matching `params.name`, and `resources/read` requires it
   matching `params.uri`. Use names returned by that route's list response.
3. For `perSessionClient` or OpenAPI `cookieSession` tools, create a UUID v4 for
   each independent workflow and send it as `X-MCPHub-State-Id` on tool calls.
   Authenticated OpenAI/ChatGPT tool calls that cannot set this extension may
   instead reuse their client-declared `_meta["openai/session"]` conversation
   hint when the explicit header is absent. MCPHub hashes that hint before use;
   it is correlation metadata, not authentication. An invalid explicit state
   header fails closed and never falls back. Stateless tools need neither value.
   Reuse is limited to the same bearer credential, user and route. State is
   process-local, expires after 30 idle minutes, and requires sticky routing
   across replicas. Restart, expiry or credential/route changes require
   rebuilding application state. See
   [explicit-state configuration](/configuration/mcp-settings#stateful-tools-over-mcp-2026-07-28).
4. Verify listing and calling tools with your actual permissions, then verify
   resource reads and MCP Apps if used. Modern Apps hosts must declare their UI
   capability on each request. Modern calls do not depend on `Mcp-Session-Id`
   or `enableSessionRebuild`; those remain legacy mechanisms.

## Cache behavior

Modern list results combine upstream discovery snapshots with live configuration,
permissions and per-request capabilities. Positive hints are private and bounded
by the shortest remaining upstream freshness and a maximum five-second projection
window. Discovery age is retained; repeated gateway lists do not renew it. Empty
upstream lists also participate in the bound. Unknown/invalid TTLs, partial pages,
failed or incomplete discovery, gateway-generated Smart Routing entries, built-in
prompts/resources and unknown hosted permission freshness use zero.

Every request rebuilds its projection. Configuration, membership, permission or
runtime changes detected during projection force zero. List refreshes revoke the
previous snapshot's freshness before awaiting a new envelope; failure, disconnect
or replacement cannot establish new freshness. Template lists use the actual
responses fetched for that request. No gateway response cache is added.

Clients may retain an already-issued list for at most five seconds after a local
configuration/permission change; server invalidation cannot retract client caches.
Keep caches separate by endpoint, authenticated identity and per-request
capabilities. A cached list never authorizes a call: MCPHub rechecks access on each
request. Use zero when an upstream supplies no trustworthy freshness.

Modern resource reads continue to bypass the SDK response cache, subtract handling
time from a valid upstream TTL and restrict sharing to the requesting authorization
context. Missing or invalid TTLs, built-in resources and gateway-generated read
errors use zero. Legacy response shapes and session behavior are unchanged.

## Legacy SSE deprecation plan

The public notice will accompany the next release that includes this plan.
The release notes must record the actual notice date **N** and the earliest
eligible removal date **N + 12 calendar months**. This page and the ADR do not
establish an earlier notice date. Until those release notes are published, the
notice date and removal date remain unannounced.

The intended removal release is the first major release on or after that date
that meets the readiness criteria below. If readiness is incomplete, postpone
removal and publish the revised target; do not shorten the notice window.
Publish the exact target release and date at least 90 days before removal,
remind users 30 days before removal, and include the migration instructions in
each announcement. Actual removal requires a separate reviewed change.

### Preserve route scope and authentication

Prefix every URL below with the deployment's configured base path, if any.
Group IDs remain preferable to names; retain the same route identifier and
bearer header name/value. Group names take precedence over server names.

| Existing SSE connection | Streamable HTTP replacement | SSE message endpoint being retired |
| - | - | - |
| `/sse` | `/mcp` | `/messages` |
| `/sse/{group}` | `/mcp/{group}` | `/messages` |
| `/sse/{server}` | `/mcp/{server}` | `/messages` |
| `/{user}/sse` | `/{user}/mcp` | `/{user}/messages` |
| `/{user}/sse/{group}` | `/{user}/mcp/{group}` | `/{user}/messages` |
| `/{user}/sse/{server}` | `/{user}/mcp/{server}` | `/{user}/messages` |

Smart Routing suffixes such as `$smart/{group}` are preserved as well. The SSE
client follows its advertised message URL and session query; do not translate
that message URL into a new HTTP endpoint. Replace the connection URL and let
the HTTP transport manage its requests.

First migrate the transport independently of the protocol revision. For example,
with the legacy TypeScript SDK (`@modelcontextprotocol/sdk` 1.29.0, the version
used by MCPHub's independent compatibility tests):

```typescript theme={null}
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const client = new Client({ name: 'my-client', version: '1.0.0' });
await client.connect(
  new StreamableHTTPClientTransport(new URL('https://hub.example.com/alice/mcp/my-group-id'), {
    requestInit: { headers: { Authorization: 'Bearer YOUR_EXISTING_KEY' } },
  }),
);
const tools = await client.listTools();
// Use the returned tool names; retain this client for the workflow.
await client.close();
```

This keeps the legacy initialization and `Mcp-Session-Id` lifecycle. Existing
stateful tools keep session isolation; no `X-MCPHub-State-Id` is required for
this transport-only migration. Modern discovery and explicit state are a
separate upgrade described above. Existing SSE session IDs cannot be carried
across transports: start a new HTTP workflow and repeat any login/tool setup.

### Readiness and removal boundaries

Before announcing the exact removal target, maintainers must record:

* The release containing the public notice and its actual date, plus proof that
  at least 12 calendar months will have elapsed at removal.
* Passing legacy SSE and Streamable HTTP compatibility suites throughout the
  window, including authenticated global, group, server and user routes,
  session continuation/rebuild and stateful-tool isolation.
* A migration checklist for each documented client integration: HTTP transport,
  preserved route/authentication, successful listing/calling, and resources,
  Apps or stateful workflows where used. Record tested client versions and
  unresolved blockers; there must be zero unresolved release-blocking migration
  defects. Operator confirmations may supplement this checklist; absence of
  telemetry is not evidence that nobody uses SSE.
* Published release notes and documentation in both languages, the 90-day and
  30-day reminders, and a support path for deployments that still use SSE.

The removal inventory is limited to the SSE GET routes, their POST message
routes, `handleSseConnection`, `handleSseMessage`, SSE transport construction,
and SSE-only tests/imports. Audit every caller before removing shared helpers.
Retain `/mcp` POST/GET/DELETE routes, legacy HTTP initialization, session maps
and cleanup, session creation/rebuild locks, bearer/group authorization,
`perSessionClient` isolation, OpenAPI cookie jars and modern explicit state.
The `server-legacy` package also supplies shared legacy HTTP/OAuth functionality;
SSE retirement alone is not grounds to remove the dependency.

The plan is tracked in [#1272](https://github.com/samanhappy/mcphub/issues/1272).
The notice release must open a separate removal task carrying the actual dates,
client checklist and inventory. Legacy `2025-11-25` Streamable HTTP remains
supported independently.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.