typescript-sdk/packages/middleware/fastify
Repository files (latest commit first)
Filename Latest commit message Latest commit date
github-actions[bot] cc4b41617c
Version Packages (#2555)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-28 00:52:57 +01:00
..
src Implement MCP 2026-07-28 (#2286) 2026-06-26 14:01:10 +01:00
test Implement MCP 2026-07-28 (#2286) 2026-06-26 14:01:10 +01:00
CHANGELOG.md Version Packages (#2555) 2026-07-28 00:52:57 +01:00
eslint.config.mjs v2: codemod iterations, canonical zod schema exports from sdk-shared (#2354) 2026-06-25 19:42:44 +01:00
package.json Version Packages (#2555) 2026-07-28 00:52:57 +01:00
README.md Adds Fastify Middleware for v2 (#1536) 2026-03-31 13:51:14 +00:00
tsconfig.json refactor: move the schema source modules into @modelcontextprotocol/core (#2477) 2026-07-13 17:19:58 +01:00
tsdown.config.ts feat(packaging): ship CommonJS builds alongside ESM for v2 packages (#2405) 2026-07-01 19:40:37 +03:00
typedoc.json Adds Fastify Middleware for v2 (#1536) 2026-03-31 13:51:14 +00:00
vitest.config.js Adds Fastify Middleware for v2 (#1536) 2026-03-31 13:51:14 +00:00

@modelcontextprotocol/fastify

Fastify adapters for the MCP TypeScript server SDK.

This package is a thin Fastify integration layer for @modelcontextprotocol/server.

It does not implement MCP itself. Instead, it helps you:

  • create a Fastify app with sensible defaults for MCP servers
  • add DNS rebinding protection via Host header validation (recommended for localhost servers)

Install

npm install @modelcontextprotocol/server @modelcontextprotocol/fastify fastify

# For MCP Streamable HTTP over Node.js (IncomingMessage/ServerResponse):
npm install @modelcontextprotocol/node

Exports

  • createMcpFastifyApp(options?)
  • hostHeaderValidation(allowedHostnames)
  • localhostHostValidation()

Usage

Create a Fastify app (localhost DNS rebinding protection by default)

import { createMcpFastifyApp } from '@modelcontextprotocol/fastify';

const app = createMcpFastifyApp(); // default host is 127.0.0.1; protection enabled

Streamable HTTP endpoint (Fastify)

import { createMcpFastifyApp } from '@modelcontextprotocol/fastify';
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
import { McpServer } from '@modelcontextprotocol/server';

const app = createMcpFastifyApp();
const mcpServer = new McpServer({ name: 'my-server', version: '1.0.0' });

app.post('/mcp', async (request, reply) => {
    // Stateless example: create a transport per request.
    // For stateful mode (sessions), keep a transport instance around and reuse it.
    const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
    await mcpServer.connect(transport);

    // Clean up when the client closes the connection (e.g. during SSE streaming).
    reply.raw.on('close', () => {
        transport.close();
    });

    await transport.handleRequest(request.raw, reply.raw, request.body);
});

If you create a new McpServer per request in stateless mode, also call mcpServer.close() in the close handler. To reject non-POST requests with 405 Method Not Allowed, add routes for GET and DELETE that send a JSON-RPC error response.

Host header validation (DNS rebinding protection)

import { hostHeaderValidation } from '@modelcontextprotocol/fastify';

app.addHook('onRequest', hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']));