Перейти к содержанию

MCP-серверы

Что это такое?

Ознакомьтесь с базовой информацией, чтобы узнать подробности: MCP-серверы (Model Context Protocol).

Koda CLI выступает в роли MCP-клиента: подключается к MCP-серверам, обнаруживает их инструменты и делает их доступными агенту. Серверы можно настраивать через файл settings.json или добавлять подкомандой koda mcp.

Быстрый пример

.kodacli/settings.json
{
  "mcpServers": {
    "Notion": {
      "command": "npx",
      "args": ["-y", "@notionhq/notion-mcp-server"],
      "env": {
        "NOTION_TOKEN": "..."
      }
    }
  }
}

Эквивалент через подкоманду:

koda mcp add Notion npx -y @notionhq/notion-mcp-server \
  --env NOTION_TOKEN=... \
  --scope user

Транспорт

Транспорт определяет способ связи Koda CLI с MCP-сервером и выбирается автоматически по используемому полю в конфигурации:

Транспорт Поле Когда использовать
stdio command локальный процесс, общение через потоки
sse url удалённый сервер по протоколу Server-Sent Events
http httpUrl удалённый сервер по протоколу Streamable HTTP

Транспорт stdio подходит для локальных серверов: для него указываются command и при необходимости args и env.

Для удалённых серверов предпочтителен http (Streamable HTTP) — современный и рекомендованный способ. Транспорт sse — более старый механизм: он всё ещё поддерживается, но для новых серверов следует выбирать http.

Для sse и http указывается URL эндпоинта и опционально headers.

Подробное описание полей конфигурации — в разделе «Поля конфигурации».


Добавление через koda mcp

Подкоманда koda mcp управляет серверами из терминала — без ручного редактирования settings.json. Полный справочник опций — на странице аргументов CLI.

koda mcp add

Добавляет или обновляет сервер в настройках.

# stdio-сервер (по умолчанию)
koda mcp add local-tools node ./mcp-server.js --scope project

# SSE-сервер с заголовком
koda mcp add remote --transport sse \
  --header "Authorization: Bearer ${MCP_TOKEN}" \
  https://example.com/sse

# HTTP-сервер с ограничением инструментов и доверием
koda mcp add gated --transport http \
  --include-tools list,read --trust \
  https://example.com/mcp

Ключевые опции:

Опция Алиас Назначение
--scope -s user — глобально, project — для текущего проекта
--transport -t stdio (по умолчанию), sse, http
--env -e переменные окружения в формате KEY=value (только stdio)
--header -H HTTP-заголовки для sse и http
--timeout таймаут подключения в миллисекундах
--trust доверять серверу: пропускать подтверждения вызовов инструментов
--description текстовое описание сервера
--include-tools разрешить только перечисленные инструменты
--exclude-tools скрыть перечисленные инструменты от модели

koda mcp remove

Удаляет сервер из настроек.

koda mcp remove Notion --scope user

koda mcp list

Показывает настроенные серверы и их статус после реальной попытки подключения:

  • ✓ Connected — сервер ответил на ping;
  • ✗ Disconnected — подключиться не удалось;
  • … Connecting — подключение ещё выполняется.
koda mcp list

Управление внутри сессии

В интерактивном режиме доступны слеш-команды:

Команда Назначение
/mcp показать серверы, инструменты и prompts (алиас /mcp list)
/mcp list то же самое, с подсказками
/mcp desc показать описания серверов и инструментов
/mcp schema показать схемы параметров инструментов
/mcp nodesc скрыть описания
/mcp auth <server> OAuth-аутентификация для сервера
/mcp refresh переобнаружить серверы и инструменты

Ctrl + T переключает отображение описаний инструментов.

Статусы серверов в выводе /mcp:

  • 🟢 Ready — подключён, инструменты доступны;
  • 🔄 Starting — подключение выполняется;
  • 🔴 Disconnected — ошибка подключения.

Конфигурация серверов

Серверы описываются в settings.json внутри объекта mcpServers. Ключ — имя сервера, значение — его конфигурация.

settings.json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
      "trust": false,
      "includeTools": ["read_file"],
      "excludeTools": []
    },
    "remote-api": {
      "httpUrl": "https://example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      },
      "timeout": 10000
    }
  }
}

Поля конфигурации

Поле Транспорт Назначение
command stdio исполняемая команда запуска сервера
args stdio массив аргументов команды
env stdio переменные окружения процесса сервера
url sse URL SSE-эндпоинта
httpUrl http URL Streamable HTTP-эндпоинта
headers sse, http HTTP-заголовки запросов
timeout все таймаут подключения в миллисекундах
trust все true — доверять всем инструментам без подтверждения
description все описание сервера для отображения в /mcp
includeTools все allowlist инструментов: разрешить только перечисленные
excludeTools все denylist инструментов: скрыть перечисленные от модели

Области настроек

Область Путь Назначение
User ~/.kodacli/settings.json глобальные настройки
Workspace <workspace>/.kodacli/settings.json настройки проекта

Параметр mcpServers объединяется между областями: серверы из workspace добавляются к серверам из user.

Подробнее — на странице настроек.


Вызов инструментов MCP

Агент автоматически использует инструменты MCP, когда они подходят для задачи.

Вы: Покажи последние 10 заказов из базы
Агент: [использует query_database из MCP-сервера SQLite]

По умолчанию CLI запрашивает подтверждение перед каждым вызовом инструмента. Чтобы пропускать подтверждения для доверенного сервера, установите "trust": true или используйте --trust при добавлении.

Подтверждениями также управляет флаг --approval-mode:

  • default — запрашивать подтверждение;
  • auto_edit — автоматически подтверждать инструменты редактирования;
  • yolo — автоматически подтверждать все инструменты.

OAuth-аутентификация

Некоторые MCP-серверы (например, Atlassian, Google) требуют OAuth. Если сервер поддерживает динамическое обнаружение OAuth, CLI определит это автоматически.

/mcp auth <server>

Команда запускает процесс аутентификации, после чего переобнаруживает инструменты сервера. Без аргумента /mcp auth выводит список серверов с поддержкой OAuth.


Фильтрация серверов

Чтобы ограничить набор серверов, которые могут использоваться:

Способ Где Назначение
allowMCPServers settings allowlist: разрешить только перечисленные серверы
excludeMCPServers settings denylist: исключить перечисленные серверы
--allowed-mcp-server-names CLI-флаг переопределяет обе настройки при запуске

Серверы, не попавшие в allowlist, помечаются как заблокированные и отображаются со статусом 🔴 Blocked в /mcp.

settings.json
{
  "allowMCPServers": ["filesystem", "git"],
  "excludeMCPServers": ["legacy-api"]
}

Рекомендации безопасности

  1. Доверяйте только проверенным серверам:

    • Используйте официальные серверы.
    • Проверяйте код кастомных серверов.
  2. Ограничивайте доступ:

    {
      "args": ["/home/user/projects/myproject"]
    }
    

    Не давайте доступ ко всей файловой системе — указывайте только нужные директории.

  3. Используйте переменные окружения:

    {
      "env": {
        "API_KEY": "${API_KEY}"
      }
    }
    
  4. Требуйте подтверждение:

    • Для операций записи.
    • Для удаления данных.
    • Для выполнения команд.
    • Не устанавливайте "trust": true для непроверенных серверов.

Предостережение

Прежде чем использовать сторонний сервер MCP, убедитесь, что вы доверяете его источнику и понимаете инструменты, которые он предоставляет. Вы используете сторонние серверы на свой страх и риск.


Создание собственного MCP-сервера

MCP-сервер можно написать на любом языке, например:

  • TypeScript/JavaScript — официальная библиотека @modelcontextprotocol/sdk;
  • Python — официальная библиотека mcp;
  • Go — через github.com/mark3labs/mcp-go;
  • Любой другой — через стандартные потоки или HTTP.

Сервер должен реализовать:

  1. Инициализация — handshake с клиентом;
  2. Список инструментов — что может делать сервер;
  3. Вызов инструментов — выполнение функций;
  4. Ресурсы (опционально) — данные для чтения;
  5. Промпты (опционально) — шаблоны текста.

Используйте официальную библиотеку mcp:

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

mcp = FastMCP("SQLite MCP")

@mcp.tool()
def query_database(sql: str) -> list[dict]:
    """Выполняет SQL-запрос к базе данных и возвращает результаты."""
    conn = sqlite3.connect("example.db")
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    cursor.execute(sql)
    results = [dict(row) for row in cursor.fetchall()]
    conn.close()
    return results

@mcp.resource("db://tables")
def list_tables() -> list[str]:
    """Возвращает список таблиц в базе данных."""
    conn = sqlite3.connect("example.db")
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
    tables = [row[0] for row in cursor.fetchall()]
    conn.close()
    return tables

if __name__ == "__main__":
    mcp.run()

Подключение:

koda mcp add sqlite-mcp python /path/to/server.py --scope user

Используйте пакет @modelcontextprotocol/sdk:

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

const server = new McpServer({
  name: "Weather MCP",
  version: "1.0.0",
});

server.tool(
  "getWeather",
  "Получает текущую погоду для указанного города",
  {
    city: z.string().describe("Название города"),
  },
  async ({ city }) => {
    const temperature = Math.floor(Math.random() * 30) + 10;
    return {
      content: [
        {
          type: "text",
          text: `Температура в городе ${city}: ${temperature}°C`,
        },
      ],
    };
  }
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

main().catch(console.error);

Подключение:

koda mcp add weather-mcp npx tsx /path/to/server.ts --scope user

Используйте библиотеку github.com/mark3labs/mcp-go:

main.go
package main

import (
    "context"
    "github.com/mark3labs/mcp-go/mcp"
    "github.com/mark3labs/mcp-go/server"
)

func main() {
    s := server.NewMCPServer(
        "File System MCP",
        "1.0.0",
        server.WithToolCapabilities(true),
    )

    s.AddTool(mcp.NewTool(
        "read_file",
        mcp.WithDescription("Читает содержимое файла"),
        mcp.WithString("path", mcp.Required(), mcp.Description("Путь к файлу")),
    ), readFileHandler)

    server.ServeStdio(s)
}

func readFileHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    path := req.Params.Arguments["path"].(string)
    return &mcp.CallToolResult{
        Content: []mcp.Content{
            mcp.TextContent{Text: "Содержимое файла: " + path},
        },
    }, nil
}

Подключение:

koda mcp add fs-mcp go run /path/to/main.go --scope user