docs: update docs
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
|
||||
- **Польза**: Записывая статус в «уточку», модель создает для самой себя краткое резюме (summary) пройденных этапов.
|
||||
|
||||
## Как это описать в описании MCP-сервера:
|
||||
## Как это описать в описании MCP-сервера
|
||||
|
||||
Вы можете описать это как «Explicit Reasoning Buffer» (Буфер явных рассуждений).
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
---
|
||||
|
||||
Чтобы сделать свой Model Context Protocol (MCP) сервер, вам нужно реализовать приложение, которое общается с клиентом (например, Claude Desktop, Cursor или ИИ-агентом) через JSON-RPC 2.0. Протокол стандартизирован компанией Anthropic и работает поверх стандартных потоков ввода-вывода (Stdio) или WebSockets. [1, 2]
|
||||
Чтобы сделать свой Model Context Protocol (MCP) сервер, вам нужно реализовать приложение, которое общается с клиентом (например, Claude Desktop, Cursor или ИИ-агентом) через JSON-RPC 2.0. Протокол стандартизирован компанией Anthropic и работает поверх стандартных потоков ввода-вывода (Stdio) или Streamable HTTP. [1, 2]
|
||||
|
||||
---
|
||||
|
||||
@@ -160,299 +160,136 @@ if __name__ == "__main__":
|
||||
|
||||
---
|
||||
|
||||
Развертывание MCP-сервера на Vercel накладывает важное техническое ограничение: [Vercel](https://vercel.com/) работает на Serverless-функциях, поэтому стандартный локальный протокол связи (через терминал Stdio) здесь использовать нельзя.
|
||||
## Деплой MCP-сервера на Vercel
|
||||
|
||||
Вместо этого удаленные серверы общаются через SSE (Server-Sent Events) и POST-запросы. Vercel предоставляет официальный пакет `@vercel/mcp-adapter`, который делает за вас всю грязную работу по управлению сессиями в Serverless-среде. [1, 2, 3]
|
||||
Vercel работает на Serverless-функциях, поэтому стандартный локальный протокол Stdio здесь использовать нельзя. Современное решение — **Streamable HTTP** (спека MCP 2026-07-28). Пакет `mcp-handler` от Vercel принимает HTTP POST-запросы и отвечает JSON-RPC. Stateless, без Redis, без долгоживущих SSE-соединений — идеально для serverless.
|
||||
|
||||
Ниже пошаговый план, как создать такой сервер на SvelteKit и развернуть на Vercel. [3, 4]
|
||||
> **Актуальные пакеты** (сентябрь 2026): `mcp-handler` v2.1.1 + `@modelcontextprotocol/server` v2 + `zod` v4. Пакеты `@vercel/mcp-adapter` и `@modelcontextprotocol/sdk` v1 — **устарели**.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 1. Инициализация SvelteKit-проекта
|
||||
|
||||
Если у вас еще нет проекта, создайте его:
|
||||
### Шаг 1. Инициализация Next.js-проекта
|
||||
|
||||
```bash
|
||||
npm create svelte@latest my-mcp-server
|
||||
npx create-next-app@latest my-mcp-server --typescript --app
|
||||
cd my-mcp-server
|
||||
npm install
|
||||
```
|
||||
|
||||
Установите необходимые зависимости для работы MCP-сервера в среде Vercel: [4]
|
||||
Установите зависимости для MCP-сервера:
|
||||
|
||||
```bash
|
||||
npm install @modelcontextprotocol/sdk @vercel/mcp-adapter
|
||||
npm install -D @sveltejs/adapter-vercel
|
||||
npm install mcp-handler@^2 @modelcontextprotocol/server@^2 zod@^4
|
||||
```
|
||||
|
||||
Убедитесь, что в файле `svelte.config.js` подключен верный адаптер: [5]
|
||||
### Шаг 2. Создание API эндпоинта (route.ts)
|
||||
|
||||
```js
|
||||
import adapter from "@sveltejs/adapter-vercel";
|
||||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
preprocess: vitePreprocess(),
|
||||
kit: {
|
||||
adapter: adapter(), // Адаптер для Vercel
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 2. Создание API эндпоинта (+server.ts)
|
||||
|
||||
По спецификации MCP на базе SSE, серверу требуются два роута: один открывает бесконечный поток для чтения событий (SSE), а второй принимает входящие POST-команды от клиента. Пакет `@vercel/mcp-adapter` объединяет их в один обработчик. [2, 6]
|
||||
|
||||
Создайте файл `src/routes/api/mcp/+server.ts` и добавьте следующий код:
|
||||
Создайте файл `app/api/mcp/route.ts`:
|
||||
|
||||
```typescript
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { createMcpHandler } from "mcp-handler";
|
||||
import { z } from "zod";
|
||||
import { createActionHandler } from "@vercel/mcp-adapter";
|
||||
import type { RequestHandler } from "./$types";
|
||||
|
||||
// 1. Инициализируем стандартный MCP-сервер из SDK Anthropic
|
||||
const server = new McpServer({
|
||||
name: "SvelteKit MCP Server",
|
||||
version: "1.0.0",
|
||||
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, солнечно.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// 2. Регистрируем ваш инструмент (Tool)
|
||||
server.tool(
|
||||
"getWeather",
|
||||
"Возвращает текущую погоду для указанного города",
|
||||
{
|
||||
city: z.string().describe("Название города на английском или русском"),
|
||||
},
|
||||
async ({ city }) => {
|
||||
// Здесь может быть ваш реальный fetch к какому-нибудь Weather API
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `В городе ${city} сейчас отличная погода, +22°C, солнечно.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// 3. Создаем обработчик для Vercel с помощью адаптера.
|
||||
// Адаптер автоматически поддерживает Streamable HTTP и SSE.
|
||||
const mcpHandler = createActionHandler(server);
|
||||
|
||||
// Экспортируем методы для SvelteKit
|
||||
export const GET: RequestHandler = async ({ request }) => {
|
||||
return mcpHandler(request);
|
||||
};
|
||||
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
return mcpHandler(request);
|
||||
};
|
||||
export { handler as GET, handler as POST };
|
||||
```
|
||||
|
||||
---
|
||||
### Шаг 3. Деплой на Vercel
|
||||
|
||||
## Шаг 3. Деплой на Vercel
|
||||
1. Запуште код в Git-репозиторий (GitHub, GitLab или Bitbucket).
|
||||
2. Vercel → **Add New > Project** → выбрать репозиторий.
|
||||
3. Framework: **Next.js** (автоопределение).
|
||||
4. **Deploy**.
|
||||
|
||||
1. Запуште ваш код в Git-репозиторий (GitHub, GitLab или Bitbucket).
|
||||
2. Зайдите в панель управления Vercel и нажмите **Add New > Project**.
|
||||
3. Выберите ваш репозиторий. Vercel автоматически определит, что это SvelteKit, и выставит правильные настройки сборки.
|
||||
4. Нажмите **Deploy**. [7]
|
||||
URL: `https://my-mcp-server.vercel.app`
|
||||
MCP-эндпоинт: `https://<ваш-проект>.vercel.app/api/mcp`
|
||||
|
||||
После завершения деплоя вы получите URL вашего сайта, например: `https://my-mcp-server.vercel.app`. Ваш MCP эндпоинт будет доступен по адресу `https://<ваш-проект>.vercel.app`.
|
||||
**Лимиты Vercel Hobby (бесплатно):**
|
||||
|
||||
## Шаг 4. Подключение к клиенту (Cursor / Claude Desktop)
|
||||
| Ресурс | Лимит | Наш сервер |
|
||||
| --------------- | ----------- | -------------- |
|
||||
| Таймаут функции | 300с (макс) | ~1мс на вызов |
|
||||
| Деплои/день | 100 | 1 (autodeploy) |
|
||||
| Redis | Не нужен | Stateless |
|
||||
|
||||
Поскольку сервер теперь находится в сети и работает по протоколу SSE, его настройка в приложениях немного отличается от локальной. [2]
|
||||
### Шаг 4. Подключение к клиентам
|
||||
|
||||
### Для Cursor (и аналогичных IDE):
|
||||
**Cursor:**
|
||||
|
||||
1. Откройте **Settings > Features > MCP**.
|
||||
2. Нажмите **+ Add New MCP Server**.
|
||||
3. Заполните поля:
|
||||
- **Name**: `SvelteKit-MCP`
|
||||
- **Type**: из выпадающего списка выберите `SSE`.
|
||||
- **URL**: `https://<ваш-проект>.vercel.app` [8]
|
||||
1. Settings > Features > MCP → + Add New MCP Server
|
||||
2. Type: **Streamable HTTP**
|
||||
3. URL: `https://<ваш-проект>.vercel.app/api/mcp`
|
||||
|
||||
### Для Claude Desktop:
|
||||
|
||||
Откройте файл конфигурации `claude_desktop_config.json` и пропишите вызов через команду `curl` или встроенный в Node.js транспорт (утилита автоматически преобразует SSE в понятный для Claude формат):
|
||||
**Claude Desktop:**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"sveltekit-remote-mcp": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/inspector", "sse", "https://<ваш-проект>.vercel.app"]
|
||||
"my-mcp": {
|
||||
"url": "https://<ваш-проект>.vercel.app/api/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Важные нюансы при работе на Vercel:
|
||||
Если клиент не поддерживает Streamable HTTP, используйте `mcp-remote` как бридж:
|
||||
|
||||
- **Таймауты serverless-функций**: На бесплатном тарифе Vercel (Hobby) лимит на выполнение функции составляет 10–15 секунд. Убедитесь, что ваши инструменты (запросы к сторонним API, вычисления) укладываются в это время, иначе соединение оборвется.
|
||||
- **Базы данных и переменные окружения**: Если вашему инструменту понадобятся API-ключи, обязательно добавьте их в панель Vercel в разделе **Project Settings > Environment Variables**. [9, 10]
|
||||
|
||||
---
|
||||
|
||||
Поскольку данные статичны, мы можем сделать код максимально чистым, используя TypeScript и встроенную валидацию через Zod.
|
||||
|
||||
Вот готовый пример реализации файла `src/routes/api/mcp/+server.ts`, где данные (например, документация по вашему проекту или готовая база знаний) хранятся прямо внутри:
|
||||
|
||||
```typescript
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { z } from "zod";
|
||||
import { createActionHandler } from "@vercel/mcp-adapter";
|
||||
import type { RequestHandler } from "./$types";
|
||||
|
||||
// 1. Статические данные (база знаний сервера)
|
||||
const KNOWLEDGE_BASE: Record<string, string> = {
|
||||
api: "Наш API использует методы GET для чтения и POST для отправки команд.",
|
||||
deploy: "Деплой автоматизирован через Vercel Git Integration при каждом пуше в main.",
|
||||
contacts: "Техническая поддержка доступна по адресу support@mycompany.com.",
|
||||
rules: "Все новые фичи должны быть покрыты тестами перед слиянием (ветка staging).",
|
||||
};
|
||||
|
||||
// 2. Инициализируем MCP-сервер
|
||||
const server = new McpServer({
|
||||
name: "SvelteKit Static MCP",
|
||||
version: "1.0.0",
|
||||
});
|
||||
|
||||
// 3. Регистрируем инструмент для поиска по готовым данным
|
||||
server.tool(
|
||||
"getStaticData",
|
||||
"Возвращает готовую справочную информацию по ключевому слову (api, deploy, contacts, rules).",
|
||||
{
|
||||
topic: z.enum(["api", "deploy", "contacts", "rules"]).describe("Ключевое слово темы для поиска"),
|
||||
},
|
||||
async ({ topic }) => {
|
||||
// Извлекаем уже готовые данные
|
||||
const info = KNOWLEDGE_BASE[topic];
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: info || `Информация по теме "${topic}" не найдена.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// 4. Настройка адаптера для работы с Vercel Serverless
|
||||
const mcpHandler = createActionHandler(server);
|
||||
|
||||
export const GET: RequestHandler = async ({ request }) => mcpHandler(request);
|
||||
export const POST: RequestHandler = async ({ request }) => mcpHandler(request);
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"my-mcp": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-remote", "https://<ваш-проект>.vercel.app/api/mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Как это будет работать для ИИ:
|
||||
### Проверка сервера
|
||||
|
||||
Когда вы подключите этот сервер к Cursor или Claude Desktop, модель поймет, какие темы доступны (благодаря `z.enum`). Если вы спросите ИИ: «Как связаться с поддержкой?» или «Каковы правила деплоя?», модель автоматически вызовет инструмент `getStaticData` с нужным параметром и мгновенно получит зашитый в код ответ.
|
||||
|
||||
## Что делать дальше?
|
||||
|
||||
1. Замените ключи и тексты в объекте `KNOWLEDGE_BASE` на ваши реальные данные.
|
||||
2. Обновите список доступных тем в `z.enum([...])`.
|
||||
3. Сделайте `git commit` и `git push` — Vercel сам пересоберет проект за пару секунд.
|
||||
|
||||
---
|
||||
|
||||
## Вот 3 лучших способа проверить валидность вашего сервера от самого простого к продвинутому.
|
||||
|
||||
### Способ 1. Самый быстрый (в браузере за 5 секунд)
|
||||
|
||||
Так как ваш сервер развернут на Vercel и принимает GET-запросы, вы можете проверить его прямо в браузере или через curl.
|
||||
|
||||
1. Откройте браузер и перейдите по адресу вашего эндпоинта (например, `https://<ваш-проект>.vercel.app`).
|
||||
2. Что вы должны увидеть: Браузер должен начать бесконечную загрузку страницы или отобразить текстовый поток (SSE Stream), начинающийся со строки:
|
||||
|
||||
```
|
||||
event: endpoint
|
||||
data: /api/mcp?session_id=...
|
||||
```
|
||||
|
||||
Если вы увидели эту строку и статус ответа `200 OK` — транспортный уровень SSE работает корректно.
|
||||
|
||||
---
|
||||
|
||||
### Способ 2. Официальный веб-интерфейс (MCP Inspector)
|
||||
|
||||
Команда Anthropic создала специальную интерактивную панель для тестирования локальных и удаленных серверов.
|
||||
|
||||
Запустите в терминале команду (утилита скачается и запустится автоматически через npx):
|
||||
**curl (быстрая проверка JSON-RPC):**
|
||||
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector sse https://<ваш-проект>.vercel.app
|
||||
```
|
||||
|
||||
(Замените URL на ваш адрес на Vercel)
|
||||
|
||||
Что произойдет дальше:
|
||||
|
||||
1. В терминале появится ссылка (обычно `http://localhost:5173`). Откройте ее в браузере.
|
||||
2. Вы увидите графическую панель управления вашим MCP-сервером.
|
||||
3. Нажмите кнопку **List Tools** — в интерфейсе должен появиться ваш инструмент `getStaticData` со всей схемой параметров.
|
||||
4. Вы можете заполнить поля формы (например, выбрать тему `api`) и нажать **Call Tool**. Вы мгновенно увидите сырой JSON-ответ от Vercel.
|
||||
|
||||
> Это эталонный метод проверки: если Inspector работает без ошибок, значит, любой ИИ (Cursor, Claude) гарантированно поймет ваш сервер.
|
||||
|
||||
### Способ 3. Проверка через Postman / Insomnia / cURL
|
||||
|
||||
Если вы хотите убедиться, что JSON-RPC команды обрабатываются правильно, можно сымитировать запрос от ИИ вручную. Для этого нужно сделать POST-запрос, но с одной важной деталью: протокол SSE требует ID сессии, который сервер выдает при GET-запросе.
|
||||
|
||||
Проще всего сделать это через curl в два шага:
|
||||
|
||||
**Шаг 1: Инициализация сессии (GET)**
|
||||
|
||||
```bash
|
||||
curl -i https://<ваш-проект>.vercel.app
|
||||
```
|
||||
|
||||
В ответе найдите строку `data: /api/mcp?session_id=ХХХХХХ`. Скопируйте этот хвост с ID сессии.
|
||||
|
||||
**Шаг 2: Вызов инструмента (POST)**
|
||||
|
||||
Отправьте JSON-RPC запрос на полученный адрес сессии:
|
||||
|
||||
```bash
|
||||
curl -X POST "https://<ваш-проект>.vercel.app/api/mcp?session_id=ХХХХХХ" \
|
||||
curl -X POST "https://<ваш-проект>.vercel.app/api/mcp" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "getStaticData",
|
||||
"arguments": {
|
||||
"topic": "api"
|
||||
}
|
||||
"name": "getWeather",
|
||||
"arguments": { "city": "Moscow" }
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
Правильный ответ сервера должен выглядеть так:
|
||||
**MCP Inspector (локально):**
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": {
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Наш API использует методы GET для чтения и POST для отправки команд."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```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
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user