Skip to content

Latest commit

 

History

History
1379 lines (1077 loc) · 40.4 KB

File metadata and controls

1379 lines (1077 loc) · 40.4 KB

Komma igång med MCP

Välkommen till dina första steg med Model Context Protocol (MCP)! Oavsett om du är nybörjare eller vill fördjupa din förståelse, kommer den här guiden att leda dig genom den grundläggande installationen och utvecklingsprocessen. Du kommer att upptäcka hur MCP möjliggör smidig integration mellan AI-modeller och applikationer, och lära dig hur du snabbt kan förbereda din miljö för att bygga och testa MCP-drivna lösningar.

TLDR; Om du bygger AI-appar, vet du att du kan lägga till verktyg och andra resurser till din LLM (large language model) för att göra den mer kunnig. Men om du placerar dessa verktyg och resurser på en server, kan appen och serverns kapacitet användas av vilken klient som helst, med eller utan en LLM.

Översikt

Den här lektionen ger praktisk vägledning för att ställa in MCP-miljöer och bygga dina första MCP-applikationer. Du kommer att lära dig hur du ställer in nödvändiga verktyg och ramverk, bygger grundläggande MCP-servrar, skapar värdapplikationer och testar dina implementationer.

Model Context Protocol (MCP) är ett öppet protokoll som standardiserar hur applikationer tillhandahåller kontext till LLMs. Tänk på MCP som en USB-C-port för AI-applikationer – det ger ett standardiserat sätt att ansluta AI-modeller till olika datakällor och verktyg.

Lärandemål

I slutet av den här lektionen kommer du att kunna:

  • Ställa in utvecklingsmiljöer för MCP i C#, Java, Python, TypeScript och Rust
  • Bygga och distribuera grundläggande MCP-servrar med anpassade funktioner (resurser, prompts och verktyg)
  • Skapa värdapplikationer som ansluter till MCP-servrar
  • Testa och felsöka MCP-implementationer

Ställa in din MCP-miljö

Innan du börjar arbeta med MCP är det viktigt att förbereda din utvecklingsmiljö och förstå det grundläggande arbetsflödet. Den här sektionen guidar dig genom de första stegen för att säkerställa en smidig start med MCP.

Förutsättningar

Innan du dyker in i MCP-utveckling, se till att du har:

  • Utvecklingsmiljö: För ditt valda språk (C#, Java, Python, TypeScript eller Rust)
  • IDE/Editor: Visual Studio, Visual Studio Code, IntelliJ, Eclipse, PyCharm eller någon modern kodredigerare
  • Paketadministratörer: NuGet, Maven/Gradle, pip, npm/yarn eller Cargo
  • API-nycklar: För de AI-tjänster du planerar att använda i dina värdapplikationer

Grundläggande struktur för MCP-server

En MCP-server innehåller vanligtvis:

  • Serverkonfiguration: Inställning av port, autentisering och andra inställningar
  • Resurser: Data och kontext som görs tillgängliga för LLMs
  • Verktyg: Funktionalitet som modeller kan anropa
  • Prompts: Mallar för att generera eller strukturera text

Här är ett förenklat exempel i TypeScript:

import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// Create an MCP server
const server = new McpServer({
  name: "Demo",
  version: "1.0.0"
});

// Add an addition tool
server.tool("add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

// Add a dynamic greeting resource
server.resource(
  "file",
  // The 'list' parameter controls how the resource lists available files. Setting it to undefined disables listing for this resource.
  new ResourceTemplate("file://{path}", { list: undefined }),
  async (uri, { path }) => ({
    contents: [{
      uri: uri.href,
      text: `File, ${path}!`
    }]
// Add a file resource that reads the file contents
server.resource(
  "file",
  new ResourceTemplate("file://{path}", { list: undefined }),
  async (uri, { path }) => {
    let text;
    try {
      text = await fs.readFile(path, "utf8");
    } catch (err) {
      text = `Error reading file: ${err.message}`;
    }
    return {
      contents: [{
        uri: uri.href,
        text
      }]
    };
  }
);

server.prompt(
  "review-code",
  { code: z.string() },
  ({ code }) => ({
    messages: [{
      role: "user",
      content: {
        type: "text",
        text: `Please review this code:\n\n${code}`
      }
    }]
  })
);

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);

I koden ovan:

  • Importerar vi nödvändiga klasser från MCP TypeScript SDK.
  • Skapar och konfigurerar vi en ny MCP-serverinstans.
  • Registrerar vi ett anpassat verktyg (calculator) med en hanteringsfunktion.
  • Startar vi servern för att lyssna på inkommande MCP-förfrågningar.

Testning och felsökning

Innan du börjar testa din MCP-server är det viktigt att förstå de tillgängliga verktygen och bästa praxis för felsökning. Effektiv testning säkerställer att din server beter sig som förväntat och hjälper dig att snabbt identifiera och lösa problem. Följande sektion beskriver rekommenderade metoder för att validera din MCP-implementation.

MCP tillhandahåller verktyg för att hjälpa dig testa och felsöka dina servrar:

  • Inspector-verktyg, en grafisk gränssnitt som låter dig ansluta till din server och testa dina verktyg, prompts och resurser.
  • curl, du kan också ansluta till din server med ett kommandoradsverktyg som curl eller andra klienter som kan skapa och köra HTTP-kommandon.

Använda MCP Inspector

MCP Inspector är ett visuellt testverktyg som hjälper dig:

  1. Upptäcka serverkapacitet: Identifiera tillgängliga resurser, verktyg och prompts automatiskt
  2. Testa verktygsutförande: Prova olika parametrar och se svar i realtid
  3. Visa servermetadata: Undersök serverinformation, scheman och konfigurationer
# ex TypeScript, installing and running MCP Inspector
npx @modelcontextprotocol/inspector node build/index.js

När du kör ovanstående kommandon kommer MCP Inspector att starta ett lokalt webbgränssnitt i din webbläsare. Du kan förvänta dig att se en instrumentpanel som visar dina registrerade MCP-servrar, deras tillgängliga verktyg, resurser och prompts. Gränssnittet låter dig interaktivt testa verktygsutförande, inspektera servermetadata och visa svar i realtid, vilket gör det enklare att validera och felsöka dina MCP-serverimplementationer.

Här är en skärmdump av hur det kan se ut:

MCP Inspector serveranslutning

Vanliga installationsproblem och lösningar

Problem Möjlig lösning
Anslutning nekad Kontrollera om servern körs och porten är korrekt
Fel vid verktygsutförande Granska parameterverifiering och felhantering
Autentiseringsfel Kontrollera API-nycklar och behörigheter
Fel vid schemavalidering Säkerställ att parametrarna matchar det definierade schemat
Server startar inte Kontrollera portkonflikter eller saknade beroenden
CORS-fel Konfigurera korrekta CORS-headers för cross-origin-förfrågningar
Autentiseringsproblem Kontrollera token giltighet och behörigheter

Lokal utveckling

För lokal utveckling och testning kan du köra MCP-servrar direkt på din dator:

  1. Starta serverprocessen: Kör din MCP-serverapplikation
  2. Konfigurera nätverk: Säkerställ att servern är tillgänglig på den förväntade porten
  3. Anslut klienter: Använd lokala anslutnings-URL:er som http://localhost:3000
# Example: Running a TypeScript MCP server locally
npm run start
# Server running at http://localhost:3000

Bygga din första MCP-server

Vi har täckt Kärnkoncept i en tidigare lektion, nu är det dags att omsätta den kunskapen i praktiken.

Vad en server kan göra

Innan vi börjar skriva kod, låt oss påminna oss om vad en server kan göra:

En MCP-server kan till exempel:

  • Komma åt lokala filer och databaser
  • Ansluta till fjärr-API:er
  • Utföra beräkningar
  • Integrera med andra verktyg och tjänster
  • Tillhandahålla ett användargränssnitt för interaktion

Bra, nu när vi vet vad vi kan göra med den, låt oss börja koda.

Övning: Skapa en server

För att skapa en server behöver du följa dessa steg:

  • Installera MCP SDK.
  • Skapa ett projekt och ställ in projektstrukturen.
  • Skriv serverkoden.
  • Testa servern.

-1- Skapa projekt

TypeScript

# Create project directory and initialize npm project
mkdir calculator-server
cd calculator-server
npm init -y

Python

# Create project dir
mkdir calculator-server
cd calculator-server
# Open the folder in Visual Studio Code - Skip this if you are using a different IDE
code .

.NET

dotnet new console -n McpCalculatorServer
cd McpCalculatorServer

Java

För Java, skapa ett Spring Boot-projekt:

curl https://start.spring.io/starter.zip \
  -d dependencies=web \
  -d javaVersion=21 \
  -d type=maven-project \
  -d groupId=com.example \
  -d artifactId=calculator-server \
  -d name=McpServer \
  -d packageName=com.microsoft.mcp.sample.server \
  -o calculator-server.zip

Extrahera zip-filen:

unzip calculator-server.zip -d calculator-server
cd calculator-server
# optional remove the unused test
rm -rf src/test/java

Lägg till följande kompletta konfiguration i din pom.xml-fil:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <!-- Spring Boot parent for dependency management -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.0</version>
        <relativePath />
    </parent>

    <!-- Project coordinates -->
    <groupId>com.example</groupId>
    <artifactId>calculator-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Calculator Server</name>
    <description>Basic calculator MCP service for beginners</description>

    <!-- Properties -->
    <properties>
        <java.version>21</java.version>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
    </properties>

    <!-- Spring AI BOM for version management -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- Dependencies -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
    </dependencies>

    <!-- Build configuration -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <release>21</release>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <!-- Repositories for Spring AI snapshots -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
</project>

Rust

mkdir calculator-server
cd calculator-server
cargo init

-2- Lägg till beroenden

Nu när du har skapat ditt projekt, låt oss lägga till beroenden:

TypeScript

# If not already installed, install TypeScript globally
npm install typescript -g

# Install the MCP SDK and Zod for schema validation
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript

Python

# Create a virtual env and install dependencies
python -m venv venv
venv\Scripts\activate
pip install "mcp[cli]"

Java

cd calculator-server
./mvnw clean install -DskipTests

Rust

cargo add rmcp --features server,transport-io
cargo add serde
cargo add tokio --features rt-multi-thread

-3- Skapa projektfiler

TypeScript

Öppna package.json-filen och ersätt innehållet med följande för att säkerställa att du kan bygga och köra servern:

{
  "name": "calculator-server",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "tsc && node ./build/index.js",
    "build": "tsc && node ./build/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "A simple calculator server using Model Context Protocol",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.16.0",
    "zod": "^3.25.76"
  },
  "devDependencies": {
    "@types/node": "^24.0.14",
    "typescript": "^5.8.3"
  }
}

Skapa en tsconfig.json med följande innehåll:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Skapa en katalog för din källkod:

mkdir src
touch src/index.ts

Python

Skapa en fil server.py

touch server.py

.NET

Installera de nödvändiga NuGet-paketen:

dotnet add package ModelContextProtocol --prerelease
dotnet add package Microsoft.Extensions.Hosting

Java

För Java Spring Boot-projekt skapas projektstrukturen automatiskt.

Rust

För Rust skapas en src/main.rs-fil som standard när du kör cargo init. Öppna filen och ta bort standardkoden.

-4- Skapa serverkod

TypeScript

Skapa en fil index.ts och lägg till följande kod:

import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
 
// Create an MCP server
const server = new McpServer({
  name: "Calculator MCP Server",
  version: "1.0.0"
});

Nu har du en server, men den gör inte mycket, låt oss fixa det.

Python

# server.py
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")

.NET

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(consoleLogOptions =>
{
    // Configure all logs to go to stderr
    consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
});

builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithToolsFromAssembly();
await builder.Build().RunAsync();

// add features

Java

För Java, skapa de centrala serverkomponenterna. Börja med att modifiera huvudapplikationsklassen:

src/main/java/com/microsoft/mcp/sample/server/McpServerApplication.java:

package com.microsoft.mcp.sample.server;

import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.microsoft.mcp.sample.server.service.CalculatorService;

@SpringBootApplication
public class McpServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(McpServerApplication.class, args);
    }
    
    @Bean
    public ToolCallbackProvider calculatorTools(CalculatorService calculator) {
        return MethodToolCallbackProvider.builder().toolObjects(calculator).build();
    }
}

Skapa kalkylatorservicen src/main/java/com/microsoft/mcp/sample/server/service/CalculatorService.java:

package com.microsoft.mcp.sample.server.service;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;

/**
 * Service for basic calculator operations.
 * This service provides simple calculator functionality through MCP.
 */
@Service
public class CalculatorService {

    /**
     * Add two numbers
     * @param a The first number
     * @param b The second number
     * @return The sum of the two numbers
     */
    @Tool(description = "Add two numbers together")
    public String add(double a, double b) {
        double result = a + b;
        return formatResult(a, "+", b, result);
    }

    /**
     * Subtract one number from another
     * @param a The number to subtract from
     * @param b The number to subtract
     * @return The result of the subtraction
     */
    @Tool(description = "Subtract the second number from the first number")
    public String subtract(double a, double b) {
        double result = a - b;
        return formatResult(a, "-", b, result);
    }

    /**
     * Multiply two numbers
     * @param a The first number
     * @param b The second number
     * @return The product of the two numbers
     */
    @Tool(description = "Multiply two numbers together")
    public String multiply(double a, double b) {
        double result = a * b;
        return formatResult(a, "*", b, result);
    }

    /**
     * Divide one number by another
     * @param a The numerator
     * @param b The denominator
     * @return The result of the division
     */
    @Tool(description = "Divide the first number by the second number")
    public String divide(double a, double b) {
        if (b == 0) {
            return "Error: Cannot divide by zero";
        }
        double result = a / b;
        return formatResult(a, "/", b, result);
    }

    /**
     * Calculate the power of a number
     * @param base The base number
     * @param exponent The exponent
     * @return The result of raising the base to the exponent
     */
    @Tool(description = "Calculate the power of a number (base raised to an exponent)")
    public String power(double base, double exponent) {
        double result = Math.pow(base, exponent);
        return formatResult(base, "^", exponent, result);
    }

    /**
     * Calculate the square root of a number
     * @param number The number to find the square root of
     * @return The square root of the number
     */
    @Tool(description = "Calculate the square root of a number")
    public String squareRoot(double number) {
        if (number < 0) {
            return "Error: Cannot calculate square root of a negative number";
        }
        double result = Math.sqrt(number);
        return String.format("√%.2f = %.2f", number, result);
    }

    /**
     * Calculate the modulus (remainder) of division
     * @param a The dividend
     * @param b The divisor
     * @return The remainder of the division
     */
    @Tool(description = "Calculate the remainder when one number is divided by another")
    public String modulus(double a, double b) {
        if (b == 0) {
            return "Error: Cannot divide by zero";
        }
        double result = a % b;
        return formatResult(a, "%", b, result);
    }

    /**
     * Calculate the absolute value of a number
     * @param number The number to find the absolute value of
     * @return The absolute value of the number
     */
    @Tool(description = "Calculate the absolute value of a number")
    public String absolute(double number) {
        double result = Math.abs(number);
        return String.format("|%.2f| = %.2f", number, result);
    }

    /**
     * Get help about available calculator operations
     * @return Information about available operations
     */
    @Tool(description = "Get help about available calculator operations")
    public String help() {
        return "Basic Calculator MCP Service\n\n" +
               "Available operations:\n" +
               "1. add(a, b) - Adds two numbers\n" +
               "2. subtract(a, b) - Subtracts the second number from the first\n" +
               "3. multiply(a, b) - Multiplies two numbers\n" +
               "4. divide(a, b) - Divides the first number by the second\n" +
               "5. power(base, exponent) - Raises a number to a power\n" +
               "6. squareRoot(number) - Calculates the square root\n" + 
               "7. modulus(a, b) - Calculates the remainder of division\n" +
               "8. absolute(number) - Calculates the absolute value\n\n" +
               "Example usage: add(5, 3) will return 5 + 3 = 8";
    }

    /**
     * Format the result of a calculation
     */
    private String formatResult(double a, String operator, double b, double result) {
        return String.format("%.2f %s %.2f = %.2f", a, operator, b, result);
    }
}

Valfria komponenter för en produktionsklar tjänst:

Skapa en startkonfiguration src/main/java/com/microsoft/mcp/sample/server/config/StartupConfig.java:

package com.microsoft.mcp.sample.server.config;

import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class StartupConfig {
    
    @Bean
    public CommandLineRunner startupInfo() {
        return args -> {
            System.out.println("\n" + "=".repeat(60));
            System.out.println("Calculator MCP Server is starting...");
            System.out.println("SSE endpoint: http://localhost:8080/sse");
            System.out.println("Health check: http://localhost:8080/actuator/health");
            System.out.println("=".repeat(60) + "\n");
        };
    }
}

Skapa en hälsokontroller src/main/java/com/microsoft/mcp/sample/server/controller/HealthController.java:

package com.microsoft.mcp.sample.server.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestController
public class HealthController {
    
    @GetMapping("/health")
    public ResponseEntity<Map<String, Object>> healthCheck() {
        Map<String, Object> response = new HashMap<>();
        response.put("status", "UP");
        response.put("timestamp", LocalDateTime.now().toString());
        response.put("service", "Calculator MCP Server");
        return ResponseEntity.ok(response);
    }
}

Skapa en undantagshanterare src/main/java/com/microsoft/mcp/sample/server/exception/GlobalExceptionHandler.java:

package com.microsoft.mcp.sample.server.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException ex) {
        ErrorResponse error = new ErrorResponse(
            "Invalid_Input", 
            "Invalid input parameter: " + ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    public static class ErrorResponse {
        private String code;
        private String message;

        public ErrorResponse(String code, String message) {
            this.code = code;
            this.message = message;
        }

        // Getters
        public String getCode() { return code; }
        public String getMessage() { return message; }
    }
}

Skapa en anpassad banner src/main/resources/banner.txt:

_____      _            _       _             
 / ____|    | |          | |     | |            
| |     __ _| | ___ _   _| | __ _| |_ ___  _ __ 
| |    / _` | |/ __| | | | |/ _` | __/ _ \| '__|
| |___| (_| | | (__| |_| | | (_| | || (_) | |   
 \_____\__,_|_|\___|\__,_|_|\__,_|\__\___/|_|   
                                                
Calculator MCP Server v1.0
Spring Boot MCP Application

Rust

Lägg till följande kod högst upp i src/main.rs-filen. Detta importerar de nödvändiga biblioteken och modulerna för din MCP-server.

use rmcp::{
    handler::server::{router::tool::ToolRouter, tool::Parameters},
    model::{ServerCapabilities, ServerInfo},
    schemars, tool, tool_handler, tool_router,
    transport::stdio,
    ServerHandler, ServiceExt,
};
use std::error::Error;

Kalkylatorservern kommer att vara enkel och kan lägga till två tal tillsammans. Låt oss skapa en struct för att representera kalkylatorförfrågan.

#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
pub struct CalculatorRequest {
    pub a: f64,
    pub b: f64,
}

Skapa sedan en struct för att representera kalkylatorservern. Denna struct kommer att hålla verktygsroutern, som används för att registrera verktyg.

#[derive(Debug, Clone)]
pub struct Calculator {
    tool_router: ToolRouter<Self>,
}

Nu kan vi implementera Calculator-structen för att skapa en ny instans av servern och implementera serverhanteraren för att tillhandahålla serverinformation.

#[tool_router]
impl Calculator {
    pub fn new() -> Self {
        Self {
            tool_router: Self::tool_router(),
        }
    }
}

#[tool_handler]
impl ServerHandler for Calculator {
    fn get_info(&self) -> ServerInfo {
        ServerInfo {
            instructions: Some("A simple calculator tool".into()),
            capabilities: ServerCapabilities::builder().enable_tools().build(),
            ..Default::default()
        }
    }
}

Slutligen behöver vi implementera huvudfunktionen för att starta servern. Denna funktion kommer att skapa en instans av Calculator-structen och köra den över standard in-/utgång.

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let service = Calculator::new().serve(stdio()).await?;
    service.waiting().await?;
    Ok(())
}

Servern är nu inställd för att tillhandahålla grundläggande information om sig själv. Nästa steg är att lägga till ett verktyg för att utföra addition.

-5- Lägga till ett verktyg och en resurs

Lägg till ett verktyg och en resurs genom att lägga till följande kod:

TypeScript

server.tool(
  "add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

server.resource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  async (uri, { name }) => ({
    contents: [{
      uri: uri.href,
      text: `Hello, ${name}!`
    }]
  })
);

Ditt verktyg tar parametrarna a och b och kör en funktion som producerar ett svar i formen:

{
  contents: [{
    type: "text", content: "some content"
  }]
}

Din resurs nås via en sträng "greeting" och tar en parameter name och producerar ett liknande svar som verktyget:

{
  uri: "<href>",
  text: "a text"
}

Python

# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"

I koden ovan har vi:

  • Definierat ett verktyg add som tar parametrarna a och p, båda heltal.
  • Skapat en resurs kallad greeting som tar parametern name.

.NET

Lägg till detta i din Program.cs-fil:

[McpServerToolType]
public static class CalculatorTool
{
    [McpServerTool, Description("Adds two numbers")]
    public static string Add(int a, int b) => $"Sum {a + b}";
}

Java

Verktygen har redan skapats i föregående steg.

Rust

Lägg till ett nytt verktyg inuti impl Calculator-blocket:

#[tool(description = "Adds a and b")]
async fn add(
    &self,
    Parameters(CalculatorRequest { a, b }): Parameters<CalculatorRequest>,
) -> String {
    (a + b).to_string()
}

-6- Slutlig kod

Låt oss lägga till den sista koden vi behöver så att servern kan starta:

TypeScript

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);

Här är den fullständiga koden:

// index.ts
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// Create an MCP server
const server = new McpServer({
  name: "Calculator MCP Server",
  version: "1.0.0"
});

// Add an addition tool
server.tool(
  "add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

// Add a dynamic greeting resource
server.resource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  async (uri, { name }) => ({
    contents: [{
      uri: uri.href,
      text: `Hello, ${name}!`
    }]
  })
);

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
server.connect(transport);

Python

# server.py
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"

# Main execution block - this is required to run the server
if __name__ == "__main__":
    mcp.run()

.NET

Skapa en Program.cs-fil med följande innehåll:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(consoleLogOptions =>
{
    // Configure all logs to go to stderr
    consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
});

builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithToolsFromAssembly();
await builder.Build().RunAsync();

[McpServerToolType]
public static class CalculatorTool
{
    [McpServerTool, Description("Adds two numbers")]
    public static string Add(int a, int b) => $"Sum {a + b}";
}

Java

Din kompletta huvudapplikationsklass bör se ut så här:

// McpServerApplication.java
package com.microsoft.mcp.sample.server;

import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.microsoft.mcp.sample.server.service.CalculatorService;

@SpringBootApplication
public class McpServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(McpServerApplication.class, args);
    }
    
    @Bean
    public ToolCallbackProvider calculatorTools(CalculatorService calculator) {
        return MethodToolCallbackProvider.builder().toolObjects(calculator).build();
    }
}

Rust

Den slutliga koden för Rust-servern bör se ut så här:

use rmcp::{
    ServerHandler, ServiceExt,
    handler::server::{router::tool::ToolRouter, tool::Parameters},
    model::{ServerCapabilities, ServerInfo},
    schemars, tool, tool_handler, tool_router,
    transport::stdio,
};
use std::error::Error;

#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
pub struct CalculatorRequest {
    pub a: f64,
    pub b: f64,
}

#[derive(Debug, Clone)]
pub struct Calculator {
    tool_router: ToolRouter<Self>,
}

#[tool_router]
impl Calculator {
    pub fn new() -> Self {
        Self {
            tool_router: Self::tool_router(),
        }
    }
    
    #[tool(description = "Adds a and b")]
    async fn add(
        &self,
        Parameters(CalculatorRequest { a, b }): Parameters<CalculatorRequest>,
    ) -> String {
        (a + b).to_string()
    }
}

#[tool_handler]
impl ServerHandler for Calculator {
    fn get_info(&self) -> ServerInfo {
        ServerInfo {
            instructions: Some("A simple calculator tool".into()),
            capabilities: ServerCapabilities::builder().enable_tools().build(),
            ..Default::default()
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let service = Calculator::new().serve(stdio()).await?;
    service.waiting().await?;
    Ok(())
}

-7- Testa servern

Starta servern med följande kommando:

TypeScript

npm run build

Python

mcp run server.py

För att använda MCP Inspector, använd mcp dev server.py som automatiskt startar Inspector och tillhandahåller den nödvändiga proxysessionstoken. Om du använder mcp run server.py måste du manuellt starta Inspector och konfigurera anslutningen.

.NET

Se till att du är i din projektkatalog:

cd McpCalculatorServer
dotnet run

Java

./mvnw clean install -DskipTests
java -jar target/calculator-server-0.0.1-SNAPSHOT.jar

Rust

Kör följande kommandon för att formatera och köra servern:

cargo fmt
cargo run

-8- Kör med Inspector

Inspector är ett utmärkt verktyg som kan starta upp din server och låter dig interagera med den så att du kan testa att den fungerar. Låt oss starta den:

Note

Det kan se annorlunda ut i "command"-fältet eftersom det innehåller kommandot för att köra en server med din specifika runtime.

TypeScript

npx @modelcontextprotocol/inspector node build/index.js

eller lägg till det i din package.json som så här: "inspector": "npx @modelcontextprotocol/inspector node build/index.js" och kör sedan npm run inspector

Python omsluter ett Node.js-verktyg som heter inspector. Det är möjligt att kalla detta verktyg så här:

mcp dev server.py

Men det implementerar inte alla metoder som finns tillgängliga på verktyget, så det rekommenderas att köra Node.js-verktyget direkt som nedan:

npx @modelcontextprotocol/inspector mcp run server.py

Om du använder ett verktyg eller IDE som låter dig konfigurera kommandon och argument för att köra skript, se till att ställa in python i Command-fältet och server.py som Arguments. Detta säkerställer att skriptet körs korrekt.

.NET

Se till att du är i din projektkatalog:

cd McpCalculatorServer
npx @modelcontextprotocol/inspector dotnet run

Java

Säkerställ att din kalkylatorserver körs. Kör sedan Inspector:

npx @modelcontextprotocol/inspector

I Inspector-webbgränssnittet:

  1. Välj "SSE" som transporttyp
  2. Ställ in URL till: http://localhost:8080/sse
  3. Klicka på "Connect" Connect

Du är nu ansluten till servern
Testsektionen för Java-servern är nu klar

Nästa sektion handlar om att interagera med servern.

Du bör se följande användargränssnitt:

Connect

  1. Anslut till servern genom att välja knappen "Connect".
    När du har anslutit till servern bör du se följande:

    Connected

  2. Välj "Tools" och "listTools", du bör se "Add" dyka upp. Välj "Add" och fyll i parametervärdena.

    Du bör se följande svar, dvs. ett resultat från verktyget "add":

    Result of running add

Grattis, du har lyckats skapa och köra din första server!

Rust

För att köra Rust-servern med MCP Inspector CLI, använd följande kommando:

npx @modelcontextprotocol/inspector cargo run --cli --method tools/call --tool-name add --tool-arg a=1 b=2

Officiella SDK:er

MCP tillhandahåller officiella SDK:er för flera språk:

  • C# SDK - Underhålls i samarbete med Microsoft
  • Java SDK - Underhålls i samarbete med Spring AI
  • TypeScript SDK - Den officiella TypeScript-implementeringen
  • Python SDK - Den officiella Python-implementeringen
  • Kotlin SDK - Den officiella Kotlin-implementeringen
  • Swift SDK - Underhålls i samarbete med Loopwork AI
  • Rust SDK - Den officiella Rust-implementeringen

Viktiga punkter

  • Att sätta upp en MCP-utvecklingsmiljö är enkelt med språk-specifika SDK:er
  • Att bygga MCP-servrar innebär att skapa och registrera verktyg med tydliga scheman
  • Testning och felsökning är avgörande för pålitliga MCP-implementationer

Exempel

Uppgift

Skapa en enkel MCP-server med ett verktyg du väljer:

  1. Implementera verktyget i ditt föredragna språk (.NET, Java, Python, TypeScript eller Rust).
  2. Definiera inparametrar och returvärden.
  3. Kör inspektionsverktyget för att säkerställa att servern fungerar som avsett.
  4. Testa implementationen med olika indata.

Lösning

Lösning

Ytterligare resurser

Vad händer härnäst

Nästa: Kom igång med MCP-klienter

Ansvarsfriskrivning:
Detta dokument har översatts med hjälp av AI-översättningstjänsten Co-op Translator. Även om vi strävar efter noggrannhet, vänligen notera att automatiska översättningar kan innehålla fel eller felaktigheter. Det ursprungliga dokumentet på dess originalspråk bör betraktas som den auktoritativa källan. För kritisk information rekommenderas professionell mänsklig översättning. Vi ansvarar inte för eventuella missförstånd eller feltolkningar som uppstår vid användning av denna översättning.