MCP Server Development: Deploy on Vercel met Next.js voor SaaS

Als je de afgelopen maanden SaaS-producten bouwt, heb je waarschijnlijk gemerkt dat elke productmanager nu "AI-functies" wil. Begrijpelijk. Maar de echte vraag is niet of je AI moet toevoegen -- het is hoe je AI-modellen gestructureerde, veilige toegang geeft tot de gegevens en mogelijkheden van jouw applicatie. Dat is precies wat het Model Context Protocol (MCP) oplost, en het implementeren van MCP-servers op Vercel met Next.js is één van de meest praktische patronen geworden die ik heb gezien voor SaaS-teams die snel willen voortgang boeken zonder nieuwe infrastructuur op te zetten.

Ik heb de afgelopen maanden MCP-servers voor clients gebouwd -- sommige eenvoudige tool-serving setups, anderen met complexe multi-tenant auth-flows. Dit artikel behandelt alles wat ik heb geleerd over het bouwen, implementeren en schalen van MCP-servers op Vercel met Next.js.

MCP Server Development: Deploy on Vercel with Next.js for SaaS

Inhoudsopgave

Wat is MCP en waarom SaaS-teams dit moeten begrijpen

Het Model Context Protocol (MCP) is een open standaard -- oorspronkelijk ontwikkeld door Anthropic en nu wijd aanvaard -- die bepaalt hoe AI-modellen interageren met externe tools en gegevensbronnen. Beschouw het als een USB-C-poort voor AI: een gestandaardiseerde interface die elke AI-client kan gebruiken om verbinding te maken met elke MCP-compatibele server.

Voordat MCP bestond, zou je, als je Claude, GPT of een ander model met je SaaS-app wilde laten interageren, aangepaste integraties voor elke AI-provider moeten bouwen. Function calling met OpenAI zag er anders uit dan tool use met Anthropic. MCP verandert dat. Je bouwt één server, en elke MCP-compatibele client kan het gebruiken.

Voor SaaS-teams is dit belangrijk omdat:

  • Je gebruikers verwachten AI-integraties. Tegen midden-2026 rapporteert ongeveer 68% van de B2B SaaS-gebruikers dat zij AI-assistenten naast hun primaire tools gebruiken (Gartner, Q1 2026).
  • MCP wordt de standaard. Claude Desktop, Cursor, Windsurf, VS Code Copilot en tientallen andere clients ondersteunen MCP nu standaard.
  • Een MCP-server bouwen is goedkoper dan aangepaste integraties bouwen voor elke AI-provider.

MCP versus traditionele API-integraties

Aspect Traditionele API MCP-server
Clientcompatibiliteit Een-op-een per provider Elke MCP-compatibele client
Detectie Handmatig docs lezen Automatische tool/resource detectie
Auth-flow Custom per integratie Gestandaardiseerde OAuth 2.1 / API-sleutels
Onderhoudsbelasting Hoog (N integraties) Laag (1 server)
Real-time gegevens Polling of webhooks Server-sent events / streaming
Instellingstijd Dagen tot weken per client Uren voor de server, minuten per client

Architectuuroverzicht: MCP op Vercel

Hier is de architectuur waar ik op ben uitgekomen na het itereren over verschillende benaderingen:

┌─────────────────┐     ┌──────────────────────┐     ┌─────────────────┐
│  MCP Clients    │     │  Vercel (Next.js)    │     │  Je SaaS        │
│                 │     │                      │     │  Backend        │
│  - Claude       │────▶│  /api/mcp (HTTP+SSE) │────▶│  - Database     │
│  - Cursor       │     │  /api/mcp/sse        │     │  - APIs         │
│  - Custom Apps  │◀────│  /api/auth/[...mcp]  │     │  - Services     │
└─────────────────┘     └──────────────────────┘     └─────────────────┘

Het belangrijkste inzicht: je MCP-server vervangt je bestaande API niet. Het zit ervoor als een vertaallaag. De MCP-server stelt tools en resources beschikbaar die toewijzen aan je bestaande SaaS-functionaliteit, maar in een formaat dat AI-modellen kunnen detecteren en gebruiken.

Op Vercel wordt dit uitgevoerd als serverless functions. De nieuwste MCP-spec (v2025-12) ondersteunt HTTP met Server-Sent Events (SSE) als transport, wat goed werkt met Vercels streaming-ondersteuning in Next.js route handlers.

Waarom Next.js op Vercel?

Je zou een MCP-server kunnen bouwen met elk framework -- Express, Fastify, Hono, wat dan ook. Maar Next.js op Vercel geeft je echte voordelen voor SaaS:

  1. Je marketingsite, app en MCP-server leven in één repository. Minder infrastructuur om te beheren.
  2. Edge middleware handelt authenticatie af voordat requests je MCP-endpoints bereiken.
  3. Vercels streaming-ondersteuning werkt goed met SSE-gebaseerd MCP-transport.
  4. Automatische schaling -- je hoeft niet na te denken over servers.
  5. Als je al Next.js draait (en statistisch gezien waarschijnlijk wel), is er nul nieuwe infrastructuur.

We doen veel Next.js-development bij Social Animal, en dit patroon is één van onze meest aangevraagde architecturen geworden.

MCP Server Development: Deploy on Vercel with Next.js for SaaS - architecture

Je Next.js MCP-server instellen

Laten we dit bouwen. Ik ga ervan uit dat je Next.js 15+ hebt met de App Router.

Dependencies installeren

pnpm add @modelcontextprotocol/sdk zod
pnpm add -D @types/node

Het @modelcontextprotocol/sdk pakket (v1.12+ vanaf begin 2026) bevat alles wat je nodig hebt voor HTTP+SSE transport. Eerdere versies ondersteunden alleen stdio, wat niet werkt op serverless.

De MCP Route Handler maken

// app/api/mcp/route.ts
import { McpServer } from '@modelcontextprotocol/sdk/server';
import { httpTransport } from '@modelcontextprotocol/sdk/server/http';
import { z } from 'zod';

const server = new McpServer({
  name: 'your-saas-mcp',
  version: '1.0.0',
  description: 'MCP server for YourSaaS platform',
});

// Register tools (we'll flesh these out next)
server.tool(
  'get-projects',
  'List all projects for the authenticated user',
  {
    status: z.enum(['active', 'archived', 'all']).optional().default('active'),
    limit: z.number().min(1).max(100).optional().default(20),
  },
  async ({ status, limit }, context) => {
    // Your actual business logic here
    const projects = await fetchProjects(context.auth.userId, { status, limit });
    return {
      content: [
        {
          type: 'text',
          text: JSON.stringify(projects, null, 2),
        },
      ],
    };
  }
);

const handler = httpTransport(server, {
  sessionManagement: true,
  cors: {
    origin: '*', // Lock this down in production
  },
});

export const GET = handler;
export const POST = handler;
export const DELETE = handler;

SSE Endpoint voor streaming

Sommige MCP-clients geven voorkeur aan SSE-transport voor langdurige bewerkingen:

// app/api/mcp/sse/route.ts
import { sseTransport } from '@modelcontextprotocol/sdk/server/sse';
import { server } from '../mcp-server'; // Extract server config to shared module

export const GET = sseTransport(server, {
  // Vercel has a 30-second timeout on Hobby, 300s on Pro
  // For long-running tools, you'll need Pro plan minimum
  keepAliveInterval: 15000,
});

MCP-tools en resources implementeren

Dit is waar het echte werk gebeurt. MCP maakt onderscheid tussen tools (acties die de AI kan uitvoeren) en resources (gegevens die de AI kan lezen). Dit goed doen maakt het verschil tussen een MCP-server waar AI-clients van houden en één waarmee zij worstelen.

Goede tools ontwerpen

De grootste fout die ik zie: tools die te granulair of te breed zijn. Als je 50 kleine tools beschikbaar stelt, raken AI-modellen overweldigd. Als je 3 mega-tools stelt bloot die elk 20 parameters nemen, maken modellen fouten.

Mijn vuistregel: één tool per gebruikerintentie. Als een gebruiker zou zeggen "toon me mijn recente facturen," dat is één tool. Splits het niet op in list-invoices + filter-invoices + format-invoices.

// Good: clear intent, reasonable parameters
server.tool(
  'search-customers',
  'Search for customers by name, email, or account ID. Returns matching customer profiles with recent activity.',
  {
    query: z.string().describe('Search term - can be name, email, or account ID'),
    includeInactive: z.boolean().optional().default(false),
  },
  async ({ query, includeInactive }, context) => {
    const customers = await customerService.search({
      query,
      tenantId: context.auth.tenantId,
      includeInactive,
    });
    
    return {
      content: [{
        type: 'text',
        text: JSON.stringify(customers.map(c => ({
          id: c.id,
          name: c.name,
          email: c.email,
          plan: c.plan,
          mrr: c.mrr,
          lastActive: c.lastActiveAt,
        })), null, 2),
      }],
    };
  }
);

Resources beschikbaar stellen

Resources zijn alleen-lezen gegevens die AI-clients als context kunnen gebruiken. Beschouw ze als bestanden die het model kan raadplegen:

server.resource(
  'api-docs',
  'Your SaaS API documentation',
  'text/markdown',
  async () => {
    const docs = await fs.readFile('./docs/api-reference.md', 'utf-8');
    return { content: docs };
  }
);

// Dynamic resource with URI template
server.resourceTemplate(
  'project/{projectId}/analytics',
  'Analytics summary for a specific project',
  'application/json',
  async ({ projectId }, context) => {
    const analytics = await analyticsService.getSummary(projectId, context.auth.tenantId);
    return { content: JSON.stringify(analytics) };
  }
);

Authenticatie en Multi-Tenancy

Dit is het onderdeel waar iedereen het eerste keer fout doet. MCP ondersteunt OAuth 2.1 voor authenticatie, en als je een multi-tenant SaaS bouwt, heb je dit absoluut nodig.

OAuth 2.1 Flow voor MCP

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/api/mcp')) {
    const authHeader = request.headers.get('authorization');
    
    if (!authHeader?.startsWith('Bearer ')) {
      return NextResponse.json(
        { error: 'Missing or invalid authorization header' },
        { status: 401 }
      );
    }
    
    // Validate the token and inject tenant context
    // This is where your existing auth system plugs in
  }
}

export const config = {
  matcher: '/api/mcp/:path*',
};

Voor het OAuth discovery endpoint dat MCP-clients nodig hebben:

// app/.well-known/oauth-authorization-server/route.ts
export function GET() {
  return Response.json({
    issuer: 'https://your-saas.com',
    authorization_endpoint: 'https://your-saas.com/oauth/authorize',
    token_endpoint: 'https://your-saas.com/api/oauth/token',
    registration_endpoint: 'https://your-saas.com/api/oauth/register',
    scopes_supported: ['mcp:read', 'mcp:write', 'mcp:admin'],
    response_types_supported: ['code'],
    code_challenge_methods_supported: ['S256'],
  });
}

Multi-Tenant isolatie

Elke MCP-tool-invocatie moet worden gespecificeerd op de geverifieerde tenant. Ik gebruik een patroon waarbij de auth-context automatisch wordt ingespoten in elke tool-handler:

const withTenant = (handler) => async (params, context) => {
  const tenant = await resolveTenant(context.auth.token);
  if (!tenant) throw new McpError('Invalid tenant');
  return handler(params, { ...context, tenant });
};

Vertrouw nooit op tool-parameters voor tenant-identificatie. Leid het altijd af van het auth-token.

Implementatie op Vercel: Configuratie en valkuilen

vercel.json configuratie

{
  "functions": {
    "app/api/mcp/route.ts": {
      "maxDuration": 60
    },
    "app/api/mcp/sse/route.ts": {
      "maxDuration": 300
    }
  },
  "headers": [
    {
      "source": "/api/mcp/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "no-store" }
      ]
    }
  ]
}

De valkuilen die niemand je vertelt

1. Function timeouts. Vercel Hobby-plan maxed af op 30 seconden. Pro geeft je 300 seconden. Voor MCP-tools die trage API's aanroepen of gegevens verwerken, heb je minimaal Pro nodig. Op $20/maand per teamlid is dit geen groot probleem voor de meeste SaaS-teams.

2. Cold starts. Serverless cold starts kunnen 200-800ms toevoegen aan de eerste request. MCP-clients houden hier over het algemeen goed mee om -- ze verwachten geen sub-50ms-responses. Maar als het je dwarszit, gebruik Vercels cron om functions warm te houden.

3. SSE en streaming. Vercel ondersteunt streaming-responses, maar er zijn edge cases met hun CDN-laag. Zet Cache-Control: no-store op alle MCP-routes. Ik leerde dit op de harde manier toen gecachte SSE-responses ervoor zorgden dat clients verouderde tool-lijsten ontvingen.

4. Request body grootte. Vercel beperkt request bodies tot 4.5MB op serverless functions. Als je MCP-tools bestandsuploads of grote payloads verwerken, moet je in plaats daarvan ondertekende upload-URLs gebruiken.

5. Environment variabelen. Vergeet niet om de openbare URL van je MCP-server in te stellen als env var. Tijdens ontwikkeling gebruik je iets als ngrok of Vercels preview URLs, maar in productie moet het je canonieke domein zijn.

# .env.production
MCP_SERVER_URL=https://your-saas.com/api/mcp
MCP_SERVER_NAME=your-saas-mcp

Prestatieoptimalisatie en schaling

Caching-strategieën

MCP tool-responses kunnen worden gecachet als de gegevens niet frequent veranderen:

import { unstable_cache } from 'next/cache';

const getCachedAnalytics = unstable_cache(
  async (tenantId: string, projectId: string) => {
    return analyticsService.getSummary(tenantId, projectId);
  },
  ['analytics-summary'],
  { revalidate: 300 } // 5 minutes
);

Connection pooling

Als je MCP-tools een database aanroepen, gebruik connection pooling. Op Vercel krijgt elke function invocation zijn eigen execution context, dus zonder pooling zul je snel database-verbindingen uitputten.

import { Pool } from '@neondatabase/serverless';

// Neon's serverless driver handles pooling automatically
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

Ik zou Neon of PlanetScale aanbevelen voor database-ondersteunde MCP-tools op Vercel. Beide hanteren het serverless connection-model goed.

Benchmarks

Dit zijn de metingen die we hebben gedaan op verschillende productie MCP-implementaties op Vercel Pro:

Metriek Cold Start Warm P99
Eenvoudige tool (geen DB) 420ms 45ms 180ms
DB-ondersteunde tool (Neon) 680ms 95ms 320ms
Tool met externe API 850ms 280ms 1200ms
SSE-verbinding setup 520ms 60ms 250ms
Tool discovery (list) 380ms 30ms 120ms

Deze nummers zijn prima voor AI client-interacties. Modellen nemen sowieso seconden om responses te genereren -- je MCP-server zal niet de bottleneck zijn.

Monitoring en observeerbaarheid

Je moet weten wat er in productie gebeurt. MCP-servers hebben unieke observeerbaarheidsbehoeften omdat de "gebruikers" AI-modellen zijn, geen mensen.

Wat je moet bijhouden

  • Tool invocation frequentie -- welke tools gebruiken modellen eigenlijk?
  • Foutpercentages per tool -- faalt een specifieke tool vaker dan anderen?
  • Token/tenant distributie -- hamert één tenant op je server?
  • Response payload sizes -- overmaat responses verspillen model context windows
// Simple logging middleware for MCP tools
const withLogging = (toolName: string, handler: Function) => {
  return async (params: any, context: any) => {
    const start = performance.now();
    try {
      const result = await handler(params, context);
      const duration = performance.now() - start;
      
      console.log(JSON.stringify({
        type: 'mcp_tool_invocation',
        tool: toolName,
        tenant: context.auth?.tenantId,
        duration,
        success: true,
        responseSize: JSON.stringify(result).length,
      }));
      
      return result;
    } catch (error) {
      console.error(JSON.stringify({
        type: 'mcp_tool_error',
        tool: toolName,
        tenant: context.auth?.tenantId,
        error: error.message,
      }));
      throw error;
    }
  };
};

Leid deze logs naar Axiom (Vercels geïntegreerde logging), Datadog, of wat je al gebruikt. Vercels ingebouwde Log Drains maken dit eenvoudig.

Kostenanalyse: MCP-servers uitvoeren op Vercel

Laten we het hebben over geld. Hier is een realistische kostenuitsplitsing voor een mid-size SaaS die een MCP-server op Vercel draait in 2026:

Component Hobby Pro Enterprise
Basisplan €0/mnd €20/mnd per seat Op maat
Function invocations (inbegrepen) 100K 1M Op maat
Extra invocations N.v.t. €0,60 per 1M Onderhandelbaar
Bandbreedte (inbegrepen) 100GB 1TB Op maat
Max function duration 30s 300s 900s
Edge middleware Inbegrepen Inbegrepen Inbegrepen
Geschat maandelijks (10K MCP-requests/dag) Niet haalbaar ~€25-40 Op maat

Voor de meeste SaaS-producten handelt het Pro-plan MCP-verkeer comfortabel af. Bij ~10.000 MCP-tool-invocaties per dag (wat behoorlijk actief is), kijk je naar ~300K function executions per maand -- ruimschoots binnen Pros inbegrepen allocation.

Vergelijk dit met het uitvoeren van een dedicated MCP-server op AWS: je zou minimaal een EC2-instance (€30-50/mnd), load balancer (€18/mnd) en je tijd voor infrastructuurbeheer nodig hebben. Vercel wint op operationele eenvoud.

Als je de juiste architectuur voor je SaaS evalueert, kunnen we je helpen dit in te schatten. Controleer onze pricing page of neem direct contact op.

Veelgestelde vragen

Wat is het Model Context Protocol (MCP) en hoe verschilt het van function calling? MCP is een open standaard voor het verbinden van AI-modellen met externe tools en gegevens. In tegenstelling tot provider-specifieke function calling (OpenAI's function calling, Anthropic's tool use), is MCP universeel. Je bouwt één MCP-server, en elke compatibele client -- Claude, Cursor, custom apps -- kan je tools automatisch detecteren en gebruiken. Function calling vereist dat je tools afzonderlijk voor elke AI-provider definieert.

Kan ik een MCP-server op Vercels gratis Hobby-plan implementeren? Technisch gezien ja, maar ik zou het niet voor productie aanbevelen. De 30-seconden function timeout is te restrictief voor MCP-tools die databases opvragen of externe API's aanroepen. Je krijgt ook beperkte invocations (100K/maand). Het Pro-plan op €20/maand per seat is het minimum dat ik voor een echte workload zou suggereren.

Hoe verwerk ik authenticatie tussen MCP-clients en mijn SaaS? De MCP-spec ondersteunt OAuth 2.1. Je stelt een .well-known/oauth-authorization-server endpoint beschikbaar dat MCP-clients automatisch detecteren. Wanneer een gebruiker via een AI-client zoals Claude verbinding maakt, worden zij omgeleid naar je standaard OAuth-flow, verlenen toestemming, en ontvangt de client een scoped access token. Dit token wordt met elke MCP-request verzonden.

Wat is het verschil tussen MCP-tools en MCP-resources? Tools zijn acties -- dingen die de AI kan doen (een project creëren, een e-mail verzenden, een query uitvoeren). Resources zijn gegevens -- dingen die de AI kan lezen voor context (documentatie, configuratiebestanden, analytics summaries). Tools worden op aanvraag aangeroepen; resources worden in het context window van het model geladen. Ontwerp tools voor acties, resources voor referentiemateriaal.

Hoeveel MCP-tools moet mijn server beschikbaar stellen? Gebaseerd op mijn ervaring is 5-15 tools de sweet spot voor de meeste SaaS-producten. Minder dan 5 en je MCP-server is niet erg nuttig. Meer dan 20 en AI-modellen maken slechtere tool-selectie besluiten. Groepeer gerelateerde bewerkingen in enkele tools met parameteropties in plaats van elke CRUD-operatie afzonderlijk beschikbaar te stellen.

Werkt dit met andere frameworks dan Next.js? Absoluut. De @modelcontextprotocol/sdk werkt met elk Node.js framework. Je zou Hono, Express, of zelfs Astro met SSR endpoints kunnen gebruiken. Next.js op Vercel is gewoon een bijzonder handige combinatie vanwege de ingebouwde streaming-ondersteuning, edge middleware en zero-config deployment. Als je een ander stack gebruikt, heeft ons headless CMS development team MCP-servers over meerdere frameworks gebouwd.

Hoe test ik mijn MCP-server tijdens ontwikkeling? De MCP Inspector (onderdeel van de officiële MCP-toolkit) is je beste vriend. Het verbindt zich met je lokale server en laat je tools aanroepen, resources doornemen en responses interactief debuggen. Voor geautomatiseerde tests, schrijf integratietests die je MCP-server in-process instantiëren en tools programmatisch aanroepen -- de SDK ondersteunt dit zonder HTTP transport nodig.

Wat gebeurt er wanneer Vercel-functions cold starten tijdens een MCP-request? MCP-clients zijn ontworpen om tolerant te zijn voor latentie -- zij wachten normaal gesproken op AI-model-responses die seconden duren. Een 400-800ms cold start is in de praktijk niet waarneembaar. Als je je zorgen maakt, laat je met Vercels Pro-plan cron-gebaseerde warming configureren, en de SDK bevat automatische retry-logica voor voorbijgaande fouten. In zes maanden productiegebruik zijn cold starts nog nooit een door gebruikers gerapporteerd probleem voor onze clients.