Skip to main content
Glama
RockFlow-AI

broker-mcp-demo

by RockFlow-AI
README.md
# Broker MCP Demo

基于 [FastMCP](https://github.com/jlowin/fastmcp) 的券商 MCP Server **Demo**(Python 版),
做了两点简化:

- **鉴权用静态 API key**(`Authorization: Bearer <api-key>`),不走 OAuth;
- **不内置任何真实服务地址**:下游券商后端地址由使用者通过环境变量自行配置,
  未配置时各工具返回内置示例数据(响应带 `"mock": true` 标记),开箱即可体验。

## 架构

```
┌─────────────┐  Bearer <api-key>  ┌────────────────────┐   HTTP   ┌──────────────┐
│  MCP Client │───────────────────▶│  Broker MCP Demo   │─────────▶│  券商后端服务  │
│  (Claude…)  │◀───────────────────│  (API key 校验)     │◀─────────│ (自行配置)   │
└─────────────┘                    └────────────────────┘          └──────────────┘
```

请求流程:

1. 客户端带 `Authorization: Bearer <api-key>` 请求 `POST /mcp`;如需按用户维度
   执行,同时在请求头 `X-User-Id` 中原样透传券商体系内的用户 ID。
2. 服务端将 key 与 `BROKER_MCP_API_KEYS` 中配置的逐一比对,命中放行、否则 `401`。
3. 工具调用被代理到 `BROKER_MCP_BACKEND_BASE_URL` 指向的券商后端;
   未配置时返回内置示例数据。

调用方身份由两层组成:API key 解析出的 `client_id`(哪家券商)+ 请求头
`X-User-Id` 透传的用户 ID(该券商体系内的哪个用户)。持仓、资产、订单、下单等
工具会把 `X-User-Id` 原样透传给券商后端,按用户维度执行;未携带时该 header
不下发(如仅体验行情类工具)。

## 工具

共 10 个示例工具,覆盖行情、持仓 / 订单、交易、知识库四类。下游接口路径均为示意,
接入真实后端时按约定改 [tools/](src/broker_mcp_demo/tools/) 里的 `path` 即可。

### 行情([market.py](src/broker_mcp_demo/tools/market.py))

| 工具 | 参数 | 说明 |
|------|------|------|
| `search_ticker` | `keyword` | 按公司名 / 代码搜索标的,解析出 `market` + `symbol` |
| `get_latest_quote` | `market`, `symbol` | 查询标的最新行情 |
| `get_chart` | `market`, `symbol`, `span=1month` | 历史 K 线;`span` 支持 `1day` / `1week` / `1month` / `1year` / `5year` |

### 持仓 / 资产 / 订单([portfolio.py](src/broker_mcp_demo/tools/portfolio.py))

| 工具 | 参数 | 说明 |
|------|------|------|
| `get_positions` | — | 当前持仓列表(含盈亏) |
| `get_assets` | — | 账户资产(现金、市值、总资产等) |
| `get_orders` | `status=OPEN`, `limit=20` | 订单列表;`status` 支持 `OPEN` / `FILLED` / `CANCELLED` / `ALL` |
| `get_order` | `order_id` | 单个订单详情 |
| `cancel_order` | `order_id` | 撤销一个未成交订单 |

### 交易([trade.py](src/broker_mcp_demo/tools/trade.py))

| 工具 | 参数 | 说明 |
|------|------|------|
| `create_order` | `symbol`, `market`, `side`, `order_type`, `quantity`, `price?`, `validity` | 创建(提交)一个交易订单 |

- `order_type`:`MARKET_ORDER`(市价)/ `LIMIT_ORDER`(限价,需带 `price`)。
- `side`:`BUY` / `SELL`;`validity`:`GOOD_FOR_DAY` / `GOOD_TILL_CANCELLED`。

### 知识库([knowledge.py](src/broker_mcp_demo/tools/knowledge.py))

| 工具 | 参数 | 说明 |
|------|------|------|
| `search_knowledge_base` | `query`, `language=zh-Hans`, `top=10` | 搜索平台知识库(开户、出入金、交易规则等 QA) |

- `language`:`zh-Hans` / `zh-Hant` / `en`;`top` 范围 3~20。
- 真实项目通常由后端做向量检索 + 语义排序(如 Azure Cognitive Search、
  Elasticsearch、Milvus 等),本 demo 不绑定具体实现。

> 每个工具都套了 [decorators.py](src/broker_mcp_demo/tools/decorators.py) 的 `log_tool`
> 装饰器,统一打印调用方(API key 对应的 client_id)、入参与耗时日志。新增工具时
> 在对应模块 `register(mcp)` 内用 `@mcp.tool` + `@log_tool` 声明,并在
> [tools/\_\_init\_\_.py](src/broker_mcp_demo/tools/__init__.py) 的 `register_tools()` 注册。

## 运行

```bash
pip install -r requirements.txt

cp .env.example .env   # 按需修改 API key、后端地址
python -m broker_mcp_demo
```

默认监听 `0.0.0.0:8000`,MCP 端点为 `/mcp`,健康检查为 `/health`。

### 配置

全部通过环境变量(前缀 `BROKER_MCP_`)或 `.env` 注入,参考 [.env.example](.env.example):

| 变量 | 说明 |
|------|------|
| `BROKER_MCP_API_KEYS` | **必填**(除非关闭鉴权)。逗号分隔,每条为 `key` 或 `key:client_id`,如 `demo-key-1:alice,demo-key-2:bob` |
| `BROKER_MCP_BACKEND_BASE_URL` | 下游券商后端根地址(demo 不内置真实地址,自行配置);留空时工具返回示例数据 |
| `BROKER_MCP_HOST` / `BROKER_MCP_PORT` | 监听地址 / 端口,默认 `0.0.0.0:8000` |
| `BROKER_MCP_TRANSPORT` | `http`(默认)或 `stdio` |
| `BROKER_MCP_AUTH_DISABLED` | `true` 关闭鉴权,仅本地调试用 |
| `BROKER_MCP_BACKEND_TIMEOUT` | 下游请求超时秒数,默认 `30` |

### 客户端接入

以 Claude Code 为例(HTTP 模式 + API key):

```bash
claude mcp add --transport http broker-demo http://localhost:8000/mcp \
  --header "Authorization: Bearer demo-key-1"
```

或在 MCP 客户端的 JSON 配置中:

```json
{
  "mcpServers": {
    "broker-demo": {
      "type": "http",
      "url": "http://localhost:8000/mcp",
      "headers": {
        "Authorization": "Bearer demo-key-1"
      }
    }
  }
}
```

### stdio 模式

用于本地调试,走 stdin/stdout 且不启用鉴权:

```bash
BROKER_MCP_TRANSPORT=stdio python -m broker_mcp_demo
```

## 目录结构

```
src/broker_mcp_demo/
├── __main__.py     入口(python -m broker_mcp_demo)
├── config.py       环境变量 / .env 配置读取
├── auth.py         API key 鉴权(ApiKeyVerifier)
├── identity.py     解析调用方身份(client_id + X-User-Id)
├── backend.py      下游后端 HTTP 调用封装(未配置地址时回退示例数据)
├── server.py       FastMCP 实例装配
└── tools/          MCP 工具
    ├── __init__.py     register_tools() 注册入口
    ├── decorators.py   log_tool 计时日志装饰器
    ├── market.py       行情
    ├── portfolio.py    持仓 / 资产 / 订单
    ├── trade.py        下单
    └── knowledge.py    平台知识库搜索
```

## License

[Apache-2.0](LICENSE)