@double-coding/dsh-connectors 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/CONTRIBUTING.md +173 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +156 -0
  4. package/README.md +153 -2
  5. package/assets/readme/architecture.webp +0 -0
  6. package/assets/readme/hero-en.svg +62 -0
  7. package/assets/readme/hero.svg +62 -0
  8. package/assets/readme/panel.webp +0 -0
  9. package/cordis.patch.yml +8 -0
  10. package/dist/client.js +5385 -0
  11. package/dist/client.js.map +7 -0
  12. package/dist/host/catalog.d.ts +7 -0
  13. package/dist/host/catalog.js +15 -0
  14. package/dist/host/catalog.js.map +1 -0
  15. package/dist/host/cli/adapters.d.ts +69 -0
  16. package/dist/host/cli/adapters.js +577 -0
  17. package/dist/host/cli/adapters.js.map +1 -0
  18. package/dist/host/cli/exec.d.ts +34 -0
  19. package/dist/host/cli/exec.js +186 -0
  20. package/dist/host/cli/exec.js.map +1 -0
  21. package/dist/host/cli/service.d.ts +44 -0
  22. package/dist/host/cli/service.js +711 -0
  23. package/dist/host/cli/service.js.map +1 -0
  24. package/dist/host/cli/version.d.ts +1 -0
  25. package/dist/host/cli/version.js +16 -0
  26. package/dist/host/cli/version.js.map +1 -0
  27. package/dist/host/connections.d.ts +106 -0
  28. package/dist/host/connections.js +1207 -0
  29. package/dist/host/connections.js.map +1 -0
  30. package/dist/host/errors.d.ts +4 -0
  31. package/dist/host/errors.js +8 -0
  32. package/dist/host/errors.js.map +1 -0
  33. package/dist/host/instanceUrl.d.ts +1 -0
  34. package/dist/host/instanceUrl.js +27 -0
  35. package/dist/host/instanceUrl.js.map +1 -0
  36. package/dist/host/mcpServers.d.ts +19 -0
  37. package/dist/host/mcpServers.js +243 -0
  38. package/dist/host/mcpServers.js.map +1 -0
  39. package/dist/host/oauth.d.ts +49 -0
  40. package/dist/host/oauth.js +215 -0
  41. package/dist/host/oauth.js.map +1 -0
  42. package/dist/host/openExternal.d.ts +1 -0
  43. package/dist/host/openExternal.js +45 -0
  44. package/dist/host/openExternal.js.map +1 -0
  45. package/dist/host/providers.d.ts +105 -0
  46. package/dist/host/providers.js +199 -0
  47. package/dist/host/providers.js.map +1 -0
  48. package/dist/host/routes.d.ts +18 -0
  49. package/dist/host/routes.js +514 -0
  50. package/dist/host/routes.js.map +1 -0
  51. package/dist/host/sse-bridge.d.ts +1 -0
  52. package/dist/host/sse-bridge.js +168 -0
  53. package/dist/host/sse-bridge.js.map +1 -0
  54. package/dist/host/store.d.ts +184 -0
  55. package/dist/host/store.js +98 -0
  56. package/dist/host/store.js.map +1 -0
  57. package/dist/index.d.ts +5 -0
  58. package/dist/index.js +35 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/shared/categories.d.ts +12 -0
  61. package/dist/shared/categories.js +59 -0
  62. package/dist/shared/categories.js.map +1 -0
  63. package/dist/shared/customConfig.d.ts +1 -0
  64. package/dist/shared/customConfig.js +2 -0
  65. package/dist/shared/customConfig.js.map +1 -0
  66. package/dist/shared/types.d.ts +222 -0
  67. package/dist/shared/types.js +2 -0
  68. package/dist/shared/types.js.map +1 -0
  69. package/package.json +96 -4
  70. package/providers/README.md +44 -0
  71. package/providers/amap/icon.png +0 -0
  72. package/providers/amap/provider.json +34 -0
  73. package/providers/baidu-netdisk/icon.png +0 -0
  74. package/providers/baidu-netdisk/provider.json +36 -0
  75. package/providers/circleci/icon.svg +1 -0
  76. package/providers/circleci/provider.json +29 -0
  77. package/providers/cloudflare-docs/icon.svg +1 -0
  78. package/providers/cloudflare-docs/provider.json +26 -0
  79. package/providers/context7/icon.png +0 -0
  80. package/providers/context7/provider.json +25 -0
  81. package/providers/deepwiki/icon.svg +5 -0
  82. package/providers/deepwiki/provider.json +26 -0
  83. package/providers/firecrawl/icon.png +0 -0
  84. package/providers/firecrawl/provider.json +40 -0
  85. package/providers/gitee/icon.svg +1 -0
  86. package/providers/gitee/provider.json +32 -0
  87. package/providers/github/icon.svg +1 -0
  88. package/providers/github/provider.json +33 -0
  89. package/providers/gitlab/icon.svg +1 -0
  90. package/providers/gitlab/provider.json +31 -0
  91. package/providers/gitlab-self-hosted/icon.svg +1 -0
  92. package/providers/gitlab-self-hosted/provider.json +39 -0
  93. package/providers/grafana/icon.svg +1 -0
  94. package/providers/grafana/provider.json +32 -0
  95. package/providers/linear/icon.svg +1 -0
  96. package/providers/linear/provider.json +41 -0
  97. package/providers/microsoft-learn/icon.svg +6 -0
  98. package/providers/microsoft-learn/provider.json +26 -0
  99. package/providers/neon/icon.svg +1 -0
  100. package/providers/neon/provider.json +41 -0
  101. package/providers/notion/icon.svg +1 -0
  102. package/providers/notion/provider.json +29 -0
  103. package/providers/posthog/icon.svg +1 -0
  104. package/providers/posthog/provider.json +38 -0
  105. package/providers/postman/icon.svg +1 -0
  106. package/providers/postman/provider.json +29 -0
  107. package/providers/qcc/icon.png +0 -0
  108. package/providers/qcc/provider.json +50 -0
  109. package/providers/sentry/icon.svg +1 -0
  110. package/providers/sentry/provider.json +30 -0
  111. package/providers/sourcegraph/icon.png +0 -0
  112. package/providers/sourcegraph/provider.json +32 -0
  113. package/providers/supabase/icon.svg +1 -0
  114. package/providers/supabase/provider.json +52 -0
  115. package/providers/tavily/icon.svg +4 -0
  116. package/providers/tavily/provider.json +41 -0
  117. package/providers/tencent-docs/icon.png +0 -0
  118. package/providers/tencent-docs/provider.json +34 -0
  119. package/providers/tencent-yuanbao-search/icon.png +0 -0
  120. package/providers/tencent-yuanbao-search/provider.json +32 -0
  121. package/providers/tianyancha/icon.png +0 -0
  122. package/providers/tianyancha/provider.json +34 -0
  123. package/providers/yunxiao/icon.svg +1 -0
  124. package/providers/yunxiao/provider.json +30 -0
  125. package/schema/provider.schema.json +325 -0
@@ -0,0 +1,173 @@
1
+ # 贡献 Provider
2
+
3
+ `dsh-connectors` 的内置 provider 只包含数据:新增一个 provider 就是加一个目录,不用改核心代码。契约文件是 [`schema/provider.schema.json`](schema/provider.schema.json)。
4
+
5
+ ## 我们接受什么
6
+
7
+ - 厂商官方的远程 MCP 服务;普通 provider 的地址必须是 `https://`。
8
+ - 需要用户填写完整 MCP 地址的服务用 `instance` 描述,地址在运行时提供(可 https / http / 内网),`auth` 可选 `none`、`bearer`、`header`、`oauth2`。
9
+ - 目录内的静态描述、示例和可选图标。
10
+ - 用真实凭据验证过能连接并注册工具。
11
+
12
+ ## 我们不接受什么
13
+
14
+ - provider 携带可执行代码、构建脚本或运行时注入逻辑。
15
+ - 把 token / client secret / 固定内网地址写进 `provider.json`。
16
+ - 非 `instance` 的 `http://` 地址、代理服务或非官方转接端点(这类场景请使用面板里的「自定义连接器」导入)。
17
+ - 遥测、数据上报或远程配置。
18
+
19
+ ## 目录结构
20
+
21
+ ```text
22
+ providers/
23
+ acme/
24
+ provider.json # 必需
25
+ icon.svg # 可选,也支持 icon.png / icon.webp
26
+ ```
27
+
28
+ - `provider.json` 的 `id` 必须与目录名一致。
29
+ - `serverName` 缺省等于 `id`,必须全局唯一(决定工具前缀 `mcp__<serverName>__`)。
30
+ - 图标建议 24×24 的 SVG;没有图标时客户端用首字母色块兜底。
31
+
32
+ ## 快速开始
33
+
34
+ ```bash
35
+ npm run provider:new -- acme --auth bearer --name "Acme"
36
+ # 编辑 providers/acme/provider.json,替换 TODO 与示例地址
37
+ # 可选:放入 providers/acme/icon.svg
38
+ npm run check
39
+ ```
40
+
41
+ `npm run check` 会依次执行类型检查、构建、provider 校验与服务地址/契约测试(重复 id / serverName、字段缺失、URL、排序等)。
42
+
43
+ ## 通用服务地址 provider(instance)
44
+
45
+ 如果服务需要用户填写**完整的 MCP 地址**(自建 GitLab、高德等),在 provider 中增加 `instance` 描述,并且不要设置 `server.url`:
46
+
47
+ ```json
48
+ {
49
+ "instance": {
50
+ "label": "服务地址",
51
+ "placeholder": "https://example.com/mcp",
52
+ "hint": "填写完整的 MCP 端点;不要包含账号密码或锚点。",
53
+ "help": {
54
+ "url": "https://example.com/docs/mcp",
55
+ "label": "查看接入指引",
56
+ "hint": "在控制台创建服务后复制地址。"
57
+ }
58
+ },
59
+ "server": {
60
+ "serverName": "example",
61
+ "transport": "streamable-http"
62
+ },
63
+ "auth": { "type": "none" }
64
+ }
65
+ ```
66
+
67
+ 规则:
68
+
69
+ - `instance.label` 必填;`placeholder` / `hint` / `help` 可选。`help` 用于在地址弹窗里提供获取地址的官方指引(`{ url, label, hint? }`,url 必须是 https)。
70
+ - 带 `instance` 时禁止设置 `server.url`;完整地址由用户填写。
71
+ - 用户填写的地址在运行时校验:允许 http/https 与内网,允许 query(用于 `?key=...` 这类地址),拒绝账号密码与锚点;界面会对 http 显示明文提示。
72
+ - 地址按用户输入原样保存,不再自动追加路径;provider 的 placeholder / hint 要写清完整端点示例。
73
+ - `auth` 四类均可:`none` 保存地址后直接连接;`bearer` / `header` 保存地址后弹出独立令牌弹窗;`oauth2` 要求实例支持 DCR,保存地址后发起授权。
74
+ - 带 `instance` 的 provider 加号会先写入一条无 URL 的安装记录,再打开独立地址弹窗;详情只显示提示与「配置」按钮。
75
+ - 已配置地址后 `instanceReady=true`;「更换地址」会断开旧连接、清除旧凭据并更新 URL,需要重新配置或授权。未配置时关闭弹窗仍保持安装,可再次打开继续填写。
76
+
77
+ ### 预置地址(instance.presets)
78
+
79
+ 如果地址是一组固定端点(企查查按数据域拆了 10 个 MCP 服务),用 `presets` 把弹窗从手填改成下拉选择:
80
+
81
+ ```json
82
+ {
83
+ "instance": {
84
+ "label": "数据域",
85
+ "noun": "数据域",
86
+ "presets": [
87
+ { "label": "工商信息", "url": "https://example.com/mcp/company/stream" },
88
+ { "label": "风险信息", "url": "https://example.com/mcp/risk/stream" }
89
+ ]
90
+ }
91
+ }
92
+ ```
93
+
94
+ - `presets` 每项必填 `label` / `url`,`url` 必须是 https;数组不能为空。
95
+ - 有 `presets` 时用户只能从列表选择,不再手填地址,也不再显示 http 风险提示。
96
+ - `noun` 只影响界面措辞:卡片和详情的「更换地址」会变成「更换数据域」,详情提示改成「选择数据域」;不填时仍说「地址」。
97
+ - 每个预置仍是一个独立的 MCP 端点,切换后会断开当前连接、清除旧凭据并需要重新连接,界面上要写清这一点。
98
+
99
+ ## 传输
100
+
101
+ - `server.transport` 支持 `streamable-http` 与旧版 `sse`。`sse` 地址同样必须是 https,由插件内置的 stdio 桥转接到 `@deepseek-ai/dsh-mcp-client`,provider 不需要额外代码。
102
+
103
+ ## Auth 类型
104
+
105
+ | type | 适用场景 | 关键字段 |
106
+ | --- | --- | --- |
107
+ | `none` | 公开 MCP,无需凭据 | — |
108
+ | `bearer` | `Authorization: Bearer <token>` | `label`,可选 `help` |
109
+ | `header` | 自定义请求头,如 `X-API-Key` | `header`、`prefix`(可选)、`label`、`help` |
110
+ | `oauth2` | OAuth 2.0 Authorization Code + PKCE | `flow: "pkce"`、`registration`、可选 `scopes` / `clientName` |
111
+
112
+ OAuth 的 `registration`:
113
+
114
+ - `"dcr"`:服务端支持动态客户端注册(优先)。
115
+ - `{ "clientId": "..." }`:厂商提供公开客户端 ID,不要求 client secret。
116
+ - `"user"`:用户在面板里填写 AppKey / SecretKey。provider 要声明 `endpoints`,可选 `authorizeParams`、`tokenMethod`、`pkce`;用于不支持 DCR、由用户自建应用的服务。
117
+
118
+ 服务端提供标准 OAuth 元数据时,发现过程由宿主完成,provider 声明 `registration` 与 `scopes` 即可;`user` 模式直接使用 provider 的 `endpoints`。
119
+
120
+ 1. 先向 MCP 端点发送一个未授权的 `initialize`,从 401 的 `WWW-Authenticate` 里读取 `resource_metadata` 地址(RFC 9728,优先);
121
+ 2. 没有该头时依次尝试 `{origin}/.well-known/oauth-protected-resource{path}` 与 `{resource}/.well-known/oauth-protected-resource` 两种拼法;
122
+ 3. 从资源元数据的 `authorization_servers[0]` 取 issuer,再读 `{issuer}/.well-known/oauth-authorization-server`;
123
+ 4. `scopes` 以 provider 声明为准,未声明才用资源元数据的第一个;
124
+ 5. 授权请求、换 token 和刷新 token 都会带上资源元数据里的 `resource`(RFC 8707)。天眼查会强校验它必须等于 MCP 端点,其他服务忽略即可。
125
+
126
+ 当前不支持 device code 和 mTLS;自定义连接器也没有多字段凭据表单。只支持 API Key 的服务用 `bearer` / `header`;同时支持 OAuth 与 API Key 的服务,内置卡片走 OAuth,Key 用法交给自定义连接器的 `headers`。
127
+
128
+ ## 凭据帮助链接
129
+
130
+ token 类 provider 建议提供 `help`:
131
+
132
+ ```json
133
+ "help": {
134
+ "url": "https://vendor.example/tokens",
135
+ "label": "创建 API Key",
136
+ "hint": "在 Settings → API 创建;令牌只保存在本机。"
137
+ }
138
+ ```
139
+
140
+ UI 会在授权表单里展示该链接与提示。链接必须是厂商官方的凭据创建页。
141
+
142
+ ## 示例与文案
143
+
144
+ - `summary`:卡片上的一句话,≤ 1 行。
145
+ - `description`:详情弹窗里的 1–2 句说明。
146
+ - `examples`:1–6 条可直接发给 Agent 的提示词;不要写「点这里」这类操作说明。
147
+ - `category`:只能是 `开发工具 / 项目管理 / 数据库 / 知识检索 / 办公协作 / 安全运维 / 数据分析 / 其他`。
148
+
149
+ ## 验证清单
150
+
151
+ - [ ] `npm run check` 通过
152
+ - [ ] 目录里有 `provider.json`,`id` 与目录名一致
153
+ - [ ] 地址是厂商官方 `https://` MCP 端点,且已在浏览器/文档中确认
154
+ - [ ] 使用真实凭据安装、连接成功,记录工具数量
155
+ - [ ] 凭据只保存在宿主侧,`provider.json` 中没有密钥
156
+ - [ ] 示例提示词可执行,不包含内部项目名或个人信息
157
+ - [ ] 图标(如有)为品牌官方素材,无外部脚本/引用
158
+ - [ ] PR 描述包含厂商 MCP 文档链接与实测工具数
159
+
160
+ ## 发布与兼容
161
+
162
+ - `schemaVersion` 当前固定为 `1`;新增能力会通过向后兼容的可选字段扩展。
163
+ - 删除或重命名 provider id 会被视为破坏性变更,需要单独讨论。
164
+ - 校验与目录加载逻辑在 `src/host/providers.ts`,契约在 `schema/provider.schema.json`。
165
+
166
+ ## 发布
167
+
168
+ 1. 修改 `package.json` 的 `version`,提交到 `main`。
169
+ 2. 打同名 tag(`vX.Y.Z`)并推送到 GitHub。
170
+ 3. 在 GitHub 创建该 tag 的 Release。`publish-npm.yml` 会跑 `npm run check`,然后发布到 npm(Trusted Publishing + provenance)。
171
+ 4. 首次发布需要先在本地执行一次 `npm login --registry=https://registry.npmjs.org` 和 `npm publish --access public` 创建包,再到 npm 包设置里配置 Trusted Publishing:organization `double-coding-lab`、repository `dsh-connectors`、workflow `publish-npm.yml`。
172
+
173
+ 只 push 不会发 npm;必须是 Release published。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-connectors contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md ADDED
@@ -0,0 +1,156 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/double-coding-lab/dsh-connectors/main/assets/readme/hero-en.svg" width="100%" alt="dsh-connectors: an MCP and CLI connector panel for DeepSeek Harness">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="./README.md">简体中文</a> · <strong>English</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/@double-coding/dsh-connectors"><img alt="npm" src="https://img.shields.io/npm/v/@double-coding/dsh-connectors"></a>
11
+ <a href="https://github.com/double-coding-lab/dsh-connectors"><img alt="GitHub" src="https://img.shields.io/github/stars/double-coding-lab/dsh-connectors?style=flat"></a>
12
+ <img alt="MIT" src="https://img.shields.io/badge/license-MIT-111827">
13
+ <img alt="DeepSeek Harness 0.2" src="https://img.shields.io/badge/DSH-0.2.1%20rc-1F8A5B">
14
+ </p>
15
+
16
+ dsh-connectors is the **Connectors** panel for DeepSeek Harness. It includes 27 MCP connectors and 6 CLI connectors (DingTalk, Feishu, Tencent Meeting, WeCom, Hugging Face, Agent Mail). OAuth runs in your browser, credentials stay on your machine, and connected tools show up in your conversations.
17
+
18
+ ## Architecture
19
+
20
+ <p align="center">
21
+ <img src="https://raw.githubusercontent.com/double-coding-lab/dsh-connectors/main/assets/readme/architecture.webp" width="100%" alt="dsh-connectors architecture: panel, plugin host, DSH runtime, and external services">
22
+ </p>
23
+
24
+ - The panel talks to the plugin host over `/dsh-connectors/api/*`; no token is kept in the browser.
25
+ - The host writes each connection as a `dsh-mcp-client` loader entry, so DSH owns the connection, tool registration, and reconnects.
26
+ - Three external paths: MCP over Streamable HTTP, legacy MCP over the SSE bridge, and CLI + Skills. OAuth runs in the system browser and returns to a host callback.
27
+
28
+ ## UI and demo
29
+
30
+ ![Connector panel](https://raw.githubusercontent.com/double-coding-lab/dsh-connectors/main/assets/readme/panel.webp)
31
+
32
+ Browse by category or search, then click the plus button on a card to install.
33
+
34
+ ## What it does
35
+
36
+ - **OAuth in your browser**: DCR + PKCE with automatic token refresh, including self-hosted GitLab and services that need a user-supplied endpoint.
37
+ - **Tokens and custom endpoints**: API-key services use a token dialog; self-hosted services take a full MCP URL that stays on your machine.
38
+ - **CLI login and updates in the panel**: DingTalk, Feishu, Tencent Meeting, WeCom, Hugging Face, and Agent Mail run through their official CLIs; install, login, update, and uninstall all happen in the panel.
39
+ - **SSE-only servers work too**: a built-in stdio bridge adapts them for `dsh-mcp-client`; Baidu Netdisk uses this path.
40
+ - **Custom `mcpServers`**: paste standard JSON for Streamable HTTP, SSE, or stdio; private or localhost URLs require explicit confirmation.
41
+ - **A provider is a data file**: adding a connector means adding a `provider.json`; no core code changes and no per-vendor branches.
42
+ - **Credentials stay on the machine**: connection records, tokens, and OAuth client data live on the host, are never returned by the API, and are redacted from logs.
43
+
44
+ ## Built-in catalog
45
+
46
+ The plugin ships 27 MCP providers and 6 CLI connectors. The category table covers MCP only; CLI connectors are listed separately and custom connectors are not counted.
47
+
48
+ | Category | Connectors |
49
+ | --- | --- |
50
+ | Developer tools (9) | GitHub, GitLab, self-hosted GitLab, Gitee, Postman, CircleCI, Yunxiao, Sourcegraph, Cloudflare Docs |
51
+ | Search & knowledge (7) | Context7, Microsoft Learn, DeepWiki, Firecrawl, Tavily, Tencent Yuanbao Search, Amap |
52
+ | Productivity (3) | Notion, Tencent Docs, Baidu Netdisk |
53
+ | Analytics (3) | PostHog, Tianyancha, QCC |
54
+ | Security & ops (2) | Sentry, Grafana |
55
+ | Databases (2) | Neon, Supabase |
56
+ | Project management (1) | Linear |
57
+ | CLI (6) | DingTalk, Feishu, Tencent Meeting, WeCom, Hugging Face, Agent Mail |
58
+
59
+ | Auth method | Count | How it works | Examples |
60
+ | --- | --- | --- | --- |
61
+ | OAuth 2.0 (DCR + PKCE) | 16 | Browser authorization with automatic token refresh | GitLab, Notion, Firecrawl, Tencent Docs |
62
+ | API key / token | 6 | Paste a key in the token dialog; sent as a Bearer header | GitHub, Grafana, Baidu Netdisk |
63
+ | No credentials | 5 | The card asks for no credential; connect directly after install | Context7, Microsoft Learn, DeepWiki |
64
+ | CLI + Skills | 6 | Runs the vendor CLI; login, update, and uninstall in the panel; no remote MCP server | DingTalk, Feishu, Hugging Face |
65
+
66
+ ## Install
67
+
68
+ Requirements: Node `^22.19.0 || >=24.0.0`, DeepSeek Harness `>=0.2.0-rc.2 <0.3.0`.
69
+
70
+ ### DSH Desktop
71
+
72
+ Open **Settings → Plugins** or **Add plugin**, enter the package name `@double-coding/dsh-connectors` (a GitHub repo URL or a local directory also works), and install it from the dialog.
73
+
74
+ The Desktop app manages its own profile. A terminal install into `web` or another profile will not show up in Desktop. Fully quit and restart Desktop after installation.
75
+
76
+ ### dsh web
77
+
78
+ ```bash
79
+ dsh plugin --profile web add @double-coding/dsh-connectors
80
+ ```
81
+
82
+ `web` is the default web profile. If you use a custom profile, replace `web` with the name your host actually loads:
83
+
84
+ ```bash
85
+ dsh plugin --profile <profile> add @double-coding/dsh-connectors
86
+ ```
87
+
88
+ Stop the running `dsh web` process and start it again; refreshing the page alone does not load the host plugin.
89
+
90
+ <details>
91
+ <summary>Install from source</summary>
92
+
93
+ ```bash
94
+ npm install
95
+ npm run build
96
+ dsh plugin --profile <profile> add link:.
97
+ ```
98
+
99
+ Use your actual profile name, then restart as described above.
100
+
101
+ </details>
102
+
103
+ ### Open the panel
104
+
105
+ After the restart, **Connectors** appears in the sidebar. Pick a connector and click the plus button on its card; follow the browser or token prompt to finish.
106
+
107
+ ## Add a provider
108
+
109
+ Built-in providers are pure data: `providers/<id>/provider.json`, plus an optional icon (`icon.svg`, `icon.png`, or `icon.webp`).
110
+
111
+ ```bash
112
+ npm run provider:new -- acme --auth bearer --name "Acme"
113
+ ```
114
+
115
+ ```json
116
+ {
117
+ "$schema": "../../schema/provider.schema.json",
118
+ "schemaVersion": 1,
119
+ "id": "acme",
120
+ "name": "Acme",
121
+ "category": "开发工具",
122
+ "summary": "One line describing what this connector does.",
123
+ "examples": ["Use Acme to check the latest build"],
124
+ "server": {
125
+ "serverName": "acme",
126
+ "transport": "streamable-http",
127
+ "url": "https://mcp.example.com/mcp"
128
+ },
129
+ "auth": { "type": "bearer", "label": "Acme API Key" }
130
+ }
131
+ ```
132
+
133
+ `category` uses the fixed identifiers defined by the schema (`开发工具` means Developer tools).
134
+
135
+ Then run:
136
+
137
+ ```bash
138
+ npm run check
139
+ ```
140
+
141
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) (Chinese) and [provider.schema.json](./schema/provider.schema.json) for the contract, auth types, OAuth registration, and the PR checklist. Providers cannot contain executable code; use the in-app **Custom connector** for local stdio or private endpoints.
142
+
143
+ ## Security and limits
144
+
145
+ - Single-user and local: no backend, no telemetry; records and credentials stay on the machine.
146
+ - Tokens and OAuth refresh credentials are used only on the host, are not returned by the API, and are redacted from error logs.
147
+ - Authorization scopes, quotas, and terms of third-party services belong to those vendors; the catalog only declares endpoints and auth methods.
148
+ - The SSE bridge forwards tool calls only; for example, Baidu Netdisk's SSE mode does not include local uploads.
149
+
150
+ ## Contributing
151
+
152
+ Open a PR for a new official MCP provider, a fix, or a docs change. Read [CONTRIBUTING.md](./CONTRIBUTING.md) before adding a provider.
153
+
154
+ ## License
155
+
156
+ [MIT](./LICENSE)
package/README.md CHANGED
@@ -1,3 +1,154 @@
1
- # Temporary Holding Version
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/double-coding-lab/dsh-connectors/main/assets/readme/hero.svg" width="100%" alt="dsh-connectors:DeepSeek Harness 的 MCP 与 CLI 连接器面板">
3
+ </p>
2
4
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
5
+ <p align="center">
6
+ <strong>简体中文</strong> · <a href="./README.en.md">English</a>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/@double-coding/dsh-connectors"><img alt="npm" src="https://img.shields.io/npm/v/@double-coding/dsh-connectors"></a>
11
+ <a href="https://github.com/double-coding-lab/dsh-connectors"><img alt="GitHub" src="https://img.shields.io/github/stars/double-coding-lab/dsh-connectors?style=flat"></a>
12
+ <img alt="MIT" src="https://img.shields.io/badge/license-MIT-111827">
13
+ <img alt="DeepSeek Harness 0.2" src="https://img.shields.io/badge/DSH-0.2.1%20rc-1F8A5B">
14
+ </p>
15
+
16
+ dsh-connectors 是 DeepSeek Harness 的「连接器」面板。内置 27 个 MCP 连接器和 6 个 CLI 连接器(钉钉、飞书、腾讯会议、企业微信、Hugging Face、Agent Mail)。OAuth 在浏览器里完成,凭据只保存在本机;连上后就能在对话里调用这些工具。
17
+
18
+ ## 架构
19
+
20
+ <p align="center">
21
+ <img src="https://raw.githubusercontent.com/double-coding-lab/dsh-connectors/main/assets/readme/architecture.webp" width="100%" alt="dsh-connectors 架构:面板、插件宿主、DSH 运行时与外部服务">
22
+ </p>
23
+
24
+ - 面板通过 `/dsh-connectors/api/*` 调插件宿主,不在浏览器里保存任何令牌。
25
+ - 插件宿主把连接配置写成 `dsh-mcp-client` 的 loader 条目,由 DSH 负责连接、注册工具与断线恢复。
26
+ - 三种外部通道:MCP(Streamable HTTP)、旧版 MCP(SSE 桥)、CLI + Skills;OAuth 授权在系统浏览器完成,回调由宿主接收。
27
+
28
+ ## 界面与演示
29
+
30
+ ![连接器面板](https://raw.githubusercontent.com/double-coding-lab/dsh-connectors/main/assets/readme/panel.webp)
31
+
32
+ 按分类浏览、搜索,点卡片右下角的加号安装。
33
+
34
+ ## 主要能力
35
+
36
+ - **OAuth 在浏览器里完成**:DCR + PKCE,令牌过期前自动刷新;也支持 GitLab 自建、企查查数据域这类需要填写地址的服务。
37
+ - **Token 和自定义地址**:需要 API Key 的服务用独立令牌弹窗;自建服务填写完整的 MCP 地址,地址只保存在本机。
38
+ - **CLI 连接的登录和更新也在面板里**:钉钉、飞书、腾讯会议、企业微信、Hugging Face、Agent Mail 通过官方 CLI 工作;安装、登录、更新、卸载都在面板里完成。
39
+ - **SSE 服务也能接入**:插件内置 stdio 桥,把只提供 SSE 的 MCP Server 转接给 `dsh-mcp-client`;百度网盘用的就是这种方式。
40
+ - **自定义 `mcpServers`**:粘贴标准 JSON,支持 Streamable HTTP、SSE 与 stdio;内网 / localhost 地址需要二次确认。
41
+ - **Provider 只包含数据**:新增连接器就是加一个 `provider.json`,不用改核心代码,也没有厂商分支。
42
+ - **凭据留在本机**:连接记录、令牌和 OAuth 客户端信息由宿主保管,接口不回传,日志脱敏。
43
+
44
+ ## 内置连接器目录
45
+
46
+ 插件内置 27 个 MCP provider 和 6 个 CLI 连接器。下面的分类表只统计 MCP;CLI 单独一行,自定义连接器不计入。
47
+
48
+ | 分类 | 连接器 |
49
+ | --- | --- |
50
+ | 开发工具(9) | GitHub、GitLab、GitLab 自建、Gitee、Postman、CircleCI、云效、Sourcegraph、Cloudflare Docs |
51
+ | 知识检索(7) | Context7、Microsoft Learn、DeepWiki、Firecrawl、Tavily、腾讯元宝搜索、高德地图 |
52
+ | 办公协作(3) | Notion、腾讯文档、百度网盘 |
53
+ | 数据分析(3) | PostHog、天眼查、企查查 |
54
+ | 安全运维(2) | Sentry、Grafana |
55
+ | 数据库(2) | Neon、Supabase |
56
+ | 项目管理(1) | Linear |
57
+ | CLI(6) | 钉钉、飞书、腾讯会议、企业微信、Hugging Face、Agent Mail |
58
+
59
+ | 认证方式 | 数量 | 工作方式 | 代表连接器 |
60
+ | --- | --- | --- | --- |
61
+ | OAuth 2.0(DCR + PKCE) | 16 | 浏览器授权,令牌过期前自动刷新 | GitLab、Notion、Firecrawl、腾讯文档 |
62
+ | API Key / Token | 6 | 在令牌弹窗粘贴 Key,按 Bearer 头发送 | GitHub、Grafana、百度网盘 |
63
+ | 无需凭据 | 5 | 卡片不要求凭据,安装后直接连接 | Context7、Microsoft Learn、DeepWiki |
64
+ | CLI + Skills | 6 | 调用厂商 CLI;登录、更新、卸载在面板里,不走远程 MCP | 钉钉、飞书、Hugging Face |
65
+
66
+ ## 安装
67
+
68
+ 要求:Node `^22.19.0 || >=24.0.0`,DeepSeek Harness `>=0.2.0-rc.2 <0.3.0`。
69
+
70
+ ### DSH Desktop
71
+
72
+ 打开「设置 → 插件」或插件页的「添加插件」,输入包名 `@double-coding/dsh-connectors`(也支持 GitHub 仓库地址或本地目录),按提示安装。
73
+
74
+ Desktop 的 profile 由应用管理。从终端装到 `web` 等其它 profile 不会出现在 Desktop 里;安装完成后完全退出并重新启动 Desktop。
75
+
76
+ ### dsh web
77
+
78
+ ```bash
79
+ dsh plugin --profile web add @double-coding/dsh-connectors
80
+ ```
81
+
82
+ `web` 是默认的 Web profile。如果你自定义过 profile,把 `web` 换成宿主实际加载的名称:
83
+
84
+ ```bash
85
+ dsh plugin --profile <profile> add @double-coding/dsh-connectors
86
+ ```
87
+
88
+ 装完先停掉原来的 `dsh web` 进程再启动;只刷新网页不会加载后端插件。
89
+
90
+ <details>
91
+ <summary>从源码安装</summary>
92
+
93
+ ```bash
94
+ npm install
95
+ npm run build
96
+ dsh plugin --profile <profile> add link:.
97
+ ```
98
+
99
+ `<profile>` 同样换成实际 profile;装完按上面的方式重启。
100
+
101
+ </details>
102
+
103
+ ### 打开面板
104
+
105
+ 重启后侧栏出现「连接器」。选一个连接器,点卡片右下角的加号,按提示完成授权或粘贴令牌。
106
+
107
+ ## 添加内置 Provider
108
+
109
+ 内置 provider 是纯数据,放在 `providers/<id>/provider.json`,图标可选(`icon.svg` / `icon.png` / `icon.webp`)。
110
+
111
+ ```bash
112
+ npm run provider:new -- acme --auth bearer --name "Acme"
113
+ ```
114
+
115
+ ```json
116
+ {
117
+ "$schema": "../../schema/provider.schema.json",
118
+ "schemaVersion": 1,
119
+ "id": "acme",
120
+ "name": "Acme",
121
+ "category": "开发工具",
122
+ "summary": "一句话说明这个连接器能做什么。",
123
+ "examples": ["用 Acme 查一下最近的构建"],
124
+ "server": {
125
+ "serverName": "acme",
126
+ "transport": "streamable-http",
127
+ "url": "https://mcp.example.com/mcp"
128
+ },
129
+ "auth": { "type": "bearer", "label": "Acme API Key" }
130
+ }
131
+ ```
132
+
133
+ 编辑完成后运行:
134
+
135
+ ```bash
136
+ npm run check
137
+ ```
138
+
139
+ 契约校验、auth 类型、OAuth 注册方式和 PR 检查清单见 [CONTRIBUTING.md](./CONTRIBUTING.md) 与 [provider.schema.json](./schema/provider.schema.json)。provider 不允许携带可执行代码;确需本地 stdio 或内网地址时,用面板里的「自定义连接器」。
140
+
141
+ ## 安全与边界
142
+
143
+ - 单用户、本机运行:没有后端、没有遥测,连接记录与凭据只存在本机。
144
+ - 令牌与 OAuth 刷新凭据只在宿主侧使用,接口不回传,错误日志会脱敏。
145
+ - 第三方服务的授权范围、配额与条款由对应厂商负责;内置目录只声明地址与认证方式。
146
+ - SSE 桥只转接工具调用;例如百度网盘的 SSE 模式不包含本地上传。
147
+
148
+ ## 参与贡献
149
+
150
+ 新增官方 MCP provider、修 bug 或改文档,都可以提 PR。加 provider 前先读 [CONTRIBUTING.md](./CONTRIBUTING.md)。
151
+
152
+ ## License
153
+
154
+ [MIT](./LICENSE)
Binary file
@@ -0,0 +1,62 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="420" viewBox="0 0 1200 420" role="img" aria-labelledby="hero-title hero-desc">
2
+ <title id="hero-title">dsh-connectors — DeepSeek Harness 连接器面板</title>
3
+ <desc id="hero-desc">Manage MCP and CLI connectors from the DeepSeek Harness sidebar.</desc>
4
+
5
+ <rect width="1200" height="420" rx="26" fill="#0B0D10"/>
6
+
7
+ <g id="title-block">
8
+ <text x="64" y="86" fill="#7F8996" font-size="15" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" letter-spacing="2">DEEPSEEK HARNESS · CONNECTOR PLUGIN</text>
9
+ <text x="64" y="166" fill="#F7F8FA" font-size="58" font-weight="700" letter-spacing="-1">dsh-connectors</text>
10
+ <text x="64" y="224" fill="#C9D0D9" font-size="24">MCP and CLI connectors for DeepSeek Harness</text>
11
+ <line x1="64" y1="312" x2="628" y2="312" stroke="#242A32" stroke-width="1"/>
12
+ <text x="64" y="340" fill="#6F7884" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, monospace">streamable-http · sse · cli + skills · mcpServers</text>
13
+ </g>
14
+
15
+ <g id="panel-proof">
16
+ <rect x="672" y="56" width="464" height="308" rx="22" fill="#11151A" stroke="#262C34"/>
17
+ <text x="700" y="94" fill="#F4F6F8" font-size="20" font-weight="600">Connectors</text>
18
+ <circle cx="1096" cy="84" r="14" fill="#FFFFFF"/>
19
+ <path d="M1096 78v12M1090 84h12" stroke="#11151A" stroke-width="1.6" stroke-linecap="round"/>
20
+ <rect x="700" y="110" width="408" height="32" rx="9" fill="#0C1014" stroke="#242A32"/>
21
+ <circle cx="716" cy="126" r="5" fill="none" stroke="#6F7884" stroke-width="1.4"/>
22
+ <line x1="720" y1="130" x2="724" y2="134" stroke="#6F7884" stroke-width="1.4" stroke-linecap="round"/>
23
+ <text x="734" y="131" fill="#79828E" font-size="14">Search connectors</text>
24
+
25
+ <g id="row-0">
26
+ <rect x="690" y="160" width="408" height="44" rx="10" fill="#0E1217"/>
27
+ <rect x="700" y="166" width="32" height="32" rx="9" fill="#FFFFFF"/>
28
+ <image x="706" y="172" width="20" height="20" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cGF0aCBmaWxsPSIjMTgxNzE3IiBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+Cg=="/>
29
+ <text x="744" y="188" fill="#F4F6F8" font-size="18" font-weight="600">GitHub</text>
30
+ <rect x="998" y="172" width="72" height="20" rx="10" fill="#161C23" stroke="#2A313A"/>
31
+ <text x="1034" y="186" fill="#A7B0BC" font-size="16" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" text-anchor="middle">OAuth</text>
32
+ <circle cx="1084" cy="182" r="4" fill="#3DDC97"/>
33
+ </g>
34
+ <g id="row-1">
35
+ <rect x="690" y="212" width="408" height="44" rx="10" fill="#0E1217"/>
36
+ <rect x="700" y="218" width="32" height="32" rx="9" fill="#FFFFFF"/>
37
+ <image x="706" y="224" width="20" height="20" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFnUlEQVR42u2XeWwUVRzHX5RDSBFqWo5ylBZru7NHry1GlHiBQrmKQAul21a6M7vdtggiAQmGEoE/1KhRkwJGawKCGENCkHgQoBhjuQSNRkwpxnB5QJB23nszs9fXzMz2gE53+YNE/+Aln8xm5+287/zm9/3OWwKA/JeQuwKcEu+DQ+KVgsguCiI7Lois1Qq7xFqdPtb6wALamraEtrr8fee4yumJ9Eblt+R90eqsV4IkaX+YDN8TJRmbQVJ2hWICRK0Pgsj3CiKFILJ+sXkZMqsZVm5TUdTAkTSPwuW/eU7+fBnj3lRBOoGkg5GXk3eHSPKuKMnY0kuAXeJ9EER2Nt7iOplVDOOWUly6FkUHiyKzimJgMYXTx2CXYgJKZKQ2B0E4QP4EBpyObB+5NUKy1oOk7I4JEGr5Tdhr+RhBZFoiAWnlFAV1DP/IUejjj+tRTG5gIM/KxnlHDYNrMUXSwTCIDJBLALkGDDqB/ePeARn1UUxAni/UTb4vTJw+dbotQfl1RjxHMa+Ro/dQg8CcDQrINBk5lRSuSor7jkVAKEAuAOQiQDqAe9twZsRnwVRDQIEv3I3bHyFOSfVnVlNkVJpltiKjihmLrGhSYTWkt1WQp2Vkehiy13BkbFCQub6H9M0KMtcqWwwBNol1kyMy4vSzpsI6hvEV1Cjz+KW3UEGNZ0+mdeLdfUH0Nzbu1ECekTGxhMJdSpG3qIfchTLyqpTymA2VbgSvQlJL2aHXPtWgaFGcaY/gZFsE35/r4bR+bIvg2NkIbtAo4o33vwji3pkyUstucYiXwuHnuYYAl6j1IKlDx5bTKwUBhvbLEdyJceB4CMNKZNw/v5cIiV2212qDzQpUaiaeIHF6tRxXwGywkaUUP5y/MyJOtYUxtpxi8GzTpoLEvhMCmukCx0bFZJNC7Mv5QuF5ZihNKqGYUEFx7g5V4npnFNPXcoxYIMMpKU35YjCWhNuCxLk9SFzNIeJ4SVln85gW1EUMmWN+Pn/FFKF7XudqRxSd3HohvSv03tAX1Ofqx65eufB3BI+vZkhbzFe6vLEcKPSoxO1RSWGFSuzL2B6b1NMsuojUUoqMKorHXmRG0LjrGUYvpth1JGQp4GRbGNnLKHL95nydonoG3VlzN3A8uZojW2RP5TUwU8CUWo08WquRKQGNOCR2Jsd7c+A4JIZ0D8OoMooxSyhSFlHcM0NGy49hSwE7DgVBnujsnt8b/btJVSzqqmMZufWsK4oVIgQUYvPz0YLIWKIEHLvU7GY9eq1G404Ng2fL1i8w0XhP/Ko//zxvrAdyG0Ik74UwcdZpD9u8LGEEJy+gKF7P+222ytcVDJ0bN8oPOGtU4qpRTQGuBm5g93HxdgTojVn3nnUEKxowdRXHyDJrATlevXrKpqLlQVLYELOhe41q4AzwN2zLEgsYUCzjrb3WEdx+JYJJ1QwTK1k/AhicPl5VVK8Sd12sAoJPJYKk6nuArxMtnl3DjETb32rtgC9PhYwQeyjOjdglLd8mBolNjFXAVh8kQp1G7BJrF7yJNyETPBS/XLAOp6bPgxhYLMe7RofDp6U4/CHi8Mea0F2rkFwfz8q5jeev2+iRFRwyt3bAiq0qhsyR49w9a3X6FdKFIWBqQ4i4a9UZ2TWJNyHDSijKtij9OqCkUcHw+XGuI7Edgo+TLsweMPaAfE2ixXV0f69r1iwXv3ojivyAuVWzzgAKl6SuKpQipEAKG5g5EFCSHT7+YSIL6ucHzZLR/JW1A/S9Q9oSarjA0gGmgJLJUoS4pbCB2YQinymI7Fyiu3+w2uyBb3+2juBPWkJImicjpyaOA3wsS/BR0oW5LRe52y7xZrvEf7JL/HB/pHv4YUHkR37/K/oNgJZwxCQaRQuAo69+rB0dNIse6uf3+rU/cPk46c3d/4b/CwH/Ak8c/zLL6A8WAAAAAElFTkSuQmCC"/>
38
+ <text x="744" y="240" fill="#F4F6F8" font-size="18" font-weight="600">Tencent Docs</text>
39
+ <rect x="998" y="224" width="72" height="20" rx="10" fill="#161C23" stroke="#2A313A"/>
40
+ <text x="1034" y="238" fill="#A7B0BC" font-size="16" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" text-anchor="middle">OAuth</text>
41
+ <circle cx="1084" cy="234" r="4" fill="#3DDC97"/>
42
+ </g>
43
+ <g id="row-2">
44
+ <rect x="690" y="264" width="408" height="44" rx="10" fill="#0E1217"/>
45
+ <rect x="700" y="270" width="32" height="32" rx="9" fill="#FFFFFF"/>
46
+ <image x="706" y="276" width="20" height="20" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFeElEQVR4nMWXa2wUVRTHfzO73dnulm3pAsVCreXdolQeMXwQHwGaCEYggYgxxEcMJggJCWiMX/yAkhASgyY+MOAjmPgFEImNVj4o8lKB2kfsoiCs5dHti213O7s7Mztzze1W+8bFB/yTyWTmnnv//3vuuefeozAA9XX1gcJg4Xq/37/E4/Hc5XK5JiqKovIvIIRwbNuOmKYZ1nW9JhqN7p0zZ05smGEoFFqeSCTaxP8MydHU1LR8EHl9ff0Sx3HErYLkamhoWNJLfvbs2TzDMFLiFkNy1p6tzVOLiorWezwejVsMyRkcF9zo9vl8K//JALoDYQNsB0o0GOu++TECgcCjbk3TSm6mU2cadrXC8W6IGGBY4BewIA9emQLTc7Mfy+PxFCupVCqmadqYbDr8nISnw3AlBbkOdBlgWuB2BN1J8ChwaIHCI+OzE2AYRlwK6NE0zZ/NzJedh5gNtgUBFRb6QdhwtENwPg52GmxTIVQFs/KyEqAjPZBN1G7qFoJmIcoahVgVEuJisr/takqIZacdwWEh+FKI8vrsdoLkzirLXQUSoTZeOFOHdNXu6VDm7W8v1qB6gUJhHiyrPYP/u0vUimxGhqw80NnVLfQXXxVi1Wpx7otvR7X76cAJIUoeFGblWnH5l+b/zgOF0S58Rg+MCTKz9fdR7e6NXAJvATlGgsnXWrJygHqjxk/aYWUYVndMwAkUgN8LTZdG73AqBPk+CI6l6kopC3+EN8/9AwEJB544DxsuwjdtcMDrpaZwKthJiHTAzvcgafR3sB2c7XsQoTCQ5OTEGRzJL+KHC7D5GMyrhg5zZAHKSHnguUtwsAPucEMyDZ5xUH61k917tzFBFRA3obgYKmeDUBCnG6H2PIrm5nrLdda9/Aan7plK9ELfFLuhogR+XjZyHogNFPBVN6y7kCHPAbaXwuIx8JsLrFMhZu96C4UUWB6IJsG0IccNehKry6R52xb0tYuYaUNNKzz7PVxPguiCt6tgw/S/EbC5GfZ3Qo6APVNhcf5g1Xt+ukr+voOsicisFIe0jWF62B8oZdbW1cy/v3yQ/ZFWqKrpXRkWlsGpqsEC3EPXpNXKvGfmDieXmDB3EivSm1jU0srsaIQ23eFEzng2rpnMqoLh9kuL4M4gNF+By4nh7e6hP3KUvmVLg+GANiRMg1FQ49BUUsSxyUW9M9tZCVtvkHp1Ga/K8LEkhv2a4QVDQMSCHTIFDsG2MARVgRKVRoL90zLkb4dhSwOkh2TAl+qhU94AbZhTkIUHHi+EvW0gg+KDNui2YWkAdBs+isCZmMADtJiZk2/FBPi6AzYeF6AoHO2EDVMg4ILDLbDvV+lWmXJh6+DwGH0bftwBG36D4hxIpDMnngx2qTZhCVJp+GyuwvJxGfvaGMw/KsBUel2NjCMbcDKupwu23p9ZqoGQQaiOtAxPjYPdUyHXBT125giW7640zPDDt/f1k0vMC8DpBxTuLugjH/BoLnj9oeHkfVBveCG5noaaKPyeApl/ZvngsQHEI+HQNaiLgpGGMj8snwSTRrkl9eYBXdcv+ny+Mm4DEolEWLUs6xq3CaZpXlZjsdjnt0tAT0/PIbW9vf0dy7IGHG23BqZpGpGWyPu9H3V1dX9fmllpIeK6ED2JvkcXjp4QsZQjulOi/0kKYaZvPJTkamxs7C3NlD8VyeK0tLT0w9zc3JEv1Scb4PnXoCgIqgqmju4LUvnwDiJeN/mmrIShJQqfPglrK0aeeTKZbA+Hw89UVFRUy++/MmF5eXl1Y2PjtIKCgvU+n2+Jpmn95bmigGUi5LHrUuXuRXWrJFwKmpMg1/HiFaJXgKzxbFkv9An6szy3LCscj8e/iUaj71ZWVv5Vnv8Bxx3LDavStScAAAAASUVORK5CYII="/>
47
+ <text x="744" y="292" fill="#F4F6F8" font-size="18" font-weight="600">Baidu Netdisk</text>
48
+ <rect x="998" y="276" width="72" height="20" rx="10" fill="#161C23" stroke="#2A313A"/>
49
+ <text x="1034" y="290" fill="#A7B0BC" font-size="16" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" text-anchor="middle">SSE</text>
50
+ <circle cx="1084" cy="286" r="4" fill="#4A525E"/>
51
+ </g>
52
+ <g id="row-3">
53
+ <rect x="690" y="316" width="408" height="44" rx="10" fill="#0E1217"/>
54
+ <rect x="700" y="322" width="32" height="32" rx="9" fill="#FFFFFF"/>
55
+ <image x="706" y="328" width="20" height="20" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NSIgaGVpZ2h0PSI4OCIgZmlsbD0ibm9uZSI+Cgk8cGF0aCBmaWxsPSIjRkZEMjFFIiBkPSJNNDcuMjEgNzYuNWEzNC43NSAzNC43NSAwIDEgMCAwLTY5LjUgMzQuNzUgMzQuNzUgMCAwIDAgMCA2OS41WiIgLz4KCTxwYXRoCgkJZmlsbD0iI0ZGOUQwQiIKCQlkPSJNODEuOTYgNDEuNzVhMzQuNzUgMzQuNzUgMCAxIDAtNjkuNSAwIDM0Ljc1IDM0Ljc1IDAgMCAwIDY5LjUgMFptLTczLjUgMGEzOC43NSAzOC43NSAwIDEgMSA3Ny41IDAgMzguNzUgMzguNzUgMCAwIDEtNzcuNSAwWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiMzQTNCNDUiCgkJZD0iTTU4LjUgMzIuM2MxLjI4LjQ0IDEuNzggMy4wNiAzLjA3IDIuMzhhNSA1IDAgMSAwLTYuNzYtMi4wN2MuNjEgMS4xNSAyLjU1LS43MiAzLjctLjMyWk0zNC45NSAzMi4zYy0xLjI4LjQ0LTEuNzkgMy4wNi0zLjA3IDIuMzhhNSA1IDAgMSAxIDYuNzYtMi4wN2MtLjYxIDEuMTUtMi41Ni0uNzItMy43LS4zMloiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkYzMjNEIgoJCWQ9Ik00Ni45NiA1Ni4yOWM5LjgzIDAgMTMtOC43NiAxMy0xMy4yNiAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzYtMi4zMyAxLjE1LTUuNDYgMi43NC04LjkgMi43NC03LjE5IDAtMTMtNi44OC0xMy0yLjM4czMuMTYgMTMuMjYgMTMgMTMuMjZaIgoJLz4KCTxwYXRoCgkJZmlsbD0iIzNBM0I0NSIKCQlmaWxsLXJ1bGU9ImV2ZW5vZGQiCgkJZD0iTTM5LjQzIDU0YTguNyA4LjcgMCAwIDEgNS4zLTQuNDljLjQtLjEyLjgxLjU3IDEuMjQgMS4yOC40LjY4LjgyIDEuMzcgMS4yNCAxLjM3LjQ1IDAgLjktLjY4IDEuMzMtMS4zNS40NS0uNy44OS0xLjM4IDEuMzItMS4yNWE4LjYxIDguNjEgMCAwIDEgNSA0LjE3YzMuNzMtMi45NCA1LjEtNy43NCA1LjEtMTAuNyAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzZsLS4xNC4wN2MtMi4zMSAxLjE1LTUuMzkgMi42Ny04Ljc3IDIuNjdzLTYuNDUtMS41Mi04Ljc3LTIuNjdjLTIuNi0xLjI5LTQuMjMtMi4xLTQuMjMuMjkgMCAzLjA1IDEuNDYgOC4wNiA1LjQ3IDEwLjk3WiIKCQljbGlwLXJ1bGU9ImV2ZW5vZGQiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkY5RDBCIgoJCWQ9Ik03MC43MSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0yNC4yMSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0xNy41MiA0OGMtMS42MiAwLTMuMDYuNjYtNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMC0xLjMzIDMuNzYgNy4xIDcuMSAwIDAgMC0xLjk0LS4zYy0xLjU1IDAtMi45NS41OS0zLjk0IDEuNjZhNS44IDUuOCAwIDAgMC0uOCA3IDUuMyA1LjMgMCAwIDAtMS43OSAyLjgyYy0uMjQuOS0uNDggMi44LjggNC43NGE1LjIyIDUuMjIgMCAwIDAtLjM3IDUuMDJjMS4wMiAyLjMyIDMuNTcgNC4xNCA4LjUyIDYuMSAzLjA3IDEuMjIgNS44OSAyIDUuOTEgMi4wMWE0NC4zMyA0NC4zMyAwIDAgMCAxMC45MyAxLjZjNS44NiAwIDEwLjA1LTEuOCAxMi40Ni01LjM0IDMuODgtNS42OSAzLjMzLTEwLjktMS43LTE1LjkyLTIuNzctMi43OC00LjYyLTYuODctNS03Ljc3LS43OC0yLjY2LTIuODQtNS42Mi02LjI1LTUuNjJhNS43IDUuNyAwIDAgMC00LjYgMi40NmMtMS0xLjI2LTEuOTgtMi4yNS0yLjg2LTIuODJBNy40IDcuNCAwIDAgMCAxNy41MiA0OFptMCA0Yy41MSAwIDEuMTQuMjIgMS44Mi42NSAyLjE0IDEuMzYgNi4yNSA4LjQzIDcuNzYgMTEuMTguNS45MiAxLjM3IDEuMzEgMi4xNCAxLjMxIDEuNTUgMCAyLjc1LTEuNTMuMTUtMy40OC0zLjkyLTIuOTMtMi41NS03LjcyLS42OC04LjAxLjA4LS4wMi4xNy0uMDIuMjQtLjAyIDEuNyAwIDIuNDUgMi45MyAyLjQ1IDIuOTNzMi4yIDUuNTIgNS45OCA5LjNjMy43NyAzLjc3IDMuOTcgNi44IDEuMjIgMTAuODMtMS44OCAyLjc1LTUuNDcgMy41OC05LjE2IDMuNTgtMy44MSAwLTcuNzMtLjktOS45Mi0xLjQ2LS4xMS0uMDMtMTMuNDUtMy44LTExLjc2LTcgLjI4LS41NC43NS0uNzYgMS4zNC0uNzYgMi4zOCAwIDYuNyAzLjU0IDguNTcgMy41NC40MSAwIC43LS4xNy44My0uNi43OS0yLjg1LTEyLjA2LTQuMDUtMTAuOTgtOC4xNy4yLS43My43MS0xLjAyIDEuNDQtMS4wMiAzLjE0IDAgMTAuMiA1LjUzIDExLjY4IDUuNTMuMTEgMCAuMi0uMDMuMjQtLjEuNzQtMS4yLjMzLTIuMDQtNC45LTUuMi01LjIxLTMuMTYtOC44OC01LjA2LTYuOC03LjMzLjI0LS4yNi41OC0uMzggMS0uMzggMy4xNyAwIDEwLjY2IDYuODIgMTAuNjYgNi44MnMyLjAyIDIuMSAzLjI1IDIuMWMuMjggMCAuNTItLjEuNjgtLjM4Ljg2LTEuNDYtOC4wNi04LjIyLTguNTYtMTEuMDEtLjM0LTEuOS4yNC0yLjg1IDEuMzEtMi44NVoiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkZEMjFFIgoJCWQ9Ik0zOC42IDc2LjY5YzIuNzUtNC4wNCAyLjU1LTcuMDctMS4yMi0xMC44NC0zLjc4LTMuNzctNS45OC05LjMtNS45OC05LjNzLS44Mi0zLjItMi42OS0yLjljLTEuODcuMy0zLjI0IDUuMDguNjggOC4wMSAzLjkxIDIuOTMtLjc4IDQuOTItMi4yOSAyLjE3LTEuNS0yLjc1LTUuNjItOS44Mi03Ljc2LTExLjE4LTIuMTMtMS4zNS0zLjYzLS42LTMuMTMgMi4yLjUgMi43OSA5LjQzIDkuNTUgOC41NiAxMS0uODcgMS40Ny0zLjkzLTEuNzEtMy45My0xLjcxcy05LjU3LTguNzEtMTEuNjYtNi40NGMtMi4wOCAyLjI3IDEuNTkgNC4xNyA2LjggNy4zMyA1LjIzIDMuMTYgNS42NCA0IDQuOSA1LjItLjc1IDEuMi0xMi4yOC04LjUzLTEzLjM2LTQuNC0xLjA4IDQuMTEgMTEuNzcgNS4zIDEwLjk4IDguMTUtLjggMi44NS05LjA2LTUuMzgtMTAuNzQtMi4xOC0xLjcgMy4yMSAxMS42NSA2Ljk4IDExLjc2IDcuMDEgNC4zIDEuMTIgMTUuMjUgMy40OSAxOS4wOC0yLjEyWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiNGRjlEMEIiCgkJZD0iTTc3LjQgNDhjMS42MiAwIDMuMDcuNjYgNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMSAxLjMzIDMuNzYgNy4xIDcuMSAwIDAgMSAxLjk1LS4zYzEuNTUgMCAyLjk1LjU5IDMuOTQgMS42NmE1LjggNS44IDAgMCAxIC44IDcgNS4zIDUuMyAwIDAgMSAxLjc4IDIuODJjLjI0LjkuNDggMi44LS44IDQuNzRhNS4yMiA1LjIyIDAgMCAxIC4zNyA1LjAyYy0xLjAyIDIuMzItMy41NyA0LjE0LTguNTEgNi4xLTMuMDggMS4yMi01LjkgMi01LjkyIDIuMDFhNDQuMzMgNDQuMzMgMCAwIDEtMTAuOTMgMS42Yy01Ljg2IDAtMTAuMDUtMS44LTEyLjQ2LTUuMzQtMy44OC01LjY5LTMuMzMtMTAuOSAxLjctMTUuOTIgMi43OC0yLjc4IDQuNjMtNi44NyA1LjAxLTcuNzcuNzgtMi42NiAyLjgzLTUuNjIgNi4yNC01LjYyYTUuNyA1LjcgMCAwIDEgNC42IDIuNDZjMS0xLjI2IDEuOTgtMi4yNSAyLjg3LTIuODJBNy40IDcuNCAwIDAgMSA3Ny40IDQ4Wm0wIDRjLS41MSAwLTEuMTMuMjItMS44Mi42NS0yLjEzIDEuMzYtNi4yNSA4LjQzLTcuNzYgMTEuMThhMi40MyAyLjQzIDAgMCAxLTIuMTQgMS4zMWMtMS41NCAwLTIuNzUtMS41My0uMTQtMy40OCAzLjkxLTIuOTMgMi41NC03LjcyLjY3LTguMDFhMS41NCAxLjU0IDAgMCAwLS4yNC0uMDJjLTEuNyAwLTIuNDUgMi45My0yLjQ1IDIuOTNzLTIuMiA1LjUyLTUuOTcgOS4zYy0zLjc4IDMuNzctMy45OCA2LjgtMS4yMiAxMC44MyAxLjg3IDIuNzUgNS40NyAzLjU4IDkuMTUgMy41OCAzLjgyIDAgNy43My0uOSA5LjkzLTEuNDYuMS0uMDMgMTMuNDUtMy44IDExLjc2LTctLjI5LS41NC0uNzUtLjc2LTEuMzQtLjc2LTIuMzggMC02LjcxIDMuNTQtOC41NyAzLjU0LS40MiAwLS43MS0uMTctLjgzLS42LS44LTIuODUgMTIuMDUtNC4wNSAxMC45Ny04LjE3LS4xOS0uNzMtLjctMS4wMi0xLjQ0LTEuMDItMy4xNCAwLTEwLjIgNS41My0xMS42OCA1LjUzLS4xIDAtLjE5LS4wMy0uMjMtLjEtLjc0LTEuMi0uMzQtMi4wNCA0Ljg4LTUuMiA1LjIzLTMuMTYgOC45LTUuMDYgNi44LTcuMzMtLjIzLS4yNi0uNTctLjM4LS45OC0uMzgtMy4xOCAwLTEwLjY3IDYuODItMTAuNjcgNi44MnMtMi4wMiAyLjEtMy4yNCAyLjFhLjc0Ljc0IDAgMCAxLS42OC0uMzhjLS44Ny0xLjQ2IDguMDUtOC4yMiA4LjU1LTExLjAxLjM0LTEuOS0uMjQtMi44NS0xLjMxLTIuODVaIgoJLz4KCTxwYXRoCgkJZmlsbD0iI0ZGRDIxRSIKCQlkPSJNNTYuMzMgNzYuNjljLTIuNzUtNC4wNC0yLjU2LTcuMDcgMS4yMi0xMC44NCAzLjc3LTMuNzcgNS45Ny05LjMgNS45Ny05LjNzLjgyLTMuMiAyLjctMi45YzEuODYuMyAzLjIzIDUuMDgtLjY4IDguMDEtMy45MiAyLjkzLjc4IDQuOTIgMi4yOCAyLjE3IDEuNTEtMi43NSA1LjYzLTkuODIgNy43Ni0xMS4xOCAyLjEzLTEuMzUgMy42NC0uNiAzLjEzIDIuMi0uNSAyLjc5LTkuNDIgOS41NS04LjU1IDExIC44NiAxLjQ3IDMuOTItMS43MSAzLjkyLTEuNzFzOS41OC04LjcxIDExLjY2LTYuNDRjMi4wOCAyLjI3LTEuNTggNC4xNy02LjggNy4zMy01LjIzIDMuMTYtNS42MyA0LTQuOSA1LjIuNzUgMS4yIDEyLjI4LTguNTMgMTMuMzYtNC40IDEuMDggNC4xMS0xMS43NiA1LjMtMTAuOTcgOC4xNS44IDIuODUgOS4wNS01LjM4IDEwLjc0LTIuMTggMS42OSAzLjIxLTExLjY1IDYuOTgtMTEuNzYgNy4wMS00LjMxIDEuMTItMTUuMjYgMy40OS0xOS4wOC0yLjEyWiIKCS8+Cjwvc3ZnPgo="/>
56
+ <text x="744" y="344" fill="#F4F6F8" font-size="18" font-weight="600">Hugging Face</text>
57
+ <rect x="998" y="328" width="72" height="20" rx="10" fill="#161C23" stroke="#2A313A"/>
58
+ <text x="1034" y="342" fill="#A7B0BC" font-size="16" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" text-anchor="middle">CLI</text>
59
+ <circle cx="1084" cy="338" r="4" fill="#3DDC97"/>
60
+ </g>
61
+ </g>
62
+ </svg>