DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

nekojackie /

nekojackie/dsh-mcp-manager

Verified

Manage MCP servers inside DeepSeek Harness: enable/disable, OAuth 2.1 authorization, scheduled + after-expiry token renewal, and a tool browser with descriptions. Generated by DeepSeek V4.1 Flash.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@66a17a2b

dsh-mcp-manager

Manage MCP servers from inside DeepSeek Harness (DSH): add / enable / disable / remove / reconnect, authorize them with OAuth 2.1, keep their tokens alive with scheduled and after-expiry renewal, and browse every tool each server exposes — with its description — in one settings page.

本项目由 DeepSeek V4.1 Flash 生成 / This project was generated by DeepSeek V4.1 Flash.

功能 · 安装 · 使用 · OAuth 2.1 · 自动续期 · Agent 工具 · 架构 · 安全 · 测试 · 许可

English summary

A DSH plugin that owns the whole MCP server lifecycle: a Settings page under Settings → Plugins → MCP Servers, six agent-callable tools (mcp_manager_*), a loopback HTTP bridge for the page, and a built-in OAuth 2.1 client (RFC 9728 discovery, RFC 8414/OIDC metadata, RFC 7591 dynamic client registration, authorization code + PKCE S256, RFC 8707 resource, refresh, sign-out, paste-token fallback) with a token renewal policy that is editable in the UI and also self-heals after expiry. Tokens live only in the Harness credential store. Generated by DeepSeek V4.1 Flash; review before production use.


为什么需要它

DSH 官方的 @deepseek-ai/dsh-mcp-client 每个实例只连一个服务器,清单要手写进 cordis.patch.yml;它只支持静态 headers,不做 OAuth;token 过期后也不会续期,连接会 一直带着过期令牌,直到下一次调用 401。这个插件把这三件事补齐,并且不重新实现 MCP 协议—— 它编排真正的 mcp-client 子插件,所以被管理的服务器在 Harness 里就是普通 MCP 工具。

功能

能力 说明
服务器管理 添加 / 编辑 / 启用 / 停用 / 重连 / 移除;stdio(command/args/env/cwd)与 streamable-http(url/headers)都支持
工具浏览 每个服务器展开后列出全部工具:公共名 mcp__<服务器>__<工具>、工具描述、入参名;页面与 agent 都能查
OAuth 2.1 受保护资源发现、授权服务器元数据、动态客户端注册、授权码 + PKCE S256、一次性 state、resource 指示符、刷新、粘贴令牌兜底、退出授权
定时续期 后台按策略检查(默认每 5 分钟),在到期前(默认 10 分钟)自动换令牌并重连;策略可在页面上改
过期后自动续期 已过期的令牌下一轮必续;更关键的是 401 自愈——某次 mcp__* 调用被判未授权时立即换令牌重连,下一次调用恢复正常
失败退避 续期失败按 30s → 60s → 120s …(上限为检查间隔)重试,不会每轮都打授权服务器
如实状态 connected / no-tools / disabled / error / connecting,不猜测"连接成功"
给 agent 的能力 6 个工具:mcp_manager_list / add / remove / set_enabled / tools / oauth
凭证安全 OAuth token 只写进 DSH 凭据库,不进配置、不进日志、不进页面

安装

方式 1:一条命令

git clone https://github.com/nekojackie/dsh-mcp-manager.git
dsh plugin --profile <profile> add /path/to/dsh-mcp-manager
dsh <profile>

dsh plugin add 会在 profile 里装包,并自动把 bundle 写进 dsh.profile.bundles; mcp-manager 这行配置由 bundle 自带的 patch 插入,不用手写 YAML。

  • <profile> 是 ~/.dsh/profiles/<名字> 的名字,桌面版一般是 desktop;
  • dsh 不在 PATH 时用应用目录下的 resources/runtime/cli/bin/dsh (Windows 是 dsh.cmd);
  • 装完在 设置 → 插件 里能看到 MCP Server Manager(行 id mcp-manager,状态 active), 旁边的 MCP 服务器 页签就是本插件的界面。

方式 2:让 DSH 自己装

把下面整段发给 DSH 助手即可,它自己会克隆、安装、重启并汇报:

帮我安装并启用 DSH 插件:https://github.com/nekojackie/dsh-mcp-manager

1. 把仓库克隆到任意目录(例如 ~/.dsh/plugins/dsh-mcp-manager;没有 git 就下载 ZIP 解压);
2. 执行 dsh plugin --profile <当前 profile> add <该目录绝对路径>;
   如果 dsh 命令不可用,改用 plugin_manager 的 install_bundle,target 指向该目录;
3. 重启 DSH,确认「设置 → 插件」里插件行是 active、并出现「MCP 服务器」页签;
4. 用 mcp_manager_list 把当前 MCP 服务器清单贴给我;
5. 不要改动我已有的 MCP 服务器配置。

这是 AI 生成的插件,OAuth token 会写进 DSH 凭据库,安装前可以先看一眼下面的「安全说明」。

使用

设置界面

设置 → 插件 → MCP 服务器(与 "全部" 页签并列):

  • 每张卡片:名称、传输方式、命令或 URL、状态点、工具数、启用开关、刷新 / 重连 / 编辑 / 移除;
  • 展开卡片:该服务器的每个工具 + 描述 + 入参;
  • 自动续期设置(可折叠):启用开关、检查间隔(秒)、提前续期(秒)、"过期后仍自动续期"、保存 / 恢复默认;
  • 授权成功后卡片会自己跟上:已授权 → 正在连接… → 工具数量,不需要手点刷新。

直接改配置

清单与续期策略都保存在本插件这一行的 config 里:

- id: mcp-manager
  name: dsh-mcp-manager
  config:
    refreshIntervalMs: 300000      # 检查周期,0 = 关闭,默认 5 分钟
    refreshLeadMs: 600000          # 提前多久续期,默认 10 分钟
    refreshOnExpiry: true          # 过期后仍自动续期(默认开)
    servers:
      - name: demo                 # ^[A-Za-z0-9_-]{1,32}$,同时是工具前缀
        enabled: true
        transport: stdio
        command: npx
        args: ['-y', '@modelcontextprotocol/server-everything']
        env: {}
        cwd: ''
        toolCallTimeoutMs: 60000
        failOnStartupError: false
      - name: docs
        enabled: true
        transport: streamable-http
        url: http://127.0.0.1:3000/mcp
        headers: {}
        oauth:
          enabled: true            # 需要 OAuth 时
          scopes: []               # 留空 = 用服务器元数据里的 required_scopes
          clientId: ''             # 留空 = 动态客户端注册

服务器字段:name enabled transport command args env cwd url headers toolCallTimeoutMs failOnStartupError oauth{enabled,scopes,clientId,clientSecret,resourceMetadataUrl,authorizationServer}。

OAuth 2.1 授权

受 OAuth 保护的 streamable-http 服务器(其 /.well-known/oauth-protected-resource 会声明 authorization_servers 与 required_scopes)不再需要手工复制 token:

  1. 编辑服务器,勾选 使用 OAuth 授权,保存;
  2. 卡片上点 授权(浏览器) → 插件完成发现 + 动态注册 + PKCE,返回授权链接并在浏览器打开;
  3. 在授权页同意后回跳到 http://127.0.0.1:<DSH 端口>/api/dsh-mcp-manager/oauth/callback;
  4. 插件换取 token(存进凭据库)、重连该服务器,工具随即出现。
其它操作 行为
粘贴令牌 已有 access token 时的兜底;存为非过期授权
刷新令牌 立即用 refresh_token 换新并重连
全部续期 对所有已授权服务器强制续期一遍
退出授权 删除本地授权记录并断开
  • 授权链接 10 分钟有效、state 一次性;重复打开会提示"已使用",重新点授权即可(会顶掉旧尝试)。
  • 令牌过期前 60 秒内的下一次连接也会兜底刷新。
  • 刷新失败(invalid_grant)会清掉本地记录并把状态显示为未授权,不会静默失联。

自动续期

触发 行为
定时 每 refreshIntervalMs 检查,expiresAt 进入 refreshLeadMs 窗口即续期 + 重连
已过期 过期但仍有 refresh_token 的授权,下一轮必定续期
过期自愈 mcp__* 调用返回 401/unauthorized/invalid_token/token expired 等时,立刻续期 + 重连(每台 30s 最多一次,最多 3 次,30/60/120s 退避)

页面会显示当前策略、上次续期时间、下次检查时间,以及"上次续期触发:定时 / 过期后自愈 / 手动"。

Agent 工具

工具 作用
mcp_manager_list 列出受管服务器:传输、地址、状态、工具数、启动错误
mcp_manager_add 新增或替换(同名覆盖)一台服务器;含 oauth 设置
mcp_manager_remove 移除服务器及其配置
mcp_manager_set_enabled 启用 / 停用(保留配置)
mcp_manager_tools 列出已注册的 MCP 工具:公共名、描述、入参名,可按服务器过滤
mcp_manager_oauth status / authorize / paste-token / refresh / refresh-all / signout

架构

lib/index.js    Host 半边:清单校验与持久化(configEditor)、子插件编排(ctx.plugin 真 mcp-client)、
                6 个 agent 工具、12 条回环桥接路由(11 POST + GET 回调)、续期定时器与 401 自愈
lib/oauth.js    OAuth 2.1 引擎:仅 node:crypto + 全局 fetch;发现 / 注册 / PKCE / 换取 / 刷新 / 凭据读写
lib/client.js   Web 半边:settings.plugins.tab 页签,纯 JS(无构建、无 Harness 内部包依赖)
docs/*.md       实现契约(v1 基础 / OAuth / 定时续期 / 可编辑策略),Host 与 Web 两半的字段与接口
fixtures/*.mjs  本地测试夹具:假 MCP 服务器(stdio / HTTP)、OAuth 授权服务器 + 受保护 MCP、引擎端到端断言

数据流:页面 ⇄ POST /api/dsh-mcp-manager/*(仅回环)⇄ Host;Host 用 configEditor 写 profile patch 并 触发 Loader 重载,用 ctx.plugin() 把每个启用的服务器实例化为一个真正的 mcp-client,用 ctx.tools.schemas() 汇总 mcp__* 工具。

安全说明

  • OAuth token 只进 DSH 凭据库 ~/.dsh/.credentials.yaml,记录键 mcp-manager/<slug> (服务器名 docs → mcp-manager/docs)。不写进 cordis.patch.yml、不返回给页面、不进 agent 上下文、不写日志。
  • 页面拿到的只有:是否已授权、过期时间、scope、clientSecretSet(是否已保存)。
  • 桥接路由只接受回环请求;除 OAuth 回调(GET,仅回环)外均只接受 POST。
  • clientSecret、headers、env 属于配置,会留在 profile patch 里——共享机器请优先用凭据中心的环境变量。
  • 授权页会展示 client_id 与 PKCE challenge;请不要把授权链接转发给别人。

已知限制

  • OAuth 仅实现授权码 + PKCE 流程;依赖授权服务器支持动态客户端注册,否则需在表单里填 clientId。
  • client_credentials、设备码等流程不支持。
  • 过期自愈依赖错误文本能看出是鉴权问题(401/403/unauthorized/invalid_token/token expired 等); 服务端如果只回自定义错误,则只能等下一轮定时续期。
  • 修改清单或续期策略都会重载插件,因此所有服务器会重连一次;"重连"按钮是单服务器路径。
  • 停用的服务器不续期。
  • 续期成功会重连该服务器(旧连接带着旧令牌),会有约半秒的重连窗口。
  • 页面外观未做逐像素比对;逻辑与桥接行为有端到端测试。

开发与测试

仓库自带夹具,不需要外网:

# 1) OAuth 引擎端到端(会自己起授权服务器与受保护 MCP)
node fixtures/oauth-mcp-rig.mjs 8792 &
node fixtures/verify-oauth-engine.mjs 8792
# → 44 项断言:发现 / 动态注册 / PKCE / state / 回调换取 / Bearer 注入 / 过期刷新 /
#   invalid_grant 清库 / 粘贴令牌 / 退出 / 重放拒绝

# 2) 无鉴权的 MCP 服务器(stdio 与 HTTP),用来验证管理器本身
node fixtures/mock-mcp-server.mjs            # stdio
node fixtures/mock-mcp-http.mjs 8791         # streamable-http,路径 /mcp

语法检查:node --check lib/index.js、node --check lib/client.js、node --check lib/oauth.js (三个文件都没有构建步骤)。

兼容性

  • 开发与验证环境:DSH 0.2.1-rc.2、Node 24 / Windows 11;使用 Node >= 20 的语法与 API。
  • 依赖 Harness 提供的 @deepseek-ai/dsh-mcp-client(运行时动态导入,不打包)。
  • 回环回调天然适配桌面端;远程/容器部署时授权回跳地址需能访问 127.0.0.1:<端口>。

许可

MIT

声明

本项目由 DeepSeek V4.1 Flash 生成,包含 AI 生成的代码与文档。它按"现状"提供,不附带任何担保; 涉及 OAuth 凭证、远程服务器与配置写入,请在正式环境使用前自行审阅并做好备份。

—/ 5

No ratings yet

Verified DSH bundle

Commit 66a17a2b5aa1

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout