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

MCP-серверы

v0.1.6

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

Ознакомьтесь с базовой информацией, чтобы узнать подробности: 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": "..."
      }
    }
  }
}

Аргументы с дефисом

В примере выше аргумент -y передан в settings.json. Через koda mcp add такой аргумент передать нельзя: команда воспримет его как свою опцию или завершится ошибкой неизвестного аргумента. Для серверов, которым нужны npx -y, docker run --rm и подобные аргументы, добавляйте конфигурацию в файл настроек.

Удалённый сервер подключается по адресу, а не командой:

.kodacli/settings.json
{
  "mcpServers": {
    "Remote API": {
      "httpUrl": "https://example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      }
    }
  }
}

Транспорт

Транспорт определяет способ связи Koda CLI с MCP-сервером. В файле настроек выбирать его отдельно не нужно — CLI смотрит, какое поле заполнено:

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

Если в одном сервере заполнено несколько полей, приоритет такой: сначала httpUrl, затем url, затем command. При добавлении через koda mcp add транспорт задаётся опцией --transport.

WebSocket

CLI не поддерживает транспорт WebSocket. Если сервер умеет Streamable HTTP или SSE, используйте http или sse. Для WebSocket-серверов подойдёт плагин для IDE.

stdio: локальный процесс

CLI запускает сервер как дочерний процесс, поэтому нужное ПО должно быть установлено в системе. Кроме command, можно передать args, env и cwd. Процесс наследует переменные окружения вашей оболочки, а env добавляет или переопределяет нужные значения.

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

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

koda mcp add Notion npx @notionhq/notion-mcp-server \
  --env NOTION_TOKEN=${NOTION_TOKEN} \
  --scope user

-y для npx

Аргумент -y передайте через settings.json: koda mcp add воспримет его как свою опцию. Без -y команда npx может запросить подтверждение установки пакета.

http: Streamable HTTP

Для удалённых серверов это предпочтительный способ: обычный HTTP с потоковым ответом. Указывается адрес эндпоинта и при необходимости заголовки.

settings.json
{
  "mcpServers": {
    "remote-http": {
      "httpUrl": "https://example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      },
      "timeout": 30000
    }
  }
}

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

koda mcp add remote-http --transport http \
  --header "Authorization: Bearer ${MCP_TOKEN}" \
  https://example.com/mcp --scope user

Если сервер отвечает 401 и поддерживает динамическое обнаружение OAuth, CLI предложит авторизоваться — см. OAuth-аутентификацию. Если токен у вас уже есть, передайте его заголовком Authorization — тогда автоматическое обнаружение не понадобится.

sse: Server-Sent Events

Более старый сетевой транспорт. Имеет смысл, только если сервер отдаёт исключительно SSE-эндпоинт; для новых серверов выбирайте http.

settings.json
{
  "mcpServers": {
    "remote-sse": {
      "url": "https://example.com/sse",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      }
    }
  }
}

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

koda mcp add remote-sse --transport sse \
  --header "Authorization: Bearer ${MCP_TOKEN}" \
  https://example.com/sse --scope user

Что выбрать

  • Сервер запускается командой на вашей машине — stdio.
  • Сервер доступен по HTTP-адресу — http.
  • Сервер отдаёт только SSE-поток — sse.

Адрес эндпоинта и нужные аргументы обычно приводит документация самого сервера. Готовые настройки популярных серверов, в том числе подключаемых по SSE и HTTP, — на странице примеров подключения.

Подстановка секретов

В строках настроек CLI подставляет переменные окружения в форматах $VAR и ${VAR}. Так токен не остаётся в файле settings.json:

settings.json
{
  "mcpServers": {
    "remote-http": {
      "httpUrl": "https://example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      }
    }
  }
}

Если переменная не задана, значение остаётся как есть и подключение, скорее всего, не удастся — проверьте её через koda mcp list.

Таймаут

Поле timeout задаётся в миллисекундах и действует как для подключения к серверу, так и для каждого вызова его инструментов. Значение по умолчанию — 10 минут. Для koda mcp add та же опция называется --timeout.

Проверка подключения

koda mcp list

Команда реально пытается подключиться к каждому серверу и показывает ✓ Connected, ✗ Disconnected или … Connecting. Внутри сессии тот же результат даёт слеш-команда /mcp.

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


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

v1.1.1

Подкоманда 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

Аргументы запуска, начинающиеся с дефиса (-y, --rm), команда может принять за свои опции или завершиться ошибкой неизвестного аргумента. Для таких серверов добавляйте конфигурацию в settings.json — см. примеры подключения.

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

Опция Алиас Назначение
--scope -s user — глобально, project — для текущего проекта
--transport -t stdio (по умолчанию), sse, http
--env -e переменные окружения в формате KEY=value (только stdio)
--header -H HTTP-заголовки для sse и http
--timeout таймаут в миллисекундах: подключение и вызовы инструментов; по умолчанию 10 минут
--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. Ключ — имя сервера, значение — его конфигурация.

Примеры конфигурации и справочник параметров — в настройках.

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

Какое поле какой транспорт включает — см. таблицу в разделе «Транспорт».

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

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

Серверы задаются в пользовательских и workspace-настройках: параметр 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