Перейти до змісту

Перші кроки

Машинний переклад

Цю сторінку перекладено автоматично з англомовної документації, і основною версією є англомовна сторінка. Якщо щось читається неправильно, на сторінці Переклади пояснено, як про це повідомити.

Головна сторінка рухається швидко: написати сервер, запустити його, викликати інструмент.

Ця сторінка йде повільніше: усі три речі, які може надавати сервер, і назва для всього, що трапиться дорогою.

Хост, клієнт і сервер

Три слова, які ви бачитимете на кожній сторінці відтепер:

  • Хост — це LLM-застосунок: Claude, IDE, середовище виконання агентів. Це те, з чим говорить користувач.
  • Клієнт живе всередині хоста й говорить мовою MCP. Хост запускає по одному клієнту на кожен сервер, до якого під'єднаний.
  • Сервер — це те, що ви створюєте за допомогою цього SDK. Він надає речі клієнтам. Він ніколи не говорить із моделлю напряму.

Ви пишете сервер. Хости — це чийсь інший продукт. SDK також дає вам Client. Ним ви тестуватимете свої сервери, і він з'явиться далі на цій сторінці.

Три примітиви

Сервер надає рівно три види речей. Відрізняє їх те, хто вирішує їх використати:

Примітив Хто керує Що це таке Приклад
Інструменти Модель Функція, яку модель викликає, щоб виконати дію Виклик API, запис у базу даних
Ресурси Застосунок Дані, які хост завантажує в контекст моделі Вміст файлу, відповідь API
Промпти Користувач Багаторазовий шаблон повідомлення, який користувач викликає за назвою Слеш-команда, пункт меню

«Хто керує» — у цьому й увесь сенс поділу. Інструмент запускається, бо модель вирішила його викликати. Ресурс долучається, бо застосунок вирішив, що він потрібен моделі. Промпт запускається, бо його обрав користувач.

Info

Якщо ви вже створювали веб-API, більша частина інтуїції у вас є: ресурс — це GET (завантажує дані й нічого не змінює), а інструмент — це POST (виконує роботу й може мати побічні ефекти). Промпт не має HTTP-аналога; він ближчий до збереженого запиту, який користувач запускає за назвою.

Один сервер, усі три

server.py
from mcp.server import MCPServer

mcp = MCPServer("Demo")


@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b


@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"


@mcp.prompt()
def summarize(text: str) -> str:
    """Summarize a piece of text in one sentence."""
    return f"Summarize the following text in one sentence:\n\n{text}"

Три звичайні функції, три декоратори. Кожен декоратор — це вся реєстрація:

  • @mcp.tool() робить add інструментом.
  • @mcp.resource("greeting://{name}") робить greeting шаблоном ресурсу: {name} в URI — це параметр функції.
  • @mcp.prompt() робить summarize промптом. Рядок, який він повертає, стає повідомленням користувача.

Усе інше (назву, опис, схему аргументів) SDK зчитує із самої функції: її назви, докстрингу, анотацій типів. Ви нічого з цього не оголошували окремо.

Tip

Дві половини SDK мають два шляхи імпорту: from mcp import Client і from mcp.server import MCPServer. Шляху from mcp import MCPServer не існує.

Спробуйте самі

Запустіть його за допомогою MCP Inspector:

uv run mcp dev server.py

Відкрийте URL, який він надрукує. В Inspector є по одній вкладці на кожен примітив; пройдіть їх по черзі.

Tools. Один запис: add з описом Add two numbers. Форма має обов'язкове цілочислове поле для a і ще одне для b. Заповніть їх, викличте інструмент, і результатом буде 3. Inspector побудував цю форму з a: int, b: int. Так само робить і будь-який інший клієнт.

Resources. Список Resources порожній. greeting розташований у Resource Templates, бо greeting://{name} має параметр: немає жодного конкретного ресурсу, який можна показати в списку, поки хтось не вкаже name. Передайте World і прочитайте:

Hello, World!

Prompts. Один запис: summarize з єдиним обов'язковим аргументом text. Отримайте його з якимось текстом — і повернеться одне повідомлення з role: user та вашим відрендереним рядком як вмістом. Оце й увесь промпт: функція, яка будує повідомлення.

Inspector запустив ваш сервер через stdio, один із транспортів, якими може говорити MCP-сервер. Поки що обирати транспорт не потрібно; для цього є сторінка Запуск сервера.

Можливості

В Inspector ви бачили три вкладки. Звідки він знав, що їх три?

Коли клієнт під'єднується, сервер оголошує свої можливості: на які сімейства запитів він відповідатиме. Клієнт використовує це оголошення, щоб вирішити, про що взагалі просити. Ви його не писали; MCPServer оголошує його за вас.

Подивіться самі. Client з SDK приймає об'єкт сервера напряму й під'єднується до нього в пам'яті (без підпроцесу, без порту):

import asyncio

from mcp import Client

from server import mcp


async def main() -> None:
    async with Client(mcp) as client:
        print(client.server_capabilities.model_dump(exclude_none=True))


asyncio.run(main())
{'prompts': {'list_changed': True}, 'resources': {'subscribe': True, 'list_changed': True}, 'tools': {'list_changed': True}}

Цей словник — оголошені можливості вашого сервера. Це перше, про що дізнається кожен клієнт, що під'єднується:

Можливість Клієнт тепер може викликати
tools tools/list, tools/call
resources resources/list, resources/templates/list, resources/read
prompts prompts/list, prompts/get

MCPServer обслуговує всі три примітиви, тож усі три завжди оголошено.

Зверніть увагу на те, чого там немає. completions (автодоповнення аргументів для шаблонів ресурсів і промптів) потребує обробника, який пишете ви; у цього сервера його немає, тож можливість відсутня, і коректний клієнт про неї не проситиме. Це правило для всього необов'язкового: зареєструйте річ — і можливість з'явиться; Автодоповнення це доводить.

Info

Client(mcp) — той самий клієнт у пам'яті, яким протестовано кожен приклад у цій документації, і саме ним ви тестуватимете свої. Йому присвячено цілу сторінку: Тестування.

Чого ви не писали

Озирніться на цю сторінку. Ви написали три невеликі функції Python. Ви не писали:

  • JSON Schema. a: int, b: int і є схема для add.
  • Обробник запитів. tools/list, resources/read, prompts/get: усе обслуговується за вас.
  • Оголошення можливостей. MCPServer зробив його за вас.
  • Жодного рядка протоколу. Узгодження версії, обрамлення JSON-RPC, обмін можливостями: усе це відбулося всередині mcp dev і Client(mcp), і ви цього не бачили.

У цьому співвідношенні й увесь сенс SDK.

Підсумки

  • Хост — це LLM-застосунок, клієнт — його половина, що говорить мовою MCP, сервер — те, що ви створюєте.
  • Інструментами керує модель, ресурсами — застосунок, промптами — користувач.
  • Один декоратор на примітив: @mcp.tool(), @mcp.resource(uri), @mcp.prompt(). Назва, опис і схема беруться з функції.
  • URI з {param} створює шаблон ресурсу, який показується окремо від конкретних ресурсів.
  • Можливості сервера оголошуються за вас, а клієнт просить лише те, що сервер оголосив.
  • Client(mcp) під'єднується до об'єкта сервера в пам'яті: ваш тестовий стенд із першого дня.

Далі — Під'єднання до справжнього хоста: цей сервер усередині Claude Desktop або IDE, по-справжньому. Потім Тестування: одна сторінка, один клієнт у пам'яті — і більше ніколи не доведеться гадати, чи воно працює. Після цього кожен примітив отримує власну сторінку, починаючи з того, яким керує модель: Інструменти.