oas-execute-mcp

oas-execute-mcp

An MCP server that adds a safety layer with eight independent checks and audit logging between a language model and a broker order, supporting both on-disk simulation and live MetaTrader 5 terminals.

Category
访问服务器

README

oas-execute-mcp

An MCP server that puts a safety layer between a language model and a broker order.

A model calls order_submit. Before anything reaches the broker, the request passes six independent checks, any one of which can refuse it — seven across the write paths, since the stop-loss rule governs modifications rather than opens. Every attempt — allowed or refused — is appended to an audit log with the reason. The broker itself sits behind a swappable backend, so the same tool surface runs against an on-disk simulator or a live MetaTrader 5 terminal without the model knowing which.

Built for an agent that, on its own channel, submitted orders against a $100k prop-firm evaluation account without per-trade human approval, where a mis-sized order was not a failed test.


Why it exists

The interesting part of giving an agent a tool that spends money is not the happy path. It is:

  • what the tool returns when it half-succeeds — the order filled but the stop did not attach;
  • where a timeout lands — the broker never answered, and you do not know whether it filled;
  • how a failure is stopped from being reported as a success by the layer above it.

So the design rule here is that the model's own account of what happened is never trusted. Position state is re-read from the broker on every call. The refusals are explicit, few, and sit directly on the execution path rather than beside it in a prompt.

The safety layer

Seven checks, each able to refuse independently, all logged with a machine-readable reason. Six of them stand between order_submit and the broker; check_sl_widen_block governs modifications, so it never sees an open:

Check Refuses when
check_killswitch A kill-switch file exists on disk. Trips instantly, no restart needed.
check_rate_limit Orders are arriving faster than the configured ceiling.
check_gate_pass_freshness The upstream decision record is stale — no order may ride an old approval.
check_position_sanity Size, side or symbol disagree with what the broker reports.
check_sl_widen_block A stop-loss modification would move the stop away from price.
check_session_override_kill Manual overrides this session exceed the allowed count.
check_live_equity_kill Account equity has crossed the configured floor.

The audit append runs after the gates on every path, allowed or refused — it is the record, not a check: a refusal that leaves no trace is treated as a failure of the system.

safety.py groups these into run_entry_safety_gates, run_modify_safety_gates and run_close_safety_gates, so a close is never blocked by a rule that should only govern an open — the failure mode where a safety system traps you in a position it was meant to protect.

Tool surface

Seven tools: order_submit · order_modify · order_close · close_all · position_list · account_info · health_check.

Architecture

    model tool call
          │
          ▼
   server.py  ── MCP stdio server, tool schemas + dispatch
          │
          ▼
   safety.py  ── 7 gates, audit log, kill switch     ◄── refuses here, before the broker
          │
          ▼
   backends/  ── swappable
      ├── stub.py      on-disk simulation, no broker, deterministic
      └── mt5_demo.py  file bridge → MetaTrader 5 (Wine/macOS) via an MQL5 EA
                       localhost HTTP listener, shared-secret token on the firing route

The MQL5 expert advisor (oas_execute_mcp/mql5/OAS_Bridge.mq5) polls a localhost endpoint and executes on the terminal side. backends/base.py is the interface; adding a broker means implementing it, and nothing above the backend changes.

Install

pip install -e ".[dev]"

Point your MCP client at it:

{
  "mcpServers": {
    "oas-execute": {
      "command": "/path/to/.venv/bin/python",
      "args": ["-m", "oas_execute_mcp.server"],
      "cwd": "/path/to/parent-of-this-package"
    }
  }
}

Backend selection and paths are environment variables:

Variable Default Purpose
OAS_EXECUTE_BACKEND stub stub or mt5_demo
OAS_DATA_DIR ./oas_execute_mcp/data State, audit log, account record
OAS_MT5_COMMON_FILES MT5-under-Wine default MT5 Common/Files for the bridge

It ships defaulting to stub. You have to choose to point it at a broker.

No credentials live in this repository, and none should. The MT5 backend follows whatever terminal is already logged in; the account record it reads is documentary (login and server name), carries no password, and belongs outside version control.

Tests

PYTHONPATH=. python3 tests/test_smoke.py     # full submit → modify → close cycle + failure modes
for t in tests/test_*.py; do PYTHONPATH=. python3 "$t"; done   # the whole suite
python3 -m pytest tests/ -q                  # same suite, if you would rather type this

Nine test files, all passing on a clean checkout. Each one is a self-contained checker: it runs its assertions at module scope and exits non-zero on failure, so the suite needs nothing but an interpreter. tests/suite_test.py drives the same scripts as subprocesses so pytest is a working entry point too — it is a bridge, not a second suite, and there is no version of the tests that only one runner sees. They cover the submit/modify/close cycle against the stub, stop-loss anchoring and re-derivation after a charged fill, the bridge client-mode handshake, quote and position routes, and the gate that stops an error-shaped payload from being consumed as an empty position list — a real incident, where a timeout returned {"positions": []} and a downstream reader believed it.

Two tests skip rather than pass when their subject is absent. They exercise a consumer of this server, so they need the host project (OAS_HOST_REPO, OAS_RECONCILE_CMD). A check that silently turns green when the thing it checks is missing is worse than no check.

Status and limits

  • The stub backend is complete and deterministic. mt5_demo is in production use against a MetaTrader 5 terminal running under Wine on macOS.
  • check_rate_limit is implemented but is not exercised by the test bench — the bench simulates broker timeouts and kill-switch fire, not rate-limit responses. Stated because the distinction between "implemented" and "tested" is the whole subject of this repository.
  • The MT5 bridge is macOS/Wine-shaped. A native Windows install needs OAS_MT5_COMMON_FILES set and has not been tested by me.
  • Single-terminal by design: the listener is a singleton on one port, and a second server process detects the first and forwards to it rather than competing for the bind.

License

MIT — see LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选