Payment Orchestrator MCP Server
Оркестратор маршрутизации платежей
Доказательства на критическом пути, ИИ по краям.
Получив авторизацию карты, он решает, какой платежный провайдер должен её обработать — на основе эмпирических доказательств одобрения, с допуском по комиссии, который оператор задает в реальных единицах. Если попытка отклоняется, конечный автомат, ключом к которому является класс ошибки отклонения, решает, что делать дальше: тот же PSP позже, фейловер сейчас, другой канал или остановка. Само решение о маршрутизации детерминировано и аудируемо; внутри него не выполняется языковая модель.
Создано и выпущено внутри Claude Code: движок, ИИ-пограничный слой, среда оценки, веб-интерфейс, API и этот README были созданы в агентских сессиях — одна оркестрирующая сессия делегировала субагентам (бэкенд, UI, публикация, кейс) — и защищены тестами и оценками, которые вы можете запустить сами. Инженерная дисциплина та же, что описана в nutri.: конвенции, которые агент должен загрузить, структурные ограничения и машина — а не обещание — как определение готовности. Ограничения поймали то, что иначе ушло бы в продакшн: переписывание, которое теряло все пути API (найдено пост-деплойной проверкой), UI, помечавший валидных эмитентов как невиданных, и два неверных предположения автора (правило количества страниц, DNS-настройка), на которые субагенты отказались реагировать.
Живое демо https://orchestrator.vryahn.com · Кейс
https://vryahn.com/work/routing · API api/README.md ·
MCP MCP.md
Вневыборочный реплей на 84 011 ТЕСТОВЫХ транзакциях (дни 22–31, таблицы обучены на днях 1–21): ожидаемое одобрение 72,02% при cost_bias=0 против фактически наблюдаемых 66,13% — +5,89 п.п., направленно, не A/B-результат. См. Ограничения.
Запуск
Python 3.11. requirements.txt — это среда выполнения: fastapi плюс стандартная библиотека, и единственное, что устанавливает Vercel. requirements-dev.txt добавляет офлайн-стек (duckdb, pandas, numpy, pyarrow, mcp, uvicorn, httpx), необходимый для регенерации данных, запуска бэктеста, обслуживания MCP или локального тестирования.
python3.11 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python cli.py --txn-file demo_transactions.json # 8 decision-boundary cases
.venv/bin/uvicorn api.index:app --reload --port 8000 # API on /api/*, UI from public/Таблицы, которые читает движок (routing_tables.json, routing_meta.json), закоммичены, поэтому свежий клон маршрутизирует — и деплоится — без офлайн-конвейера. Перегенерируйте их, только если модель данных изменится:
.venv/bin/python synth_attempts.py # seeded ~300k attempts -> attempts.parquet
.venv/bin/python build_routing_tables.py # -> routing_tables.json, routing_meta.json
.venv/bin/python backtest.py --json # -> backtest_summary.json
.venv/bin/python tests.py # engine
.venv/bin/python tests_ai.py # AI edges + HTTP contract
.venv/bin/python evals/decline_eval.py # normalizer against the golden setRelated MCP server: ai-log-mcp-server
Архитектура
flowchart LR
subgraph offline["OFFLINE — batch, once per rebuild"]
G["synth_attempts.py<br/>seeded generator"] --> A[("attempts.parquet<br/>1 row = 1 attempt, ~300k")]
A -->|"build_routing_tables.py"| T[("routing_tables.json + routing_meta.json<br/>segment x PSP: n, approvals, p_hat, Wilson LB<br/>4-level hierarchy")]
A -->|"backtest.py — train d1-21, test d22-31"| B["backtest_summary.json<br/>out-of-sample lift"]
end
subgraph edgein["EDGE IN — language to enum"]
RAW["raw PSP decline<br/>ISO 8583 / decline_code / refusalReason / bank prose"] --> N{"decline_normalizer.py<br/>table -> LLM -> safe fallback"}
EV["evals/ — 48 golden declines<br/>accuracy by route, hallucination gate"] -.->|"scores"| N
end
subgraph online["ONLINE — pure engine, never touches raw data"]
X["txn: amount, bin6/issuer, funding,<br/>channel, attempt #, error history"] --> D{"decide(txn, config)"}
T --> D
N -->|"error_class"| D
D --> S1["1. resolve segment per PSP<br/>walk L0 to L3 until n >= min_support"]
S1 --> S2["2. score = Wilson LB x amount x (1 - fee)<br/>= expected net collected"]
S2 --> S3["3. pick PSP — cost_bias 0..1 maps to<br/>fee tolerance 0..10pp; psps_down excluded"]
S3 --> S4["4. retry state machine<br/>keyed on last error_class"]
S4 --> R["Decision: route_psp, eligible_psps with scores,<br/>retry policy, reasoning lines"]
end
R --> OPS["ops.py — route, explain, simulate,<br/>evidence, normalize, backtest"]
B --> OPS
OPS --> CLI["cli.py"]
OPS --> API["api/index.py — FastAPI on Vercel<br/>+ public/ web UI, same origin"]
OPS --> MCP["mcp_server.py — 6 MCP tools"]Почему такая архитектура
Офлайн/онлайн-разделение.
decide(txn, config) -> Decisionчистый. Он загружает предварительно материализованные таблицы один раз и никогда не читает сырые попытки, поэтому решение занимает микросекунды, тестируется без базы данных и аудируется постфактум. Это та же граница, которую вы бы провели в продакшне между слоем сверки и слоем маршрутизации.Иерархия сегментов с фолбэком. L0 — это
gateway_group × funding × issuer_bucket × amount_band; L3 — этоgateway_groupсам по себе. Поддержка разрешается для каждого PSP, по одному измерению за раз (диапазон сумм → эмитент → funding), пока ячейка не превыситmin_support(по умолчанию 200), и использованный уровень сообщается вместе с решением. Канал является первостепенным и никогда не отбрасывается: пользователь-присутствующий и офлайн-сессии — это разные миры.Нижняя граница Уилсона, а не сырая доля. Сегмент с 3/3 одобрений — это не 100%-ный сегмент. Граница сжимается к нулю по мере разрежения поддержки, поэтому хорошо обоснованные 78% побеждают удачные 100% без отдельного правила доверия, прикрученного сбоку.
cost_biasкак явная ручка в реальных единицах. Компромисс формулируется как «процентные пункты одобрения, которые я отдам за более дешевый PSP» —tolerance = cost_bias × 10 п.п., и побеждает самый дешёвый PSP в пределах этого допуска от лучшего по одобрению. Смешанная оценка позволила бы разнице в доли процента комиссии молча перевесить двузначный разрыв в одобрении; фильтр допуска — нет. Бэктест оценивает ручку: 72,02% / +5,89 п.п. одобрения приcost_bias=0, 71,56% / +5,43 п.п. при 0,5, 69,57% / +3,44 п.п. при 1,0.Повтор по классу ошибки, а не по слепому счётчику.
insufficient_funds— это проблема счёта, и он повторяет того же PSP в следующем платёжном окне;bank_auth_requiredв офлайн-сессии не может быть удовлетворён без клиента, поэтому он переносится на канал с присутствием пользователя, а не сжигает попытки;fraud_riskнавсегда останавливает цепочку;generic_declineпереключается на следующего PSP по рейтингу. Неизвестный класс деградирует до общей политики фейловера и сообщает об этом.
Где ИИ уместен — а где нет
Внутри decide() нет LLM. Деньги не должны двигаться на основе сэмплированного токена. Языковая модель ограничена двумя краями, где естественный язык действительно является проблемой.
Внутри — decline_normalizer.py. Каждый PSP отклоняет на своём диалекте: числовые коды ISO 8583, Stripe-подобный decline_code, Adyen-подобный refusalReason или сырой банковский текст. Конечный автомат повторов завязан на одно перечисление, поэтому диалекты должны схлопнуться до того, как движок их увидит. Детерминированная таблица обрабатывает коды, несущие основной объём, — уверенность 1.0, нулевая задержка, нулевая стоимость. Только промах таблицы доходит до цепочки моделей (Gemini, затем Mistral), которая отвечает по ограниченной схеме перечисления. Всё, что вне перечисления или ниже уверенности 0,6, отбрасывается в пользу generic_decline, который является безопасным значением по умолчанию для политики повторов. Репозиторий проходит зелёным без заданных API-ключей.
Измерено, а не принято на веру — evals/. 48 золотых отклонений: ~60% попаданий в таблицу, ~40% намеренно вне таблицы (опечатки, многословный банковский текст, необычные коды) плюс несколько действительно неоднозначных, где generic_decline — правильный ответ. evals/baseline.json фиксирует два базовых уровня. Только таблица (без ключей): 32/48 = 66,67%, т.е. 100% на 28 случаях с табличным маршрутом и безопасный generic_decline по умолчанию на 20, которые проваливаются. LLM (ключи настроены, запуск против развёрнутого API с --remote): 48/48 = 100% — 28 табличных, 19 отвечено gemini-3.6-flash, 1 — низкоуверенным фолбэком, где ожидаемым ответом был generic_decline. Запускатор сообщает точность по маршрутам и по классам, утверждает отсутствие галлюцинаций и валит сборку, если точность падает более чем на 2 п.п. ниже соответствующего базового уровня.
Снаружи — mcp_server.py. Шесть MCP-инструментов — route_transaction, explain_decision, simulate, segment_evidence, normalize_decline, backtest_summary — позволяют агенту управлять движком на английском. Агент может запрашивать каждое решение, но не менять ни одного. См. MCP.md.
Ограничения
Данные синтетические. Структура призвана сделать решения о маршрутизации нетривиальными, а не воспроизвести какой-либо реальный портфель.
Нет живых PSP-коннекторов: движок решает, но не отправляет.
Нет скоринга фрода, оркестрации 3DS, сетевых токенов или принудительного применения правил повторов схемы.
Бэктест носит направленный характер. Историческая маршрутизация не была рандомизирована, лимиты мощности не моделируются, а «ожидаемое одобрение» — это ставка Уилсона-НБ за период TRAIN, применённая к объёму TEST, а не живой A/B-результат.
Таблицы объединяют все попытки, в то время как бэктест обучается и воспроизводится только на первых попытках; продакшн-таблицы только для первых попыток были бы следующим исправлением.
LLM-оценка — это 48 случаев и один прогон; 100% на таком маленьком золотом наборе — это защита от регрессий, а не заявление о длинном хвосте в проде.
Карта файлов
файл | назначение |
| сидированный генератор для |
| строит |
| движок: |
| диалекты отклонений PSP → перечисление |
| операторские функции (route, explain, simulate, evidence, normalize, backtest), общие для API и MCP |
| FastAPI на Vercel; контракт в |
| MCP stdio-сервер, шесть инструментов; см. |
| CLI-фронтенд: одна транзакция через флаги или пакет через |
| статический веб-интерфейс, обслуживается Vercel с того же источника, что и API |
| 8 транзакций на границах решений с примечаниями |
| реплей TRAIN дни 1–21 / TEST дни 22–31 при |
| 48 золотых отклонений, скоринг-раннер и записанный базовый уровень |
| проверки на основе assert: движок, затем ИИ-края и HTTP-контракт |
Брайан Родригес Абарка · vryahn.com · Начато с технического упражнения, обобщено как личный проект. Синтетические данные.
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 Servers
- AlicenseNot gradedqualityDmaintenanceEnables natural-language investigation of Datadog data including logs, metrics, monitors, traces, hosts, dashboards, events, and incidents, all through read-only API access.2,053MIT
- FlicenseNot gradedqualityBmaintenanceEnables querying and managing AI logs through tools like listing logs, retrieving jobs, and performing AI-powered chat queries. Also provides access to gateway security reports and guardrail testing.
- AlicenseAqualityBmaintenanceInvestigate fraud directly from Claude, Cursor, or any MCP-compatible client. Analyze suspicious activity with clear, evidence-backed verdicts. Pivot from a single signup to every account sharing the same device, IP address, or email inbox. Check entities against a cross-operator abuse network, review linked accounts, and efficiently process your fraud review queue. Read-only by default, with no r10269MIT
- FlicenseNot gradedqualityBmaintenanceEnables operations teams to diagnose and resolve stuck orders via natural-language queries. It provides evidence-based resolution proposals, but any state-changing action requires explicit human confirmation.
Related MCP Connectors
See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.
A paid remote MCP for AI SDK data query MCP, built to return verdicts, receipts, usage logs, and aud
Enterprise AI Control Plane: governance, guardrails, spend tracking, compliance & smart routing.
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/vryahn/payment_orchestrator'
If you have feedback or need assistance with the MCP directory API, please join our Discord server