Payment Delay MCP
Payment Delay MCP — предоставление production ML-модели любой LLM через MCP
Классификатор scikit-learn, развёрнутый за микросервисом FastAPI и опубликованный для языковых моделей в виде инструментов Model Context Protocol, — так что готовый чат-клиент сам находит и корректно вызывает модель, без единой строки интеграционного кода, написанного под неё.

Тезис
Модель — это полезная нагрузка, а не суть.
Большинство демо «на базе ИИ» зашивают вызов модели в специализированное приложение. Этот проект переворачивает подход: классификатор публикуется как протокол, поэтому LLM-клиент взаимозаменяем. Один и тот же сервер обслуживает OpenWebUI в Docker, OpenCode в CLI и Claude Desktop — без изменения кода и без клиентских адаптеров.
Обзор
Телеком-оператор хочет знать, какие клиенты заплатят с опозданием. Обученный классификатор отвечает на этот вопрос, но файл .pkl — это не продукт: кому-то всё равно придётся написать связующий код для его вызова, и этот код переписывается для каждого нового потребителя.
Этот репозиторий и есть такой связующий код, написанный один раз в виде протокола. Четыре слоя, каждый из которых разворачивается независимо:
flowchart TB
subgraph reasoning["Reasoning path"]
UI["OpenWebUI<br/>:3000"] -->|OpenAI protocol| LL["LiteLLM<br/>:4000"]
LL -->|bedrock_mantle| BR["AWS Bedrock<br/>gpt-oss-120b"]
end
subgraph tools["Tool path"]
UI -->|OpenAPI| MCPO["mcpo<br/>:8001"]
MCPO -->|MCP over stdio| FM["FastMCP server<br/>5 tools · 2 resources · 1 prompt"]
FM -->|HTTP| API["FastAPI service<br/>:8000"]
API --> PRED["inference.predictor<br/>the only code that<br/>opens the pickle"]
PRED --> PKL[("models/*.pkl<br/>RandomForest +<br/>RandomOverSampler")]
end
style reasoning fill:#1f2a3710,stroke:#8884
style tools fill:#1f372a10,stroke:#8884Эти два пути намеренно разделены. LLM никогда ничего не исполняет. Она отправляет сообщение tool_calls, в котором указаны инструмент и его аргументы; клиент выполняет его и возвращает результат. Именно это различие делает модель заменяемой — и именно поэтому данный стек работает одинаково, независимо от того, является ли слой рассуждений Bedrock, локальной Ollama или Claude.
Related MCP server: Company API MCP Server
Ключевая идея: выбор инструмента — это задача документации
LLM выбирает инструмент по его имени, сигнатуре и docstring — и ни по чему больше. Ни тонкой настройки, ни примеров, ни логики маршрутизации. Поэтому docstrings и есть интерфейс, и их написание — инженерная работа, а не комментарий.
Два инструмента здесь во многом пересекаются. Оба предсказывают задержку платежа. Чтобы модель выбирала правильно без подсказок, потребовалось закодировать операционные ограничения прямо в описании:
Инструмент | Когда модель должна его выбрать | Различающий сигнал |
| У пользователя есть CSV — путь или вставленный текст | Docstring предупреждает, что |
| Пользователь описывает одного клиента в свободной форме | Docstring гласит: «для случаев на естественном языке, когда LLM извлекает данные одного клиента в структурированные признаки» |
Подтверждённый результат: для клиента, описанного простым английским языком, gpt-oss-120b без подсказок выбрал predict_single_customer вместо predict_payment_delay, заполнил словарь признаков из текста и вернул обоснованный ответ. Это подтверждено в логах обоих переходов: POST /predict_single_customer 200 на mcpo, затем POST /predict 200 в сервисе модели.
В этом и состоит всё утверждение проекта, и его можно проверить: отключите инструмент — и та же модель уверенно и неправильно ответит на тот же вопрос, а обе панели логов останутся пустыми.
Запрос: от начала до конца
То, что большинство диаграмм использования инструментов опускают: один вопрос пользователя стоит двух обращений к модели, и промежуточное сообщение ассистента должно быть воспроизведено дословно, иначе tool_call_id повиснет:
sequenceDiagram
participant U as User
participant W as OpenWebUI
participant L as LiteLLM
participant M as Bedrock model
participant O as mcpo
participant S as FastMCP
participant A as FastAPI + model
U->>W: "Will customer X pay late?"
W->>L: messages[] + tools[]
L->>M: translated to Bedrock
M-->>W: finish_reason: tool_calls
Note over W: the client executes,<br/>not the model
W->>O: POST /predict_single_customer
O->>S: MCP call over stdio
S->>A: POST /predict
A-->>S: {prediction, probability_yes}
S-->>O: result
O-->>W: 200 OK
W->>L: messages[] + assistant(tool_calls) + tool(result)
L->>M: second round trip
M-->>U: grounded natural-language answerМассив tools[] отправляется заново при каждом запросе — модель не хранит состояние и заново обнаруживает набор инструментов на каждом витке.
Что проверено
Четыре контрольные точки, каждая подтверждена логами, а не предположениями:
# | Слой | Подтверждение |
1 | Сервис модели |
|
2 | Мост mcpo | 5 инструментов отображаются на |
3 | LiteLLM к Bedrock |
|
4 | Полный автономный цикл |
|
Контрольная точка 3 важнее, чем кажется: finish_reason: tool_calls — единственный способ отличить «модель отказалась использовать инструмент» от «инструмент ей вообще не предлагался». В окне чата эти сбои выглядят одинаково.
Модель
Раскрытие информации о наборе данных. Обучающие данные — это публичный телеком-бенчмарк по оттоку (churn), в котором целевой столбец переименован в
payment_delayдля целей этого упражнения. Признаки — это поля записей звонков и аккаунтов, а не история платежей. Моделирование настоящее, и пайплайн настоящий; бизнес-обёртка синтетическая. Относитесь к цифрам как к рабочему примеру, а не как к валидированной модели кредитного риска.
Свойство | Значение |
Строк / столбцов | 3,000 / 20 |
Баланс классов |
|
Пайплайн |
|
Разбиение | 80/20 стратифицированное |
Признаки при инференсе | 36 — 19 исходных плюс 17 производных флагов |
Порог решения | 0.35, сохраняется как артефакт |
Порог — это не 0.5, и он не захардкожен. Он поставляется как models/threshold.pkl и может быть переопределён для каждого запроса, потому что при цели с 13.77% положительных примеров порог по умолчанию оптимизирует не то. Более низкий порог ловит больше неплательщиков ценой большего числа ложных срабатываний, и какой компромисс верен — это бизнес-решение, а не модельное, поэтому API предоставляет его как параметр.
Ничто в кодовой базе не захардкоживает имя столбца. Порядок признаков берётся из feature_columns.pkl, границы выбросов — из outlier_bounds.pkl, поэтому переобучение не требует изменения кода.
Инженерные решения, которые стоит отстаивать
MCP-сервер никогда не импортирует модель. Он вызывает API по HTTP. Это сохраняет процесс MCP лёгким — ни sklearn, ни 9 MB pickle в памяти — и позволяет сервису модели масштабироваться, разворачиваться и мониториться как любому другому микросервису. Адаптер протокола не должен содержать бизнес-логики.
Предсказание выполняется вне цикла событий. Вызов инференса отправляется через run_in_threadpool, поэтому CPU-интенсивные вычисления никогда не блокируют асинхронный цикл FastAPI при конкурентных запросах.
Дисциплина stdio. MCP через stdio требует, чтобы stdout переносил только JSON-RPC кадры, поэтому случайный print() повреждает поток и убивает сессию. В связи с этим всё логирование направляется в stderr, httpx и httpcore заглушаются, а launcher.py перенаправляет вывод uvicorn в файл лога, ждёт /health и только затем передаёт клиенту чистый stdio.
Две точки входа для двух топологий. server.py — точка входа для контейнера, где API является отдельным сервисом. launcher.py — локальная точка входа, которая сама запускает API и ждёт его, — правильная форма для десктопного MCP-клиента, ожидающего, что один процесс владеет своими зависимостями.
Пин, документирующий реальный инцидент. mcp>=1.2.0,<2.0: mcp 2.x переименовал streamablehttp_client, а mcpo 0.0.20 всё ещё импортирует старое имя, поэтому mcpo зацикливается при падении на 2.x. Ограничение закомментировано в requirements.txt с указанием причины, потому что пин версии без причины удаляется следующим человеком, который его прочитает.
Структура репозитория
mcp-payment-delay/
├── src/payment_delay/
│ ├── config.py # single source of truth for paths + endpoints, all env-overridable
│ ├── inference/predictor.py # the only code that opens the pickle; imports no web framework
│ ├── api/main.py # thin FastAPI adapter over the predictor
│ └── mcp_server/
│ ├── server.py # FastMCP tools, resources, prompt (container entrypoint)
│ ├── api_client.py # HTTP calls into the model service
│ └── launcher.py # starts the API, then serves MCP on clean stdio (local entrypoint)
├── models/ # model, threshold, outlier bounds, feature order
├── data/telecomunicatii.csv # sample dataset
├── deploy/litellm_config.yaml # Bedrock routing
├── scripts/bedrock_smoke_test.py # asserts a tool call comes back, not merely a 200
├── docs/ # architecture + Docker runbook
├── Dockerfile # one image, serves both the API and the mcpo bridge
└── docker-compose.yml # API + mcpo + LiteLLM + OpenWebUIНачало работы
Запустите сервис модели отдельно — облачные учётные данные не нужны
python3 -m venv .venv && source .venv/bin/activate
make install # pip install -e ".[dev]"
make api # http://localhost:8000/docsЭндпоинт | Назначение |
| сервис работает, модель загружена |
| тип модели, классы, признаки, порог |
| обязательные столбцы CSV |
| одна строка (JSON-объект или CSV из одной строки) -> одно да/нет |
| CSV из нескольких строк -> одно да/нет на строку |
| CSV из нескольких строк -> одно да/нет для всего файла |
curl -F "file=@data/telecomunicatii.csv" \
"http://localhost:8000/predict/summary?threshold=0.35"Подключите свой MCP-клиент
python3 -m payment_delay.mcp_server.launcherПредоставляет инструменты через stdio и запускает API, если он ещё не здоров. opencode.json подключает это к OpenCode; Claude Desktop и любой другой stdio MCP-клиент подключаются так же.
Запустите полный стек
cp .env.example .env # add your Bedrock key
python3 scripts/bedrock_smoke_test.py
make stack # http://localhost:3000Полный рунбук, включая настройку учётных данных и устранение неполадок: docs/docker-stack.md.
MCP-поверхность
Пять инструментов, два ресурса, один шаблон промпта:
get_api_health service + model status
get_model_info model metadata, classes, features, endpoints
get_input_schema expected CSV columns
predict_payment_delay CSV in (path or text), per-row or aggregate, threshold configurable
predict_single_customer one customer as a JSON object
payment-delay://context business + modelling context, injected as a resource
payment-delay://api-contract the HTTP contract these tools call
interpret_payment_delay_result prompt template for business-language explanationРесурсы и промпты — недооценённая половина MCP. Контекстный ресурс означает, что клиенту не нужно объяснять, для чего предназначена модель, — он может прочитать это сам.
Технологический стек
FastAPI · FastMCP · mcpo · scikit-learn · imbalanced-learn · pandas · LiteLLM · AWS Bedrock · OpenWebUI · Docker Compose · uvicorn · httpx
Документация
Архитектура — слои, пайплайн предсказаний и почему разделение проходит именно там
Руководство по Docker-стеку — учётные данные, запуск, проверки здоровья, устранение неполадок
docs/assignment/ — исходный бриф
Eduard-Gabriel Tudoran, 2026.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Unified MCP Server is a remote MCP connector for AI agents and vertical AI products that provides access to 22,000+ authorized SaaS tools across 400+ integrations and 24 categories directly inside LLMs (Claude, GPT, Gemini, Cohere). Tools operate only on explicitly authorized customer connections, enabling agents to safely read and write against live third-party systems.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Connect MCP clients to 2,000+ AI models without managing provider API keys.
Discover and call 10,000+ production APIs from one MCP server. Pay-per-call billing for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceExposes enterprise KPIs, health scores, forecasting, and anomaly detection as MCP tools, resources, and prompts for use by any MCP-compatible agent.2AGPL 3.0
- FlicenseNot gradedqualityCmaintenanceExposes internal company services as LLM-callable MCP tools, enabling AI agents to perform business operations like customer management, order processing, and support ticketing through natural language.
- FlicenseNot gradedqualityCmaintenanceExposes a governed lending portfolio (loans, customers, risk-tier history) to any MCP-compatible AI client via read-only tools, schema resources, and analysis prompts, wrapping an existing API gateway instead of connecting directly to the database.
- FlicenseAqualityBmaintenanceMCP server exposing a fictional payment domain as tools, resources, and prompts, enabling reasoning over transactions, payment hubs, services, and system health.8
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/eddii1/mcp-payment-delay'
If you have feedback or need assistance with the MCP directory API, please join our Discord server