Галоўная / Артыкулы

Створыце свой першы сервер MCP на Python: інструменты, рэсурсы, запыты і інспектар

Створыце сервер MCP на Python з FastMCP: прыступны адказчык з інструментамі, рэсурсамі і запытамі, stdio проты HTTP, аптрымкаванне за дапамою Inspector і адна настройка для 3 кліентаў.

Выдавец: REACTAPP.TOP9 хв чытання2056 слоў

Крыніцы: What Is MCP? Build a Custom MCP Server in Python

Уявіце тры файлы на мове Python, якія здаюцца практычна ідэнтычнымі, паведамленыяяя Claude, Cursor і ChatGPT; кожны з іх вызывае API Slack, аналізуе адпаведны ўтварэнне і прыменяе яго да паводлівання адзінам конкрэтным кліенту AI. Цяпер уявіце, што всі трое можна заменіць на адзін файл, з якога кожны з тых кліентоў можа безпосерэдна чытаць даныя. Калі Slack змянюе які-небудзь пункт, яго трэба пасправіць толькі раз. Гэты адзін файл — гэта сервер MCP, і яго стварэнне займае працовы дзень.

MCP за калькі рэчэй

Протакол Model Context Protocol настолькі просты, што можа быць опісаны за тры паведамленні. Кліент падключаецца да сервера і запытае, што той можа зрабіць. Сервер адпавядае, пераказваючы інструменты, якія можа вызываць мадэль, даныя, якія можа запрашаць хост, і запросы, якія можа выбраць корыстнік. Пасля чаго кліент вызывае інструмент з аргументамі, сервер яго запускае і адпавядае. У сэты — гэта ўсё.

Тое, што робіць MCP прыдатным для вікорыстання, — не фармат паведамлення, а спяшчана даговорэнасць. Claude Code, Cursor, Copilot у VS Code і іншыя прыстроі віконваюць адно і тое ж прыема-перадачу дадзеных, таму файл на Python, напісаны зараз, можа быць прыўязаны да будзь-каго з іх пазней.

Сервер можа запрошваць адну з трохоў відменнасцей можлівасцей:

  • Інструменты — гэта функцыі, якія можна вызваць, і якія модэль выбірае па імені; напрыклад, функцыя для пошуку ў базе дадзеных, стварэння галузі чысткі логаў.
  • Рэсурсы — гэта толькі для чытання матэрыялы, такія як файлы налашчэння, схемы чыст няўяўленні, якія хост запрашвае, калі яму трэба дадатковыя даны.
  • Запросы — гэта шаблоны, якія можна вікорыстоўваць знову, і якія выбірае корыстнік; яны праказваюцца як команда з слэшам у Claude Code чыст пунктам у меню ў Claude Desktop.

У практыцы большасць сервераў поставляюць інструменты, а рэсурсы і інструкціі ўступаюць у другую параду. Калі вы хочаце выучыць толькі адна з трох, выучыце інструменты. Тое, як пераходзяць звесці і як працюе аўтэнтыфікацыя, мае значэнне пазней. Наразе запамятаце гэта: адзін сервер, многа кліентаў, тры рэчы, якія трэба адкрыць.

Чаму раней множыліся інтэграцыі

Да появы MCP, падключэнне AI-інструмента да бэкэнда значыла напісанне адаптара між структурой вашага бэкэнда і фарматам вызову інструмента, які хацеў кліент. Одні кліенты чакалі схему інструментаў Anthropic, іншыя вікорыстоўвалі свой саўстанні фармат, а трэція хацелі структуру вызову функцый OpenAI. Пошук у Slack заставаўся ідэнтычным, пакуль навакол яго росла троха шароў-обгортак.

Арыметыка быстра стаець складнай. Тры кліенты і два бэкенды значыць шасць адаптароў, якія трэба падтрымваць. Чэрговы кліент даўае восьмы, а трэці бэкенд — дванаццаць, пры чым кожны з іх мае свою сістэму аўтэнтыфікацыі, механізмы перапрыбуткі і іншыя особлівасці. MCP раздзеляе гэты продукт на часты. Кліенты і бэкенды больш не спілкуюцца адзін з другім. Оба спілкуюцца з пратакам, таму адпрацоўка новага кліента на базе AI коштае толькі аднае запісу ў налашчаннях, а не новай інтэграцыі.

Дызайн пратакі навмысна несбалансаваны. Кліент вяршыць усё: якія серверы запускаць, калі вызываць інструменты і як адображаць рэзультаты. Задачы сервера значна меньшыя — ён проста адзначае своі інструменты і адпавядае, калі яго вызываюць. Гэтая асіметрыя дапамагла заставіць пратаку настаць дастатнька компактной, ўсе вядомы кліенты моглі яе шыбка адпрацаваць.

Памочны інструмент у аднам файле

Прампт-дапаможнік — гэта класычны внутрэнні інструмент, які інжынеры постаўляюць перапісваць. Ён чытае локальны журнал git і падсумоввае, што розробнік зрабіў вчора. У даным прыкладзе ён будзе прэдставлены як інструмент, рэсурс і прампт у аднам файле Python.

Вам патрэбна пакетацыя FastMCP — высокага рэвэля Python, на якім базуюцца багатыя серверы MCP.

pip install fastmcp

Створыце standup_server.py. Спачатку ён імпортуе бібліятэку і задае параметры адпрацоўвання.

# standup_server.py
import subprocess
from typing import TypedDict

from fastmcp import FastMCP

mcp = FastMCP("standup-helper")


class StandupSummary(TypedDict):
    branch: str
    since: str
    commit_count: int
    commits: list[str]


@mcp.tool()
def summarize_standup(
    branch: str = "main",
    since: str = "yesterday",
) -> StandupSummary:
    """Summarize recent git activity for a standup.

    Reads the local git log on the given branch since the
    given time window. Returns commit count and one-line
    subjects for each commit. Used by AI clients via MCP.
    """
    try:
        result = subprocess.run(
            [
                "git", "log",
                f"--since={since}",
                "--pretty=format:%h %s",
                branch,
            ],
            capture_output=True,
            text=True,
            timeout=5,
            check=True,
        )
    except (subprocess.CalledProcessError,
            subprocess.TimeoutExpired) as exc:
        return {
            "branch": branch,
            "since": since,
            "commit_count": 0,
            "commits": [f"git error: {exc}"],
        }

    lines = [
        line for line in result.stdout.splitlines() if line
    ]
    return {
        "branch": branch,
        "since": since,
        "commit_count": len(lines),
        "commits": lines,
    }


# resources and prompts come next

У закуліссях дэкаратар выконвае чатыры задачы. Ён чытае падказкі пра тыпы, каб створыць схему JSON, выкарыстоўвае докстрынг як апісанне, якое паказваецца модэлю, уключае інструмент у спектар можлівасцей сервера пад час абмовкі, а таксама перадае прыходзячыя запыткі JSON-RPC да відпаведнай функцыі.

Зверніце ўвагу на запыткі падзеяў з строгім таймаутам у пяць секунд. Калі команда git застоіцца, прыкладнае застосунак, які чакае на адпаведзь інструмента, таксама застоіцца, таму кожны зов на зовнішній інструмент патрэбуе таймаута. Рамка з адмовамі таксама вяртае той самы фармат слоўніка, як і рамка з успехам, таму модэль завжды атрымлеў прыемнае для аналізу структуру. Болей складны інструмент можа таксама вызваць GitHub CLI для адкрытых запыткаў pull request, дадаўшы ўтрохтуючы запыт падзеяў і дадаўшы выходны даныя да слоўніка.

Далей ідуць рэсурс і запрошэнне, якія завершаюць файл.

# standup_server.py (continued)

@mcp.resource("recent_commits://main")
def recent_commits_main() -> str:
    """Last 10 commits on the main branch, plain text.

    Resources are pulled by the host opportunistically.
    They are not invoked by the model the way tools are.
    """
    result = subprocess.run(
        [
            "git", "log",
            "-n", "10",
            "--pretty=format:%h %ad %s",
            "--date=short",
            "main",
        ],
        capture_output=True,
        text=True,
        timeout=5,
    )
    return result.stdout or "(no commits found)"


@mcp.prompt("standup_template")
def standup_template(focus: str = "shipping work") -> str:
    """Reusable standup question exposed as a prompt
    template. Surfaces as a slash command in clients that
    expose prompts (e.g. /standup_template in Claude Code).
    """
    return (
        f"Summarize what I worked on yesterday, focusing on "
        f"{focus}. Use the summarize_standup tool to get the "
        f"git log, then write a one-paragraph standup note."
    )


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

URI рэсурса — гэта проста строка. Не існуе жаднага строгага шэмы, які бы кантролаваў яго форму, хоць звычайна ўжываецца шэма, за якой следуе шлях, а FastMCP падтрымляе шаблоны URI, калі патрэбны параметры. Прампт — гэта проста функцыя, якая вяртае фарматаваны тэкст. Кліенты прэдставляюць яго як шаблон, які выкананы корыстнікам, а Claude Code адкрывае яго як команду з слэшам. Прампты ніколі не вводзяцца аўтаматычна, таму корыстнік завжды выбірае іх.

Пасляльні лінія запускае сервер. Не існуе порту, жаднага веб-фрэймворку і жаднага цыклу здарэнняў, якія трэба кантролаваць, таму ўсе пытанні стандартнага вводу-выводу адбываюцца за дапамогою FastMCP.

Транспорты і аўтэнтыфікацыя

Транспорт вялічыць, як паведамленні JSON-RPC перавозяцца межы кліентам і серверам.

Для локальных сервераў выкорыстоўваюце stdio. Хост запускае ваш скрыпт як дзеціны працэс. Stdio абходзіць весь сетавы стак: няма порту, няма TLS і няма аўтэнтыфікацыі, таму што дзеціны працэс успадковуе межы доверлівасці хоста.

Выкорыстоўваюце Streamable HTTP, калі сервер павінен зберагаць стан між запытамі або калі да яго можна дасягнуць з калькулятараў. Аддалены сервер знаходзіцца на сеткі, таму яму патрэбна строгая аўтэнтыфікацыя.

# bottom of standup_server.py

if __name__ == "__main__":
    # Default transport is stdio. The host (Claude Code,
    # Cursor, Claude Desktop, etc.) launches this script
    # as a subprocess and talks to it over stdin/stdout.
    # No port, no TLS, no auth. The trust boundary is
    # whoever launched the host.
    mcp.run()

    # To expose the same server over the network instead,
    # use Streamable HTTP. SSE was deprecated in the
    # March 2025 spec update. Do not use it for new code.
    #
    # Production HTTP also needs an auth layer in front.
    # OAuth 2.1 with Dynamic Client Registration is the
    # current pattern. See Week 22 for the full flow.
    #
    # mcp.run(
    #     transport="streamable-http",
    #     host="0.0.0.0",
    #     port=8000,
    # )

Выклік функцыі run без жадных аргументаў означае вікорыстанне stdio, а прыклад у каментарах паказвае, як выглядае апградацыя працы з HTTP. У гэтым варыянцы застаёцца stdio, што ўсунецца правым выборам для большасці внутрашніх інструментаў распрацоўшчыкаў. Інструмент, які чытае толькі локальныя файлы або локальны рэпазітарый, узагалі не павінен працаваць праз сеткавы інтэрфейс.

Локальны цыкл разработкі

Не тэставайце новы сервер, падключаючы яго безпосерэдня да кліента AI. Кліенты ствараюцца так, каб быць стойкімі: яны тылуць несувязы між схемамі і ігнаруюць відсутныя можлівасці, каб чат продаваў працаваць, а калі інструмент не функцыонуе, мадэль проста праганяецца.

У замен выкорыстоўваюце офіцыйны MCP Inspector — інтэрфейс разработкі на базе браузера, які вяршыць вяроўнаванне з вашым серверам праз stdio.

npx @modelcontextprotocol/inspector python standup_server.py

Каманды запускае ваш скрыпт як падпроцэс і ачынае локальную панель керування. Вы можэце прачытаць необработаныя даныя, адразу пабачыць, якія можлівасці прызнаў ваш сервер, і выкананыць інструменты і рэсурсы ў рэальны час.

У гэтым цыкле часта з’яўляюцца тры проблемы:

  1. Несувпадэнне схемы. Значэнне, якое вяртае функцыя, не паспаўляе з ўказаным тыпам, і інспектар адразу на гэта звяртае ўвагу.
  2. Відсутняя можлівасць. Вы вызываеце ўсё тое, чаго сервер ніколі не прызнаў, і панель керування паказвае тое, што на самай працэўцы пераговора было фактычна зарэўнавана.
  3. Забрудненне выходных даных. Будзь-які непатрэбны вызов print() пашкоджае стрым JSON-RPC, адколі стандартны ввод-выход несе паведамленні. Направляйце логі ў стандартныя памылкі за дапамогою модуля logging у Python, які протакол выдзеляе для чытальных дыягназ.

FastMCP таксама працюе ў рэжыме разработкі, які перазапускае сервер, калі змінюецца файл, што дапамагае пад час працы ў інспектары.

Адны сервер, калькі кліентав

Цяпер дызайн прадае своі плоды. Існуе адны файл на Python, які пераканальваецца ў інспектары, і яго можна прыўязаць да розных кліентав AI без якога-лібо коду, спецыфічнага для кліента. Кожны кліент чытае файл налашчэння, у яком указаны локальныя серверы, якія трэба запусціць, і структура JSON застаецца аднаковай у Claude Code, Cursor і Claude Desktop: аб’ект mcpServers, які містыць команду для запуску і яе аргументы.

{
  "mcpServers": {
    "standup-helper": {
      "command": "python",
      "args": ["/Users/you/code/standup_server.py"]
    }
  }
}
{
  "mcpServers": {
    "standup-helper": {
      "command": "python",
      "args": ["/Users/you/code/standup_server.py"]
    }
  }
}
{
  "mcpServers": {
    "standup-helper": {
      "command": "python",
      "args": ["/Users/you/code/standup_server.py"]
    }
  }
}

Ключ, команда і аргументы ў всіх трохіх варыянтах аднаковыя. Толькі месца знаходжэння файла налаштавання разлічаецца залежна ад кліента.

Ачыньце будзь-кой з іх і запытайце пра стэндап. Кліент запускае працэс Python, домовляецца пра можлівасці праз stdio, паказвае інструмент падсумаваў модэлю і перадае вызов модэлю назад у ваш скрыпт. Git запускаецца, дыкшанарыя вяртаецца, а модэль запісвае стэндап па той самы кодовы тракт у кожны раз.

ChatGPT не ў гэтым спіску, таму што яго канектары працуюць з даўальнымі серверамі праз Streamable HTTP. Чырагаванне гэтага дапаможніка ў яго будзе вымагаць публічнага URL і шара аўтэнтыфікацыі, што ўжо зусім іншы спосаб работы, чым у гэтым строго локальным варыянцы.

Калі не варта вжываць MCP

Гэты протакол — не універсальны інструмент. Якіясь сітуацыі яму не падходзяць:

  • Траектары, чуткія да затрымкі. Кожны вызов інструмента адбываецца за допамогай JSON-RPC, таму інструменты, якія выконваюцца ў внутршніх цыклах, должны вікорыстоўваць прымытую інтэграцыю з SDK.
  • Адзінакавы інтэрактыўны выхід. Калі вам патрэбны конкрэтныя графікі або адзінакавы форма, вам неабходна стварыць інтэграцыю з хостам, адколі пратакол раздзеляе даныя і ўпрадзенне інфармацыі.
  • Настройкі, якімі вы абсалютна керуеце. Калі адна команда стварае як кліент AI, так і бэкэнд, іх прымытая вяроўнаважанне можа быць простэйшай для падтрымкі, чым вставка MCP між німі.

Маленькі пратакол, вялікія змяны

Цэлы пратакол складаецца з трох прымітыў, двух срэдств транспортування і аднага сэансу абмену данымі JSON-RPC. Самэй тое, што ён такі маленькі, являецца яго сілой: ён аддзеляе тых, хто стварае інтэлект, ад тых, хто забезпечвае кантэкст. Стварэнне першага сервера займае канічна час, але гэта себе выплачвае ў кожны раз, калі з’яўляецца яшчэ адна АІ-інструментальная практыка.

Спадневана літэратура

  • Аўтаналізуючыяся каманды з калькольнікамі ў LangGraph: архітэктар, тэставальнік, дэбаггер — Створыце машыну станоў у LangGraph на Python, дзе архітэктар, распрацоўшчык, сандбокс pytest, дэбаггер і рэвізор сааверцуюць і працуюць па цыклу, пакуль тэсты не пройдуць.
  • Заўядомыя запуск Qwen3.8-Flash-Next як калькольніка з llama.cpp і OpenCode — Пасляпасна інструкцыя па наладзе для запуску 125B MoE-модэлю для програмавання на вашай сабеўскай GPU з адпаведнымі інструментамі, які будзе працаваць праз API у стылі OpenAI і керавацца з OpenCode.
  • Практычныя прыемы: Чым являецца Retrieval-Augmented Generation (RAG)? Практычныя рэкамендацыі — Паследовы выкладкі па тэме «Практычныя прыемы: Чым являецца Retrieval-Augmented Generation (RAG)? Практычныя рэкамендацыі»: контракты, перакантрольваннія і шаблоны коду для команд, якія вікорыстоўваюць гэты падход.