HttpMcpServer
MCP server over Streamable HTTP using Express. Each HTTP client gets its own
session. Extends BaseMcpServer. See
src/mcp/mcp-server.ts for the full signature.
constructor(serverInfo, observer?, sessionToolFactory?)
| Parameter | Type | Description |
|---|---|---|
serverInfo |
HttpServerInfo |
{ name: string; version: string; port: number } |
observer |
McpServerObserver? |
Optional observer notified about tool calls and resource reads |
sessionToolFactory |
SessionToolFactory? |
Optional factory producing session-scoped tool sets (see below) |
When a sessionToolFactory is provided, every new HTTP session gets its own
SessionToolSet from the factory in addition to the shared tool inventory.
This lets each session carry independent state (e.g. a dedicated workspace
root) without sharing mutable data across concurrent clients. The tool set's
dispose() hook is awaited when the session ends (DELETE or stop()), so
session-scoped resources are released reliably. Dispose errors are swallowed
so teardown never blocks.
start()
Binds Express to the configured port. Idempotent: subsequent calls are no-ops while the server is already listening.
stop()
Closes all active HTTP sessions (each transport is closed), clears the session map, then stops the Express listener and destroys all remaining connections, including idle keep-alive and open SSE sockets, so the process can shut down and the port is fully released. Idempotent; safe to call when not running.
Request routing (/mcp)
| Method | Session ID header | Action |
|---|---|---|
| DELETE | present | Disconnect that session |
| DELETE | missing | 404 |
| POST | present | Route to existing session |
| POST | missing | Initialize a new session, or answer a server/discover probe |
| GET | present | Route to existing session |
| GET | missing | 400 |
| Other | missing | 400 |
| Other | present | Route to existing session; the SDK rejects unsupported methods |
A session-less POST whose JSON-RPC method is server/discover is answered
with HTTP 200 + JSON-RPC -32601 (Method not found) without creating a
session. Modern clients probe with this method before the legacy initialize
handshake; answering -32601 lets them fall back cleanly instead of getting a
hard connect failure and wasting a session. All other session-less POSTs are
replayed byte-identically into the initialize path, so existing behaviour is
unchanged.
Lifecycle
constructor(info, observer?, sessionToolFactory?): initialises Express app and wires routesregisterTool(item): tools must be registered beforestart()(they are copied into each per-sessionMcpServerat creation time)start(): begins listening on the configured port- Client sends
POST /mcp(initialize) →handleCreateSessioncreates a transport, connects a freshMcpServer(viacreateFreshMcpServer()), registers the shared tools plus (when configured) the session tool set from the factory, stores the session, forwards the response - Subsequent requests include
Mcp-Session-Id→ routed viahandleExistingSession DELETE /mcp→handleDeleteremoves the session, disposes the session tool set (if any), then closes the sessionstop()→onStop()snapshots and clears all sessions, disposes each session tool set, closes each transport, then stops Express and destroys any lingering keep-alive/SSE connections
Lifecycle hooks
HttpMcpServer overrides hook() to return an
HttpServerHookBuilder, adding the HTTP session events on top of the base
events:
| Event | Fires when |
|---|---|
sessionCreated |
an initial POST /mcp yields a session id |
sessionDisposed |
a session is torn down via DELETE /mcp or during stop() |
See Hooks for usage.
Types
HttpServerInfo
Extends ServerInfo with the TCP port for Express to
bind to.
| Field | Type | Description |
|---|---|---|
name |
string |
Server name |
version |
string |
Server version |
port |
number |
TCP port for Express to bind to |
SessionToolFactory & SessionToolSet
Defined in src/mcp/session-tools.ts.
| Type | Shape |
|---|---|
SessionToolSet |
{ tools: (Tool \| ToolPackage)[]; dispose(): Promise<void> } |
SessionToolFactory |
{ create(): SessionToolSet } |
SessionToolSet.tools: the tool instances (or packages) registered for one session, in addition to the server's shared inventory.SessionToolSet.dispose(): called exactly once when the session is torn down; should release any session-scoped resources. Must not throw (errors are caught and logged by the server).SessionToolFactory.create(): invoked once per new session to produce a fresh, independent tool set.
See also: BaseMcpServer, StdioMcpServer,
Architecture,
Quickstart