# Започване с MCP Добре дошли в първите си стъпки с Model Context Protocol (MCP)! Независимо дали сте нови в MCP или искате да задълбочите разбирането си, това ръководство ще ви преведе през основния процес на настройка и разработка. Ще откриете как MCP позволява безпроблемна интеграция между AI модели и приложения, и ще научите как бързо да подготвите средата си за създаване и тестване на решения с MCP. > TLDR; Ако създавате AI приложения, знаете, че можете да добавяте инструменти и други ресурси към вашия LLM (голям езиков модел), за да направите LLM по-знаещ. Но ако поставите тези инструменти и ресурси на сървър, възможностите на приложението и на сървъра могат да се използват от всеки клиент с/без LLM. ## Обзор Този урок предоставя практическо ръководство за настройка на MCP среди и създаване на първите ви MCP приложения. Ще научите как да настроите необходимите инструменти и рамки, да създадете базови MCP сървъри, да създадете хост приложения и да тествате вашите реализации. Model Context Protocol (MCP) е отворен протокол, който стандартизира начина, по който приложенията предоставят контекст на LLM. Мислете за MCP като за USB-C порт за AI приложения - той предлага стандартизиран начин за свързване на AI модели с различни източници на данни и инструменти. ## Учебни цели Към края на този урок ще можете да: - Настроите среди за разработка на MCP с C#, Java, Python, TypeScript и Rust - Създадете и внедрите базови MCP сървъри с персонализирани функции (ресурси, подсказки и инструменти) - Създадете хост приложения, които се свързват с MCP сървъри - Тествате и отстранявате грешки при реализации на MCP ## Настройка на вашата MCP среда Преди да започнете работа с MCP, е важно да подготвите средата си за разработка и да разберете основния работен процес. Този раздел ще ви преведе през първоначалните стъпки, за да ви осигури гладък старт с MCP. ### Изисквания Преди да се потопите в разработката на MCP, уверете се, че имате: - **Среда за разработка**: За избрания от вас език (C#, Java, Python, TypeScript или Rust) - **IDE/редактор**: Visual Studio, Visual Studio Code, IntelliJ, Eclipse, PyCharm или някой модерен редактор за код - **Мениджъри на пакети**: NuGet, Maven/Gradle, pip, npm/yarn или Cargo - **API ключове**: За всички AI услуги, които планирате да използвате в хост приложенията си ## Основна структура на MCP сървър MCP сървърът обикновено включва: - **Конфигурация на сървъра**: Настройка на порт, удостоверяване и други настройки - **Ресурси**: Данни и контекст, достъпни за LLM - **Инструменти**: Функционалности, които моделите могат да извикват - **Подсказки**: Шаблони за генериране или структуриране на текст Ето един опростен пример на TypeScript: ```typescript import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; // Създаване на MCP сървър const server = new McpServer({ name: "Demo", version: "1.0.0" }); // Добавяне на инструмент за събиране server.tool("add", { a: z.number(), b: z.number() }, async ({ a, b }) => ({ content: [{ type: "text", text: String(a + b) }] }) ); // Добавяне на динамичен ресурс за поздрав server.resource( "file", // Параметърът 'list' контролира как ресурсът изброява наличните файлове. Задаването му на undefined деактивира изброяването за този ресурс. new ResourceTemplate("file://{path}", { list: undefined }), async (uri, { path }) => ({ contents: [{ uri: uri.href, text: `File, ${path}!` }] }) ); // Добавяне на файлов ресурс, който чете съдържанието на файла 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}` } }] }) ); // Започнете да получавате съобщения на stdin и да изпращате съобщения на stdout const transport = new StdioServerTransport(); await server.connect(transport); ``` В горния код ние: - Импортираме необходимите класове от MCP TypeScript SDK. - Създаваме и конфигурираме нов MCP сървър. - Регистрираме персонализиран инструмент (`calculator`) с функция за обработка. - Стартираме сървъра, за да слуша входящи MCP заявки. ## Тестване и отстраняване на грешки Преди да започнете да тествате вашия MCP сървър, е важно да разберете наличните инструменти и добрите практики за отстраняване на грешки. Ефективното тестване гарантира, че вашият сървър работи както се очаква, и ви помага бързо да идентифицирате и разрешите проблеми. Следващият раздел описва препоръчителни подходи за валидиране на вашата MCP реализация. MCP предоставя инструменти, които помагат при тестването и отстраняването на грешки на вашите сървъри: - **Inspector tool**, този графичен интерфейс ви позволява да се свържете със сървъра и да тествате вашите инструменти, подсказки и ресурси. - **curl**, можете също да се свържете със сървъра си чрез команден инструмент като curl или други клиенти, които могат да изготвят и изпращат HTTP команди. ### Използване на MCP Inspector [MCP Inspector](https://github.com/modelcontextprotocol/inspector) е визуален инструмент за тестване, който ви помага да: 1. **Откриете възможностите на сървъра**: Автоматично откриване на налични ресурси, инструменти и подсказки 2. **Тествате изпълнението на инструменти**: Пробвайте различни параметри и вижте отговорите в реално време 3. **Прегледате метаданните на сървъра**: Изследвайте информацията за сървъра, схеми и конфигурации ```bash # Пример TypeScript, инсталиране и стартиране на MCP Inspector npx @modelcontextprotocol/inspector node build/index.js ``` Когато изпълните горните команди, MCP Inspector ще стартира локален уеб интерфейс в браузъра ви. Можете да очаквате табло за управление, показващо регистрираните MCP сървъри, наличните им инструменти, ресурси и подсказки. Интерфейсът ви позволява интерактивно да тествате изпълнението на инструменти, да преглеждате метаданни на сървъра и да виждате отговори в реално време, което улеснява валидирането и отстраняването на грешки при MCP реализации. Ето екранна снимка на как може да изглежда: ![MCP Inspector server connection](../../../../translated_images/bg/connected.73d1e042c24075d3.webp) ## Често срещани проблеми при настройка и решения | Проблем | Възможно решение | |---------|------------------| | Връзката отказана | Проверете дали сървърът работи и дали портът е правилен | | Грешки при изпълнение на инструмент | Прегледайте валидацията на параметрите и обработката на грешки | | Проблеми с удостоверяване | Проверете API ключовете и разрешенията | | Грешки при валидация на схема | Уверете се, че параметрите съответстват на дефинираната схема | | Сървърът не стартира | Проверете за конфликти на портове или липсващи зависимости | | Грешки CORS | Настройте правилните CORS заглавки за заявки от други източници | | Проблеми с удостоверяване | Проверете валидността на токена и разрешенията | ## Локална разработка За локална разработка и тестване можете да стартирате MCP сървъри директно на вашия компютър: 1. **Стартирайте процеса на сървъра**: Стартирайте вашето MCP сървър приложение 2. **Конфигурирайте мрежата**: Уверете се, че сървърът е достъпен на очаквания порт 3. **Свържете клиенти**: Използвайте локални URL адреси като `http://localhost:3000` ```bash # Пример: Стартиране на TypeScript MCP сървър локално npm run start # Сървърът работи на http://localhost:3000 ``` ## Създаване на първия ви MCP сървър В предишен урок разгледахме [Основни концепции](../../01-CoreConcepts/README.md), сега е време да приложим тези знания на практика. ### Какво може да прави един сървър Преди да започнем да пишем код, нека си припомним какво може да прави един сървър: MCP сървърът може например да: - Дава достъп до локални файлове и бази данни - Свързва се с отдалечени API-та - Извършва изчисления - Интегрира се с други инструменти и услуги - Предлага потребителски интерфейс за взаимодействие Отлично, сега когато знаем какво може, нека започваме да пишем код. ## Упражнение: Създаване на сървър За да създадете сървър, трябва да следвате следните стъпки: - Инсталирайте MCP SDK. - Създайте проект и настройте структурата на проекта. - Напишете кода на сървъра. - Тествайте сървъра. ### -1- Създаване на проект #### TypeScript ```sh # Създайте проектна директория и инициализирайте npm проект mkdir calculator-server cd calculator-server npm init -y ``` #### Python ```sh # Създайте директория за проекта mkdir calculator-server cd calculator-server # Отворете папката във Visual Studio Code - Пропуснете това, ако използвате друг IDE code . ``` #### .NET ```sh dotnet new console -n McpCalculatorServer cd McpCalculatorServer ``` #### Java За Java създайте Spring Boot проект: ```bash 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 ``` Разархивирайте zip файла: ```bash unzip calculator-server.zip -d calculator-server cd calculator-server # по желание премахнете неизползвания тест rm -rf src/test/java ``` Добавете следната пълна конфигурация във вашия *pom.xml* файл: ```xml 4.0.0 org.springframework.boot spring-boot-starter-parent 3.5.0 com.example calculator-server 0.0.1-SNAPSHOT Calculator Server Basic calculator MCP service for beginners 21 21 21 org.springframework.ai spring-ai-bom 1.0.0-SNAPSHOT pom import org.springframework.ai spring-ai-starter-mcp-server-webflux org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin 21 spring-milestones Spring Milestones https://repo.spring.io/milestone false spring-snapshots Spring Snapshots https://repo.spring.io/snapshot false ``` #### Rust ```sh mkdir calculator-server cd calculator-server cargo init ``` ### -2- Добавяне на зависимости След като имате създаден проект, нека добавим зависимостите: #### TypeScript ```sh # Ако не е инсталиран, инсталирайте TypeScript глобално npm install typescript -g # Инсталирайте MCP SDK и Zod за валидиране на схеми npm install @modelcontextprotocol/sdk zod npm install -D @types/node typescript ``` #### Python ```sh # Създайте виртуална среда и инсталирайте зависимости python -m venv venv venv\Scripts\activate pip install "mcp[cli]" ``` #### Java ```bash cd calculator-server ./mvnw clean install -DskipTests ``` #### Rust ```sh cargo add rmcp --features server,transport-io cargo add serde cargo add tokio --features rt-multi-thread ``` ### -3- Създаване на файлове на проекта #### TypeScript Отворете файла *package.json* и заменете съдържанието му със следното, за да осигурите възможност за билд и стартиране на сървъра: ```json { "name": "calculator-server", "version": "1.0.0", "main": "index.js", "type": "module", "scripts": { "build": "tsc", "start": "npm run build && 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" } } ``` Създайте файл *tsconfig.json* със следното съдържание: ```json { "compilerOptions": { "target": "ES2022", "module": "Node16", "moduleResolution": "Node16", "outDir": "./build", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules"] } ``` Създайте директория за изходния код: ```sh mkdir src touch src/index.ts ``` #### Python Създайте файл *server.py* ```sh touch server.py ``` #### .NET Инсталирайте нужните NuGet пакети: ```sh dotnet add package ModelContextProtocol --prerelease dotnet add package Microsoft.Extensions.Hosting ``` #### Java При Java Spring Boot проекти структурата на проекта се създава автоматично. #### Rust При Rust по подразбиране се създава файл *src/main.rs* при стартиране на `cargo init`. Отворете файла и изтрийте кода по подразбиране. ### -4- Създаване на код на сървъра #### TypeScript Създайте файл *index.ts* и добавете следния код: ```typescript import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; // Създайте MCP сървър const server = new McpServer({ name: "Calculator MCP Server", version: "1.0.0" }); ``` Сега имате сървър, но той не прави много, нека оправим това. #### Python ```python # server.py from mcp.server.fastmcp import FastMCP # Създайте MCP сървър mcp = FastMCP("Demo") ``` #### .NET ```csharp 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 За Java създайте основните компоненти на сървъра. Първо модифицирайте основния клас на приложението: *src/main/java/com/microsoft/mcp/sample/server/McpServerApplication.java*: ```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(); } } ``` Създайте услугата калкулатор *src/main/java/com/microsoft/mcp/sample/server/service/CalculatorService.java*: ```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); } } ``` **Допълнителни компоненти за продукционно готова услуга:** Създайте конфигурация за стартиране *src/main/java/com/microsoft/mcp/sample/server/config/StartupConfig.java*: ```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"); }; } } ``` Създайте контролер за здравето *src/main/java/com/microsoft/mcp/sample/server/controller/HealthController.java*: ```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> healthCheck() { Map response = new HashMap<>(); response.put("status", "UP"); response.put("timestamp", LocalDateTime.now().toString()); response.put("service", "Calculator MCP Server"); return ResponseEntity.ok(response); } } ``` Създайте обработчик на изключения *src/main/java/com/microsoft/mcp/sample/server/exception/GlobalExceptionHandler.java*: ```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 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; } // Гетъри public String getCode() { return code; } public String getMessage() { return message; } } } ``` Създайте персонален банер *src/main/resources/banner.txt*: ```text _____ _ _ _ / ____| | | | | | | | | __ _| | ___ _ _| | __ _| |_ ___ _ __ | | / _` | |/ __| | | | |/ _` | __/ _ \| '__| | |___| (_| | | (__| |_| | | (_| | || (_) | | \_____\__,_|_|\___|\__,_|_|\__,_|\__\___/|_| Calculator MCP Server v1.0 Spring Boot MCP Application ``` #### Rust Добавете следния код в началото на файла *src/main.rs*. Той импортира необходимите библиотеки и модули за вашия MCP сървър. ```rust 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; ``` Калкулаторният сървър ще бъде прост и ще може да събира две числа. Нека създадем структура, която да представлява заявката към калкулатора. ```rust #[derive(Debug, serde::Deserialize, schemars::JsonSchema)] pub struct CalculatorRequest { pub a: f64, pub b: f64, } ``` След това създайте структура, която да представлява калкулаторния сървър. Тази структура ще държи маршрутизатора за инструментите, който се използва за регистрация на инструменти. ```rust #[derive(Debug, Clone)] pub struct Calculator { tool_router: ToolRouter, } ``` Сега можем да имплементираме `Calculator` структурата за създаване на нов инстанс на сървъра и имплементиране на обработчика, който предоставя информация за сървъра. ```rust #[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() } } } ``` Накрая трябва да имплементираме главната функция за стартиране на сървъра. Тази функция ще създаде инстанс на `Calculator` структурата и ще я стартира чрез стандартен вход/изход. ```rust #[tokio::main] async fn main() -> Result<(), Box> { let service = Calculator::new().serve(stdio()).await?; service.waiting().await?; Ok(()) } ``` Сървърът вече е настроен да предоставя основна информация за себе си. След това ще добавим инструмент за извършване на събиране. ### -5- Добавяне на инструмент и ресурс Добавете инструмент и ресурс с следния код: #### TypeScript ```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}!` }] }) ); ``` Вашият инструмент приема параметри `a` и `b` и изпълнява функция, която връща отговор във формата: ```typescript { contents: [{ type: "text", content: "some content" }] } ``` Вашият ресурс се достъпва чрез низ "greeting" и приема параметър `name`, като връща подобен на инструмента отговор: ```typescript { uri: "", text: "a text" } ``` #### Python ```python # Добавете инструмент за събиране @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b # Добавете динамичен ресурс за поздравление @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" ``` В горния код: - Дефинирахме инструмент `add`, който приема параметри `a` и `b`, и двата цели числа. - Създадохме ресурс, наречен `greeting`, който приема параметър `name`. #### .NET Добавете това във вашия Program.cs файл: ```csharp [McpServerToolType] public static class CalculatorTool { [McpServerTool, Description("Adds two numbers")] public static string Add(int a, int b) => $"Sum {a + b}"; } ``` #### Java Инструментите вече са създадени в предишната стъпка. #### Rust Добавете нов инструмент в блока `impl Calculator`: ```rust #[tool(description = "Adds a and b")] async fn add( &self, Parameters(CalculatorRequest { a, b }): Parameters, ) -> String { (a + b).to_string() } ``` ### -6- Финален код Нека добавим последния необходим код, за да може сървърът да стартира: #### TypeScript ```typescript // Започнете да получавате съобщения на stdin и да изпращате съобщения на stdout const transport = new StdioServerTransport(); await server.connect(transport); ``` Ето пълния код: ```typescript // index.ts import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; // Създаване на MCP сървър const server = new McpServer({ name: "Calculator MCP Server", version: "1.0.0" }); // Добавяне на инструмент за събиране 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}!` }] }) ); // Започване на получаване на съобщения от stdin и изпращане на съобщения в stdout const transport = new StdioServerTransport(); server.connect(transport); ``` #### Python ```python # server.py from mcp.server.fastmcp import FastMCP # Създаване на MCP сървър mcp = FastMCP("Demo") # Добавяне на инструмент за събиране @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b # Добавяне на динамичен ресурс за поздрав @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" # Главен блок за изпълнение - това е необходимо за стартиране на сървъра if __name__ == "__main__": mcp.run() ``` #### .NET Създайте файл Program.cs със следното съдържание: ```csharp 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 Вашият завършен основен клас на приложението трябва да изглежда така: ```java // 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 Крайният код за Rust сървъра трябва да изглежда така: ```rust 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, } #[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, ) -> 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> { let service = Calculator::new().serve(stdio()).await?; service.waiting().await?; Ok(()) } ``` ### -7- Тест на сървъра Стартирайте сървъра със следната команда: #### TypeScript ```sh npm run build ``` #### Python ```sh mcp run server.py ``` > За да използвате MCP Inspector, използвайте командата `mcp dev server.py`, която автоматично стартира Inspector и осигурява необходимия прокси сесия токен. Ако използвате `mcp run server.py`, ще трябва ръчно да стартирате Inspector и да конфигурирате връзката. #### .NET Уверете се, че сте в директорията на проекта: ```sh cd McpCalculatorServer dotnet run ``` #### Java ```bash ./mvnw clean install -DskipTests java -jar target/calculator-server-0.0.1-SNAPSHOT.jar ``` #### Rust Изпълнете следните команди за форматиране и стартиране на сървъра: ```sh cargo fmt cargo run ``` ### -8- Стартиране чрез inspector Inspector е страхотен инструмент, който може да стартира вашия сървър и ви позволява да взаимодействате с него, за да тествате дали всичко работи. Нека го стартираме: > [!NOTE] > командата може да изглежда различно в полето "command", тъй като съдържа команда за стартиране на сървър с вашия специфичен runtime. #### TypeScript ```sh npx @modelcontextprotocol/inspector node build/index.js ``` или го добавете към вашия *package.json* така: `"inspector": "npx @modelcontextprotocol/inspector node build/index.js"` и след това стартирайте `npm run inspector` #### Python Python обвива Node.js инструмент, наречен inspector. Можете да извикате този инструмент по следния начин: ```sh mcp dev server.py ``` Все пак, той не поддържа всички методи, налични в инструмента, затова се препоръчва да стартирате Node.js инструмента директно, както е показано по-долу: ```sh npx @modelcontextprotocol/inspector mcp run server.py ``` Ако използвате инструмент или IDE, която позволява конфигуриране на команди и аргументи за стартиране на скриптове, уверете се, че сте задали `python` в полето `Command` и `server.py` като `Arguments`. Това гарантира, че скриптът ще се изпълни правилно. #### .NET Уверете се, че сте в директорията на проекта си: ```sh cd McpCalculatorServer npx @modelcontextprotocol/inspector dotnet run ``` #### Java Уверете се, че вашият calculator server работи След това стартирайте инспектора: ```cmd npx @modelcontextprotocol/inspector ``` В уеб интерфейса на инспектора: 1. Изберете "SSE" като тип транспорт 2. Задайте URL на: `http://localhost:8080/sse` 3. Натиснете "Connect" ![Connect](../../../../translated_images/bg/tool.163d33e3ee307e20.webp) **Вече сте свързани със сървъра** **Тестовият раздел за Java сървъра е завършен** Следващият раздел е за взаимодействие със сървъра. Трябва да видите следния потребителски интерфейс: ![Connect](../../../../translated_images/bg/connect.141db0b2bd05f096.webp) 1. Свържете се със сървъра като изберете бутона Connect След като се свържете със сървъра, трябва да видите следното: ![Connected](../../../../translated_images/bg/connected.73d1e042c24075d3.webp) 1. Изберете "Tools" и "listTools", трябва да видите, че се показва "Add", изберете "Add" и попълнете стойностите на параметрите. Трябва да видите следния отговор, т.е. резултат от инструмента "add": ![Result of running add](../../../../translated_images/bg/ran-tool.a5a6ee878c1369ec.webp) Поздравления, успяхте да създадете и стартирате първия си сървър! #### Rust За да стартирате Rust сървъра с MCP Inspector CLI, използвайте следната команда: ```sh npx @modelcontextprotocol/inspector cargo run --cli --method tools/call --tool-name add --tool-arg a=1 b=2 ``` ### Официални SDK MCP предоставя официални SDK за множество езици: - [C# SDK](https://github.com/modelcontextprotocol/csharp-sdk) - Поддържан в сътрудничество с Microsoft - [Java SDK](https://github.com/modelcontextprotocol/java-sdk) - Поддържан в сътрудничество с Spring AI - [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) - Официална TypeScript имплементация - [Python SDK](https://github.com/modelcontextprotocol/python-sdk) - Официална Python имплементация - [Kotlin SDK](https://github.com/modelcontextprotocol/kotlin-sdk) - Официална Kotlin имплементация - [Swift SDK](https://github.com/modelcontextprotocol/swift-sdk) - Поддържан в сътрудничество с Loopwork AI - [Rust SDK](https://github.com/modelcontextprotocol/rust-sdk) - Официална Rust имплементация ## Основни изводи - Настройването на MCP среди за разработка е лесно с езиково-специфични SDK - Изграждането на MCP сървъри включва създаване и регистриране на инструменти с ясни схеми - Тестването и отстраняването на грешки са от съществено значение за надеждни MCP реализации ## Примери - [Java Calculator](../samples/java/calculator/README.md) - [.Net Calculator](../../../../03-GettingStarted/samples/csharp) - [JavaScript Calculator](../samples/javascript/README.md) - [TypeScript Calculator](../samples/typescript/README.md) - [Python Calculator](../../../../03-GettingStarted/samples/python) - [Rust Calculator](../../../../03-GettingStarted/samples/rust) ## Задача Създайте прост MCP сървър с инструмент по ваш избор: 1. Реализирайте инструмента на предпочитания от вас език (.NET, Java, Python, TypeScript или Rust). 2. Определете входни параметри и стойности за връщане. 3. Стартирайте инспекторския инструмент, за да проверите дали сървърът работи както трябва. 4. Тествайте реализацията с различни входни данни. ## Решение [Решение](./solution/README.md) ## Допълнителни ресурси - [Създаване на агенти с Model Context Protocol в Azure](https://learn.microsoft.com/azure/developer/ai/intro-agents-mcp) - [Дистанционен MCP с Azure Container Apps (Node.js/TypeScript/JavaScript)](https://learn.microsoft.com/samples/azure-samples/mcp-container-ts/mcp-container-ts/) - [.NET OpenAI MCP Agent](https://learn.microsoft.com/samples/azure-samples/openai-mcp-agent-dotnet/openai-mcp-agent-dotnet/) ## Какво следва Следва: [Започване с MCP Clients](../02-client/README.md) --- **Отказ от отговорност**: Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за никакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.