Skip to content

feat(external-agent): one-click MCP connect for Qoder and 千问办公 - #146

Open
Alphaxiaoteng wants to merge 1 commit into
0xsline:mainfrom
Alphaxiaoteng:feat/external-agent-qoder-qwenwork
Open

feat(external-agent): one-click MCP connect for Qoder and 千问办公#146
Alphaxiaoteng wants to merge 1 commit into
0xsline:mainfrom
Alphaxiaoteng:feat/external-agent-qoder-qwenwork

Conversation

@Alphaxiaoteng

Copy link
Copy Markdown
Contributor

Why

The MCP guide already writes the endpoint + bearer token into Claude Code, Codex, Cursor and Antigravity. Two agents people actually run are missing, and they need different treatment — which is the point of this PR:

  • Qoder keeps custom MCP servers in a mergeable settings.json that supports headers, so it can be a genuine one-click connect.
  • 千问办公 (Qwen Work) keeps them in its in-app connector store. There is no on-disk file for custom servers, so a "connect" button would have to write to a private path that does not exist. It gets a copy-JSON card instead.

Change

Server (server/external-agent/client-connect.ts)

  • CONNECT_CLIENTS gains qoder.
  • connectJsonClientconnectJsonClients (a client may now have more than one config file), and the per-client path table becomes jsonClientFiles().
  • Qoder ships an international and a China build that hold the same settings file under ~/.qoder or ~/.qoder-cn. Only the installed one is meaningful, so existing homes are both updated and an absent sibling is skipped; when neither exists yet the documented ~/.qoder path is created.
  • Merge semantics unchanged: atomic temp+rename, unrelated servers and settings preserved, unparseable JSON refused rather than clobbered.

Editor guide (src/components/settings/McpGuide.tsx, new mcpClientConfig.ts)

  • ClientSnippet gains mode: 'connect' | 'paste'. Connect cards keep the existing button; paste cards get a copy button plus the JSON itself rendered, so it is still selectable when the clipboard is unavailable.
  • qwenWorkConnectJson() holds the snippet shape in a pure module so it is testable without a DOM. Note its type is streamable-http, which is what Qwen Work's importer expects — deliberately different from the http the file writer emits.
  • EN + IT dictionaries for the new strings.

Docs### Qoder and ### Qwen Work (千问办公) in README.md / README_ZH.md, including the dual-build paths and an explicit statement that OpenChatCut does not write into Qwen Work's store.

Verification

Real end-to-end run on Node 24, with HOME pointed at a throwaway directory and OPENCHATCUT_MCP_TOKEN set to a synthetic value, so nothing on the developer's machine was touched and no real credential appears anywhere:

  • POST /api/external-agent/connect-client {client:'qoder'}{"ok":true,"paths":["~/.qoder/settings.json"]}, and the file appears with the bearer header. First attempt without Origin/Sec-Fetch-Site correctly got 403 invalid request origin from the CSRF shape gate.
  • With ~/.qoder-cn also present → both paths written; a pre-existing {"theme":"dark","mcpServers":{"keepme":…}} survived intact.
  • Using the written file as a real client would: initialize200 + serverInfo {openchatcut}, tools/list200 / 31 tools, tools/call openchatcut_status200. Same request without the bearer header → 403, with a wrong token → 403.
  • Browser: the guide dialog renders both new cards; clicking Qoder's 连接 shows 已写入 ~/.qoder/settings.json and the file lands on disk; the 千问办公 card shows the JSON and its copy path was exercised through the failure branch (the automation context denies clipboard-write), which is what the on-screen snippet covers.

Suite, same branch:

  • npm test → exit 0
  • npm run build (tsc -b && vite build) → exit 0
  • npm run lint → 0 warnings / 0 errors on 1850 files
  • npx tsc -b → clean
  • npm run verify:i18n → 通过, 2458 英文词条
  • client-connect.verify.ts → merges idempotent, broken JSON refused, codex CLI + env var synced
  • mcpClientConfig.verify.ts → registered in verify:components, verify-registration clean

Not included

No Qwen Work file write, because there is no public path to write to; if they add one this becomes a mode: 'connect' card.

Qoder keeps its MCP servers in a mergeable settings.json, so the guide can
write it directly. It ships an international and a China build that hold the
same file under ~/.qoder or ~/.qoder-cn, and only the installed one matters,
so both existing homes are updated and an absent sibling is skipped.

千问办公 has no on-disk config for custom MCP servers - they live in its
in-app connector store - so a file writer would only invent one. Its card
copies the exact JSON its importer expects instead, and shows it so the text
can still be selected when the clipboard is blocked.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant