Multiple MCP Routes

Hi,

I have a nextjs app and under /mcp there is this file:

import { createMcpHandler } from "mcp-handler";
import axios from "axios";
import { z } from "zod";

const handler = createMcpHandler(
  async (server) => {
    server.tool(
      "example",
      "example-tool",
      {
        key: z.string(),
      },
      async (args, context) => {
        const authHeader = context?.requestInfo?.headers["authorization"];
        console.log(authHeader);

        try {
          const url = `https://exampleapi.com/`;

          const res = await axios.get(url);

          switch (res.status) {
            case 400:
              throw new Error("Missing");
            case 404:
              throw new Error("Not Valid");
            case 423:
              throw new Error("Product Blocked");
            case 402:
              throw new Error("Payment Required");
            case 500:
              throw new Error("Internal Server Error");
          }

          return {
            content: [
              {
                type: "text",
                text: res.data,
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: error,
              },
            ],
          };
        }
      },
    );
  },
  {
    capabilities: {
      tools: {
        example: {
          description: "Get example data!",
        },
      },
    },
  },
  {
    basePath: "",
    verboseLogs: false,
    maxDuration: 60,
    disableSse: true,
      onEvent: async (event) => {
          console.log(event);
      }
  },
);

export { handler as GET, handler as POST, handler as DELETE };

when i am now doing a second one under /internal-api/mcp with the same file i get a 404 returned. How can I have multiple mcps in one project?

This is my proxy.ts

import createMiddleware from "next-intl/middleware";

export default createMiddleware({
  locales: ["en", "de"],
  localeDetection: true,
  localePrefix: "never",
  defaultLocale: "en",
});

export const config = {
  matcher: ["/((?!api|_next|internal-api|mcp|.*\\..*).*)"],
};

Hey, Nico!

Can you check the following?

File Structure

  • Is your file structure exactly as follows?

    app/
      ├── mcp/
      │   └── route.ts
      └── internal-api/
          └── mcp/
              └── route.ts
    
  • Is the /internal-api/mcp/route.ts file located exactly where you think it is?


Middleware Matcher

  • Does your middleware matcher correctly exclude the intended directories?

    matcher: ["/((?!api|_next|internal-api|mcp|.*\\..*).*)"]
    
  • Could the matcher still be interfering with the route in unexpected ways?


Route Handler Export

  • In /internal-api/mcp/route.ts, are you exporting your handlers like this?

    export { handler as GET, handler as POST, handler as DELETE };
    
  • Are the imports and export names correct and consistent?


Debugging Steps

  • Does the route work when you visit it directly in the browser?

  • Is the file definitely located at app/internal-api/mcp/route.ts?

  • Does a minimal test handler work?

    export async function GET() {
      return Response.json({ message: "Internal MCP route working" });
    }
    
  • Do you see any relevant console or server logs when you hit the route?


BasePath Configuration

  • Are you using basePath: "" in both handlers?
  • Could the shared or empty basePath be causing conflicts?
  • Does the issue go away if you remove or change the basePath?

Hi,

Seems like the baseUrl was the Problem!

Fixxed it now!