Payment Delay MCP
Payment Delay MCP - 通过 MCP 将生产级 ML 模型提供给任意 LLM
一个部署在 FastAPI 微服务背后的 scikit-learn 分类器,以 Model Context Protocol 工具的形式发布给语言模型——因此现成的聊天客户端无需编写任何针对它的集成代码,即可正确发现并调用该模型。

核心论点
模型是载荷,而不是重点。
大多数"AI 驱动"的演示都将模型调用硬编码进一个定制应用中。本项目将其反转:分类器以协议的形式发布,因此 LLM 客户端是可替换的。同一个服务器驱动着 Docker 中的 OpenWebUI、CLI 上的 OpenCode 以及 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 来选择工具——仅此而已。没有微调、没有示例、没有路由逻辑。因此 docstring 就是接口,编写 docstring 是工程工作,而不是注释。
这里有两个工具高度重叠。两者都预测付款延迟。要让模型在无提示的情况下正确选择,需要将操作约束直接编码进描述中:
工具 | 模型应选择它的时机 | 消歧信号 |
| 用户有一个 CSV,以路径或粘贴文本形式提供 | docstring 警告:当服务器运行在无法看到用户文件系统的容器中时, |
| 用户用自然语言描述一个客户 | docstring 说明"适用于 LLM 从自然语言中提取单个客户并填入结构化特征的情况" |
已验证的结果: 给定一个用纯英文描述的客户,gpt-oss-120b 在无辅助的情况下选择了 predict_single_customer 而非 predict_payment_delay,从自然语言中填充了特征字典,并返回了一个有依据的答案。两跳的日志中都得到了确认——mcpo 处 POST /predict_single_customer 200,随后模型服务处 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 answertools[] 数组在每次请求时都会重新发送——模型是无状态的,每一轮都会重新发现工具集。
已验证的内容
四个检查点,每一个都对照日志确认,而非凭假设:
# | 层 | 证据 |
1 | 模型服务 |
|
2 | mcpo 桥接层 |
|
3 | LiteLLM 到 Bedrock |
|
4 | 完整自主循环 | 从一个纯英文问题出发,mcpo 处 |
检查点 3 比看起来更重要:finish_reason: tool_calls 是区分"模型拒绝使用工具"与"工具从未提供给模型"的唯一方式。这两种失败在聊天窗口中看起来完全一样。
模型
数据集披露。 训练数据是一个公开的电信流失基准数据集,为本次练习的目的将目标列重新标记为
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 服务器从不导入模型。 它通过 HTTP 调用 API。这使 MCP 进程保持轻量——没有 sklearn,没有常驻的 9 MB pickle——并让模型服务像任何其他微服务一样进行扩展、部署和监控。协议适配器不应包含任何业务逻辑。
预测在事件循环之外运行。 推理调用通过 run_in_threadpool 分发,因此在并发请求下,CPU 密集型的评分永远不会阻塞 FastAPI 的异步循环。
stdio 纪律。 基于 stdio 的 MCP 要求 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