296 lines
13 KiB
Markdown
296 lines
13 KiB
Markdown
# FAQ: Полезно ли ИИ обращаться к MCP серверу, который отвечает только `quack`
|
||
|
||
Вот почему это технически полезно для основной модели:
|
||
|
||
## 1. Фиксация «Контекстного окна»
|
||
|
||
Когда ИИ вызывает инструмент (tool call), он обязан сформулировать аргументы.
|
||
|
||
- **Механика**: Чтобы получить `кряк` из MCP, модели придется выгрузить свои промежуточные мысли из весов (внутреннего состояния) в текст (входящий контекст).
|
||
- **Польза**: Это превращает неявные рассуждения в явные данные. При генерации следующего токена модель будет видеть свое собственное объяснение как уже случившийся факт, на который можно опираться.
|
||
|
||
## 2. Принудительное замедление (Compute-over-time)
|
||
|
||
ИИ часто «проскакивает» сложные моменты, пытаясь выдать ответ слишком быстро.
|
||
|
||
- **Механика**: Вызов MCP-инструмента прерывает процесс прямой генерации ответа.
|
||
- **Польза**: Это заставляет модель сделать паузу и структурировать задачу. Это фактически «взлом» логики, заставляющий модель использовать больше токенов на рассуждение, что почти всегда повышает качество решения.
|
||
|
||
## 3. Эффект «Внешней памяти»
|
||
|
||
Если задача огромная, ИИ может начать «забывать» детали начала условия.
|
||
|
||
- **Польза**: Записывая статус в «уточку», модель создает для самой себя краткое резюме (summary) пройденных этапов.
|
||
|
||
## Как это описать в описании MCP-сервера
|
||
|
||
Вы можете описать это как «Explicit Reasoning Buffer» (Буфер явных рассуждений).
|
||
|
||
- **Для кого**: Для сложных агентов, которые склонны к логическим циклам или галлюцинациям.
|
||
- **Суть**: Инструмент предоставляет модели безопасное пространство для «проговаривания» плана действий перед тем, как трогать реальные файлы или базу данных.
|
||
|
||
---
|
||
|
||
Чтобы сделать свой Model Context Protocol (MCP) сервер, вам нужно реализовать приложение, которое общается с клиентом (например, Claude Desktop, Cursor или ИИ-агентом) через JSON-RPC 2.0. Протокол стандартизирован компанией Anthropic и работает поверх стандартных потоков ввода-вывода (Stdio) или Streamable HTTP. [1, 2]
|
||
|
||
---
|
||
|
||
## Какое API у MCP сервера?
|
||
|
||
API MCP-сервера базируется на трех китах (примитивах), которые сервер «обнажает» для ИИ-модели: [3]
|
||
|
||
1. **Tools (Инструменты)** — функции, которые ИИ может вызывать (например, запустить код, сделать запрос к API, прочитать файл).
|
||
2. **Resources (Ресурсы)** — данные, которые ИИ может читать (текстовые файлы, логи, таблицы, данные из БД).
|
||
3. **Prompts (Промпты)** — готовые шаблоны контекста или команд, которые пользователь может выбрать для модели. [1, 2, 3]
|
||
|
||
С технической точки зрения общение идет через JSON-RPC. Клиент отправляет запросы вроде `tools/list` (получить список инструментов) и `tools/call` (вызвать конкретный инструмент с аргументами). [1]
|
||
|
||
## Как сделать свой MCP сервер (на примере Python)
|
||
|
||
Проще всего использовать официальный SDK. Напишем простой сервер на Python, который предоставляет ИИ один инструмент: калькулятор стоимости доставки.
|
||
|
||
### Шаг 1. Установка библиотек
|
||
|
||
Вам понадобится официальный SDK от Anthropic и mcp. [3]
|
||
|
||
```bash
|
||
pip install mcp pydantic
|
||
```
|
||
|
||
### Шаг 2. Код сервера (server.py)
|
||
|
||
Создайте файл и опишите логику. Сервер будет работать через стандартный ввод/вывод (Stdio), что является стандартом для локальных MCP-серверов. [1]
|
||
|
||
```python
|
||
import asyncio
|
||
from mcp.server.models import InitializationOptions
|
||
from mcp.server import Notification, Server
|
||
import mcp.types as types
|
||
from mcp.server.stdio import stdio_server
|
||
|
||
# Инициализируем сервер
|
||
server = Server("my-delivery-calculator")
|
||
|
||
# 1. Регистрируем инструмент (Tool)
|
||
|
||
@server.list_tools()
|
||
async def handle_list_tools() -> list[types.Tool]:
|
||
return [
|
||
types.Tool(
|
||
name="calculate_delivery",
|
||
description="Рассчитывает стоимость доставки в зависимости от расстояния и веса.",
|
||
inputSchema={
|
||
"type": "object",
|
||
"properties": {
|
||
"distance_km": {"type": "number", "description": "Расстояние в километрах"},
|
||
"weight_kg": {"type": "number", "description": "Вес груза в кг"}
|
||
},
|
||
"required": ["distance_km", "weight_kg"]
|
||
}
|
||
)
|
||
]
|
||
|
||
# 2. Описываем логику выполнения этого инструмента
|
||
|
||
@server.call_tool()
|
||
async def handle_call_tool(
|
||
name: str, arguments: dict | None
|
||
) -> list[types.TextContent]:
|
||
if name == "calculate_delivery":
|
||
if not arguments:
|
||
raise ValueError("Отсутствуют аргументы")
|
||
|
||
distance = arguments.get("distance_km", 0)
|
||
weight = arguments.get("weight_kg", 0)
|
||
|
||
# Простая бизнес-логика
|
||
price = (distance * 10) + (weight * 50)
|
||
|
||
return [
|
||
types.TextContent(
|
||
type="text",
|
||
text=f"Стоимость доставки составляет {price} рублей."
|
||
)
|
||
]
|
||
raise ValueError(f"Инструмент {name} не найден")
|
||
|
||
# 3. Запуск сервера через Stdio
|
||
async def main():
|
||
async with stdio_server() as (read_stream, write_stream):
|
||
await server.run(
|
||
read_stream,
|
||
write_stream,
|
||
InitializationOptions(
|
||
server_name="my-delivery-calculator",
|
||
server_version="0.1.0",
|
||
capabilities=server.get_capabilities()
|
||
)
|
||
)
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(main())
|
||
```
|
||
|
||
---
|
||
|
||
## Как протестировать и подключить?
|
||
|
||
1. **Через MCP Inspector**: Anthropic предоставляет инструмент для отладки. Запустите команду в терминале для визуального тестирования вашего сервера:
|
||
|
||
```bash
|
||
npx @modelcontextprotocol/inspector python server.py
|
||
```
|
||
|
||
Откроется веб-интерфейс, где можно проверить ответы API.
|
||
|
||
2. **В Claude Desktop**: Откройте конфигурационный файл (в Windows: `%APPDATA%\Claude\claude_desktop_config.json`, в macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`) и добавьте ваш сервер:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"my-calculator": {
|
||
"command": "python",
|
||
"args": ["/абсолютный/путь/к/server.py"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
После перезапуска Claude увидит ваш инструмент и сможет вызывать его для расчетов. [3, 4]
|
||
|
||
---
|
||
|
||
## Деплой MCP-сервера на Vercel
|
||
|
||
Vercel работает на Serverless-функциях, поэтому стандартный локальный протокол Stdio здесь использовать нельзя. Современное решение — **Streamable HTTP** (спека MCP 2026-07-28). Пакет `mcp-handler` от Vercel принимает HTTP POST-запросы и отвечает JSON-RPC. Stateless, без Redis, без долгоживущих SSE-соединений — идеально для serverless.
|
||
|
||
> **Актуальные пакеты** (сентябрь 2026): `mcp-handler` v2.1.1 + `@modelcontextprotocol/server` v2 + `zod` v4. Пакеты `@vercel/mcp-adapter` и `@modelcontextprotocol/sdk` v1 — **устарели**.
|
||
|
||
### Шаг 1. Инициализация Next.js-проекта
|
||
|
||
```bash
|
||
npx create-next-app@latest my-mcp-server --typescript --app
|
||
cd my-mcp-server
|
||
```
|
||
|
||
Установите зависимости для MCP-сервера:
|
||
|
||
```bash
|
||
npm install mcp-handler@^2 @modelcontextprotocol/server@^2 zod@^4
|
||
```
|
||
|
||
### Шаг 2. Создание API эндпоинта (route.ts)
|
||
|
||
Создайте файл `app/api/mcp/route.ts`:
|
||
|
||
```typescript
|
||
import { createMcpHandler } from "mcp-handler";
|
||
import { z } from "zod";
|
||
|
||
const handler = createMcpHandler((server) => {
|
||
server.registerTool(
|
||
"getWeather",
|
||
{
|
||
title: "Weather",
|
||
description: "Возвращает текущую погоду для указанного города",
|
||
inputSchema: z.object({
|
||
city: z.string().describe("Название города на английском или русском"),
|
||
}),
|
||
},
|
||
async ({ city }) => {
|
||
return {
|
||
content: [
|
||
{
|
||
type: "text" as const,
|
||
text: `В городе ${city} сейчас отличная погода, +22°C, солнечно.`,
|
||
},
|
||
],
|
||
};
|
||
},
|
||
);
|
||
});
|
||
|
||
export { handler as GET, handler as POST };
|
||
```
|
||
|
||
### Шаг 3. Деплой на Vercel
|
||
|
||
1. Запуште код в Git-репозиторий (GitHub, GitLab или Bitbucket).
|
||
2. Vercel → **Add New > Project** → выбрать репозиторий.
|
||
3. Framework: **Next.js** (автоопределение).
|
||
4. **Deploy**.
|
||
|
||
URL: `https://my-mcp-server.vercel.app`
|
||
MCP-эндпоинт: `https://<ваш-проект>.vercel.app/api/mcp`
|
||
|
||
**Лимиты Vercel Hobby (бесплатно):**
|
||
|
||
| Ресурс | Лимит | Наш сервер |
|
||
| --------------- | ----------- | -------------- |
|
||
| Таймаут функции | 300с (макс) | ~1мс на вызов |
|
||
| Деплои/день | 100 | 1 (autodeploy) |
|
||
| Redis | Не нужен | Stateless |
|
||
|
||
### Шаг 4. Подключение к клиентам
|
||
|
||
**Cursor:**
|
||
|
||
1. Settings > Features > MCP → + Add New MCP Server
|
||
2. Type: **Streamable HTTP**
|
||
3. URL: `https://<ваш-проект>.vercel.app/api/mcp`
|
||
|
||
**Claude Desktop:**
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"my-mcp": {
|
||
"url": "https://<ваш-проект>.vercel.app/api/mcp"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Если клиент не поддерживает Streamable HTTP, используйте `mcp-remote` как бридж:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"my-mcp": {
|
||
"command": "npx",
|
||
"args": ["-y", "mcp-remote", "https://<ваш-проект>.vercel.app/api/mcp"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Проверка сервера
|
||
|
||
**curl (быстрая проверка JSON-RPC):**
|
||
|
||
```bash
|
||
curl -X POST "https://<ваш-проект>.vercel.app/api/mcp" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"jsonrpc": "2.0",
|
||
"id": 1,
|
||
"method": "tools/call",
|
||
"params": {
|
||
"name": "getWeather",
|
||
"arguments": { "city": "Moscow" }
|
||
}
|
||
}'
|
||
```
|
||
|
||
**MCP Inspector (локально):**
|
||
|
||
```bash
|
||
npx @modelcontextprotocol/inspector npx mcp-remote http://localhost:3000/api/mcp
|
||
```
|
||
|
||
**MCP Inspector (удалённо):**
|
||
|
||
```bash
|
||
npx @modelcontextprotocol/inspector npx mcp-remote https://<ваш-проект>.vercel.app/api/mcp
|
||
```
|