Skip to main content
Glama
kaerf15
by kaerf15
README.md
# Just One API · MCP Server

把 [Just One API](https://justoneapi.com) 的 **237+ 个数据接口**(抖音 / 小红书 / 淘宝 / 亚马逊 / TikTok 等 30+ 平台)收敛为**固定几个元工具**的 [MCP](https://modelcontextprotocol.io) 服务。

核心特性:

- **工具数量不随接口增长而爆炸**——无论后端多少接口,对外只暴露固定的 4 个核心工具 + 2 个维护工具。
- **自然语言智能选接口**——基于阿里云百炼 `text-embedding-v4`(2048 维)的跨语言语义检索,中文随口提问即可命中英文接口描述。
- **SDK / 后端更新时,MCP 代码零改动**——接口知识全部来自数据产物(`catalog.json` + `embeddings.json`),增删改接口只需重建数据,并支持热加载(无需重启)。

设计细节见 [`docs/mcp-server-design.md`](docs/mcp-server-design.md)。

---

## 工作原理

后端 OpenAPI 是唯一真源,派生出 MCP 的接口目录与向量索引:

```
后端 OpenAPI → normalized.json → catalog.json + embeddings.json(向量)
                                      ↓
LLM 按「搜索 → 取参数 → 调用」编排,动态使用全部 237+ 接口:
   search_endpoints → get_endpoint_schema → call_endpoint
```

### 暴露的工具

| 工具 | 作用 |
|------|------|
| `search_endpoints` | 用自然语言发现接口(语义检索,返回候选 endpoint_id) |
| `get_endpoint_schema` | 查看某接口的完整参数契约 |
| `call_endpoint` | 传参执行接口,返回数据(大结果截断 + 翻页提示) |
| `list_platforms` | 列出所有平台及接口数量 |
| `check_updates` | [维护·只读] 对比上游,列出将新增/移除/变更的接口 |
| `rebuild_catalog` | [维护·管理员] 同步上游并重建目录与向量索引 |

---

## 安装

需要 Python ≥ 3.10。

```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt          # 运行时依赖:mcp / httpx / pydantic
```

## 配置

### 服务器侧(环境变量)

| 变量 | 必需 | 说明 |
|------|------|------|
| `MCP_TRANSPORT` | 是 | 固定为 `http` |
| `MCP_HOST` / `MCP_PORT` | 否 | 监听地址,默认 `0.0.0.0:8000` |
| `MCP_ADMIN_TOKEN` | 否 | 仅当你要通过 MCP 工具远程调用 `rebuild_catalog` 时才需要;日常取数不必配置 |

### 客户端(Cursor `mcp.json` 的 headers)

| Header | 必需 | 说明 |
|--------|------|------|
| `Authorization` | 是 | `Bearer <你的 justone token>`,调用业务接口时扣你的 justone 余额 |
| `X-DashScope-Key` | 是 | 你的百炼 key,`search_endpoints` 语义检索时使用 |
| `X-Admin-Token` | **否** | **仅**在你要通过 MCP 调用 `rebuild_catalog` 重建目录时才需要,且须与服务器 `MCP_ADMIN_TOKEN` 一致;日常搜索/取数完全不需要 |

## 生成数据产物

首次运行前需生成 `catalog.json` + `embeddings.json`(调用百炼编码,增量):

```bash
python -m tools.mcp_catalog            # 生成目录 + 向量
python -m tools.mcp_catalog --no-embed # 只生成目录,跳过向量编码
```

---

## 运行

### 服务器

```bash
MCP_TRANSPORT=http MCP_HOST=0.0.0.0 MCP_PORT=8000 python -m justoneapi.mcp.server
```

如需通过 MCP 工具远程调用 `rebuild_catalog`,服务器额外设置 `MCP_ADMIN_TOKEN=<随机强串>`。

### 客户端(Cursor `mcp.json`)

日常取数只需两个 header:

```jsonc
{
  "mcpServers": {
    "justoneapi": {
      "url": "http://<服务器IP或域名>:8000/mcp",
      "headers": {
        "Authorization": "Bearer <你的 justone token>",
        "X-DashScope-Key": "<你的百炼 key>"
      }
    }
  }
}
```

仅当需要通过 MCP 调用 `rebuild_catalog` 时,才额外加上 `"X-Admin-Token": "<与服务器 MCP_ADMIN_TOKEN 一致>"`。

> 生产环境建议在前面挂 HTTPS(Nginx/Caddy 反代 + TLS),避免请求头中的 token 明文传输。

---

## 接口更新

后端 OpenAPI 是唯一真源,justone 官方 CI 每日把归一化后的 `public-api.normalized.json` 提交到公开仓库。本项目直接同步该公开产物即可跟上后端,**无需任何凭证**:

```bash
python -m scripts.sync_mcp            # 拉上游 → 有变更才重建(含接口 diff)
python -m scripts.sync_mcp --dry-run  # 只看差异,不写不重建
python -m scripts.sync_mcp --force    # 即使无变更也重建
```

也可在客户端按需调用维护工具:先 `check_updates` 看差异,确认后再 `rebuild_catalog`(需配置 `MCP_ADMIN_TOKEN` 并在 headers 带 `X-Admin-Token`)。重建为原子替换、增量编码,运行中的 server 通过 mtime 自动热加载,**无需重启**。

---

## 项目结构

```
just-one/
├── justoneapi/
│   ├── _transport.py          # 稳定调用出口 Transport.get(path, params)
│   ├── _exceptions.py
│   ├── _response.py
│   ├── _version.py
│   ├── log.py
│   ├── mcp/
│   │   ├── server.py          # FastMCP 入口,注册 6 个工具
│   │   ├── search.py          # 语义检索
│   │   ├── executor.py        # 参数校验 + 多租户 token + 调用
│   │   ├── catalog.py         # 内存目录 + mtime 热加载
│   │   ├── embedding.py       # 百炼 text-embedding-v4 封装
│   │   └── config.py          # 环境变量与平台别名
│   └── mcp_data/              # 运行时产物(生成)
│       ├── catalog.json
│       ├── embeddings.json
│       └── embeddings.meta.json
├── openapi/
│   └── public-api.normalized.json   # 接口目录唯一数据来源(由上游同步)
├── scripts/
│   └── sync_mcp.py            # 同步上游 + 重建(无需凭证)
├── tools/
│   └── mcp_catalog.py         # 由 normalized.json 生成 catalog + 向量
├── docs/
│   └── mcp-server-design.md
├── requirements.txt
├── pyproject.toml
└── README.md
```

## License

见 [LICENSE](LICENSE)。