alidocs-web-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@alidocs-web-mcpAdd the action items from our discussion to the document."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
alidocs-web-mcp
Let your AI agent read and edit the DingTalk Doc you already have open — in your own browser, under your own login, with every change landing as a suggestion you approve or discard.
Why this exists
You are editing a document in your browser. Your AI agent lives somewhere else — an IDE, a terminal, a desktop app. To let the agent help, you normally have two bad options:
Option | Why it falls short |
Server-side document API | Cannot express block-level suggestions awaiting human review, and needs its own credentials and permission plumbing |
Give the agent its own browser | Splits your session in two: the document you are looking at is not the document the agent drives |
The capability you actually want — structured, block-level editing that renders as a reviewable suggestion — only exists inside the page runtime. So instead of recreating it elsewhere, this tool connects your agent to the page you already have open.
The direction is inverted on purpose. The page dials out to a local process; the local process never reaches into your browser. That is what makes it work without debug ports, browser extensions, or any change to your agent's host application.
Related MCP server: webmcp-polyfill
What you get
Standard MCP over stdio — works with any MCP host (IDE, terminal, desktop agent). No custom protocol to adopt.
Zero runtime dependencies — plain Node ≥ 18, hand-rolled WebSocket framing.
npxand go.Zero code injection — the pairing credential is data, never a script. Nothing is ever
eval'd.Read-only by default — writes require an explicit flag, and land as suggestions rather than saved edits.
Loopback only — binds
127.0.0.1, enforces an Origin allowlist, and authenticates with an HMAC challenge-response.
Requirements
This bridge ishalf of a pair. The document page must ship a matching connector that discovers the bridge and initiates pairing. Without it, the bridge starts fine but no document tools will ever appear.
As of now that connector is not yet generally available in production DingTalk Docs. If get_bridge_status keeps reporting connected: false while the bridge is clearly running, this is almost certainly why — not a misconfiguration on your side.
Node.js ≥ 18
A DingTalk Doc page open in a browser, with the page-side connector present
Install & run
Register it with your MCP host — no global install needed:
{
"mcpServers": {
"alidocs-web-mcp": {
"command": "npx",
"args": ["-y", "alidocs-web-mcp", "--allow-write"]
}
}
}Or run it directly:
npx -y alidocs-web-mcp # read-only
npx -y alidocs-web-mcp --allow-write # allow the page to register write toolsThe bridge tries ports 19837 → 19838 → 19839 and takes the first free one. The page discovers it by probing those same ports, which is why they are fixed rather than random.
How pairing works
Three steps, and the agent can drive all of them:
Call
get_pairing_code→ you get a pairing code (a string of data) and the port.Put that code into the page's "local agent" pairing field — the agent can type and click it, or you can paste it yourself.
The page completes an HMAC handshake. From then on
tools/listincludes the document tools.
After a refresh or same-tab navigation, the page reconnects automatically using the code it kept in sessionStorage. No re-pairing.
Architecture
flowchart LR
subgraph outside["Outside the browser"]
host["MCP host<br/>(IDE / terminal / desktop agent)"]
bridge["alidocs-web-mcp<br/>pairing + dumb pipe"]
end
subgraph browser["Your browser, your login"]
page["Document page<br/>MCP server + tools"]
doc["Document<br/>suggestion state"]
end
host <-->|"stdio · standard MCP"| bridge
page -->|"1 · discover: GET /health"| bridge
page <-->|"2 · ws://127.0.0.1 · HMAC handshake<br/>3 · JSON-RPC passthrough"| bridge
page --> doc
classDef trust fill:#eef7ff,stroke:#4b86c9
classDef local fill:#f6f6f6,stroke:#999
class browser trust
class outside localTwo properties worth noting:
The page always initiates. The bridge only listens on loopback; it never dials into the browser.
The bridge is a dumb pipe. Beyond its own three tools, it merges
tools/listand forwardstools/callverbatim. It does not understand document semantics — so the page can add tools without changing the bridge.
Data flow
sequenceDiagram
autonumber
participant H as MCP host
participant B as alidocs-web-mcp
participant P as Document page
participant D as Document
Note over B: bind 127.0.0.1, generate a per-session pairing code (CSPRNG)
H->>B: tools/call get_pairing_code
B-->>H: pairingCode + port (data, never a script)
P->>B: GET /health on 19837/38/39
B-->>P: { service, originAllowed, ... }
Note over H,P: the code reaches the page via UI (typed or pasted)
P->>B: WS upgrade (Origin checked here → 403 if not allowed)
B-->>P: challenge { nonce }
P->>B: auth { mac = HMAC-SHA256(pairingCode, nonce) }
B-->>P: ready { sessionId }
B->>H: notifications/tools/list_changed
H->>B: tools/call read_document
B->>P: forwarded verbatim (id remapped)
P->>D: read
D-->>P: content
P-->>B: result
B-->>H: result
H->>B: tools/call update_block
B->>P: forwarded verbatim
P->>D: write as a suggestion (not saved)
Note over D: you approve or discard itThe pairing code itself is never transmitted — only HMAC(code, nonce) is. Someone who squats the port and captures the mac still cannot recover the code.
Bridge tools
Everything else you see in tools/list comes from the page; the bridge only forwards it.
Tool | What it does |
| Returns the pairing code (data) plus the port and write-permission state. Never returns a script. |
| Port, whether a page is paired, whether its MCP session is ready, in-flight requests, Origin allowlist, audit log path. Start here when a call fails. |
| Rotates the pairing code and drops the session. Anything the page stored becomes invalid immediately. |
CLI options
Flag | Meaning |
| Use only this port instead of the candidate set |
| Append an allowlist entry (repeatable); |
| Replace the default allowlist entirely |
| Allow the page to register write tools (read-only otherwise) |
| Audit log location, default |
| Handshake deadline, default 10000 |
| Timeout for requests forwarded to the page, default 60000 |
The default allowlist contains only the official document origins plus local dev hosts, enumerated one by one. There is deliberately no wildcard like https://*.dingtalk.com — that would let any subdomain reach your local bridge.
Security posture
This tool opens a listening port on your machine, so it is worth being explicit. Four attack directions, each with its own defence:
Direction | Defence |
A malicious web page → your local bridge | Loopback-only bind plus an Origin allowlist enforced during the WS upgrade (403 before any state changes) |
A malicious local process → the bridge | A per-session CSPRNG pairing code. Origin headers can be forged by non-browser clients; the code cannot be guessed |
A local impostor squatting the port → your page | HMAC challenge-response, so the code never goes over the wire; plus port-contention detection |
A poisoned distribution or prompt injection → your page | Credentials travel as data, never as code; read-only by default; writes only ever become suggestions |
Also: /health responses are tiered by Origin (outsiders cannot read connected or allowWrite), one session at a time, and the audit log records tool names and argument keys — never argument values or the pairing code.
Full threat model and the S1–S13 control list: docs/security.md. Reporting a vulnerability: SECURITY.md.
Troubleshooting
Symptom | Likely cause |
| No page is paired yet. Run |
| The page has no connector (see Requirements), or the page is on an origin outside the allowlist. |
| Your document origin is not allowlisted. Add it with |
| All three candidate ports are taken. Free one, or pass |
| Expected: restarting rotates the code. Pair again with the fresh one. |
| The page navigated or refreshed. It reconnects on its own; retry the call. |
| The page did not answer within |
Development
npm install # dev deps only (typescript, @types/node)
npm run build # tsc → dist/ (CommonJS + .d.ts)
npm test # runs against dist/ — i.e. against what actually ships
npm run verify # build + test
npm run typecheck # tsc --noEmitSource is TypeScript under src/; the published artifact is compiled CommonJS in dist/. Tests stay in plain JavaScript on purpose — they exercise the built output rather than the sources, so the thing being verified is the thing being published. Because the bridge uses a fixed port set, tests run serially.
Downstream projects can build contract tests against a real bridge process:
const { startTestBridge, connectFakePage } = require('alidocs-web-mcp/test-helpers');See CONTRIBUTING.md and AGENT.md (the latter lists constraints that must not be violated, e.g. "never return executable code").
Project status
Early (0.x). Verified today:
49 automated tests over the compiled artifact
12 Origin bypass attempts (subdomain suffixing, full-URL-in-Origin, trailing dot, case variants, scheme downgrade,
null, missing, port injection, backslash confusion) all rejected at the real upgrade pathBusiness messages sent before the handshake are rejected and the socket closed
Cross-implementation HMAC agreement with the page side, pinned by shared test vectors
Not yet verified: a real MCP host consuming this server end to end. Development so far used a purpose-built minimal MCP client, which also means the notifications/tools/list_changed path — how a host learns that document tools appeared after pairing — has only been covered by automated tests with a fake host, not observed against a real one.
Documentation
docs/design.md — design, trade-offs, and the three couplings you cannot separate
docs/security.md — threat model and control list
AGENT.md — conventions for AI agents working on this repo
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityBmaintenanceAn MCP server that runs in the browser, letting web pages register custom tools and prompts and expose them to an MCP client over WebSocket. Enables agents to drive UI, call page-scoped APIs, and get human-in-the-loop confirmation.Last updated6MIT
- Alicense-qualityCmaintenanceEnables browsers to act as MCP servers by relaying tools, resources, and prompts to AI agents via a WebSocket-to-stdio bridge.Last updated28MIT
- FlicenseBqualityAmaintenanceChatGPT-compatible MCP server and Electron launcher for controlled local project-file access, providing read-only and approval-gated write tools over STDIO or HTTP with optional OAuth and HTTPS tunneling.Last updated19
- AlicenseBqualityAmaintenanceA stdio MCP server that bridges the camofox-browser anti-detection browser automation API as MCP tools, with built-in SSRF and prompt injection protections.Last updated33961MIT
Related MCP Connectors
MCP-native collaborative markdown editor with real-time AI document editing
MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/magical-index/alidocs-web-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server