alidocs-web-mcp
Click on "Deploy 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: Feishu MCP Server
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 ≥ 22.12, 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, when the agent tells it to, pairs. The connector does not pop any UI on its own; the agent initiates pairing by calling window.__docMcpWsBridge.pair(code) in that page. Without the connector, 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 ≥ 22.12 (ESM-only package;
require()from CommonJS works on 22.12+)A DingTalk Doc page open in a browser, with the page-side connector present
Install & run
One-click install. Both scripts need repository content (the skill source lives in skills/), so clone first:
git clone https://github.com/magical-index/alidocs-web-mcp.git
cd alidocs-web-mcpQoder — one plugin installs the MCP server and the skill together:
./install-qoder.sh # generate the plugin from skills/ and install it (user scope)
./install-qoder.sh <plugin.zip> # use a prebuilt plugin package
./install-qoder.sh --pack-only # only build the package, do not installRun /plugins reload in Qoder afterwards. The repository does not carry a plugin directory; the script generates one into ~/.alidocs-web-mcp/plugin/ on demand. Note that qodercli plugin install accepts a directory, not a zip — hand the zip to the script and it unpacks it for you.
Claude Code — its plugin install only resolves marketplaces and its manifest format differs from Qoder's, so the two halves are installed separately (MCP via claude mcp add, skill copied into ~/.claude/skills/):
./install-claude.sh # MCP + skill
./install-claude.sh --mcp-only # MCP only
./install-claude.sh --force # overwrite an existing configurationBoth scripts support --dry-run (print the commands without running them) and --force, and skip rather than silently overwrite when something already exists. Both register npx -y … --port 0 --allow-write: npx so the bridge follows package updates (a global install never upgrades itself), and --port 0 for the reason in Several agents at once.
Or register it with your MCP host manually — no global install needed:
{
"mcpServers": {
"alidocs-web-mcp": {
"command": "npx",
"args": ["-y", "@magical-index/alidocs-web-mcp", "--port", "0", "--allow-write"]
}
}
}Or run it directly:
npx -y @magical-index/alidocs-web-mcp # read-only
npx -y @magical-index/alidocs-web-mcp --allow-write # allow the page to register write toolsBy default the bridge tries ports 19837 → 19838 → 19839 and takes the first free one. The port is no longer an identity, though: since 0.2.0 the pairing code is <port>.<secret>, so the page connects straight to the port named in the code instead of probing the candidate list.
Several agents at once
Every agent host starts its own bridge, so three fixed ports run out quickly — the fourth start fails with PORT_CONTENDED, which the host sees as stdio closing and reports as "Connection closed", making it look like a bad install. Pass --port 0 to let the OS hand out a free ephemeral port; the pairing code carries it, so nothing else changes:
{
"mcpServers": {
"alidocs-web-mcp": {
"command": "npx",
"args": ["-y", "@magical-index/alidocs-web-mcp", "--port", "0", "--allow-write"]
}
}
}Both install scripts above already do this; only hand-written configs need to add it. This needs bridge ≥ 0.2.0 together with a page connector that understands the composite code; an older bridge hands out a bare secret, and the page then falls back to probing the candidate ports — exactly the contention you were trying to escape. Note that a globally installed bridge does not refresh itself the way npx -y does, so upgrade it explicitly:
npm i -g @magical-index/alidocs-web-mcp@latestCompanion skill
skills/alidocs-edit-routing/ is an Agent Skill: before changing an existing DingTalk text document, it makes the agent ask you whether to go through dws direct write or this bridge's suggestion mode, instead of silently picking one and committing.
The install scripts above already set it up — Qoder gets it through the plugin, Claude Code gets a copy in ~/.claude/skills/. To place it manually in another host (for example Codex's ~/.agents/skills/), copy the whole directory over; the directory name must match the name in SKILL.md.
Two things to know: it only takes effect in a new session (hosts read the skills directory at session start), and it treats dws as a prerequisite skill — without dws the "direct write" channel is not available.
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), with the port already embedded in it as<port>.<secret>.The agent runs one console command in the target page (usually the document iframe's
contentWindow):await window.__docMcpWsBridge.pair(pairingCode). Only the page the agent points at connects — the connector never pops a panel on its own, so other browsers/tabs stay silent.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 handful of 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 secret (CSPRNG)
H->>B: tools/call get_pairing_code
B-->>H: pairingCode = "port.secret" (data, never a script)
P->>B: GET /health on the port from the code
B-->>P: { service, originAllowed, ... }
Note over H,P: the agent runs window.__docMcpWsBridge.pair(code) in the target page's console
P->>B: WS upgrade (Origin checked here → 403 if not allowed)
B-->>P: challenge { nonce }
P->>B: auth { mac = HMAC-SHA256(secret, 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 secret half of the pairing code is never transmitted — only HMAC(secret, nonce) is. Someone who squats the port and captures the mac still cannot recover the secret. (The port half is not a credential; it only says which bridge to talk to.)
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) — |
| 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. |
| Static fallback. Read-only listing of the tools the paired page exposes (name, description, argument schema), so a host with a stale snapshot can discover before calling. |
| Static passthrough. Some MCP hosts do not refresh |
The last two are static fallback tools; whether they appear is decided by --host-profile. Under auto (the default) they are hidden only from hosts known to honor tools/list_changed (currently only the Claude family); every unknown host is treated as non-compliant and gets them — two extra tools of noise beats a host that needs the fallback not seeing any tools at all.
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) |
| Static fallback tool profile: |
| 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 agent has not run |
| Your document origin is not allowlisted. Add it with |
| All three candidate ports are taken — usually by other agents' bridges. 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, Vitest, Biome, publint, attw)
npm run build # tsc -p tsconfig.build.json → dist/ (ESM + .d.ts)
npm test # Vitest: unit + e2e against src/, plus an artifact smoke on dist/
npm run typecheck # tsc --noEmit over src/ and test/
npm run lint # Biome (lint + format check); `npm run lint:fix` to apply
npm run verify # lint → typecheck → build → test → package checks (run before a PR)Stack: TypeScript 7 · Vitest 4 · Biome 2 · publint + attw — all dev-time only; the shipped artifact still has zero runtime dependencies.
Source is TypeScript under src/, published as ESM-only in a flat dist/. Tests are TypeScript too: unit and e2e suites import src/ directly, so a broken contract fails at typecheck instead of surfacing as an undefined assertion. What compilation itself can break — missing shebang, exports pointing at files that do not exist, vectors.json not copied, ESM-hostile code such as __dirname — is covered separately by test/artifact.test.ts, which rebuilds a stale dist/ on demand and drives the real CLI process over stdio. Because the bridge uses a fixed port set, tests run serially.
Downstream projects can build contract tests against a real bridge process:
import { startTestBridge, connectFakePage, readyOf } from '@magical-index/alidocs-web-mcp/testing';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:
75 automated tests: unit + end-to-end against the sources, plus an artifact smoke that runs the built CLI as a real process
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 agreement with the page side on both the HMAC and the pairing-code parse rules, pinned by shared test vectors
Known limitation: a small number of MCP hosts take a snapshot of tools/list at server startup and do not update it when the bridge sends notifications/tools/list_changed. Since the MCP spec has no standard field declaring that capability, the bridge can only judge conservatively from clientInfo at initialize: every unknown host is treated as non-compliant, so by default it exposes the two static fallback tools list_page_tools / call_page_tool — discover page tools and their arguments with the former, then invoke them by name with the latter (the bridge still forwards arguments verbatim and never interprets document semantics).
Documentation
skills/alidocs-edit-routing/ — companion skill: route between "dws direct write" and "interactive review" before editing a doc
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
Available Tools
5 toolscall_page_tool调用页面工具(静态透传)A
显式按名字调用一个由已建桥页面提供的文档工具。 适用场景:部分 MCP host 在 server 启动后不会刷新 tools/list(不响应 notifications/tools/list_changed), 因此页面配对后新出现的 read_document / insert_blocks 等工具对 host 不可见。 call_page_tool 恒定出现在 tools/list 中,它只按 name 与 arguments 原样转发给页面, 桥仍不理解工具语义(A10 哑管道约束)。 未建桥时返回 PAGE_NOT_CONNECTED。
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | 要调用的页面侧工具名,例如 read_document、insert_blocks。 | |
| arguments | No | 传给该页面工具的参数对象。 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that it is a dumb pipe (A10) that forwards name/arguments without semantic understanding, and that it returns PAGE_NOT_CONNECTED when no bridge is established. With only readOnlyHint/openWorldHint annotations, this adds meaningful behavioral context, though it doesn't specify side effects (which are delegated to the target tool).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the core purpose, then scenario, mechanism, and error case. Slightly long but each clause earns its place given the nuanced fallback use case.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, so the description should explain the success return and how to discover valid tool names. It mentions examples but does not direct the agent to list_page_tools for available names, nor describe the success response shape; this is a gap for a generic passthrough tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description adds that arguments are forwarded 'as-is' and provides concrete name examples, clarifying that no transformation or validation occurs beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb-resource pair: explicitly calls a page-provided document tool by name, and describes the static passthrough mechanism. The examples (read_document/insert_blocks) and contrast with host-visible tools distinguish it from siblings like list_page_tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete applicable scenario: hosts that don't refresh tools/list, making newly paired page tools invisible. It explains why this tool exists and when to use it, though it doesn't explicitly name the alternative (e.g., using the dynamically exposed tool or list_page_tools) in a 'use X instead' form.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_bridge_status查询桥状态ARead-only
返回 bridge 当前状态:监听端口、是否已建桥、页面 MCP 会话是否就绪、在途请求数、Origin 白名单、写权限开关。工具调用失败时先查这里。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds value by specifying the diagnostic contents and framing the tool as a first-stop failure investigation point, which is behavioral context beyond the annotation. No contradictions found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One compact sentence lists all returned status fields, and a second short clause gives the diagnostic use case. Every element earns its place, and the key payload is front-loaded before the usage note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only, diagnostic tool with no output schema, the description is complete: it enumerates the return contents, states the tool's diagnostic role, and benefits from annotations covering safety. Nothing an agent needs to decide whether and how to call it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter burden for the description to carry. With schema coverage reported at 100% and an empty properties object, the baseline of 4 applies; the description correctly adds nothing extraneous about parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('返回') with a clear resource ('bridge 当前状态') and enumerates the exact fields returned: listening port, bridge status, MCP session readiness, in-flight request count, Origin whitelist, and write permission. This makes the tool instantly distinguishable from sibling tools like revoke_session or call_page_tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to reach for this tool: '工具调用失败时先查这里' (check here first when tool calls fail). It provides clear diagnostic context, though it does not name alternative tools or exclusions, so it stops slightly short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_pairing_code获取配对码ARead-only
返回把「当前浏览器里已打开的钉钉文档页面」接到本 bridge 所需的配对码(一串字符串数据)。
用法:agent 在目标页面所在的浏览器上下文里执行控制台命令建连——
在该页面(通常是文档 iframe 的 contentWindow)调 await window.__docMcpWsBridge.pair(pairingCode)。
这样只有 agent 点名的那个页面会连上;其它浏览器/标签页不受影响,也不会弹任何 UI。
页面据此与 bridge 完成挑战-响应握手(配对码只用于本地计算 HMAC,明文永不上线)。
重要:本工具只返回数据,绝不返回需要执行的脚本;不要 eval 任何东西。
握手成功后 tools/list 会包含文档工具。页面刷新后由页面用 sessionStorage 里的配对码自动重连,无需再次配对。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses substantial behavioral details: no UI is shown, no script is returned, the pairing code is used only locally for HMAC and never sent online, and the page auto-reconnects after refresh using sessionStorage. These details are valuable and not present in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the tool's purpose, and every sentence adds useful context such as usage, security, and reconnection behavior. It is somewhat lengthy, but the density of practical information justifies the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter tool with no output schema, the description is complete: it explains what the returned value is, how to use it, what side effects occur, how isolation works, and what happens after page refresh. An agent has enough information to invoke and apply the pairing code correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description cannot add parameter-level detail. It does, however, clarify that the output is a string used as a pairing code for a challenge-response handshake, which gives meaningful semantic context for the return value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it returns a pairing code string required to connect an already-open DingTalk document page to the bridge. This clearly distinguishes it from siblings like get_bridge_status, revoke_session, call_page_tool, and list_page_tools, which serve different functions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage steps: the agent must run `window.__docMcpWsBridge.pair(pairingCode)` in the target page's console context. It also explains the isolation behavior (only the named page connects) and warns that the tool returns data only, never executable scripts. It does not explicitly name when not to use it versus alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_page_tools列出页面工具(静态发现)ARead-only
返回「当前已建桥页面」提供的文档工具清单(名字、描述、参数 schema),只读、以数据返回。 适用场景:部分 MCP host 不会随 notifications/tools/list_changed 刷新 tools/list, 导致页面配对后新出现的工具不可见。此时先用 list_page_tools 发现有哪些工具及其参数, 再用 call_page_tool 按名调用。未建桥时返回 PAGE_NOT_CONNECTED。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true; the description reinforces this with '只读' and adds behavior beyond annotations: results are returned as data and PAGE_NOT_CONNECTED is returned when no bridge exists. This is useful context and does not contradict the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core return value, then gives a focused scenario, workflow, and error case in four short sentences. Every sentence contributes a distinct piece of information, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description tells the agent what to expect: a list of tool names, descriptions, and parameter schemas, plus the not-connected error case. Combined with the usage scenario and empty input schema, nothing essential is missing for an agent to select and call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters and the empty schema is fully covered, so there is no input-semantics burden. The description even notes that the returned inventory includes parameter schemas, but adds no input-parameter detail because none exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: it returns the tool inventory (names, descriptions, parameter schemas) offered by the currently bridged page. This clearly differentiates it from call_page_tool, which is described as the follow-up invocation step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly gives a trigger scenario: hosts that do not refresh tools/list after page pairing, making newly exposed page tools invisible, and tells the agent to use list_page_tools first then call_page_tool. It stops short of stating when not to use the tool or comparing against the other siblings, so explicit exclusions are missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
revoke_session撤销连接A
轮换配对码并断开当前页面会话(S11)。撤销后旧配对码立即失效,页面 sessionStorage 里的旧值无法再重连,需重新调用 get_pairing_code 配对。用于结束一次授权或怀疑配对码泄露时。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
注释声明readOnlyHint=false和openWorldHint=false,描述详细说明了副作用:旧配对码失效、sessionStorage值无法重连,以及需要重新配对。无矛盾,且额外披露了内部标识S11。
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
两句话传达了目的、副作用、使用场景和后续步骤,无冗余信息,结构清晰。
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
对于零参数工具,描述已涵盖功能、副作用、使用场景和后续操作,无输出模式但描述足够。兄弟工具列表提供了上下文,无缺失信息。
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
工具无参数,模式覆盖率为100%,描述无需解释参数。基准为4,描述中提及需要重新调用get_pairing_code,但那是后续步骤,不影响此维度。
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
描述明确说明了动词(轮换、断开)和资源(配对码、页面会话),并区分了兄弟工具(get_pairing_code等)。明确表示撤销后旧配对码失效,会话断开。
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
描述了使用场景(结束授权或怀疑泄露),并指出需要重新调用get_pairing_code配对。但未显式说明何时不使用,不过基于兄弟工具列表,其他工具不执行撤销操作,因此清晰度足够。
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.2.1- First observed
call_page_tool - First observed
get_bridge_status - First observed
get_pairing_code - First observed
list_page_tools - First observed
revoke_session
TDQS
Scored across 5 tools
Each tool targets a distinct aspect of the bridge lifecycle: status, pairing, revocation, discovery of page tools, and forwarding calls. There is no meaningful overlap between them, even though get_bridge_status and list_page_tools both return state—they report on different layers (bridge vs. page-provided tools).
All tool names follow the same snake_case verb_noun pattern: get_bridge_status, get_pairing_code, revoke_session, call_page_tool, list_page_tools. The verbs are specific and the nouns clearly indicate the target, making the naming fully predictable.
Five tools is well-scoped for a bridge-focused MCP server. Each tool covers a necessary part of the pairing/connection/call lifecycle without redundancy or bloat, and the count aligns with the server's narrow purpose.
The tool surface covers the full bridge lifecycle: obtaining a pairing code, checking status, revoking sessions, enumerating page-provided tools, and invoking them. There are no obvious dead ends—even hosts that don't refresh tool lists are supported via call_page_tool and list_page_tools.
Maintenance
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.
An agent-first office suite Claude & ChatGPT read and write over one MCP URL.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables browsers to act as MCP servers by relaying tools, resources, and prompts to AI agents via a WebSocket-to-stdio bridge.19 npmMIT
- FlicenseAqualityBmaintenanceEnables reading, creating, updating, and appending Feishu documents, as well as querying and updating Bitable fields and records via the MCP protocol.12-
- AlicenseNot gradedqualityBmaintenanceEnables remote AI agents to control a local, authenticated desktop browser over MCP through an outbound WebSocket bridge and Chrome extension, supporting tab management, navigation, page reading, clicking, typing, scrolling, screenshots, and JavaScript evaluation.1MIT
- AlicenseAqualityBmaintenanceEnables AI clients to read, write, and search Feishu (Lark) documents, wiki pages, spreadsheets, and bitable records over MCP, with stdio or authenticated HTTP(S) transport.9259 npmMIT