Skip to main content
Glama
README.md
<div align="center">

# ๐Ÿ“„ wecom-doc-mcp

**Let AI read your Enterprise WeChat docs โ€” in real time.**

[![MCP](https://img.shields.io/badge/MCP-Compatible-blue?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJ3aGl0ZSI+PHBhdGggZD0iTTEyIDJMMiA3bDEwIDUgMTAtNS0xMC01ek0yIDE3bDEwIDUgMTAtNS0xMC01LTEwIDV6TTIgMTJsMTAgNSAxMC01LTEwLTUtMTAgNXoiLz48L3N2Zz4=)](https://modelcontextprotocol.io)
[![Node](https://img.shields.io/badge/Node.js-โ‰ฅ18-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org)
[![License](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](LICENSE)

<br/>

<p>
  <img src="https://img.shields.io/badge/ไผไธšๅพฎไฟก-ๆ–‡ๆกฃ-07C160?style=flat-square&logo=wechat&logoColor=white" />
  <img src="https://img.shields.io/badge/Claude_Code-Ready-D97706?style=flat-square" />
  <img src="https://img.shields.io/badge/Cookie-Auth-red?style=flat-square&logo=cookiecutter&logoColor=white" />
</p>

[English](#-why) ยท [ไธญๆ–‡](README_CN.md)

</div>

---

## ๐Ÿค” Why

> Enterprise WeChat documents sit behind SSO. AI assistants can't access them.

This MCP server bridges the gap: provide your browser cookie once, and the server handles authenticated fetching + HTML-to-Markdown conversion on every request.

```
๐Ÿ’ฌ "ๅธฎๆˆ‘็œ‹ไธ‹่ฟ™ไธชๆ–‡ๆกฃ: https://doc.weixin.qq.com/doc/w3_xxx"
         โ”‚
         โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     ๐Ÿช      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     ๐Ÿ“     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚ Claude Code  โ”‚ โ”€โ”€Cookieโ”€โ”€โ–ถ โ”‚  MCP Server   โ”‚ โ”€โ”€HTMLโ”€โ”€โ–ถ โ”‚ Markdown โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

## ๐Ÿ› ๏ธ Tools

| Tool | Description |
|:-----|:------------|
| ๐Ÿ“– `fetch_wecom_doc` | Fetch a document by URL โ†’ return Markdown |
| ๐Ÿช `set_wecom_cookie` | Save cookie locally (`chmod 600`) |
| โœ… `check_wecom_auth` | Verify if saved cookie is still valid |

## ๐Ÿš€ Quick Start

### Step 1 โ€” Install

```bash
git clone https://github.com/SIE-Operations-and-Maintenance-Team/wecom-doc-mcp.git
cd wecom-doc-mcp
npm install
```

### Step 2 โ€” Register with Claude Code

Add to `~/.mcp.json`:

```json
{
  "mcpServers": {
    "wecom-doc": {
      "command": "npx",
      "args": ["tsx", "/path/to/wecom-doc-mcp/src/index.ts"]
    }
  }
}
```

### Step 3 โ€” Get Your Cookie ๐Ÿช

```
1. ๐ŸŒ  Open doc.weixin.qq.com โ†’ log in
2. ๐Ÿ”ง  F12 โ†’ Network tab
3. ๐Ÿ“‹  Click any request โ†’ copy the Cookie header value
```

### Step 4 โ€” Use It

```text
You:    ๅธฎๆˆ‘่ฎพ็ฝฎไผไธšๅพฎไฟก Cookie: <paste>
Claude: โœ… Cookie ๅทฒไฟๅญ˜

You:    ๅธฎๆˆ‘็œ‹ไธ‹่ฟ™ไธชๆ–‡ๆกฃ: https://doc.weixin.qq.com/doc/w3_xxx
Claude: # ๆ–‡ๆกฃๆ ‡้ข˜
        ่ฟ™ๆ˜ฏๆ–‡ๆกฃ็š„ๅ†…ๅฎน...
```

## ๐Ÿ“ Architecture

```
                          wecom-doc-mcp
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚                     โ”‚
  fetch_wecom_doc โ”€โ”€โ”ค  ๐Ÿ“ก /dop-api/opendocโ”‚
        โ”‚           โ”‚  Call WeChat's       โ”‚
        โ”‚           โ”‚  internal API for    โ”‚โ”€โ”€โ”€โ”€ ๐Ÿ“ Markdown
        โ”‚           โ”‚  document JSON data  โ”‚
        โ”‚           โ”‚                     โ”‚
        โ”‚           โ”‚  ๐Ÿงน cleanDocText    โ”‚
        โ”‚           โ”‚  Strip HYPERLINK     โ”‚
        โ”‚           โ”‚  markup โ†’ clean text โ”‚
        โ”‚           โ”‚                     โ”‚
        โ”‚           โ”‚  ๐Ÿ“„ Fallback:       โ”‚
        โ”‚           โ”‚  cheerio + turndown  โ”‚
        โ”‚           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        โ”‚
  set_wecom_cookie โ”€โ”€โ”€ ๐Ÿ’พ ~/.claude/wecom-doc-mcp/.env (mode 600)
        โ”‚
  check_wecom_auth โ”€โ”€โ”€ ๐Ÿฅ /dop-api/opendoc โ†’ clientVars.isLogin?
```

## ๐Ÿ” Cookie Auth

Two modes, your choice:

| Mode | How | When |
|:-----|:----|:-----|
| ๐Ÿ’พ Persistent | `set_wecom_cookie` โ†’ saved to `~/.claude/wecom-doc-mcp/.env` | Set once, use forever (until expiry) |
| โšก Per-request | Pass `cookie` param to `fetch_wecom_doc` | Override on the fly |

> ๐Ÿ”’ Cookie file lives outside the project directory โ€” never committed, never shared, `chmod 600`.

## ๐Ÿ“‘ Supported Document Types

| Type | URL Pattern | Status |
|:-----|:------------|:------:|
| ๐Ÿ“ Documents | `/doc/` | โœ… Verified |
| ๐Ÿ“Š Spreadsheets | `/sheet/` | โœ… Verified |
| ๐ŸŽž๏ธ Slides | `/slide/` | ๐Ÿ”ง No dedicated parser |
| ๐Ÿง  Mind Maps | `/mind/` | โœ… Verified |
| ๐Ÿ”€ Flowcharts | `/flowchart/` | ๐Ÿ”ง No dedicated parser |
| ๐Ÿ“‹ Smart Sheets | `/smartsheet/` | โœ… Verified |

- โœ… Verified: exercised against real documents. Spreadsheets (4 worksheet tabs), smart sheets
  (15 worksheets / 2103 rows) and documents (2 files) were verified in this round; mind maps were
  verified by the original author (this round only added rendering unit tests, the fetching logic
  is unchanged).
- ๐Ÿงช Implemented, needs a sample: code path implemented and covered by synthetic cases, but no
  real document of this type was available; a payload mismatch raises a clear error.
- ๐Ÿ”ง No dedicated parser: the payload shape is unknown, so the tool falls back to extracting the
  page HTML, strips toolbar/menu nodes, and labels the result as page text.

**Spreadsheets** (`src/sheet.ts`): cells are not part of the document-text payload but live in
`collab_client_vars.initialAttributedText.text[0].related_sheet` as
base64 + zlib + protobuf, rendered as one Markdown table per worksheet.

- `tab=<sheetId>` in the URL selects the worksheet (forwarded to the API); otherwise the default tab is read;
- at most 100 data rows per call by default, with an explicit note of how many were omitted;
  use `rowStart` / `rowEnd` (1-based, header excluded) โ€” non-numeric or out-of-range values are reported;
- rows above the header (template title, dropdown option definitions) are listed separately;
- date cells hold Excel serial numbers (e.g. `46303` = 2026-10-08).

**Smart Sheets** (`src/smartsheet.ts`): a different payload โ€” plain JSON in `text[0].workbook`
(sheets, dashboards, forms) and `text[0].smartsheet`.

- Column names carry their type (e.g. `็Šถๆ€(ๅ•้€‰)`, `ๅผ€ๅง‹ๆ—ถ้—ด(ๆ—ฅๆœŸ)`); single-select/person columns
  resolve to option names; dates are converted from millisecond timestamps to local dates;
  number/formula columns show the computed result; unsupported shapes are marked `[ๆœช่งฃๆž็š„็ฑปๅž‹N]`;
- one request returns a single worksheet โ€” other worksheets need `tab=<sheetId>` in the link,
  otherwise the tool fails with an explicit message;
- row order follows the view definition (matching the UI); form-backed worksheets fall back to the
  payload's own order; skipped empty rows are reported.

Re-runnable checks (scripts kept in a local temp directory, not committed): `verify-sheet.ts`,
`verify-fixes.ts`, `verify-varint.ts`, `verify-smartsheet.ts` (real responses), `verify-mind.ts`,
and `verify-e2e.ts` (needs a live cookie; covers worksheets, real documents, real smart sheets,
parameter validation, error messages, and cookie leak prevention โ€” copy it into the project root
and run `npx tsx verify-e2e.ts`).

## ๐Ÿ“ฆ Tech Stack

| Dependency | Purpose |
|:-----------|:--------|
| `@modelcontextprotocol/sdk` | MCP protocol implementation |
| `cheerio` | HTML parsing |
| `turndown` | HTML โ†’ Markdown conversion |
| `tsx` | TypeScript runtime |

## ๐Ÿ“„ License

MIT

---

<div align="center">
  <sub>Built with โค๏ธ for teams drowning in enterprise docs</sub>
</div>