Закажи экспресс-аудит своего дела онлайн всего за 199 ₽
и получи рекомендации по улучшению - Жми сюда !

Мой ИИ не мог видеть мои файлы — я создал MCP-сервер с нулевой зависимостью от внешних сервисов.

Я создал слой MCP на чистом Python, который работает поверх стандартного ввода-вывода для локальных клиентов и HTTP/SSE для одновременных подключений. Один флаг. Никаких зависимостей. 5 клиентов. Менее 50 мс.

Делиться

6571b351348b3742d11b297a1ce9147b
Изображение предоставлено автором и сгенерировано с помощью ChatGPT (DALL·E).

Я занимался рефакторингом парсера. Функции стали слишком длинными, а имена переменных потеряли всякий смысл. Каждый раз, когда мне нужна была обратная связь по файлу, я останавливался, открывал чат, копировал всё целиком и ждал. Затем возвращался в редактор, применял изменения, открывал следующий файл и повторял всё заново.

В какой-то момент я посчитал. Шесть файлов. Одиннадцать вставок. Двадцать минут переключения, прежде чем я написал хотя бы одну новую строку.

Очевидным решением было предоставить инструменту ИИ прямой доступ к папке моего проекта. Именно тогда я столкнулся с MCP — протоколом контекста модели, — который как раз и создан для этой цели. Сервер работает локально, предоставляет доступ к инструментам, а клиент ИИ вызывает эти инструменты напрямую, вместо того чтобы ждать, пока я вставлю текст.

Поэтому я изучил существующие реализации. Большинство требовали FastAPI, uvicorn, LangChain или официального SDK MCP. Прежде чем написать хоть одну строчку бизнес-логики, у меня в файле требований было пять пакетов и сервер, в работоспособности которого на Windows я не был уверен.

Я отступил назад и прочитал фактическую спецификацию MCP [1]. Протокол — JSON-RPC 2.0 [2] поверх транспортного уровня. Один JSON-объект на строку. Клиент отправляет, сервер отвечает. Спецификация определяет ровно два транспорта: stdio для локальных одноклиентских соединений и HTTP с Server-Sent Events для одновременных клиентов.

Таков весь протокол.

Я задал другой вопрос: что именно нужно этому, чего нет в стандартной библиотеке Python? sys.stdin , sys.stdout , http.server , threading , queue , pathlib , json . Вот и всё. Ни одной команды pip install .

В этой статье рассматривается реализация — оба варианта передачи данных, модель безопасности для производственной среды, 50 тестов и результаты их выполнения.

Вкратце:

Большинство реализаций MCP кажутся более громоздкими, чем следовало бы. Спецификация определяет только два типа транспорта: stdio и HTTP/SSE, но на практике они обычно обернуты в фреймворки и дополнительные зависимости.

Оба механизма передачи данных я разработал с нуля, используя только стандартную библиотеку Python.

Он запускается как единый файл с одним флагом среды выполнения. Никакой установки, никакой настройки.

Для локальной работы используется стандартный ввод/вывод с одним клиентом. При необходимости параллельной обработки переключается на HTTP/SSE и обрабатывает несколько клиентов без каких-либо других изменений.

Внутри все остается неизменным. Тот же диспетчер, те же инструменты, та же модель безопасности.

Поскольку это затрагивает файловую систему, я с самого начала добавил строгие проверки путей. Распространенные шаблоны экранирования, такие как ../../, уловки с символическими ссылками и UNC-пути Windows, блокируются.

5 одновременно работающих клиентов. Общее время выполнения менее 50 мс. Проверено на Windows 11, Python 3.12.6, только на ЦП.

Полный код: https://github.com/Emmimal/local-mcp-server/

Ошибка, которая повлияла на весь дизайн.

Прежде чем перейти к архитектуре, я хочу рассказать вам о том, что чуть не заставило меня отказаться от всего этого проекта.

На начальном этапе разработки я тестировал инструмент поиска. Я указал серверу путь C:UsersAdmin и запустил поиск файлов Python. Сервер запустился. Демоверсия запустилась. И так продолжалось постоянно.

Тридцать секунд. Минута. Пять минут. Мне показалось, что где-то бесконечный цикл. Я трижды перепроверил код. Всё выглядело правильно. Я завершил процесс и перезапустил его. Результат тот же.

Спустя десять минут я наконец понял, что происходит. Инструмент поиска по умолчанию использовал rglob() . Я указал ему путь ко всей директории пользователя, и он сканировал всё — виртуальные среды, папку AppData, каждый кэшированный файл на компьютере. Десятки тысяч файлов, по одному за раз.

Я прервал процесс и изменил одну строку:

 # Before — recursive by default, scans everything for match in target.rglob(pattern): # After — shallow by default, opt-in for recursion for match in target.glob(pattern):

И сделал recursive=False параметром по умолчанию. Клиент должен явно передать recursive=True . Сервер никогда не будет выполнять рекурсивное сканирование самостоятельно.

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

Что на самом деле представляет собой MCP

Протокол контекста модели [1] — это стандартизированный способ вызова инструментов на внешних серверах для клиентов ИИ. В качестве формата сообщений он использует JSON-RPC 2.0 [2].

На практике это означает, что клиенты ИИ, такие как Claude или ChatGPT, могут напрямую получать доступ к локальным файлам и анализировать их, вместо того чтобы полагаться на копирование и вставку.

Процесс установления соединения состоит из трех фаз. Сначала клиент инициализируется, затем запрашивает информацию о доступных инструментах, после чего начинает их вызывать:

Диаграмма последовательности, иллюстрирующая жизненный цикл протокола контекста модели (MCP) между клиентом и сервером. Диаграмма подробно описывает три фазы в порядке сверху вниз: инициализация (метод initialize возвращает protocolVersion), обнаружение (метод tools/list возвращает массив инструментов) и выполнение (метод tools/call запрашивает инструмент read_file в файле main.py и возвращает содержимое выполнения).
Жизненный цикл сообщения протокола контекста модели (MCP). Четкий архитектурный обзор, демонстрирующий последовательный двунаправленный обмен данными JSON-RPC между клиентом и сервером на этапах инициализации, обнаружения и выполнения. Изображение предоставлено автором.

Всё, что происходит после этого, — это транспортировка сообщений туда и обратно.

Спецификация определяет два транспорта. stdio работает через стандартный ввод и вывод — один объект JSON на строку, который немедленно отправляется. HTTP/SSE обрабатывает запросы через HTTP POST, а ответы передаются обратно через постоянное соединение Server-Sent Events [3].

В большинстве реализаций выбирается один вариант. В этой же реализованы оба, с одним и тем же диспетчером и четырьмя одинаковыми инструментами, лежащими в основе каждого из них.

Вот что показывает демоверсия при запуске — оба транспорта регистрируют одни и те же инструменты:

 [2] Available tools [list_directory ] List files and directories. Returns name, type, size... [read_file ] Read a file's contents. Max 1 MB. Binary files returned... [search_files ] Search files by glob pattern. Use recursive=true for... [get_file_info ] Get metadata for a file or directory: size, type, ext...

Архитектура: четыре слоя

Система состоит из четырех уровней.

Архитектурная схема, иллюстрирующая развязанные уровни реализации протокола контекста модели (MCP). Схема отображает операционный поток от клиента ИИ, передающего запросы JSON-RPC 2.0, через транспортный уровень, поддерживающий стандартный ввод-вывод и HTTP/SSE. Запрос попадает в маршрутизатор Dispatcher без сохранения состояния, анализирует имена инструментов и аргументы на уровне инструментов, проходит проверку на уровне безопасности с разрешением безопасного пути в песочнице MCP_ROOT и, наконец, безопасно выполняется в базовой локальной файловой системе.
Архитектурный стек протокола контекста модели (MCP) с разделением компонентов. Структурный анализ, демонстрирующий, как необработанные сообщения клиента безопасно передаются, маршрутизируются, проверяются и выполняются в строго изолированной локальной файловой системе. Изображение предоставлено автором.

Уровень безопасности — проверяет каждый путь перед любой операцией с файловой системой. Он выполняется до всего остального, при каждом отдельном вызове.

Слой инструментов — четыре инструмента для фактической работы файловой системы: list_directory , read_file , search_files , get_file_info .

Dispatcher — маршрутизатор JSON-RPC без сохранения состояния. Он анализирует метод, вызывает нужный обработчик и возвращает ответ. Он не знает, какой транспорт запущен, и ему это не нужно.

Транспортный уровень — две реализации. StdioTransport для локальных клиентов ИИ. HTTPSSETransport для одновременных подключений. Диспетчер не знает, какая из них запущена.

Точка входа выбирает транспортный механизм при запуске:

 dispatcher = MCPDispatcher(root) if args.http: HTTPSSETransport(dispatcher, host=args.host, port=args.port).run() else: StdioTransport(dispatcher).run()

Один флаг. И всё.

Модель безопасности

Первое, о чём мне пришлось подумать при создании сервера, читающего локальные файлы, — это что помешает клиенту читать файлы, которые он не должен читать. Очевидная атака — это обход пути: вместо отправки README.md клиент отправляет ../../etc/passwd , и сервер, который не проверяет это, следует по этому пути прямо за пределы песочницы.

Решение заключалось в том, чтобы полностью определить оба пути перед их сравнением. Ключевая фраза:

 target.resolve().relative_to(base.resolve())

Path.resolve() разворачивает все символические ссылки и сворачивает все сегменты «.». relative_to() вызывает ValueError, если результат выходит за пределы базового пути. [6] Нет разбора строк, нет ручного подсчета .. «. Операционная система определяет путь; Python проверяет результат.

Переменная окружения MCP_ROOT задает корневой каталог песочницы. Я установил его конкретно в папку своего проекта, а не в домашний каталог. Каждый инструмент выполняет эту проверку перед обращением к файловой системе. Если проверка не пройдена, ошибка немедленно возвращается клиенту.

Тесты безопасности проверяют это в каждой сборке:

Атака Результат
../../etc/passwd Доступ запрещен
Символическая ссылка, указывающая за пределы корневого каталога. Доступ запрещен
Путь Windows UNC \servershare Доступ запрещен
src/main.py внутри корневого каталога Допустимый

Четыре инструмента

список_каталог

Выводит список всего содержимого каталога — имя, тип, размер, метка времени изменения, относительный путь. Каталоги отображаются перед файлами, скрытые элементы по умолчанию исключаются.

Указывая на папку проекта:

 [3] list_directory 8 entries: [F] concurrent_demo.py 4,711B [F] demo.py 10,451B [F] http_client.py 5,140B [F] local_desktop_config.json 228B [F] README.md 7,542B [F] server.py 29,222B [F] test_server.py 17,500B

Восемь записей, размеры, все внутри песочницы. Порядок сортировки ставит каталоги на первое место, потому что ключ сортировки использует p.is_file() — в Python False < True , поэтому каталоги, естественно, располагаются вверху списка.

Одна вещь, которая меня подвела в Windows: файл может отображаться в списке файлов каталога, будучи заблокированным другим процессом. item.stat() вызывает PermissionError для этой записи. Инструмент оборачивает каждый вызов stat в отдельный блок try/except и пропускает заблокированные записи без предупреждения, вместо того чтобы вызывать сбой всего списка файлов.

read_file

Считывает содержимое файла с жестким ограничением в 1 МБ. Текстовые файлы возвращаются в формате UTF-8. Двоичные файлы возвращаются в формате base64.

 read_file concurrent_demo.py: #!/usr/bin/env python3 """ concurrent_demo.py ============================ Proves the HTTP/SSE transport handles multiple concurrent clients. Spins up 5 clients simultaneously, each running ... (4509 more chars)

Я добавил резервный бинарный код после того, как впервые указал серверу на реальную папку проекта. Папки проектов Python содержат файлы .pyc , скомпилированные расширения и базы данных SQLite. Первая версия отклоняла все это с UnicodeDecodeError . Исправление: если read_text() завершается с ошибкой декодирования, используется read_bytes() , и возвращается base64. Клиент получает структурированный ответ с флагом binary: true вместо сообщения об ошибке.

Ограничение в 1 МБ существует потому, что в одном из ранних тестов случайно была прочитана база данных SQLite размером 200 МБ, и процесс завис на тридцать секунд. MAX_FILE_BYTES — это константа в начале файла server.py ; измените её, если ваш рабочий процесс требует файлов большего размера.

поиск_файлов

После инцидента с функцией rglob() этот инструмент работает следующим образом:

 [6] search_files — *.py (shallow) Found 5 file(s): -> concurrent_demo.py 4,711B -> demo.py 10,451B -> http_client.py 5,140B -> server.py 29,222B -> test_server.py 17,500B

Пять файлов, менее 30 мс. Тот же вызов для C:UsersAdmin с recursive=True всё равно просканирует всё — но теперь это осознанный выбор клиента, а не то, что сервер делает автоматически.

Флаг truncated сообщает клиенту, когда результаты были обрезаны по значению max_results . В первой версии результаты автоматически отбрасывались без каких-либо сигналов — я добавил truncated поняв, что у клиента нет способа узнать, что он получает не все результаты.

get_file_info

Возвращает метаданные, не считывая содержимое файла — это полезно, когда клиенту необходимо проверить права доступа, прежде чем принимать решение о чтении.

 [4] get_file_info name local-mcp-server path . type directory size 4096 modified 1780246573 created 1780227648 extension None readable True writable True

os.access() проверяет реальные права доступа, а не просто существование файла. В Windows файл может быть виден в списке файлов, будучи заблокированным. Знание о его недоступности до попытки чтения позволяет избежать повторного обращения к файлу.

Диспетчер

Я не хотел изобретать велосипед или переписывать основную логику только для обработки различных сетевых настроек, поэтому я создал центральный диспетчер, который обрабатывает всё. Он функционирует как базовый, без сохранения состояния механизм. Входит необработанная JSON-строка, диспетчер анализирует её, чтобы точно определить, что нужно клиенту, а затем отправляет ответ.

Я намеренно исключил из этого компонента все сетевые и файловые операции ввода-вывода. Он ничего не знает о stdin, stdout или HTTP. Вся эта сложная коммуникация полностью возложена на транспортные уровни. Транспортные уровни выполняют основную работу с фактическими сокетами или потоками и просто передают чистые данные функции dispatch() .

Для обеспечения оптимальной производительности системы, движок прослушивает только четыре метода спецификации: initialize , tools/list , tools/call и ping . Если диспетчер получает какой-либо другой запрос, он немедленно завершает обработку стандартной ошибкой JSON-RPC.

Единственное исключение — обработка уведомлений. Когда приходит сообщение без поля id , спецификация MCP предписывает, что ответ не требуется. Диспетчер обрабатывает событие внутри себя и просто возвращает None . Поскольку основной движок полностью независим от способа передачи данных, переход от локального стандартного ввода-вывода к HTTP-серверу не требует никаких внутренних изменений в коде. Транспортный уровень изменяется снаружи, но основной диспетчер остается точно таким же.

Транспорт 1: студио

В локальной конфигурации передача данных по стандартному вводу/выводу осуществляется просто строкой for line in self._stdin . Я полностью пропустил асинхронные операции, потоки и циклы событий, чтобы максимально упростить код.

На исправление ошибки в Windows у меня ушло больше времени, чем на написание самого транспортного протокола. По умолчанию Python открывает стандартный ввод и вывод в текстовом режиме в Windows, что автоматически заменяет каждый n на rn при записи данных. Это небольшое изменение полностью искажает поток JSON. В тот момент, когда клиент читает }rn{ , он сталкивается с ошибкой синтаксического анализа в следующем же сообщении, что приводит к разрыву всего соединения.

 if platform.system() == "Windows": import msvcrt msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

Установка O_BINARY отключает перевод. [8] Без этого сервер работает на macOS и Linux и незаметно ломается на Windows.

write_through=True в обертке стандартного вывода гарантирует немедленную отправку каждого запроса на запись. Клиент ИИ синхронно блокируется, ожидая ответа — любая буферизация приостанавливает взаимодействие.

Вот полный вывод демонстрационного примера stdio с моего компьютера:

 ============================================================ local-mcp-server demo [stdio transport] Root: C:UsersAdminPycharmProjectspythonProjectlocal-mcp-server ============================================================ [1] Initialize Server : local-mcp-server v1.0.0 Protocol: 2024-11-05 [2] Available tools [list_directory ] List files and directories... [read_file ] Read a file's contents. Max 1 MB... [search_files ] Search files by glob pattern... [get_file_info ] Get metadata for a file or directory... [3] list_directory 8 entries [4] get_file_info readable: True writable: True [5] read_file first small file read successfully [6] search_files Found 5 .py files ============================================================ All checks passed. Ready to connect Local Desktop. ============================================================

Транспорт 2: HTTP/SSE

Каждый клиент открывает соединение GET /sse (построенное на основе Python http.server [4]), которое остается открытым на протяжении всей сессии, позволяя серверу отправлять ответы по этому каналу в виде событий server-sent. Каждое соединение получает уникальный client_id [9] при подключении. Когда клиенту нужно ответить или отправить запрос, он отправляет отдельный POST /message.

Схема работы для каждого клиента выглядит следующим образом:

Диаграмма последовательности, показывающая жизненный цикл передачи событий, отправляемых сервером (SSE) по протоколу Model Context Protocol (MCP). На ней изображено, как клиент устанавливает постоянное соединение с сервером посредством первоначального запроса
Архитектура транспортного протокола Model Context Protocol (MCP) Server-Sent Events (SSE). На этой диаграмме подробно описано установление постоянного потока событий в нисходящем направлении в паре с независимыми операциями HTTP POST для маршрутизации сообщений от клиента к восходящему каналу. Изображение предоставлено автором.

Для корректной обработки параллельного доступа каждый клиент получает свою собственную независимую очередь сообщений. [7] Обработчик POST отправляет вызов, помещает результат непосредственно в очередь этого клиента и немедленно возвращает статус 202. Он не ждет завершения доставки SSE. Клиент просто получает ответ из своего собственного открытого потока. Именно это и обеспечивает работу параллельного доступа.

Я настроил 16 рабочих потоков-демонов для обработки входящих запросов. Поскольку каждое активное SSE-соединение удерживает один поток, наличие 5 активных SSE-клиентов оставляет 11 потоков полностью свободными для обработки входящих POST запросов в любой момент времени. Здесь нет синтаксиса async/await и нет цикла событий — только стандартная многопоточность из библиотеки. [5]

Одновременная демонстрация

Это результат, позволяющий определить, действительно ли работает протокол HTTP/SSE:

 ============================================================ Concurrent Client Demo — 5 clients, 5 simultaneous calls ============================================================ Launching 5 concurrent clients... Client Tool Result Time ---------- -------------------- ---------- -------- 1 list_directory OK ~0.034s 2 get_file_info OK ~0.021s 3 list_directory OK ~0.038s 4 search_files OK ~0.023s 5 search_files OK ~0.021s Total wall time: ~0.04s for 5 concurrent clients Result: ALL PASSED ============================================================

Пять клиентов. Пять различных вызовов инструментов. Общее время выполнения всех запусков менее 50 мс. Ни один из запусков не блокировал другой. Измерения проводились на Windows 11, Python 3.12.6, только на ЦП.

Что сломалось во время разработки?

Десятиминутное зависание я уже описывал. Еще три вещи сломались, прежде чем сервер стабилизировался.

Проблема с символом rn в Windows. При первом подключении реального клиента ИИ возникла ошибка синтаксического анализа на втором сообщении. В ходе тестирования всё выглядело нормально. Проблема заключалась в преобразовании стандартного вывода — n в rn в Windows. Я потратил час, изучая диспетчер, прежде чем нашёл причину. Две строки кода всё исправили.

Сбой при работе с бинарными файлами. Первая версия функции read_file вызывала read_text() для всего подряд. В первой реальной папке проекта она столкнулась с файлом .pyc и вызвала UnicodeDecodeError . После этого был добавлен резервный вариант с base64.

Зависание базы данных на 200 МБ. До достижения лимита в 1 МБ тестовый процесс случайно считал данные из базы данных SQLite. Процесс завис на тридцать секунд. После этого сразу же был введен лимит.

Каждая из этих проблем возникала только при запуске сервера на реальной машине, а не в тестовом каталоге.

Набор тестов

50 тестов по семи классам. Тесты безопасности выполняются в первую очередь.

Сорт Что это включает
ТестБезопасность Атаки с обходом массива, обход символических ссылок, пустые пути.
TestListDirectory Скрытые файлы, порядок сортировки, заблокированные записи, ошибки
TestReadFile Текст, двоичный/base64, ограничение 1 МБ, ошибки доступа.
TestSearchFiles Поверхностный против рекурсивного, max_results, флаг усечения
TestGetFileInfo Файл против каталога, права доступа, временные метки
TestDispatcher Все методы, уведомления, ошибки синтаксического анализа, неизвестные методы
TestHTTPTransport Контрольная точка, соединение SSE, коды ошибок 400/404

Запустите набор тестов с помощью pytest в режиме подробного вывода. Чтобы пропустить интеграционные тесты, передайте флаг not integration marker.

Подключение к локальному ИИ-клиенту

macOS: ~/Library/Application Support/Claude/local_desktop_config.json

Windows: %APPDATA%Claudelocal_desktop_config.json

 { "mcpServers": { "local-desktop": { "command": "python", "args": ["C:/absolute/path/to/local-mcp-server/server.py"], "env": { "MCP_ROOT": "C:/absolute/path/to/your/workspace" } } } }

Для HTTP/SSE:

 # Terminal 1 — start the server python server.py --http --port 8765 # Terminal 2 — run the example client python examples/http_client.py

Честные дизайнерские решения

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

Модель безопасности полностью доверяет границам песочницы, игнорируя типы файлов. Я не составлял список разрешенных безопасных расширений или список запрещенных опасных. Если путь разрешается внутри MCP_ROOT , он читаем. Одно правило обойти сложнее, чем десять.

Я также намеренно исключил подсчет токенов. Этот сервер просто возвращает необработанное содержимое файла. Управление бюджетом токенов должно осуществляться на уровне выполнения между сервером и моделью. Добавление счетчика сюда привело бы к зависимости от токенизатора — нарушив цель отсутствия зависимостей — или к необходимости использования аппроксимации со своими собственными сложными крайними случаями.

Наконец, поиск по умолчанию является поверхностным. Десятиминутное зависание во время тестирования заставило меня принять это решение. Любое поведение, которое незаметно ухудшает производительность, никогда не должно быть вариантом по умолчанию.

Чему это на самом деле учит

Я ожидал, что создание MCP-сервера будет сложным. В руководствах это выглядело довольно сложно. В каждой найденной мной реализации перед регистрацией хотя бы одного инструмента присутствовали FastAPI, uvicorn и ещё три пакета. Поэтому я предположил, что такая сложность необходима.

Это было не так. Когда я наконец прочитал саму спецификацию, протокол представлял собой цикл. Прочитать строку. Разобрать JSON. Вызвать функцию. Записать строку. Вот и всё. Фреймворки решали не проблемы MCP, а проблемы HTTP, которых нет у MCP поверх стандартного ввода-вывода.

Стандартной библиотеки было достаточно, потому что задача была небольшой. Мне не нужен был фреймворк. Мне понадобился http.server для TCP-соединений, threading для параллельных запросов, queue для отделения SSE от обработки POST-запросов и pathlib для разрешения путей. Один модуль на каждую задачу. Ничего лишнего.

Больше всего меня удивило, насколько важны были настройки по умолчанию. Каждая реальная ошибка в этом коде — зависание на десять минут, задержка на 200 МБ, повреждение JSON-файлов Windows — произошла из-за настроек по умолчанию, которые отлично работали при тестировании, но сломались на реальной машине. rglob() работала нормально в небольшой тестовой папке. Вывод в текстовом режиме работал нормально в Linux. Настройка по умолчанию, которая кажется удобной в процессе разработки, часто незаметно разрушает систему в продакшене.

Полный код: https://github.com/Emmimal/local-mcp-server/

Ссылки

[1] Протокол контекста модели. (без даты). Спецификация протокола контекста модели. https://modelcontextprotocol.io

[2] Рабочая группа JSON-RPC. (2010). Спецификация JSON-RPC 2.0. https://www.jsonrpc.org/specification

[3] WHATWG. (без даты). События, отправляемые сервером. HTML Living Standard. https://html.spec.whatwg.org/multipage/server-sent-events.html

[4] Фонд программного обеспечения Python. http.server — HTTP-серверы. Документация Python 3. https://docs.python.org/3/library/http.server.html

[5] Фонд программного обеспечения Python. Многопоточность — Параллелизм на основе потоков. Документация Python 3. https://docs.python.org/3/library/threading.html

[6] Фонд программного обеспечения Python. pathlib — Объектно-ориентированные пути к файловой системе. Документация Python 3. https://docs.python.org/3/library/pathlib.html

[7] Python Software Foundation. queue — синхронизированный класс очереди. Документация Python 3. https://docs.python.org/3/library/queue.html

[8] Фонд программного обеспечения Python. msvcrt — Полезные подпрограммы из среды выполнения MS VC++. Документация Python 3. https://docs.python.org/3/library/msvcrt.html

[9] Фонд программного обеспечения Python. (без даты). uuid — объекты UUID в соответствии с RFC 4122. Документация Python 3. https://docs.python.org/3/library/uuid.html

[10] Python Software Foundation. subprocess — Управление подпроцессами. Документация Python 3. https://docs.python.org/3/library/subprocess.html

Раскрытие информации

Весь код в этой статье написан мной и является оригинальной работой, разработанной и протестированной на Python 3.12.6, Windows 11, только на ЦП. На любом этапе не использовался графический процессор. Все показатели производительности — время отклика, результаты одновременной работы клиентов, количество тестов — получены в результате реальных запусков на моей локальной машине и полностью воспроизводимы путем клонирования репозитория и запуска demo.py и concurrent_demo.py , как описано выше. Вся реализация использует только стандартную библиотеку Python. Никакие сторонние пакеты не требуются и не используются на каком-либо этапе. Все архитектурные решения, выбор реализации, компромиссы в проектировании, опыт отладки и ошибки, описанные в разделе «Что сломалось во время разработки», являются моими собственными. У меня нет финансовых связей ни с одним инструментом, библиотекой, фреймворком или компанией, упомянутыми в этой статье. Протокол MCP — это открытая спецификация, опубликованная Anthropic [1]; эта реализация является независимой и не связана с Anthropic и не одобрена ею.

Если вы занимаетесь разработкой систем искусственного интеллекта для промышленного применения и хотите углубиться в эту тему, — воспользуйтесь учебными пособиями, программами обучения и практическими проектами на моей платформе для изучения ИИ и Python от EmiTechLogic.

Эммимал П. Александр. Посмотреть все работы Эммимал П. Александра.

Источник: towardsdatascience.com

✅ Найденные теги: Видеть, Мог, Мои, Мой, новости, Файлы

Добавить комментарий

Новости других рубрик

Архив рубрики ~Обо всем~: Сейчас Amazon продает SSD-накопитель Samsung объемом 2 ТБ со скидкой почти 40% — и он более чем быстр для ПК. Архив рубрики ~Обо всем~: Финал НБА 2026: Как посмотреть второй матч «Никс» — «Спёрс» сегодня вечером Архив рубрики ~Обо всем~: OpenAI внедряет режим блокировки для дополнительной защиты от атак с использованием мгновенной инъекции. Архив рубрики ~Обо всем~: Как очистить кэш на телефоне Android — 30-секундная процедура, которую должен выполнять каждый пользователь. Архив рубрики ~Обо всем~: Любите Wordle? Вот 10 похожих игр, которые стоит попробовать прямо сейчас. Архив рубрики ~Обо всем~: Фундаментальный выбор в обучении с подкреплением: обучение с подкреплением или обучение без подкрепления. Архив рубрики ~Обо всем~: Паровая машина и паровая рама появятся «этим летом». Архив рубрики ~Обо всем~: Я опробовал новый инструмент очистки данных Google Drive с помощью ИИ, чтобы избавиться от беспорядка, накопившегося за 14 лет, — вот результат.