# wecom-docs-mcp-server [![MCP](https://img.shields.io/badge/MCP-passthrough-blue)](https://modelcontextprotocol.io) [![Python](https://img.shields.io/badge/python-3.9+-green)](https://python.org) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow)](LICENSE) [![Tests](https://img.shields.io/badge/tests-25%20passed-brightgreen)](#tests) An ergonomic **stdio MCP facade** over WeCom's official **robot-doc MCP** backend. It proxies all 25 backend tools verbatim and adds a transform layer that makes the raw output usable by LLM agents: - **Schema passthrough** — the tool list is fetched from the backend at startup, so it auto-tracks official updates. Zero schema maintenance. - **Cell unwrap** — smartsheet `values[field] = [{"type":"text","text":...}]` cells become plain scalars (in a `_rows` view). - **ms → ISO** — 13-digit ms-epoch timestamps (`create_time`, `update_time`) convert to ISO 8601. - **Chinese error hints** — `errcode` 851003 etc. get `_error_summary` + `_error_hint` so the agent learns the fix, not just the code. > **Relationship to the backend**: This server *requires* the official robot-doc MCP backend (an apikey from WeCom admin → 智能文档机器人 → API). It is a thin proxy + ergonomics layer, **not** a replacement. --- ## Why this exists The official robot-doc backend is an **HTTP (StreamableHttp) MCP server**. Two friction points: (1) many MCP clients and dev workflows prefer **stdio**; (2) its raw output is agent-hostile — nested cell format, ms-epoch strings, opaque error codes. This server bridges both: | | official robot-doc | this server | |---|---|---| | Transport | HTTP (StreamableHttp) | **stdio** | | Tool schema | raw 25 tools | same 25, passthrough | | Cell format | `[{"type":"text",...}]` | unwrapped scalars (`_rows`) | | Timestamps | ms-epoch strings | ISO 8601 | | Error codes | `851003` only | + Chinese summary + fix hint | | apikey | required | required (proxied) | --- ## Requirements - Python 3.9+ - A WeCom **智能文档机器人** (Smart Doc Bot) with its API key — available to enterprises (≥10 members) via WeCom admin → 应用管理 → 智能文档机器人 → API. --- ## Install ```bash pip install wecom-docs-mcp-server ``` Or clone + editable: ```bash git clone https://github.com/Beltran12138/wecom-docs-mcp-server cd wecom-docs-mcp-server pip install -e . ``` --- ## Configuration | Variable | Required | Description | |---|---|---| | `WECOM_MCP_APIKEY` | **yes** | robot-doc apikey | | `WECOM_MCP_BASE_URL` | no | override backend URL (default `https://qyapi.weixin.qq.com/mcp/robot-doc`) | ### Claude Desktop (`claude_desktop_config.json`) ```json { "mcpServers": { "wecom-doc": { "command": "wecom-docs-mcp-server", "env": { "WECOM_MCP_APIKEY": "your_apikey_here" } } } } ``` --- ## Tools All 25 backend tools are exposed verbatim (fetched live at startup). By domain: | Domain | Read | Write | |---|---|---| | **doc** | get_doc_content | create_doc, edit_doc_content, upload_doc_image, upload_doc_file | | **smartsheet** (智能表) | get_sheet, get_fields, get_records | add/update/delete × sheet/fields/records | | **sheet** (电子表格) | get_info | add_sub, delete_sub, update_range_data, append_data | | **smartpage** (智能页面) | get_export_result | create, export_task | > **Permission model (empirically observed 2026-07)**: `get_doc_content` and `smartsheet_get_*` use **independent permission scopes**. A bot may read a smartsheet via `smartsheet_get_records` (errcode 0) yet get `851003 no authority` from `get_doc_content` on the same doc. Route reads by doc type. --- ## Transforms (the value-add) Applied automatically on every `tools/call` response: 1. **`_rows`** on `smartsheet_get_records` — a flattened view where cells are unwrapped to scalars and top-level record fields (`record_id`, `create_time`, …) are preserved. The original `records` array is kept intact. 2. **ms → ISO** on all successful dict payloads — 13-digit ms-epoch strings → ISO 8601. Alphanumeric IDs (`q979lj`) are untouched. 3. **`_error_summary` + `_error_hint`** on any non-zero errcode — Chinese explanation + concrete fix. --- ## Usage Read a smartsheet end-to-end: ``` User: read https://doc.weixin.qq.com/smartsheet/s3_xxx?scode=yyy Agent: 1. smartsheet_get_sheet(url=...) → sheet_id (e.g. "q979lj") 2. smartsheet_get_fields(sheet_id, url) → field schema (types, IDs) 3. smartsheet_get_records(sheet_id, url) → records + _rows (cells unwrapped, timestamps ISO) ``` > Pass the full `url` (with `?scode=`) rather than guessing `docid` — the backend resolves it. Manually extracting docid by stripping prefixes is error-prone (empirically: `301085 invalid docid`). --- ## Troubleshooting | errcode | meaning | fix | |---|---|---| | 851000 | 文档链接有误 | check url + scode, or use docid | | 851002 | 文档类型与工具不兼容 | smartsheet → use `smartsheet_get_*` | | 851003 | 无文档权限 | smartsheet 用 `smartsheet_get_*`;普通文档查后台权限 | | 851008 | 缺文档内容读取权限 | 企微后台 → 机器人 → API 权限 | | 301085 | 无效 docid | 用完整 url 含 scode | | 40058 | 参数缺失 | smartsheet 需 sheet_id(先 get_sheet)| --- ## Related | Project | Focus | |---|---| | official robot-doc MCP | backend (HTTP, ≥10 人企业) | | [wecom-bot-mcp-server](https://github.com/loonghao/wecom-bot-mcp-server) | bot messaging via webhook | | **this server** | **robot-doc stdio proxy + ergonomics** | --- ## Tests ```bash pip install -e ".[dev]" # or: pip install pytest httpx pytest ``` 25 unit tests cover SSE/JSON parsing, ms-timestamp normalization, cell unwrap, error humanizing, and server routing/post-processing — all offline (httpx mocked). --- ## License MIT