27 KiB
MCP сервер с транспортом stdio
⚠️ Важное обновление: Начиная с спецификации MCP 2025-06-18, отдельный транспорт SSE (Server-Sent Events) был устаревшим и заменён транспортом "Streamable HTTP". Текущая спецификация MCP определяет два основных механизма транспорта:
- stdio - стандартный ввод/вывод (рекомендуется для локальных серверов)
- Streamable HTTP - для удалённых серверов, которые могут использовать SSE внутренне
Этот урок обновлён и теперь фокусируется на транспорте stdio, который является рекомендуемым подходом для большинства реализаций MCP серверов.
Транспорт stdio позволяет MCP серверам общаться с клиентами через стандартные потоки ввода и вывода. Это самый часто используемый и рекомендуемый механизм транспорта в текущей спецификации MCP, обеспечивающий простой и эффективный способ создания MCP серверов, которые легко интегрируются с различными клиентскими приложениями.
Обзор
В этом уроке рассмотрено, как создавать и использовать MCP серверы с помощью транспорта stdio.
Цели обучения
К концу этого урока вы сможете:
- Создавать MCP сервер с использованием транспорта stdio.
- Отлаживать MCP сервер с помощью инспектора (Inspector).
- Использовать MCP сервер с помощью Visual Studio Code.
- Понимать текущие механизмы транспорта MCP и почему рекомендуют stdio.
Транспорт stdio - как это работает
Транспорт stdio — один из двух поддерживаемых типов транспорта в текущей спецификации MCP (2025-11-25). Вот как он работает:
- Простая коммуникация: сервер читает сообщения JSON-RPC из стандартного ввода (
stdin) и отправляет сообщения в стандартный вывод (stdout). - Основан на процессе: клиент запускает MCP сервер как подчинённый процесс.
- Формат сообщений: сообщения — отдельные запросы, уведомления или ответы JSON-RPC, разделённые символами новой строки.
- Логирование: сервер МОЖЕТ записывать UTF-8 строки в стандартный поток ошибок (
stderr) для логирования.
Ключевые требования:
- Сообщения ДОЛЖНЫ разделяться символами новой строки и НЕ ДОЛЖНЫ содержать встроенные новые строки
- Сервер НЕ ДОЛЖЕН писать в
stdoutничего, что не является валидным сообщением MCP - Клиент НЕ ДОЛЖЕН писать в
stdinсервера ничего, что не является валидным сообщением MCP
TypeScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{
name: "example-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
runServer().catch(console.error);
В приведённом коде:
- Импортируется класс
Serverи транспортStdioServerTransportиз MCP SDK - Создаётся экземпляр сервера с базовой конфигурацией и возможностями
- Создаётся экземпляр
StdioServerTransportи сервер подключается к нему, что обеспечивает связь через stdin/stdout
Python
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
# Создать экземпляр сервера
server = Server("example-server")
@server.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
В приведённом коде мы:
- Создаём экземпляр сервера с помощью MCP SDK
- Определяем инструменты с помощью декораторов
- Используем менеджер контекста stdio_server для работы с транспортом
.NET
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools<Tools>();
builder.Services.AddLogging(logging => logging.AddConsole());
var app = builder.Build();
await app.RunAsync();
Ключевое отличие от SSE в том, что stdio сервера:
- Не требуют настройки веб-сервера или HTTP эндпоинтов
- Запускаются клиентом как подчинённые процессы
- Общаются через потоки stdin/stdout
- Проще в реализации и отладке
Практическое задание: создание stdio сервера
Для создания нашего сервера нужно учитывать два момента:
- Для подключения и обмена сообщениями потребуется веб-сервер.
Лабораторная работа: создание простого MCP stdio сервера
В этой лабораторной работе мы создадим простой MCP сервер с использованием рекомендованного транспорта stdio. Этот сервер будет предоставлять инструменты, которые клиенты смогут вызывать с помощью стандартного протокола Model Context Protocol.
Предварительные требования
- Python 3.8 или новее
- MCP Python SDK:
pip install mcp - Базовые знания асинхронного программирования
Начнём с создания нашего первого MCP stdio сервера:
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
# Настроить логирование
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Создать сервер
server = Server("example-stdio-server")
@server.tool()
def calculate_sum(a: int, b: int) -> int:
"""Calculate the sum of two numbers"""
return a + b
@server.tool()
def get_greeting(name: str) -> str:
"""Generate a personalized greeting"""
return f"Hello, {name}! Welcome to MCP stdio server."
async def main():
# Использовать транспорт stdio
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
Ключевые отличия от устаревшего подхода SSE
Транспорт Stdio (текущий стандарт):
- Простая модель подчинённого процесса — клиент запускает сервер как дочерний процесс
- Связь через stdin/stdout с использованием сообщений JSON-RPC
- Не требуется настройка HTTP сервера
- Лучшее быстродействие и безопасность
- Проще в отладке и разработке
Транспорт SSE (устарел с MCP 2025-06-18):
- Требовался HTTP сервер с SSE эндпоинтами
- Более сложная настройка с инфраструктурой веб-сервера
- Дополнительные соображения безопасности для HTTP эндпоинтов
- Сейчас заменён на Streamable HTTP для веб-сценариев
Создание сервера с транспортом stdio
Чтобы создать наш stdio сервер, нужно:
- Импортировать необходимые библиотеки — необходимы компоненты MCP сервера и транспорт stdio
- Создать экземпляр сервера — определить сервер с его возможностями
- Определить инструменты — добавить функциональность для вызова
- Настроить транспорт — сконфигурировать связь stdio
- Запустить сервер — стартовать сервер и обрабатывать сообщения
Построим это шаг за шагом:
Шаг 1: Создание базового stdio сервера
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
# Настроить логирование
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Создать сервер
server = Server("example-stdio-server")
@server.tool()
def get_greeting(name: str) -> str:
"""Generate a personalized greeting"""
return f"Hello, {name}! Welcome to MCP stdio server."
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
Шаг 2: Добавление инструментов
@server.tool()
def calculate_sum(a: int, b: int) -> int:
"""Calculate the sum of two numbers"""
return a + b
@server.tool()
def calculate_product(a: int, b: int) -> int:
"""Calculate the product of two numbers"""
return a * b
@server.tool()
def get_server_info() -> dict:
"""Get information about this MCP server"""
return {
"server_name": "example-stdio-server",
"version": "1.0.0",
"transport": "stdio",
"capabilities": ["tools"]
}
Шаг 3: Запуск сервера
Сохраните код в server.py и запустите его из командной строки:
python server.py
Сервер запустится и будет ждать ввода через stdin. Он общается с помощью сообщений JSON-RPC через транспорт stdio.
Шаг 4: Тестирование с помощью Inspector
Вы можете протестировать ваш сервер с помощью MCP Inspector:
- Установите Inspector:
npx @modelcontextprotocol/inspector - Запустите Inspector и укажите ваш сервер
- Проверьте созданные вами инструменты
.NET
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddMcpServer();
Отладка вашего stdio сервера
Использование MCP Inspector
MCP Inspector — полезный инструмент для отладки и тестирования MCP серверов. Вот как использовать его с вашим stdio сервером:
-
Установка Inspector:
npx @modelcontextprotocol/inspector -
Запуск Inspector:
npx @modelcontextprotocol/inspector python server.py -
Тестирование сервера: Inspector предоставляет веб-интерфейс, где вы можете:
- Просматривать возможности сервера
- Тестировать инструменты с разными параметрами
- Отслеживать сообщения JSON-RPC
- Отлаживать проблемы подключения
Использование VS Code
Вы также можете отлаживать MCP сервер непосредственно в VS Code:
-
Создайте конфигурацию запуска в
.vscode/launch.json:{ "version": "0.2.0", "configurations": [ { "name": "Debug MCP Server", "type": "python", "request": "launch", "program": "server.py", "console": "integratedTerminal" } ] } -
Установите точки останова в коде сервера
-
Запустите отладчик и тестируйте с Inspector
Общие советы по отладке
- Используйте
stderrдля логов — никогда не пишите вstdout, так как он зарезервирован для сообщений MCP - Убедитесь, что все сообщения JSON-RPC разделены символом новой строки
- Сначала тестируйте простые инструменты перед добавлением сложного функционала
- Используйте Inspector для проверки форматов сообщений
Использование вашего stdio сервера в VS Code
После создания MCP stdio сервера вы можете интегрировать его с VS Code, чтобы использовать с Claude или другими клиентами, совместимыми с MCP.
Конфигурация
-
Создайте MCP конфигурационный файл в
%APPDATA%\Claude\claude_desktop_config.json(Windows) или~/Library/Application Support/Claude/claude_desktop_config.json(Mac):{ "mcpServers": { "example-stdio-server": { "command": "python", "args": ["path/to/your/server.py"] } } } -
Перезапустите Claude: закройте и снова откройте Claude, чтобы применить новую конфигурацию сервера.
-
Проверьте подключение: начните разговор с Claude и попробуйте использовать инструменты вашего сервера:
- «Можешь поздороваться со мной, используя инструмент приветствия?»
- «Посчитай сумму 15 и 27»
- «Какая информация о сервере?»
Пример stdio сервера на TypeScript
Вот полный пример на TypeScript для справки:
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{
name: "example-stdio-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Добавить инструменты
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_greeting",
description: "Get a personalized greeting",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "Name of the person to greet",
},
},
required: ["name"],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_greeting") {
return {
content: [
{
type: "text",
text: `Hello, ${request.params.arguments?.name}! Welcome to MCP stdio server.`,
},
],
};
} else {
throw new Error(`Unknown tool: ${request.params.name}`);
}
});
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
runServer().catch(console.error);
Пример stdio сервера на .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.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools<Tools>();
var app = builder.Build();
await app.RunAsync();
[McpServerToolType]
public class Tools
{
[McpServerTool, Description("Get a personalized greeting")]
public string GetGreeting(string name)
{
return $"Hello, {name}! Welcome to MCP stdio server.";
}
[McpServerTool, Description("Calculate the sum of two numbers")]
public int CalculateSum(int a, int b)
{
return a + b;
}
}
Итоги
В этом обновлённом уроке вы научились:
- Создавать MCP серверы с использованием текущего транспорта stdio (рекомендуемый подход)
- Понимать, почему транспорт SSE был устаревшим в пользу stdio и Streamable HTTP
- Создавать инструменты, которые можно вызывать из MCP клиентов
- Отлаживать сервер с помощью MCP Inspector
- Интегрировать stdio сервер с VS Code и Claude
Транспорт stdio предоставляет более простой, безопасный и эффективный способ создания MCP серверов по сравнению с устаревшим подходом SSE. Это рекомендуемый транспорт для большинства реализаций MCP серверов на момент спецификации 2025-06-18.
.NET
- Сначала давайте создадим несколько инструментов, для этого создадим файл Tools.cs со следующим содержимым:
using System.ComponentModel;
using System.Text.Json;
using ModelContextProtocol.Server;
Практическое задание: тестирование вашего stdio сервера
Теперь, когда вы создали сервер stdio, давайте протестируем его, чтобы убедиться, что он работает правильно.
Предварительные требования
-
Убедитесь, что у вас установлен MCP Inspector:
npm install -g @modelcontextprotocol/inspector -
Ваш код сервера должен быть сохранён (например, в
server.py)
Тестирование с Inspector
-
Запустите Inspector с вашим сервером:
npx @modelcontextprotocol/inspector python server.py -
Откройте веб-интерфейс: Inspector откроет окно браузера с возможностями вашего сервера.
-
Тестируйте инструменты:
- Попробуйте инструмент
get_greetingс разными именами - Проверьте
calculate_sumс разными числами - Вызовите
get_server_infoчтобы увидеть метаданные сервера
- Попробуйте инструмент
-
Отслеживайте связь: Inspector показывает JSON-RPC сообщения между клиентом и сервером.
Что вы должны увидеть
Когда сервер корректно запущен, вы должны увидеть:
- Возможности сервера, отображённые в Inspector
- Доступные инструменты для тестирования
- Успешный обмен сообщениями JSON-RPC
- Ответы инструментов, отображаемые в интерфейсе
Распространённые проблемы и решения
Сервер не запускается:
- Проверьте, что все зависимости установлены:
pip install mcp - Проверьте синтаксис и отступы Python
- Ищите сообщения об ошибках в консоли
Инструменты не отображаются:
- Убедитесь, что присутствуют декораторы
@server.tool() - Проверьте, что функции инструментов определены до
main() - Убедитесь, что сервер правильно сконфигурирован
Проблемы с подключением:
- Убедитесь, что сервер использует транспорт stdio корректно
- Проверьте, что другие процессы не мешают
- Проверьте синтаксис команды Inspector
Домашнее задание
Попробуйте расширить ваш сервер, добавив больше возможностей. Смотрите эту страницу, чтобы, например, добавить инструмент, который вызывает API. Решайте, каким должен быть сервер. Удачи :)
Решение
Решение Вот возможное решение с работающим кодом.
Основные выводы
Ключевые моменты из этой главы:
- Транспорт stdio является рекомендуемым механизмом для локальных MCP серверов.
- Транспорт stdio обеспечивает беспрепятственную связь между MCP серверами и клиентами через стандартные потоки ввода и вывода.
- Для использования stdio серверов напрямую можно применять как Inspector, так и Visual Studio Code, что упрощает отладку и интеграцию.
Примеры
- Калькулятор на Java
- Калькулятор на .Net
- Калькулятор на JavaScript
- Калькулятор на TypeScript
- Калькулятор на Python
Дополнительные ресурсы
Что дальше
Следующие шаги
Теперь, когда вы знаете, как создавать MCP серверы с транспортом stdio, вы можете изучить более продвинутые темы:
- Далее: HTTP Streaming с MCP (Streamable HTTP) - изучите другой поддерживаемый механизм транспорта для удалённых серверов
- Продвинуто: Лучшие практики безопасности MCP - реализуйте безопасность в ваших MCP серверах
- Для продакшна: Стратегии развертывания - развертывание серверов для продакшн использования
Дополнительные ресурсы
- Спецификация MCP 2025-11-25 - Официальная спецификация
- Документация MCP SDK - Справочник SDK по всем языкам
- Примеры от сообщества - Ещё больше примеров серверов от сообщества
Отказ от ответственности: Этот документ был переведен с использованием сервиса машинного перевода Co-op Translator. Несмотря на наши усилия по обеспечению точности, имейте в виду, что автоматический перевод может содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется обратиться к профессиональному человеческому переводу. Мы не несем ответственности за любые недоразумения или неправильные толкования, возникшие в результате использования этого перевода.