ModelFetch

Middleware

Add authentication, logging, and other cross-cutting concerns to your MCP servers

ModelFetch provides middleware support built on top of Hono's middleware system, allowing you to add authentication, logging, rate limiting, and other cross-cutting concerns to your MCP servers.

Basic Usage

Using Middleware Array

The simplest way to add middleware is using the middleware array in your config:

import handle from "@modelfetch/node";
import { bearerAuth } from "hono/bearer-auth";
import { logger } from "hono/logger";

handle({
  server: mcpServer,
  middleware: [logger(), bearerAuth({ token: "secret-token" })],
});

Using Pre/Post Hooks

For more control, use the pre and post hooks to configure the Hono app:

const mcpPath = "/mcp";

handle({
  server: mcpServer,
  path: mcpPath,
  pre: (app) => {
    // Configure middleware before MCP routes
    app.use("*", logger());
    app.use(`${mcpPath}/*`, bearerAuth({ token: "secret" }));
    // Add error handling
    app.onError((err, c) => {
      console.error("Error:", err);
      return c.json({ error: "Internal Server Error" }, 500);
    });
  },
  post: (app) => {
    // Add additional routes after MCP routes
    app.get("/health", (c) => c.json({ status: "ok" }));
    app.get("/", (c) => c.text("MCP Server"));
  },
});

Common Patterns

Authentication

import { createMiddleware } from "hono/factory";

const apiKeyAuth = createMiddleware(async (c, next) => {
  const apiKey = c.req.header("X-API-Key");
  if (!apiKey || apiKey !== process.env.API_KEY) {
    return c.json({ error: "Invalid API key" }, 401);
  }
  await next();
});

handle({
  server: mcpServer,
  middleware: [apiKeyAuth],
});

Request Logging

import { createMiddleware } from "hono/factory";

const requestLogger = createMiddleware(async (c, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${c.req.method} ${c.req.path} - ${c.res.status} ${ms}ms`);
});

handle({
  server: mcpServer,
  middleware: [requestLogger],
});

CORS Configuration

import { cors } from "hono/cors";

const mcpPath = "/mcp";

handle({
  server: mcpServer,
  path: mcpPath,
  pre: (app) => {
    app.use(
      `${mcpPath}/*`,
      cors({
        origin: ["https://app.example.com"],
        allowHeaders: ["X-API-Key", "Content-Type"],
        allowMethods: ["POST", "GET"],
        credentials: true,
      }),
    );
  },
});

Rate Limiting

import { rateLimiter } from "hono/rate-limiter";

const mcpPath = "/mcp";

handle({
  server: mcpServer,
  path: mcpPath,
  pre: (app) => {
    app.use(
      `${mcpPath}/*`,
      rateLimiter({
        windowMs: 15 * 60 * 1000, // 15 minutes
        limit: 100, // 100 requests per window
        keyGenerator: (c) => c.req.header("X-API-Key") || c.ip,
      }),
    );
  },
});