MCP-protokoll: teknisk guide för utvecklare 2026
Hur du bygger en MCP-server från grunden: arkitektur, säkerhet, auth, production-considerations. Steg-för-steg med TypeScript SDK + code-exempel.

MCP-protokoll har gått från Anthropic-experiment till industri-standard på 18 månader. För utvecklare och CTOs som vill bygga AI-agenter mot egna system är frågan inte längre om MCP, utan hur du implementerar det säkert i produktion. Den här guiden är teknisk: arkitektur, code, auth, monitoring.
Om du är ny till protokollet, läs först vår grundläggande genomgång av MCP. Den här guiden förutsätter att du vet vad MCP är och vill bygga något själv.
Hur fungerar MCP-arkitekturen tekniskt?
MCP-protokoll bygger på JSON-RPC 2.0 över två transport-typer: stdio (lokala servrar) och HTTP med Server-Sent Events (remote servrar). Klienten initierar en handshake där server och klient utbyter capabilities, sedan flödar bidirektionell kommunikation med strukturerade meddelanden.
Arkitekturen har tre lager. Det översta lagret är klienten (Claude Desktop, Cursor, eller en custom-app som använder Anthropic SDK). Det mellersta lagret är transport-protokollet som bär meddelanden, antingen via standard input/output för lokala processer eller HTTP+SSE för nätverkstjänster. Det understa lagret är själva MCP-servern som exponerar Resources, Tools och Prompts.
Handshake-flödet är standardiserat. Klienten skickar initialize med sin protocol-version och vilka capabilities den stödjer. Servern svarar med samma fält + server-info. Båda sidor förhandlar vad de kan göra. Detta är dokumenterat i den officiella protokoll-specifikationen.
Vad gör MCP-protokoll annorlunda från en vanlig REST-API? Tre saker som spelar roll i implementation:
Stateful sessions. En MCP-anslutning har långlivad state. Klient och server kommer ihåg vad de förhandlat fram. REST är stateless per request — MCP är mer som WebSocket.
Capability negotiation. Servern berättar för klienten exakt vilka Resources, Tools och Prompts den stödjer vid uppstart. Inga gissningar, ingen swagger-fil att underhålla separat.
Notifications-stöd. Servern kan pusha uppdateringar till klienten (t.ex. "resurs X har ändrats"). REST kräver polling eller separata webhook-system.
Hur bygger du en MCP-server från grunden?
Det enklaste sättet att bygga en MCP-server är TypeScript SDK från Anthropic. Du installerar paketet, definierar dina tools eller resources, och kör servern via stdio för lokala anrop eller HTTP för remote. En minimal server är cirka 30 rader kod.
Installation:
npm install @modelcontextprotocol/sdk
Här är en minimal MCP-server som exponerar ett enda tool för att hämta dagens datum:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'
const server = new McpServer({
name: 'datum-server',
version: '1.0.0',
})
server.tool(
'get_current_date',
'Hämtar dagens datum i ISO 8601-format',
{
timezone: z.string().optional().describe('IANA-timezone, t.ex. Europe/Stockholm'),
},
async ({ timezone = 'Europe/Stockholm' }) => {
const date = new Date().toLocaleString('sv-SE', { timeZone: timezone })
return {
content: [{ type: 'text', text: date }],
}
}
)
const transport = new StdioServerTransport()
await server.connect(transport)
Koden gör tre saker. Skapar en server-instans med namn och version, registrerar ett tool med Zod-schema för input-validation, och kopplar servern till stdio-transporten. När Claude Desktop startar servern kommer användaren se get_current_date som ett tillgängligt verktyg.
För att exponera Resources (data som klienten kan läsa) istället för Tools (funktioner som körs), använder du server.resource(). Skillnaden är semantisk: Resources är read-only data, Tools är actions som kan ha sideeffects. Den officiella TypeScript SDK-dokumentationen har exempel för båda mönstren.
Python-utvecklare använder Python SDK med samma decorator-baserade pattern. Båda SDK:erna ligger på 3 000+ GitHub-stjärnor och uppdateras regelbundet av Anthropic.
För production deployment byter du transport från stdio till HTTP+SSE. Det kräver ett par extra rader för att starta en Express-server eller liknande HTTP-runtime. Då blir servern accessible över nätverket istället för bara lokalt.
Hur säkrar du auth och permissions i MCP?
MCP-protokoll har inget inbyggt auth-lager. Säkerheten implementerar du i transport-lagret eller per-tool. Tre vanliga mönster: API-key-baserad auth för enkla scenarier, OAuth 2.1 för enterprise och tredjepartsintegrationer, och mTLS för server-till-server inom samma infrastruktur.
För lokala stdio-servrar är auth oftast inte ett problem eftersom användaren kör processen själv med sin egen behörighet. För HTTP-baserade remote servers blir auth kritiskt. Här är pattern för API-key i Bearer-token, som är det enklaste säkra alternativet:
import express from 'express'
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
const app = express()
app.use('/mcp', (req, res, next) => {
const auth = req.headers.authorization
const expected = `Bearer ${process.env.MCP_API_KEY}`
if (!process.env.MCP_API_KEY) {
return res.status(503).json({ error: 'MCP_API_KEY not configured' })
}
if (auth !== expected) {
return res.status(401).json({ error: 'Unauthorized' })
}
next()
})
const server = new McpServer({ name: 'protected-server', version: '1.0.0' })
// ...registrera tools här...
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => crypto.randomUUID() })
await server.connect(transport)
app.use('/mcp', transport.handler)
app.listen(3000)
Scoping är nästa lager. Inte alla klienter ska kunna anropa alla tools. Per-tool authorization kan implementeras genom att verifiera klientens identitet (via JWT-claims eller liknande) inne i tool-handlern och returnera permission-error om scope saknas.
För OAuth 2.1-baserad auth följer du standard-flow med en separat OAuth-server som issues access-tokens. MCP-protokoll har en officiell auth-specifikation som beskriver hur tokens passas i Bearer-headers. Anthropic rekommenderar OAuth för publik exponering av MCP-servrar.
Sandbox-isolering är viktig för enterprise. Om din MCP-server kör mot ett produktionsdatabas, sätt strikta SQL-permissions på den användaren som servern kör som. Aldrig SUPERUSER. Aldrig DROP TABLE. Standardprincipen är minsta möjliga privilegium per tool.
Hur testar och debuggar du MCP-servers?
Det officiella verktyget är MCP Inspector: en webbaserad UI som låter dig anropa tools, inspektera responses, och se hela JSON-RPC-trafiken i realtid. Du installerar det med npm och pekar det mot din lokala eller remote server.
Installation och uppstart:
npx @modelcontextprotocol/inspector node ./dist/server.js
Detta startar Inspector på localhost:5173 och spawnar din server som child-process via stdio. UI:n visar en lista över alla registrerade tools, resources och prompts. Du kan anropa varje tool med custom-input och se exakt vad servern svarar.
För HTTP-baserade servers anger du URL och eventuell auth-header. Inspector hanterar SSE-streaming och visar request/response-paren i en tidslinje. Detta är ovärderligt för att felsöka capability-negotiation och tool-call-fel.
Loggning på server-sidan är lika viktigt som Inspector. Eftersom MCP-protokoll använder stdio för lokala servrar är vanliga console.log-anrop farliga. De korrumperar JSON-RPC-strömmen och bryter klient-anslutningen omedelbart. Använd console.error (stderr) för all logging eller en strukturerad logger som pino. För HTTP-servers gäller vanlig request-logging utan stdio-risken.
Tre vanliga bugs vi sett i konsult-arbete för svenska SMB:
Tool-schemas matchar inte verkligheten. En Tool deklarerar att email är required, men handlern crashar på email: null. Lösning: använd Zod (eller liknande) för strict input-validation, inte bara TypeScript-typing.
Long-running tools timeout:ar. Claude Desktop har en default-timeout på ~30 sekunder per tool-call. Om din tool gör ett tungt API-call (eller väntar på extern process), implementera progress-notifications via MCP:s notification-mekanism eller bryt upp arbetet i mindre anrop.
Resource-URI:er kolliderar. Om två resources har samma URI överskrivs den ena. Lösning: använd hierarkisk URI-design (db://customers/123 istället för customer-123).
För djupare felsökning, läs Inspector-dokumentationen på GitHub.
Vilka production-considerations finns?
Tre saker är kritiska i produktion: rate-limiting så en buggig klient inte hämtar 10 000 records per minut, error-handling så fel inte läcker stack-traces till klienten, och observability så du kan reagera på incidenter.
Rate-limiting implementerar du i transport-lagret. För HTTP-baserade servers fungerar standard-bibliotek som express-rate-limit direkt. Sätt initialt 60-100 requests per minut per API-key och justera baserat på faktisk användning. För stdio-servers är rate-limiting mindre kritiskt eftersom klienten kör lokalt och styrs av användaren.
Error-handling i MCP-protokoll följer JSON-RPC-konventionen. Returnera ett strukturerat error-objekt med code, message, och valfritt data:
server.tool('fetch_customer', 'Hämta kunddata', { id: z.string() }, async ({ id }) => {
try {
const customer = await db.query('SELECT * FROM customers WHERE id = $1', [id])
if (!customer) {
return {
content: [{ type: 'text', text: `Kund med id ${id} hittades inte` }],
isError: true,
}
}
return { content: [{ type: 'text', text: JSON.stringify(customer) }] }
} catch (err) {
// Logga full error på server-sidan, returnera sanitized message
console.error('fetch_customer error:', err)
return {
content: [{ type: 'text', text: 'Internt fel vid kundhämtning' }],
isError: true,
}
}
})
Aldrig returnera raw exception-messages till klienten. De kan innehålla credentials, file-paths eller annan känslig info som AI-modellen sedan repeterar i sitt svar till slutanvändaren.
Versionering är nästa fråga. MCP-protokoll har protocol-version i handshaken (2025-06-18 är current per maj 2026). Din servers egen version sätter du i McpServer-konstruktorn. Semantic versioning rekommenderas: breaking changes i tool-signaturer = major bump.
Observability: logga varje tool-call med tool-name, klient-identifier, duration och success/failure. Detta gör att du kan se vilka tools som faktiskt används, vilka som är långsamma, och vilka som returnerar fel. Standard-loggers som Pino eller Winston fungerar utmärkt. För enterprise: skicka logs till Datadog, Honeycomb eller motsvarande.
Konkret monitoring-pattern som fungerar i produktion:
import { performance } from 'perf_hooks'
server.tool('fetch_data', 'Hämtar data', { id: z.string() }, async ({ id }) => {
const start = performance.now()
const clientId = process.env.MCP_CLIENT_ID ?? 'unknown'
try {
const result = await fetchFromSource(id)
const duration = performance.now() - start
logger.info({ tool: 'fetch_data', clientId, duration, status: 'success' })
return { content: [{ type: 'text', text: JSON.stringify(result) }] }
} catch (err) {
const duration = performance.now() - start
logger.error({ tool: 'fetch_data', clientId, duration, status: 'error', err })
return { content: [{ type: 'text', text: 'Internt fel' }], isError: true }
}
})
De fyra fält som spelar roll i monitoring: tool (vilket verktyg), clientId (vem anropade), duration (latency-mätning), och status (success/error). Med dessa kan du bygga dashboards som visar tool-usage per klient, p95-latencies per tool, och error-rates över tid. Detta är minimum för att kunna debugga incidenter och prioritera optimeringar i produktionen.
Hur integrerar du MCP mot enterprise-systems?
Tre stora kategorier av enterprise-integrationer dominerar i konsult-arbete: relationsdatabaser (Postgres, SQL Server), interna REST-API:er med befintlig SSO, och SaaS-system som Salesforce eller HubSpot. Varje typ har sina mönster.
För Postgres-integration finns en officiell MCP-server i github.com/modelcontextprotocol/servers. Den exponerar tabeller som Resources och låter klienten köra read-only queries via Tools. För svenska SMB är detta ofta tillräckligt: säljaren frågar Claude på naturlig svenska, Claude översätter till SQL, servern kör mot read-replica.
För custom enterprise-API:er rekommenderar vi en wrapper-pattern: skriv en MCP-server som internt anropar er REST-API med tjänste-konto. Klienten ser MCP-tools, men under huven sker autentisering via OAuth eller mTLS mot er befintliga backend. Detta isolerar AI-modellen från interna implementation-detaljer och låter er logga + auditera all AI-driven trafik centralt.
För SaaS-integrationer kollar du först om det finns en officiell MCP-server. MCP-registret har 6 850+ servers per maj 2026, inklusive officiella från Anthropic för Slack, GitHub och Google Drive. Är ditt SaaS inte täckt? Bygg en wrapper-server mot deras REST-API. Räkna med 1-2 dagar per integration för production-grade kvalitet.
Tre saker att tänka på vid enterprise-integration:
Audit-logging är inte valfritt. Varje tool-call ska loggas med klient-identitet, payload och resultat till en separat audit-trail. Detta är ofta krav från compliance/säkerhetsteamet. För svenska företag som omfattas av GDPR är detta särskilt viktigt. För djupare genomgång av regelverkskraven, läs vår guide om EU AI Act för svenska företag.
Sandbox-databas för demo. Innan en MCP-server går mot produktion, testa mot en sandbox-kopia. AI-genererade SQL-queries kan vara kreativa på sätt som överraskar.
Begränsa scope per role. En MCP-server som exponerar hela CRM ger AI-modellen tillgång till hela CRM. Vill du begränsa till "bara denna users konton"? Implementera scoping i tool-handler baserat på klient-identitet.
Vad kostar enterprise-grad MCP-implementation?
Realistisk kostnad för en svensk SMB ligger på 40-80 utvecklartimmar för första MCP-servern, plus hosting/drift på 200-2 000 SEK/månad beroende på trafik. Den första servern är dyrast eftersom infrastrukturen byggs då. Server två och tre tar 8-15 timmar var.
Kostnadsfördelningen för en typisk enterprise-MCP-server:
| Komponent | Timmar | Förklaring |
|---|---|---|
| Server-skeleton + tools | 8-12 | Initial setup, första 3-5 tools |
| Auth + scoping | 6-10 | OAuth eller API-key + per-tool permissions |
| Error-handling + logging | 4-8 | Strukturerad logging, audit-trail |
| Testing + Inspector-verifiering | 6-10 | Unit-tester + end-to-end via Inspector |
| Production deployment | 4-8 | Containerisering, secrets-hantering, monitoring |
| Documentation + handover | 4-8 | README, runbooks, träning för intern personal |
| Total | 32-56 | Första servern, single-system |
Tilläggskostnader varierar. Hosting: en MCP-server på Vercel/Railway/Fly.io kostar 100-500 SEK/månad för rimlig trafik. Monitoring: Datadog eller motsvarande adderar 500-2 000 SEK/månad. Säkerhetsgranskning: en intern audit lägger 8-16 timmar till första leveransen, lägre för efterföljande.
För kostnads-överblick av AI-agent-projekt i bredare bemärkelse, läs vår kostnadsguide för AI-agenter i Sverige. MCP-server är ofta en delkostnad i ett större AI-agent-projekt.
När det gäller skillnaden mellan att bygga en MCP-server och att använda en färdig chatbot-lösning, läs vår jämförelse av AI-agent vs chatbot. MCP-protokoll är vad som skiljer en riktig autonomous agent från en wrapped LLM-call. För en bredare introduktion till hur dessa pussel pussar ihop för svenska SMB, se vår pillar-artikel om AI-agenter för svenska företag.
Är MCP-protokoll värt investeringen? För Claude-baserade arbetsflöden är svaret tydligt ja. För OpenAI-tunga organisationer är svaret "vänta tills OpenAI släpper officiellt stöd, eller bygg en proxy-server om ni inte kan vänta". Vår bedömning baseras på 18 månaders adoption-data sedan Anthropic lanserade protokollet, och adoptionen accelererar.
Vanliga frågor
Stdio för lokala dev-verktyg (Claude Desktop, Cursor) där servern kör på samma maskin som klienten. HTTP+SSE för remote servrar som flera klienter ska kunna nå över nätverk. Stdio är enklare att sätta upp men begränsad till lokal användning. HTTP kräver mer infrastruktur men ger production-ready deployment med standard auth och rate-limiting.
Ja. Det finns community-SDK:er för Go, Rust, Java och C#. Protokollet är språk-agnostiskt eftersom det bygger på JSON-RPC 2.0 över stdio eller HTTP. Officiella SDK:er från Anthropic finns för TypeScript och Python och får mest underhåll. För andra språk, kolla awesome-mcp-servers-listan för aktuella alternativ.
Semantic versioning per server. Bumpa major-version när du ändrar tool-signaturer eller tar bort resources. Klienter kan se serverns version i handshake. För enterprise-deployments rekommenderas att köra gamla versionen parallellt under 30-90 dagar tills alla klienter migrerat. Detta är samma mönster som API-versionering generellt.
Ja, via progress-notifications. Servern skickar progress-meddelanden under operationens gång till klienten. Notifications är del av JSON-RPC-specifikationen och stöds av båda officiella SDK:er. Det är dock inte streaming i HTTP-bemärkelsen — det är diskreta progress-updates med procentvärden eller statusmeddelanden.
Använd MCP SDK:s in-memory transport för unit-tester istället för stdio eller HTTP. Det låter dig anropa tools programmatiskt i Jest eller Vitest utan att spawna en separat process. För end-to-end-tester kan du köra Inspector i headless mode eller skriva en simpel klient med SDK:n som anropar din server och verifierar responses.
Klienten får ett connection-error och behandlar det som tool-failure. Bra praxis är att implementera health-checks och auto-restart i din runtime (Docker, PM2, systemd). För kritiska tools, designa idempotenta operations så att retry är säkert. Loggning av crashed sessions hjälper att hitta root cause.
AI i arbete?



