Skip to main content

Middleware

Middleware allows you to intercept and process HTTP requests before they reach your tools.

HTTP Transport Only

Middleware only works with HTTP transports (streamable-http, sse). It does not work with stdio transport (the default).

For stdio transport (used by Claude Desktop), use server hooks instead.

Creating Middleware

import { Middleware, MiddlewareContext, NextFunction } from '@mcpkit-dev/core';

const loggingMiddleware: Middleware = async (ctx, next) => {
const start = Date.now();
console.log(`${ctx.method} ${ctx.path}`);

await next();

console.log(`${ctx.method} ${ctx.path} (${Date.now() - start}ms)`);
};

Using Middleware

@MCPServer({
name: 'my-server',
version: '1.0.0',
middleware: [loggingMiddleware, authMiddleware],
})
class MyServer {}

Middleware Context

interface MiddlewareContext {
request: IncomingMessage;
response: ServerResponse;
sessionId?: string;
url: URL;
method: string;
path: string;
body?: unknown;
state: Map<string, unknown>;
get<T>(key: string): T | undefined;
set<T>(key: string, value: T): void;
}

Named Middleware

import { NamedMiddleware } from '@mcpkit-dev/core';

const corsMiddleware: NamedMiddleware = {
name: 'cors',
handler: async (ctx, next) => {
ctx.response.setHeader('Access-Control-Allow-Origin', '*');
await next();
},
options: {
paths: ['/api/*'],
order: 1,
},
};

Middleware Chain Enhancements

import {
conditional,
withTimeout,
withRetry,
withErrorHandler,
} from '@mcpkit-dev/core';

// Conditional execution
const adminOnly = conditional(authMiddleware, {
when: (ctx) => ctx.path.startsWith('/admin'),
});

// With timeout
const withTimeoutMiddleware = withTimeout(slowMiddleware, {
ms: 5000,
onTimeout: () => console.log('Timed out'),
});

// With retry
const withRetryMiddleware = withRetry(unreliableMiddleware, {
attempts: 3,
delay: 1000,
});

// With error handling
const safeMiddleware = withErrorHandler(riskyMiddleware, {
onError: (error, ctx) => {
console.error('Middleware error:', error);
ctx.response.statusCode = 500;
},
});