dwin-gharibi/alopeyk-mcp
GitHub: dwin-gharibi/alopeyk-mcp
为伊朗配送平台 Alopeyk 提供自托管的 MCP 服务器,使 AI agent 能安全地调用其物流与配送 API。
Stars: 0 | Forks: 0
alopeyk-mcp
**一个可自托管的 [Model Context Protocol](https://modelcontextprotocol.io) 服务器,专为 [Alopeyk](https://alopeyk.com) (الوپیک) —— 一家伊朗的按需配送与物流公司而设计。**
[](https://github.com/alopeyk-mcp/alopeyk-mcp/actions/workflows/ci.yml)
[](https://github.com/alopeyk-mcp/alopeyk-mcp/actions/workflows/docker.yml)
[](https://www.python.org/)
[](LICENSE)
`alopeyk-mcp` 将 Alopeyk 的 API 暴露为 MCP **tools** 和 **prompts**,以便 LLM agent(如 Claude 等)能够对地址进行地理编码、获取配送报价和跟踪状态、管理商业包裹,并且 —— 在您明确允许的情况下 —— 创建和取消真实的配送/包裹。它是一个由您自己运行的轻量级、无状态、异步 Python 进程。
它沿用了同系列 `ramzinex-mcp` / `roshan-*` 服务器的结构和质量:强类型 `httpx` 客户端、`pydantic-settings` 配置、完整的测试套件、Docker / Helm / Kubernetes / Terraform 部署资产,以及生成的架构图。
## 单一服务器中的两项服务
Alopeyk 运行着 **两个截然不同的 API 服务**,而此服务器在一个进程后封装了这两者,自动将每次调用路由到正确的基础地址:
| 服务 | Base URL | 认证 | Tool 前缀 |
| --- | --- | --- | --- |
| **On-Demand** | `https://api.alopeyk.com/api/v2/` (sandbox: `https://sandbox-api.alopeyk.com/api/v2/`) | `Authorization: Bearer
` (预签发的 JWT) | `alopeyk_` |
| **Alonomic** (الونومیک) | `https://api.alopeyk.com/business-service/api/v1/` | email/password → token (已缓存,遇到 401 重新登录),或预签发的 `alonomic_token` | `alonomic_` |

## 安装
```
pip install -e . # from a checkout
# 或用于开发:
pip install -e ".[dev]"
```
需要 Python 3.11+。
## 快速开始
离线/静态 tool(文档、交通类型、城市、URL 辅助工具、包裹状态)无需任何配置即可运行:
```
python -m alopeyk_mcp # stdio transport (default)
```
要使用 On-Demand tool,请提供预签发的 JWT;要使用 Alonomic tool,请提供 email + password(或预签发的 `alonomic_token`):
```
export ALOPEYK_ENVIRONMENT=production # or sandbox
# On-Demand (/api/v2/):
export ALOPEYK_ACCESS_TOKEN=your-ondemand-jwt
# Alonomic (/business-service/):email + password 登录(已缓存,在 401 时重新登录)
export ALOPEYK_EMAIL=ops@example.com
export ALOPEYK_PASSWORD=your-password
# ...或使用预先签发的 Alonomic token 代替:
# export ALOPEYK_ALONOMIC_TOKEN=your-alonomic-token
# 选择启用受限 mutation 工具(默认为 false):
export ALOPEYK_ENABLE_ORDERING=true # allow create/cancel/finish + parcels
python -m alopeyk_mcp
```
通过 HTTP 运行以供网络客户端调用:
```
python -m alopeyk_mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

## 配置(多账号 / 多实例)
配置通过 `pydantic-settings` 从环境变量中读取。一个进程可以支撑 **多个 Alopeyk 账号/环境** —— 每个都是一个具有独立凭据和安全策略的命名*实例*。每个 API tool 都接受一个可选的 `instance` 参数;省略它即可使用默认实例。
### 简写形式(单一默认实例)
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `ALOPEYK_ENVIRONMENT` | `production` | `production` 或 `sandbox`(选择默认的 base/tracking URL)。 |
| `ALOPEYK_ACCESS_TOKEN` | — | On-Demand JWT (`Authorization: Bearer`)。 |
| `ALOPEYK_EMAIL` | — | Alonomic 登录 email(配合 `ALOPEYK_PASSWORD` 使用)。 |
| `ALOPEYK_PASSWORD` | — | Alonomic 登录 password。 |
| `ALOPEYK_ALONOMIC_TOKEN` | — | 预签发的 Alonomic token(优先于 email/password)。 |
| `ALOPEYK_ENABLE_ORDERING` | `false` | 允许创建/修改真实的配送/包裹。 |
| `ALOPEYK_READ_ONLY` | `false` | 总开关:强制关闭下单功能。 |
| `ALOPEYK_ONDEMAND_BASE_URL` | 自动推导 | 覆盖 On-Demand base URL。 |
| `ALOPEYK_BUSINESS_BASE_URL` | 自动推导 | 覆盖 Alonomic base URL。 |
| `ALOPEYK_TRACKING_URL` | 自动推导 | 覆盖 tracking web-app base URL。 |
| `ALOPEYK_VERIFY_SSL` | `true` | 验证 TLS 证书。 |
| `ALOPEYK_TIMEOUT` | `30` | 单次请求超时时间(秒)。 |
| `ALOPEYK_DEFAULT_INSTANCE` | `default` | 省略 `instance` 时使用的实例。 |
| `ALOPEYK_LOG_LEVEL` | `INFO` | `DEBUG` / `INFO` / `WARNING` / ... |
### 嵌套形式(命名实例)
| 变量 | 描述 |
| --- | --- |
| `ALOPEYK__INSTANCES____ENVIRONMENT` | 用于 `` 的 `production` / `sandbox`。 |
| `ALOPEYK__INSTANCES____ACCESS_TOKEN` | 用于 `` 的 On-Demand JWT。 |
| `ALOPEYK__INSTANCES____EMAIL` | 用于 `` 的 Alonomic 登录 email。 |
| `ALOPEYK__INSTANCES____PASSWORD` | 用于 `` 的 Alonomic 登录 password。 |
| `ALOPEYK__INSTANCES____ALONOMIC_TOKEN` | 用于 `` 的预签发 Alonomic token。 |
| `ALOPEYK__INSTANCES____ENABLE_ORDERING` | 用于 `` 的下单开关。 |
| `ALOPEYK__INSTANCES____READ_ONLY` | 用于 `` 的总开关(强制关闭下单)。 |
| `ALOPEYK__INSTANCES____ONDEMAND_BASE_URL` | 用于 `` 的 On-Demand base。 |
| `ALOPEYK__INSTANCES____BUSINESS_BASE_URL` | 用于 `` 的 Alonomic base。 |
| `ALOPEYK__INSTANCES____TRACKING_URL` | 用于 `` 的 Tracking base。 |
| `ALOPEYK__INSTANCES____VERIFY_SSL` | TLS 验证(默认为 `true`)。 |
| `ALOPEYK__INSTANCES____TIMEOUT` | 单次请求超时秒数(默认为 `30`)。 |
| `ALOPEYK__DEFAULT_INSTANCE` | 省略 `instance` 时使用的实例。 |
| `ALOPEYK__LOG_LEVEL` | `DEBUG` / `INFO` / `WARNING` / ... |
示例:一个生产环境商业账号、一个 sandbox 账号,以及一个严格的只读查看者。
```
ALOPEYK__INSTANCES__BIZ__ENVIRONMENT=production
ALOPEYK__INSTANCES__BIZ__ACCESS_TOKEN=prod-ondemand-jwt
ALOPEYK__INSTANCES__BIZ__EMAIL=ops@example.com
ALOPEYK__INSTANCES__BIZ__PASSWORD=secret
ALOPEYK__INSTANCES__BIZ__ENABLE_ORDERING=true
ALOPEYK__INSTANCES__SANDBOX__ENVIRONMENT=sandbox
ALOPEYK__INSTANCES__SANDBOX__ACCESS_TOKEN=sandbox-jwt
ALOPEYK__INSTANCES__SANDBOX__ENABLE_ORDERING=true
ALOPEYK__INSTANCES__READONLY__ACCESS_TOKEN=viewer-jwt
ALOPEYK__INSTANCES__READONLY__READ_ONLY=true
ALOPEYK__DEFAULT_INSTANCE=biz
```
请参阅 [`.env.example`](.env.example) 获取完整的带注释文件。使用 `list_instances` 查看已配置的内容(名称、环境、base URL、`has_ondemand_credentials`、`has_alonomic_credentials`、`alonomic_auth_method`、`enable_ordering`、`read_only`、`ordering_allowed`)—— 它永远不会暴露凭据的具体值。
## 控制标志与安全
| 标志 | 默认值 | 控制 | 生效条件 |
| --- | --- | --- | --- |
| `enable_ordering` | `false` | `alopeyk_create_order`, `alopeyk_cancel_order`, `alopeyk_finish_order`, `alopeyk_loyalty_products(buy=true)`, `alonomic_create_parcel`, `alonomic_update_parcel`, `alonomic_cancel_parcel` | `enable_ordering=true` **且** `read_only=false` |
| `read_only` | `false` | 强制关闭 `enable_ordering` | — |
当控制开关关闭时,该 tool 会返回
`{"error": "ordering_disabled", "message": ...}` 并且 **绝不联系 API**。
### 身份验证
- **On-Demand** — 一个预签发的 `access_token` (JWT),作为
`Authorization: Bearer ` 发送。所有 `alopeyk_*` 网络 tool 均需提供。
- **Alonomic** — 可以是预签发的 `alonomic_token`,或者是 `email` + `password`,
服务器会将后者 POST 到 `login`,将返回的 token 按实例缓存在内存中,对其进行重用,并在遇到 `401` 时重新认证一次。调用
`alonomic_login` 可显式触发/验证登录(它绝不会返回 token)。
access token、Alonomic token 和 password 绝不会被记录或回显(`Authorization` / `access_token` / `alonomic_token` / `token` /
`password` 都会从错误信息中被脱敏处理)。

## 与 MCP 客户端配合使用
将其添加到您客户端的 MCP 服务器配置中:
```
{
"mcpServers": {
"alopeyk": {
"command": "python",
"args": ["-m", "alopeyk_mcp"],
"env": {
"ALOPEYK_ENVIRONMENT": "production",
"ALOPEYK_ACCESS_TOKEN": "your-ondemand-jwt",
"ALOPEYK_EMAIL": "ops@example.com",
"ALOPEYK_PASSWORD": "your-password",
"ALOPEYK_ENABLE_ORDERING": "false"
}
}
}
}
```
## Tools
所有 34 个 tool(17 个 On-Demand `alopeyk_*` + 14 个 Alonomic `alonomic_*` + 3 个 meta)
都接受可选的 `instance` 参数,除了两个纯本地的 meta tool
(`list_instances`,`alopeyk_docs`)之外。
### On-Demand (`alopeyk_`) — `/api/v2/`,JWT Bearer
| Tool | Method · Endpoint | 备注 |
| --- | --- | --- |
| `alopeyk_get_address(lat, lng)` | `GET locations?latlng=,` | 逆地理编码 |
| `alopeyk_location_suggestion(input, latlng?)` | `GET locations?input=&location=` | 自动补全 |
| `alopeyk_get_price(transport_type, addresses, has_return?, cashed?, optimize?)` | `POST orders/price/calc` | 只读报价 |
| `alopeyk_get_batch_price(orders)` | `POST orders/batch-price` | ≤15 个订单 |
| `alopeyk_create_order(transport_type, addresses, has_return?, cashed?, scheduled_at?, discount_coupon?)` | `POST orders` | ⚠️ `enable_ordering` |
| `alopeyk_get_order(order_id)` | `GET orders/{id}?columns=...` | 只读 |
| `alopeyk_cancel_order(order_id, comment)` | `GET orders/{id}/cancel?comment=` | ⚠️ `enable_ordering` |
| `alopeyk_finish_order(order_id, comment?, rate?)` | `POST orders/{id}/finish` | ⚠️ `enable_ordering` |
| `alopeyk_get_config()` | `GET config` | 只读 |
| `alopeyk_get_profile()` | `GET show-profile?columns=*,credit` | 只读 |
| `alopeyk_validate_coupon(code)` | `POST coupons` | 只读 |
| `alopeyk_loyalty_products(product_id?, buy?)` | `GET\|POST loyalty/customer/products/{id?}` | buy ⚠️ `enable_ordering` |
| `alopeyk_tracking_url(order_token)` | _local_ `#/` | 无网络请求 |
| `alopeyk_print_invoice_url(order_id, order_token)` | _local_ | 无网络请求 |
| `alopeyk_payment_route(user_id, amount, gateway=saman)` | _local_ (saman\|zarinpal) | 无网络请求 |
| `alopeyk_transport_types()` | _local_ | motorbike, motor_taxi, cargo, cargo_s, car |
| `alopeyk_cities()` | _local_ | tehran, shemiranat, rey, karaj, isfahan, tabriz, mashhad, shiraz |
### Alonomic (`alonomic_`) — `/business-service/api/v1/`,email/password 登录
| Tool | Method · Endpoint | 备注 |
| --- | --- | --- |
| `alonomic_login()` | `POST login` | 缓存 token(绝不返回它) |
| `alonomic_get_me()` | `GET me` | 只读 |
| `alonomic_get_days()` | `GET days` | 只读 |
| `alonomic_get_days_index()` | `GET days/index` | 7 天,每天 `{same, next}` |
| `alonomic_create_parcel(drop, parcel, pickup, delivery_proofs?, parcel_extra_params?)` | `POST parcels` | ⚠️ `enable_ordering` |
| `alonomic_get_parcel(parcel_id)` | `GET parcels/{id}` | 只读 |
| `alonomic_update_parcel(parcel_id, ...)` | `PUT parcels/{id}` | ⚠️ `enable_ordering |
| `alonomic_cancel_parcel(parcel_id)` | `DELETE parcels/{id}` | ⚠️ `enable_ordering` (204) |
| `alonomic_calc_parcel(drop, parcel, pickup?)` | `POST parcels/calc` | 只读估价 |
| `alonomic_get_parcel_sizes()` | `GET parcels/size` | 12 种箱子尺寸 |
| `alonomic_get_saved_addresses()` | `GET pickup-saved-addresses` | 只读 |
| `alonomic_add_saved_address(title, lat, lng, address, ...)` | `POST pickup-saved-addresses` | 地址簿 |
| `alonomic_delete_saved_address(address_id)` | `DELETE pickup-saved-addresses/{id}` | 地址簿 (204) |
| `alonomic_parcel_statuses()` | _local_ | 静态状态 → 波斯语标签映射 |
### Meta
| Tool | 描述 |
| --- | --- |
| `healthcheck` | 调用 On-Demand 的 `config` endpoint 并报告连通性。 |
| `list_instances` | 列出已配置的实例(环境、base URL、设置了哪些凭据、`enable_ordering`、`read_only`、`ordering_allowed`)—— 绝不显示凭据值。 |
| `alopeyk_docs(topic?)` | 针对两项服务的离线参考文档 + 指向 https://docs.alopeyk.com 的链接。 |
⚠️ = 创建/修改真实的配送/包裹;受 `enable_ordering` 控制(被 `read_only` 强制关闭)。

## Prompts
服务器还附带了 MCP **prompts** —— 您的客户端可以列出并运行的安全感知工作流(详情见 [`prompts/README.md`](prompts/README.md)):
- **`quote_delivery`** — 对起点/终点进行地理编码,然后使用
`alopeyk_get_price` 获取报价。
- **`create_delivery_safely`** — 一个严谨的检查清单,用于验证
`enable_ordering`,确认地址/类型/价格,然后创建订单。
- **`track_order`** — `alopeyk_get_order` + `alopeyk_tracking_url`。
- **`alonomic_send_parcel`** — login → `days/index` → `calc` → 安全地创建包裹。
- **`address_book`** — 审查 Alonomic 保存的地址 + 包裹箱子尺寸。
## Skill
一个开箱即用的 Claude/agent skill 位于
[`skills/alopeyk/SKILL.md`](skills/alopeyk/SKILL.md)。它描述了在两种服务中何时以及如何
使用这些工具 —— 报价/跟踪、安全的配送流程,
以及 Alonomic 包裹流程 —— 并附带了 tool 调用序列的示例。
## 架构
MCP 客户端与一个 `alopeyk-mcp` 进程通信,该进程将 `alopeyk_*` 调用路由
到 On-Demand API (`/api/v2/`),并将 `alonomic_*` 调用路由到 Alonomic business
API (`/business-service/api/v1/`)。

单个进程即可服务多个账号/环境;通过 `instance` 参数来选择
具体使用哪套凭据/下单策略。

一个典型的 On-Demand 流程:建议/地理编码地址、获取报价、检查
`enable_ordering` 开关,然后创建并跟踪订单。

完整的 tool 概览,按服务分组:
订单生命周期与 Alonomic 包裹流程:

`read_only` 总开关控制着 `enable_ordering`,以及这两个环境:
使用 `make diagrams` 重新生成图表(需用到 `diagrams` 包 +
Graphviz `dot` 和 `cairosvg`)。
## 自托管与扩展
`alopeyk-mcp` 是无状态的,因此您可以在负载均衡器后运行任意数量的副本。单个进程通过
`ALOPEYK__INSTANCES____*` 即可支撑多个账号 —— 无需修改代码。如果 Alopeyk
对您进行了速率限制(HTTP 429),请进行退避处理。请参阅 [`deploy/`](deploy/) 获取 Docker Compose、Kubernetes (原生 +
Kustomize)、Helm chart 以及 Terraform module。
## 测试
```
make smoke # no-network smoke test (tools + prompts + descriptions)
make test # full pytest suite (offline; all HTTP incl. Alonomic login mocked with respx)
make lint # ruff
```
除非设置了 `ALOPEYK_LIVE=1`(并且提供了相关凭据),否则针对真实 API 的实时测试将被跳过:
```
ALOPEYK_LIVE=1 ALOPEYK_ACCESS_TOKEN=... pytest tests/live -q
```
## License
[MIT](LICENSE)。`alopeyk-mcp` 是一个非官方的、社区构建的集成;Alopeyk 和 Alonomic 的名称及标志归其所有者所有。标签:Docker, MCP服务器, Python, 人工智能, 子域名突变, 安全防御评估, 无后门, 物流API, 用户模式Hook绕过, 自动化代理, 请求拦截, 运行时操纵