Головна / Статті / MCP З нуля, частина 3: Підключення клієнта до вашого сервера

MCP З нуля, частина 3: Підключення клієнта до вашого сервера

Створіть клієнт MCP stdio, який запускає hr_server.py, викликає функцію search_employee та повертає результати — без необхідності вручну запускати сервер.

804 слів

У попередній частині залишився сервер MCP із єдиною функцією: надавати можливість пошуку в HR-системі.

HR MCP Server
      ↓
search_employee

Цей процес починався так:

python hr_server.py

Залишалося одне незрозуміле питання: хто насправді спілкується з сервером? Цю роль виконує клієнт.

Client
   ↓
MCP
   ↓
HR MCP Server

Розглядаймо ці поняття просто. Сервер пропонує можливості, а клієнт під’єднується та їх використовує.

Створимо наш клієнт

Окрім hr_server.py додайте ще один модуль:

hr_client.py

Структура проекту стає такою:

mcp-hr
│
├── hr_server.py
│
└── hr_client.py

Оскільки сервер вже написаний, увага зосереджується на клієнті.

Під’єднання до нашого сервера

Вставте наступний код у hr_client.py:

import asyncio

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
    server = StdioServerParameters(
        command="python",
        args=["hr_server.py"]
    )
    async with stdio_client(server) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

asyncio.run(main())

Спочатку цей код здається складним. Вирішальною частиною є:

server = StdioServerParameters(
    command="python",
    args=["hr_server.py"]
)

Ці параметри наказують клієнту запустити та під’єднатися до hr_server.py. Клієнт запускає процес сервера та відкриває сеанс stdio з ним.

Тепер скличемо наш інструмент

У частині 2 був описаний інструмент під назвою:

search_employee

Клієнт може шукати Джона ось так:

await session.initialize()
result = await session.call_tool(
    "search_employee",
    {"name": "John"}
)

print(result.content[0].text)

Простими словами, клієнт просить сеанс виконати search_employee з ім’ям Джон. Повний скрипт клієнта є таким:

import asyncio

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
    server = StdioServerParameters(
        command="python3",
        args=["hr_server.py"]
    )
    async with stdio_client(server) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool(
                "search_employee",
                {"name": "John"}
            )
            print(result.content[0].text)

asyncio.run(main())

Цей файл є повною клієнтською частиною демонстрації.

Запустимо його

У терміналі виконайте:

python hr_client.py

Корисна деталь: hr_server.py не потребує окремого ручного запуску. Клієнт запускає його через:

command="python",
args=["hr_server.py"]

а потім під’єднується до запущеного процесу.

Що відбувається?

Клієнт надсилає запит до інструменту у такому форматі:

Tool:
  search_employee
Name:
  John

Сервер отримує його та виконує:

search_employee("John")

Він розрішує:

John → Finance

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

hr_client.py
     │
     │  search_employee("John")
     ↓
hr_server.py
     │
     ↓
Search employee list
     │
     ↓
John → Finance
     │
     ↓
hr_client.py

Обидві сторони протоколу зараз здійснюють справжню подорож туди й назад.

Повернення до нашого прикладу USB

Підключення клавіатури до комп’ютера є корисним порівнянням.

Keyboard
   ↓
USB
   ↓
Computer

Обидві сторони домовляються про спільний протокол кабелю. Тут клієнт використовує MCP, а сервер також MCP. Саме цей спільний контракт дозволяє їм співпрацювати.

Але чи обрав він інструмент?

Одне з обмежень легко пропустити. Розгляньмо місце виклику знову:

session.call_tool(
    "search_employee",
    {"name": "John"}
)

Хто обрав search_employee? Автор додатку — шляхом жорсткого введення назви інструменту. Клієнт ніколи не читав запитання мовою природи на кшталт «Чи працює Джон у відділі фінансів?» та не вирішував, яку функцію активувати. Наступною відсутньою складовою є автоматичний вибір інструменту.

Що далі?

Уявіть, що на сервері з’являється кілька нових інструментів:

search_employee
create_employee
get_leave_balance
list_departments

Коли користувач запитує, до якого відділу належить Джон, щось має вирішити, що правильною функцією буде:

search_employee

а не якийсь інший інструмент. Це рішення залежить від назв інструментів, їхніх описів та каталогу, який публікується. У наступному розділі розглядається, як додаток обирає серед інструментів MCP, коли їх стає багато.

До того часу важливий урок, який можна засвоїти з цього кроку, є механічним: клієнт stdio може запустити сервер, ініціалізувати сесію, викликати зазначений інструмент із аргументами та вивести структуровану відповідь — без необхідності ручного запуску окремого процесу сервера.