← Все гайды AI Release
EN Подписаться на @ai_release1

Сколько инструментов должно быть у MCP-сервера: замеры от 5 до 100

Обновлено: 30.10.2026 · AI Release · @ai_release1
Сколько инструментов должно быть у MCP-сервера: замеры от 5 до 100

TL;DR

Термины: MCP (Model Context Protocol) — открытый протокол, по которому клиент (IDE, чат) подключается к серверу и получает каталог инструментов (tools) — функций, которые модель может вызывать. Обмен идёт сообщениями JSON-RPC 2.0, по stdio (stdin/stdout процесса) или по HTTP. Каталог инструментов целиком уезжает в контекст модели при каждом запросе, поэтому N инструментов — это N описаний в каждом вызове.

Требования и подготовка

Иллюстрация к разделу «Требования и подготовка»
Иллюстрация к разделу «Требования и подготовка»

Чек-лист перед стартом:

Пример: cd ~ && mkdir mcp-scale && cd mcp-scale && python -c "import mcp; print(mcp.__file__)" → печатает /…/site-packages/mcp/__init__.py. Если вместо пути ошибка ModuleNotFoundError: No module named 'mcp' — пакет не установился, вернитесь к pip install.

Шаг 1. Соберите эталонный MCP-сервер с переключаемым числом инструментов

Иллюстрация к разделу «Шаг 1. Соберите эталонный MCP-сервер с переключаемым числом инструментов»
Иллюстрация к разделу «Шаг 1. Соберите эталонный MCP-сервер с переключаемым числом инструментов»

Что сделать: создать сервер mcp_scale_server.py, у которого количество инструментов задаётся переменной окружения TOOLS_COUNT, и пробник probe_measure.py, который подключается к нему по stdio и печатает метрики.

Зачем: чтобы во всех прогонах менялось ровно одно — N. Если менять ещё и набор инструментов, сравнение ничего не покажет.

# mcp_scale_server.py
import os
from mcp.server.fastmcp import FastMCP

N = int(os.environ.get("TOOLS_COUNT", "5"))
mcp = FastMCP("scale-probe")

def make_tool(i: int):
    def impl(topic: str) -> str:
        return f"tool-{i}: {topic}"
    return impl

for i in range(N):
    mcp.add_tool(
        make_tool(i),
        name=f"tool_{i:03d}",
        description=f"Вернуть строку tool-{i}. Используй, когда спрашивают про topic-{i}.",
    )

if __name__ == "__main__":
    mcp.run()  # по умолчанию stdio

Имя инструмента передаётся явно (name=), поэтому одинаковые имена внутренних функций impl не конфликтуют — на этом чаще всего спотыкаются.

# probe_measure.py — один прогон: N, размер каталога, задержка
import asyncio, json, os, sys, time
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def run(n: int):
    params = StdioServerParameters(
        command=sys.executable,
        args=["mcp_scale_server.py"],
        env={**os.environ, "TOOLS_COUNT": str(n)},
    )
    async with stdio_client(params) as (r, w):
        async with ClientSession(r, w) as s:
            await s.initialize()
            t0 = time.perf_counter()
            res = await s.list_tools()
            ms = (time.perf_counter() - t0) * 1000
    catalog = json.dumps([t.model_dump() for t in res.tools], ensure_ascii=False)
    print(json.dumps({
        "n": n,
        "tools": len(res.tools),
        "catalog_chars": len(catalog),
        "catalog_tokens_est": round(len(catalog) / 4),
        "list_tools_ms": round(ms, 1),
    }))

asyncio.run(run(int(sys.argv[1])))

catalog_tokens_est — грубая оценка «символы / 4»; точное число токенов даёт только токенизатор вашей модели (сверьтесь с документацией).

Как проверить:

python probe_measure.py 5

Пример вывода:

{"n": 5, "tools": 5, "catalog_chars": <ваш-замер>, "catalog_tokens_est": <ваш-замер>, "list_tools_ms": <ваш-замер>}

Главное здесь — "tools": 5 и код возврата 0. Если tools меньше N, сервер поднялся не полностью.

Шаг 2. Прогоните сетку замеров 5 → 100

Что сделать: выполнить пробник на пяти значениях N, затем заполнить по 20 задач на клиенте и посчитать долю верных вызовов.

Зачем: узкое место — не «количество инструментов» само по себе, а объём каталога в контексте и точность выбора нужного инструмента. Первое вы измеряете автоматически, второе — прогоном задач.

for n in 5 10 20 50 100; do
  python probe_measure.py "$n" >> measurements.jsonl
done
cat measurements.jsonl

Пример: после пяти итераций в файле ровно 5 строк с "n" от 5 до 100. Если строк меньше — соответствующая итерация упала, смотрите её stderr.

Теперь набор задач. Он одинаков для всех N и ссылается только на topic-0 … topic-4, поэтому существует при любом количестве инструментов:

mkdir -p tasks && python - <<'PY'
import json
rows = []
for i in range(5):
    for k in range(4):
        rows.append({"prompt": f"верни строку для topic-{i} (вариант {k})", "expect": f"tool_{i:03d}"})
open("tasks/tasks.jsonl", "w").write("\n".join(json.dumps(r, ensure_ascii=False) for r in rows))
print("tasks:", len(rows))
PY

Подключите сервер к клиенту. Формат записи одинаков у большинства клиентов, имя файла зависит от клиента — сверьтесь с документацией:

{
  "mcpServers": {
    "scale-20": {
      "command": "python",
      "args": ["/home/<user>/mcp-scale/mcp_scale_server.py"],
      "env": { "TOOLS_COUNT": "20" }
    }
  }
}

env здесь обязателен: без него клиент запустит сервер с TOOLS_COUNT по умолчанию, и все прогоны дадут одно и то же число — это самая частая ошибка в таких замерах. Модель для прогона задач берите из обзора нейросетей и моделей 2026 — прогон должен идти на той же модели, с которой сервер будет работать в бою.

Как проверить: на каждой итерации меняйте env.TOOLS_COUNT (5, 10, 20, 50, 100), перезапускайте клиент (перезапуск обязателен — каталог кешируется при старте), прогоняйте 20 задач и записывайте число совпадений expect с фактически вызванным инструментом.

Пример: задача верни строку для topic-3 (вариант 1) при ожидаемом tool_003, а в логе клиента вызов tool_003 — плюс один верный; вызов tool_013 — ошибка выбора.

Шаг 3. Сведите результаты и выберите число инструментов

Иллюстрация к разделу «Шаг 3. Сведите результаты и выберите число инструментов»
Иллюстрация к разделу «Шаг 3. Сведите результаты и выберите число инструментов»

Что сделать: собрать все замеры в таблицу, добавить колонку точности и выбрать N.

Зачем: решение принимается по двум ограничениям сразу — каталог должен влезать в бюджет контекста, а точность выбора не должна проваливаться.

python - <<'PY'
import json
rows = [json.loads(l) for l in open("measurements.jsonl")]
print(f"{'N':>4} {'tools':>6} {'tok≈':>7} {'ms':>7}")
for r in rows:
    print(f"{r['n']:>4} {r['tools']:>6} {r['catalog_tokens_est']:>7} {r['list_tools_ms']:>7}")
PY

Пример вывода:

   N  tools    tok≈      ms
   5      5  <замер>  <замер>
  10     10  <замер>  <замер>
  20     20  <замер>  <замер>
  50     50  <замер>  <замер>
 100    100  <замер>  <замер>

Заполните сводную таблицу (числа — свои; в примере только структура):

N инструментовtools в `list_tools`Каталог, токенов ≈`list_tools`, мсВерных вызовов из 20
55`<замер>``<замер>``<0–20>`
1010`<замер>``<замер>``<0–20>`
2020`<замер>``<замер>``<0–20>`
5050`<замер>``<замер>``<0–20>`
100100`<замер>``<замер>``<0–20>`

Правило выбора: берите максимальное N, при котором доля верных вызовов не ниже порога, заданного заранее (например, 0,9), а catalog_tokens_est оставляет запас контекста под сам диалог. Всё, что выше этой точки, выносите в отдельные серверы — клиент подключает несколько серверов одновременно:

{
  "mcpServers": {
    "scale-core": { "command": "python", "args": ["/home/<user>/mcp-scale/mcp_scale_server.py"], "env": { "TOOLS_COUNT": "20" } },
    "scale-extra": { "command": "python", "args": ["/home/<user>/mcp-scale/mcp_scale_server.py"], "env": { "TOOLS_COUNT": "10" } }
  }
}

Как проверить: финальный чек-лист.

Возможные проблемы и решения

Проблема. Клиент не видит ни одного инструмента, пробник зависает

import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)

Проверка: python probe_measure.py 5 снова печатает "tools": 5, а лог виден в stderr.

Проблема. При 100 инструментах модель называет инструмент, которого нет

Проблема. Запрос падает на этапе генерации, хотя list_tools работает

Резюме и следующие шаги

Оптимальное число инструментов MCP-сервера определяется двумя замерами: объёмом каталога в токенах и долей верных вызовов на фиксированном наборе задач. Прогоните сетку 5–100 на своих реальных инструментах и зафиксируйте N\*, при котором точность держится выше порога, а каталог оставляет запас контекста.

FAQ

Сколько инструментов должно быть у MCP-сервера?

Столько, сколько проходит ваш собственный замер: каталог влезает в бюджет контекста, а доля верных вызовов не ниже заданного порога. Универсального числа нет — оно зависит от модели и от того, насколько похожи описания инструментов.

Что такое MCP простыми словами?

Протокол, по которому LLM-клиент получает от сервера список функций (tools) и вызывает их. Клиент и сервер общаются сообщениями JSON-RPC 2.0, чаще всего через stdin/stdout дочернего процесса.

Почему много инструментов замедляет работу?

Каждое описание инструмента уходит в контекст при каждом запросе: растёт число входных токенов, а вместе с ним задержка и риск переполнения контекста. Плюс модели труднее выбрать нужный инструмент среди похожих имён.

Как уменьшить число инструментов без потери функций?

Разнести их по нескольким серверам в одном конфиге клиента, убрать дублирующие по смыслу инструменты и оставить в основном сервере только часто используемые. Если нужен бесплатный вариант клиента для прогонов, см. рабочие способы пользоваться ИИ-моделями бесплатно.

🤖 Кратко для ИИ