MCP: Model Context Protocol Guide
MCP er en aaben standard for at forbinde LLM'er med externe data og tools. Taenk pa det som USB-C for AI - en universel connector.
Foto: Google DeepMind / Unsplash
TL;DR
MCP lader dig eksponere tools og data som en server, som enhver MCP-compatible klient (Claude Desktop, Claude Code, IDEs) kan bruge. Du bygger serveren, klienten opdager automatisk dine capabilities.
1from mcp.server.fastmcp import FastMCP2
3mcp = FastMCP("my-tools")4
5@mcp.tool()6def add(a: int, b: int) -> int:7 """Laeg to tal sammen."""8 return a + b9
10mcp.run() # Start MCP serverPrerequisites
1pip install mcp # Python SDK2# eller3npm install @modelcontextprotocol/sdk # TypeScript SDK- • Python 3.11+ eller Node.js 18+
- • Claude Desktop eller Claude Code (som MCP klient)
- • Grundlaeggende kendskab til Claude API og tool use
Hvad er MCP?
Model Context Protocol (MCP) er en aaben standard udviklet af Anthropic. Den loser et fundamentalt problem: hvordan forbinder man LLM'er med eksterne systemer pa en standardiseret maade?
Foer MCP skulle hver AI-applikation bygge sine egne integrations. Med MCP bygger du en server een gang, og den virker med alle MCP-compatible klienter.
MCP Arkitekturen
Host (Claude Desktop / IDE)
|
v
MCP Client <---> MCP Server <---> External Systems
| |
| Tools, Resources,
| Prompts
v
LLM (Claude)MCP har tre kernekoncepter:
- Tools - Funktioner LLM'en kan kalde (database queries, API kald, beregninger)
- Resources - Data LLM'en kan laese (filer, database rows, API responses)
- Prompts - Predefinerede prompt-templates brugere kan aktivere
Byg din foerste MCP Server
Lad os bygge en MCP server der eksponerer et par nyttige tools. FastMCP er den anbefalede maade at bygge servere pa i Python:
1from mcp.server.fastmcp import FastMCP2import httpx3from datetime import datetime4
5mcp = FastMCP("weather-tools")6
7@mcp.tool()8def get_weather(city: str) -> str:9 """Hent aktuel vejrudsigt for en by.10
11 Args:12 city: Byens navn, f.eks. 'Copenhagen'13 """14 # Using Open-Meteo (free, no API key needed)15 geo = httpx.get(16 "https://geocoding-api.open-meteo.com/v1/search",17 params={"name": city, "count": 1}18 ).json()19
20 if not geo.get("results"):21 return f"Kunne ikke finde byen: {city}"22
23 lat = geo["results"][0]["latitude"]24 lon = geo["results"][0]["longitude"]25
26 weather = httpx.get(27 "https://api.open-meteo.com/v1/forecast",28 params={29 "latitude": lat,30 "longitude": lon,31 "current": "temperature_2m,wind_speed_10m,weather_code"32 }33 ).json()34
35 current = weather["current"]36 return (37 f"Vejr i {city}: "38 f"{current['temperature_2m']}C, "39 f"vind {current['wind_speed_10m']} km/t"40 )41
42@mcp.tool()43def get_time(timezone: str = "Europe/Copenhagen") -> str:44 """Hent aktuel tid i en given tidszone.45
46 Args:47 timezone: IANA timezone, f.eks. 'Europe/Copenhagen'48 """49 from zoneinfo import ZoneInfo50 now = datetime.now(ZoneInfo(timezone))51 return now.strftime("%Y-%m-%d %H:%M:%S %Z")52
53if __name__ == "__main__":54 mcp.run()Connect til Claude Desktop
For at bruge din MCP server med Claude Desktop, tilfoej den til konfigurationsfilen:
1{2 "mcpServers": {3 "weather": {4 "command": "python",5 "args": ["/path/to/weather_server.py"]6 }7 }8}Konfigurationsfilen ligger:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json
Genstart Claude Desktop, og dine tools er nu tilgaengelige. Claude kan automatisk se og bruge dem naar det er relevant.
Resources: Eksponere Data
Resources giver LLM'en laese-adgang til data. De opdages automatisk af klienten:
1from mcp.server.fastmcp import FastMCP2import sqlite33
4mcp = FastMCP("data-server")5
6# Static resource7@mcp.resource("config://app")8def get_config() -> str:9 """Returner applikationens konfiguration."""10 return """11 App: MyApp v2.112 Environment: production13 Database: PostgreSQL 1614 Cache: Redis 715 """16
17# Dynamic resource with URI template18@mcp.resource("db://customers/{customer_id}")19def get_customer(customer_id: str) -> str:20 """Hent kundedata fra database.21
22 Args:23 customer_id: Unikt kunde-ID24 """25 conn = sqlite3.connect("customers.db")26 cursor = conn.execute(27 "SELECT name, email, plan FROM customers WHERE id = ?",28 (customer_id,)29 )30 row = cursor.fetchone()31 conn.close()32
33 if not row:34 return f"Kunde {customer_id} ikke fundet"35
36 return f"Navn: {row[0]}\nEmail: {row[1]}\nPlan: {row[2]}"37
38# Tool that works with resources39@mcp.tool()40def search_customers(query: str) -> str:41 """Soeg efter kunder i databasen.42
43 Args:44 query: Soegeord (navn eller email)45 """46 conn = sqlite3.connect("customers.db")47 cursor = conn.execute(48 "SELECT id, name, email FROM customers WHERE name LIKE ? OR email LIKE ? LIMIT 10",49 (f"%{query}%", f"%{query}%")50 )51 results = cursor.fetchall()52 conn.close()53
54 if not results:55 return "Ingen kunder fundet"56
57 return "\n".join(58 f"ID: {r[0]}, Navn: {r[1]}, Email: {r[2]}"59 for r in results60 )MCP Server i TypeScript
TypeScript SDK'et er ligeledes velunderstaettet. Her er det samme weather-eksempel:
1import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";2import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";3
4const server = new McpServer({5 name: "weather-tools",6 version: "1.0.0",7});8
9server.tool(10 "get_weather",11 "Hent aktuel vejrudsigt for en by",12 { city: { type: "string", description: "Byens navn" } },13 async ({ city }) => {14 const geoRes = await fetch(15 `https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=1`16 );17 const geo = await geoRes.json();18
19 if (!geo.results?.length) {20 return { content: [{ type: "text", text: `By ikke fundet: ${city}` }] };21 }22
23 const { latitude, longitude } = geo.results[0];24 const weatherRes = await fetch(25 `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,wind_speed_10m`26 );27 const weather = await weatherRes.json();28 const { temperature_2m, wind_speed_10m } = weather.current;29
30 return {31 content: [{32 type: "text",33 text: `Vejr i ${city}: ${temperature_2m}C, vind ${wind_speed_10m} km/t`34 }]35 };36 }37);38
39const transport = new StdioServerTransport();40await server.connect(transport);Prompts: Genanvendelige Templates
MCP prompts lader dig definere genanvendelige prompt-templates som brugere kan aktivere fra klienten:
1from mcp.server.fastmcp import FastMCP2
3mcp = FastMCP("code-review-tools")4
5@mcp.prompt()6def review_code(code: str, language: str = "python") -> str:7 """Generer en code review prompt.8
9 Args:10 code: Koden der skal reviewes11 language: Programmeringssprog12 """13 return f"""Review denne {language} kode grundigt.14
15Fokuser paa:161. Bugs og logiske fejl172. Sikkerhedsproblemer183. Performance issues194. Kode-kvalitet og laebarhed205. Best practices for {language}21
22Kode:23```{language}24{code}25```26
27Giv konkrete forbedringsforslag med kodeeksempler."""28
29@mcp.prompt()30def explain_error(error_message: str, context: str = "") -> str:31 """Generer en prompt til at forklare en fejlbesked.32
33 Args:34 error_message: Den fulde fejlbesked35 context: Ekstra kontekst om hvad der blev forsoeget36 """37 prompt = f"Forklar denne fejl og hvordan den fikses:\n\n{error_message}"38 if context:39 prompt += f"\n\nKontekst: {context}"40 return promptAvanceret: Composing MCP Servere
I praksis koerer du flere MCP servere samtidig. Hver server haandterer et specifikt domaene:
1{2 "mcpServers": {3 "weather": {4 "command": "python",5 "args": ["weather_server.py"]6 },7 "database": {8 "command": "python",9 "args": ["db_server.py"],10 "env": {11 "DATABASE_URL": "postgresql://localhost/mydb"12 }13 },14 "github": {15 "command": "npx",16 "args": ["-y", "@modelcontextprotocol/server-github"],17 "env": {18 "GITHUB_TOKEN": "ghp_..."19 }20 },21 "filesystem": {22 "command": "npx",23 "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]24 }25 }26}MCP vs Direkte Tool Use
| Feature | Direkte Tool Use | MCP |
|---|---|---|
| Setup | Definer tools i API call | Separat server process |
| Genbrug | Per applikation | Alle MCP klienter |
| Discovery | Manuel | Automatisk |
| Best for | Simple, app-specifikke tools | Delte tools, desktop apps |
| Ecosystem | DIY | 1000+ community servere |
Community MCP Servere
Der er allerede et stort ecosystem af faerdige MCP servere:
- @modelcontextprotocol/server-github - GitHub repos, issues, PRs
- @modelcontextprotocol/server-filesystem - Fil-operationer
- @modelcontextprotocol/server-postgres - PostgreSQL queries
- @modelcontextprotocol/server-slack - Slack beskeder og kanaler
- @modelcontextprotocol/server-puppeteer - Browser automation
Find flere pa MCP Servers repository.
Common Pitfalls
- For brede tools - Definer specifikke tools frem for generelle. Claude vaelger bedre med klare graenser.
- Manglende beskrivelser - Tool descriptions er kritiske. LLM'en bruger dem til at forstaa hvornaar og hvordan.
- Ingen error handling - Returner meningsfulde fejlbeskeder, ikke stack traces.
- Sikkerhed - MCP servere koerer lokalt men har adgang til dine systemer. Validerer altid input.
- Timeout - Saet timeouts pa eksterne kald. En haengende MCP server blokerer hele klienten.
Naeste skridt
MCP er stadig nyt, men det vokser hurtigt. Start med at bygge en simpel server til et af dine egne systemer. For at forstaa det underliggende tool use pattern, laes vores AI Agent guide. Vil du bruge et framework i stedet, tjek LangChain guiden. Og for at give din MCP server adgang til custom data, kombiner med en RAG pipeline.