中文EN

dsh-mcp-tunnel

tools装不上npmMIT

把本机 MCP Server 通过出站-only 隧道栈(mcp-proxy + cloudflared Quick Tunnel)暴露给远程 Agent,并把公网 URL 注册进 dsh-mcp-client 的 streamable-http 配置。

下载量 / Downloads
719
测试时间 / Tested
2026-11-07
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-mcp-tunnel

沙箱测试结果

阶段结果
1 安装✗
2 列装—
3 挂载—
4 启动—
第一条错误
dsh: initialized profile web at /home/node/.dsh/profiles/web

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

dsh-mcp-tunnel

[!IMPORTANT]
依赖前置:相邻 dsh-src 检出(link: 依赖)
本项目在开发形态下使用 link: 依赖指向相邻的 DeepSeek Harness 源码检出(dsh-src),
与当前仓库保持同一父目录布局(<parent>/dsh-src)。克隆本仓库后:
1. 先把官方 deepseek-ai/deepseek-harness 检出到与本仓库同级的 dsh-src/ 目录,并执行其 pnpm install && pnpm run build;
2. 再按下方「安装」一节执行本仓库的 pnpm install --offline && pnpm build 与测试。
发布到 npm 的版本会尽量把 link: 依赖替换为 registry 真实版本;无法替换的内部包保持 link:,见各包 README 说明。

把本机 MCP Server 安全暴露给远程 Agent 的 DSH 隧道插件:一键为本机目录中的 MCP server

拉起隧道栈(mcp-proxy + cloudflared 的 Docker Compose 栈),并把最终公开 URL 注册到

@deepseek-ai/dsh-mcp-client 的 streamable-http 配置里(待确认片段,安全护栏 1)。

设计取向(对齐上游 anthropics/claude-plugins-official#mcp-tunnels,仅参考行为、不抄源码):
隧道 = 传输层;鉴权/授权应明确标注为「由暴露方自行加」。默认提供方
cloudflare-quick(免账号、开箱即用),与上游 security model 的立场一致:
免费快速隧道仅限测试,生产流量必须自行加鉴权层。

一、架构与安全模型

远程 Agent (dsh-mcp-client, streamable-http)
        │  HTTPS + Authorization: Bearer <token>
        ▼
https://<random>.trycloudflare.com        ← Cloudflare 边缘(TLS 由 Cloudflare 提供)
        │  (cloudflared 与边缘之间的出站隧道连接)
        ▼
┌──────────── Docker Compose 网络(共享命名空间)────────────┐
│  cloudflared ── network_mode: service:mcp-proxy ──► mcp-proxy │
│         (出站-only,与代理共享网络命名空间,无任何入站端口)    │
│  mcp-proxy(校验 Bearer 令牌 → 转发到上游)                        │
│       │                                                        │
│       ├─► hello-mcp(可选 FastMCP 示例:echo / uptime)          │
│       └─► 你的 MCP server 的 HTTP(S) 端点(容器网络/宿主机回环)   │
└──────────────────────────────────────────────────────────────┘
  (宿主机仅绑定 127.0.0.1:<回环调试端口> —— 公网无任何监听端口)

关键属性:

  • 出站-only:cloudflared 只主动连到 Cloudflare 边缘;公网无入站端口,

宿主机唯一端口绑定是 127.0.0.1:43180 的回环调试端口(验收标准 1)。

  • 本地 TLS 终结(命名隧道模式):certs/ 下的自签 CA + 服务端证书由隧道属主掌控,

与上游「证书用户掌控」做法一致;Quick Tunnel 模式公网侧 TLS 由 Cloudflare 提供,

证书仍生成并挂载供复用/自检。

  • 鉴权边界(重要):mcp-proxy 校验 Authorization: Bearer <token>(令牌在部署目录

.env 中,0600)。Quick Tunnel 的随机域名不是安全边界 —— **生产流量必须由暴露方

自行加鉴权层/网关**,本插件只保证「隧道=传输层」。

二、交付物

dsh-mcp-tunnel/
├── cordis.yml              # Cordis 装配(一行插件 + config 默认值;兼作 dsh.bundle.patch)
├── package.json            # dsh-mcp-tunnel,声明 dsh.bundle(MIT)
├── src/index.ts            # 装配 + 3 工具(create/status/stop)+ ctx.jobs 后台流程
├── src/tunnel-stack.ts     # compose 栈生成(迷你 .hbs 渲染器)+ 落盘
├── src/certs.ts            # 自签 CA/证书生成与目录管理(本地 openssl exec)
├── src/mcp-client-config.ts# dsh-mcp-client 追加片段:生成/校验/待确认管理
├── templates/
│   ├── docker-compose.yml.hbs   # 栈布局(mcp-proxy / cloudflared / 可选 hello-mcp)
│   └── proxy-config.env.hbs     # 代理非敏感环境配置(秘密一律走 .env)
├── README.md               # 本文档(安全模型 + 限制)
├── LICENSE                 # MIT
├── tsconfig.json           # tsc --noEmit 类型检查用
└── tests/
    ├── tunnel.smoke.ts     # 离线冒烟(node:test,无需 docker)
    └── tunnel.e2e.ts       # 真栈 e2e(需 docker + 公网,显式 DSH_MCP_TUNNEL_E2E=1 启用)

三、安装

本地开发(scratch-plugin 风格,直接加载 TS 源码):

# 你的 profile 的 cordis.patch.yml 追加:
- insert:
    - id: dsh-mcp-tunnel
      name: '/绝对路径/dsh-mcp-tunnel/src/index.ts'
      config: {}

作为 profile bundle 安装(dsh.bundle.patch: ./cordis.yml 已声明):

cd <你的 DSH profile>
pnpm add ./dsh-mcp-tunnel
# 行内引用建议改为包路径形式(随 exports 解析):
#   name: 'dsh-mcp-tunnel/src/index.ts'
依赖对齐(npm 上已发布的真实版本):peerDependencies 声明 @deepseek-ai/cordis ^4.0.1、
@deepseek-ai/dsh-tools ^0.1.1-rc.2、@deepseek-ai/dsh-jobs ^0.1.0-rc.8;dependencies 为
@deepseek-ai/schemastery ^3.18.1(运行时仅真正 import schemastery;其余为类型级/服务级
依赖)。peer 关系保留:目标运行时是 DSH 宿主,由宿主提供 cordis / dsh-tools / dsh-jobs 服务。

四、工具用法

mcp_tunnel_create

参数 · 类型 · 必填 · 说明

name · string · ✓ · 隧道名 = compose 项目名 = mcp-client serverName(^[A-Za-z0-9_-]{1,32}$)

serverDir · string · · MCP server 目录:优先读 .mcp.json(首个含 url 的条目作上游;command 型 stdio server 需先转成 HTTP 端点,见「限制」)

upstreamUrl · string · · 直接指定上游 MCP 端点(http/https),优先级高于 .mcp.json

provider · string · · cloudflare-quick(默认,免账号)/ anthropic(命名隧道,需自备 Cloudflare 账号与 DNS)

deployDir · string · · 覆盖部署目录(默认 <deployRoot>/<name>,deployRoot 默认 ~/.dsh/mcp-tunnels)

useHelloMcp · boolean · · 无上游可用时内置 hello-mcp 示例 server(echo/uptime);默认自动

token · string · · 自定义访问令牌;缺省自动生成 32 字节随机令牌写入 .env(0600)

hostProxyPort · integer · · 宿主回环调试端口(默认 43180)

行为:生成栈文件 + 证书(CA 存在即复用,验收标准 3)→ 写 .env(0600,秘密不进 compose)

→ 前置检查 docker(缺失给清晰提示,验收标准 5)→ 后台起容器(ctx.jobs,缺 jobs 时前台)

→ 轮询 cloudflared 日志出 Quick Tunnel URL → 写 state.json → 生成 待确认片段

<deployDir>/mcp-client.pending.yml。有 jobs 时返回 {kind:'background', jobId},用

job_output 收尾;无 jobs 时前台返回完整结果。

mcp_tunnel_status

参数 · 类型 · 说明

name · string · 隧道名;缺省列出全部隧道

输出:每隧道的部署目录、state.json、栈文件存在性、docker compose ps 结果、

cloudflared 最近日志尾部(≤50 行)、待确认片段(serverName/url)。

mcp_tunnel_stop

参数 · 类型 · 默认 · 说明

name · string(必填) · · 隧道名

keepCerts · boolean · true · false 时删除 certs/

行为:docker compose down 停栈并下线 URL(验收标准 4)→ 移除待确认片段 →

写入 state.json 失效标注(url 下线 + lastError,status 可见)→ 保留证书目录

供下次 create 复用(验收标准 3/4)。

五、mcp-client 配置片段(安全护栏 1)

create 绝不自动改写任何 profile 配置,只在部署目录写出待确认片段

(mcp-client.pending.yml),由你在显式确认后手动粘贴:

- insert:
    - id: mcp-<serverName>
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: <name>
        transport: streamable-http
        url: <https://xxx.trycloudflare.com>
        headers:
          Authorization: 'Bearer <token>'
        toolCallTimeoutMs: 60000
        failOnStartupError: false
  • 字段名与 @deepseek-ai/dsh-mcp-client 的 StreamableHttpConfig 完全一致;
  • 远程工具名 = mcp__<serverName>__<rawName>;
  • mcp_tunnel_stop 会删除该片段文件(验收标准 4)。若你已粘贴进 profile,

记得同步删除那一行,否则请把 URL 标注为失效;

  • 「由 apply 注入」路径(显式确认后自动写 profile 的 cordis.patch.yml)留作后续版本。

六、安全护栏清单

1. 仅显式确认后写 mcp-client 配置:插件只产出待确认片段文件,绝不自动改写 profile;

2. 秘密不进 compose:访问令牌只写入部署目录 .env(0600,docker co

…(truncated)

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:1,最后更新 2026-08-24

链接

GitHub · Homepage · npm

同类插件