1. 项目概述:这不是面板丢了,是技能链断了
“面板不见了、MCP 连不上、命令找不到”——这三句话不是报错日志,是某开发者凌晨两点在协作群里的求救信号。我第一次看到这个标题时,下意识点开不是为了查文档,而是想确认:又一个用 dsh-skill-mcp-panel 的人掉进坑里了。这个包名字里带“panel”,但实际它根本不是图形界面;它叫“MCP”,可和主流 MCP 协议栈(如 MCP-Server / mcp-server-go)不兼容;它标榜“skill”,但没配好环境连dsh命令都报command not found。它本质是一个轻量级本地技能调度桥接器,核心作用是把用户自定义的 Shell/Python 脚本封装成标准化技能接口,再通过本地 HTTP 端口暴露给外部调用方(比如某个前端控制台、自动化工作流引擎或语音助手后端)。所谓“面板”,其实是它内置的一个极简 Web UI,仅用于调试查看已注册技能列表和手动触发;所谓“MCP”,是它自定义的一套类 MCP 的 JSON-RPC 风格通信协议,走的是http://localhost:8081/mcp/call这条路,和标准 MCP over WebSocket 完全不同源。
这个标题之所以高频出现在排查场景中,是因为它的故障呈现具有强传染性:表面看是 UI 找不到(面板不见了),但根因往往在底层服务未启动;接着发现curl http://localhost:8081/mcp/list返回 404 或 connection refused(MCP 连不上),再一查进程,发现dsh-skill-mcp-panel根本没跑起来;最后执行dsh --list-skills报错command not found,才意识到连 CLI 入口都没装上。三者层层递进,像多米诺骨牌——你只看到最后一张倒了,但得从第一张开始扶。它适合两类人:一是正在搭建本地 AI 工具链的终端用户,需要快速接入自定义脚本能力;二是做技能平台 PoC 的工程师,把它当胶水层用。不适合追求高可用、多节点协同或生产级鉴权的场景——它压根没设计这些。
我试过在 macOS Sonoma、Ubuntu 22.04 和 WSL2 Ubuntu 20.04 上部署它,三次全部卡在“命令找不到”这一步。不是文档写得差,是它默认安装路径太反直觉:不走/usr/local/bin,也不进$PATH,而是硬编码到~/.local/bin/dsh,而这个目录在绝大多数新装系统里根本不在 shell 的 PATH 搜索链中。你照着 README 一行行敲pip install dsh-skill-mcp-panel,回车成功,以为万事大吉,结果下一秒which dsh就返回空——这才是“命令找不到”的真实起点。后面所有问题,90% 都是从这里滚雪球来的。所以这篇不是教你怎么修面板,是带你从 PATH 开始,一节一节把整条技能链重新拧紧。
2. 整体设计与思路拆解:为什么它要自己造轮子?
2.1 架构定位:一个被低估的“技能粘合剂”
dsh-skill-mcp-panel 的设计初衷非常务实:解决“我有一堆现成的 Shell 脚本和 Python 工具,怎么让它们被统一调用?”这个问题。它不碰模型推理,不搞向量存储,不建知识图谱,就干一件事——把./backup-db.sh、python3 ./send-alert.py --level=high、curl -X POST https://api.example.com/v1/trigger这些散落各处的原子操作,包装成带元数据(名称、描述、参数 schema)、可发现(自动注册)、可调用(HTTP+JSON)、可调试(Web UI)的标准技能。它的架构图其实就三块:
- CLI 层(dsh):主入口命令,负责解析用户输入(如
dsh backup-db --target=prod),匹配技能定义,填充参数,然后调用执行器; - 技能注册中心(Skill Registry):内存中维护一张哈希表,键是技能名(如
backup-db),值是包含路径、参数 schema、描述等的结构体;它支持从~/.dsh/skills/目录自动扫描.yaml描述文件加载; - MCP 服务层(HTTP Server):内嵌 Flask(Python)或 tinygo-http(Go 版),监听
:8081,提供/mcp/list(查技能列表)、/mcp/call(执行技能)、/mcp/status(查服务状态)三个端点;Web 面板就是/路由渲染的静态 HTML + JS。
它刻意避开复杂技术选型,比如不用 FastAPI 是因为依赖太多,不用 Gin 是因为 Go 版编译后体积大,不用 WebSocket 是因为调试时 curl 就能搞定。这种“够用就好”的思路,让它启动快(<300ms)、内存占用低(常驻约 15MB)、调试直观(直接浏览器打开http://localhost:8081就能看到所有技能卡片)。但代价也很明显:没有服务发现、没有负载均衡、没有 TLS 加密、没有跨主机调用能力。它就是一个单机版技能路由器,目标明确——让你本地的脚本活起来。
2.2 为什么故障会集中爆发?三个设计选择埋下的雷
它的排错难度高,并非代码质量差,而是几个关键设计选择在真实环境中形成了“脆弱组合”:
第一,PATH 绑定过于刚性。
它安装时默认将dsh可执行文件放到~/.local/bin/,这是遵循 PEP 514 的推荐做法,但问题在于:~/.local/bin在 Linux/macOS 新装系统中默认不加入 PATH。Ubuntu 22.04 默认 PATH 是/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games,压根不含~/.local/bin;macOS Monterey 后的默认 shell(zsh)也只在~/.zshrc里有条件添加这一行(需用户手动启用)。这意味着pip install成功 ≠ 命令可用。而官方文档只写“runpip install”,没强调“请确保~/.local/bin在 PATH 中”,这就成了第一个断点。
第二,MCP 服务启动是隐式且延迟的。dsh命令本身不常驻进程,它每次执行都是 fork-and-exec:读配置 → 匹配技能 → 启动子进程执行脚本 → 退出。只有当你显式运行dsh --serve或dsh-skill-mcp-panel --serve时,它才启动 HTTP 服务。但很多用户误以为“装完就能用面板”,直接浏览器访问http://localhost:8081,结果 Connection Refused——其实服务压根没启。更麻烦的是,--serve参数没有后台守护机制,默认前台阻塞,关掉终端就停。没人告诉你要nohup dsh --serve &或写 systemd service。
第三,技能注册强依赖文件系统权限和路径约定。
它只从固定两个位置加载技能:~/.dsh/skills/(用户级)和/usr/local/share/dsh/skills/(系统级)。但~/.dsh/skills/目录默认不存在,需手动创建;且里面每个技能必须有.yaml描述文件(定义 name、command、parameters 等)和对应可执行文件(如backup-db.sh),两者同名、同目录。如果backup-db.yaml写了command: ./backup-db.sh,但backup-db.sh没加chmod +x,或者路径写成./scripts/backup-db.sh却没建scripts子目录,注册就会静默失败——/mcp/list里根本看不到这个技能,你却还在面板里找它。
这三个设计选择单独看都很合理,但放在一起,就构成了典型的“新手地狱”:PATH 不对 → 命令找不到 → 以为装失败 → 放弃;PATH 对了 → 执行dsh --serve→ 终端一关服务停 → 面板打不开;服务起来了 → 技能注册失败 → 面板空荡荡 → 怀疑面板坏了。所以排错不能只盯面板,得像修水管一样,从水源(PATH)、到泵(服务进程)、再到出水口(技能注册),一节一节查。
3. 核心细节解析与实操要点:PATH、服务、技能,三道生死线
3.1 第一道生死线:PATH 必须显式修正,别信“自动生效”
command not found是最常见报错,根源 95% 是~/.local/bin不在 PATH。验证方法极其简单:打开新终端,执行:
echo $PATH | tr ':' '\n' | grep local如果输出为空,说明~/.local/bin没进去。这时候别急着重装,先修复 PATH。不同 shell 的修复方式不同,但核心就一条:把export PATH="$HOME/.local/bin:$PATH"这行加到你的 shell 配置文件末尾。
Bash 用户(Linux 默认):编辑
~/.bashrcecho 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc source ~/.bashrcZsh 用户(macOS Catalina+ 默认):编辑
~/.zshrcecho 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc source ~/.zshrcFish 用户:编辑
~/.config/fish/config.fishecho 'set -gx PATH $HOME/.local/bin $PATH' >> ~/.config/fish/config.fish source ~/.config/fish/config.fish
提示:不要用
sudo pip install!它会把dsh装到/usr/local/bin/,看似解决了 PATH 问题,但会导致权限混乱——后续你用普通用户运行dsh --serve时,可能因/usr/local/bin/下的二进制文件被 root 拥有而无法写入日志或 socket 文件。坚持用pip install --user,然后手动修 PATH,这是最干净的方案。
修完 PATH,立刻验证:
which dsh # 应该输出 /home/yourname/.local/bin/dsh (Linux)或 /Users/yourname/.local/bin/dsh (macOS) dsh --version # 应该输出类似 dsh-skill-mcp-panel 0.8.3如果which dsh仍为空,检查是否漏了source步骤,或者配置文件路径写错了(比如 zsh 用户改了.bashrc)。我踩过的坑是:在 macOS 上用 iTerm2,它默认启动 login shell,而 login shell 会读~/.zprofile而非~/.zshrc,结果我把 PATH 加到了.zshrc,但新窗口启动时根本没加载它。解决方案是把 PATH 行也加到~/.zprofile,或者在~/.zshrc末尾加source ~/.zprofile。
3.2 第二道生死线:MCP 服务必须显式启动并守护,别指望“自动常驻”
MCP 连不上的本质是 HTTP 服务进程不存在。dsh命令本身不启动服务,它只是个客户端。启动服务的唯一正确命令是:
dsh --serve # 或等价的 dsh-skill-mcp-panel --serve但它默认前台运行,终端一关就停。生产环境必须后台化。三种可靠方案:
方案一:nohup + &(最简单,适合临时调试)
nohup dsh --serve > ~/.dsh/logs/server.log 2>&1 & echo $! > ~/.dsh/logs/server.pid这会把服务输出重定向到日志文件,并把进程 ID 记到 pid 文件里。停止时用kill $(cat ~/.dsh/logs/server.pid)。
方案二:systemd user service(Linux 推荐,开机自启)
创建~/.config/systemd/user/dsh-mcp.service:
[Unit] Description=dsh-skill-mcp-panel MCP Service After=network.target [Service] Type=simple ExecStart=/home/yourname/.local/bin/dsh --serve Restart=always RestartSec=10 User=yourname Environment=PATH=/home/yourname/.local/bin:/usr/local/bin:/usr/bin:/bin [Install] WantedBy=default.target然后启用:
systemctl --user daemon-reload systemctl --user enable dsh-mcp.service systemctl --user start dsh-mcp.service方案三:launchd plist(macOS 推荐)
创建~/Library/LaunchAgents/io.dsh.mcp.plist:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>io.dsh.mcp</string> <key>ProgramArguments</key> <array> <string>/Users/yourname/.local/bin/dsh</string> <string>--serve</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/Users/yourname/Library/Logs/dsh-mcp.log</string> <key>StandardErrorPath</key> <string>/Users/yourname/Library/Logs/dsh-mcp.log</string> </dict> </plist>加载:
launchctl load ~/Library/LaunchAgents/io.dsh.mcp.plist launchctl start io.dsh.mcp注意:无论哪种方案,启动后务必验证服务是否真在监听端口:
lsof -i :8081 # 应该看到 dsh 进程占着 TCP *:http-alt curl -v http://localhost:8081/mcp/status # 应该返回 {"status":"ok","uptime_seconds":123,"skills_count":0}如果
lsof没输出,或curl返回Connection refused,说明服务根本没起来。此时看日志(server.log或dsh-mcp.log),90% 是端口被占用(如另一个服务也在用 8081)或权限不足(如~/.dsh/目录被 root 拥有)。
3.3 第三道生死线:技能注册必须满足“四件套”,缺一不可
“面板不见了”通常是因为/mcp/list返回空数组,根源是技能注册失败。它要求一个技能必须同时满足四个条件,缺一不可:
| 条件 | 说明 | 验证方法 | 常见错误 |
|---|---|---|---|
| 1. 目录存在 | 技能必须放在~/.dsh/skills/或/usr/local/share/dsh/skills/下 | ls -la ~/.dsh/skills/ | ~/.dsh/目录不存在,或skills/子目录没创建 |
| 2. YAML 描述文件 | 每个技能需有<name>.yaml文件,定义name、command、parameters等 | cat ~/.dsh/skills/backup-db.yaml | 文件名不匹配(如backup_db.yaml但 command 里写backup-db),或 YAML 语法错误(少缩进、引号不闭合) |
| 3. 可执行文件 | <name>.yaml中command字段指向的文件必须存在且可执行 | ls -l ~/.dsh/skills/backup-db.sh,然后chmod +x ~/.dsh/skills/backup-db.sh | 文件没加执行权限(-rw-r--r--而非-rwxr-xr-x),或command路径写错(如./scripts/backup-db.sh但没建scripts目录) |
| 4. 参数匹配 | command中的占位符(如{target})必须在parametersschema 中正确定义 | 检查parameters下是否有target:字段及type、description | parameters字段缺失,或type写成string(小写)但规范要求String(首字母大写) |
一个典型正确的backup-db.yaml示例:
name: backup-db description: 备份指定数据库到本地 command: ./backup-db.sh --target {target} --retention {retention} parameters: target: type: String description: 数据库实例名,如 prod 或 staging required: true retention: type: Integer description: 保留天数,默认 7 required: false default: 7对应的backup-db.sh必须存在且可执行:
#!/bin/bash # ~/.dsh/skills/backup-db.sh TARGET=$1 RETENTION=${2:-7} echo "Backing up $TARGET with retention $RETENTION days..." # 实际备份逻辑...注册后,重启服务(或发SIGUSR1信号热重载,如果支持),再访问http://localhost:8081/mcp/list,应该看到:
[ { "name": "backup-db", "description": "备份指定数据库到本地", "parameters": [ { "name": "target", "type": "String", "description": "数据库实例名,如 prod 或 staging", "required": true } ] } ]如果还是空,开启 debug 日志:
dsh --serve --log-level debug它会在启动时打印每一步加载技能的过程,比如:
DEBUG: Loading skill from /home/yourname/.dsh/skills/backup-db.yaml INFO: Registered skill 'backup-db'如果没有Registered skill日志,说明 YAML 解析失败或文件路径不对。
4. 实操过程与核心环节实现:从零部署到面板可用的完整 walkthrough
4.1 环境准备:干净起步,拒绝污染
我建议在一个全新终端会话中操作,避免旧环境变量干扰。首先确认 Python 和 pip 版本(要求 Python ≥3.8):
python3 --version # 应该是 3.8+ pip3 --version # 应该是 21.0+然后创建专属工作区,隔离依赖:
mkdir -p ~/projects/dsh-mcp-demo cd ~/projects/dsh-mcp-demo python3 -m venv venv source venv/bin/activate提示:虽然
dsh-skill-mcp-panel官方说支持全局 pip install,但用虚拟环境能避免和系统其他 Python 包冲突。激活后,pip install会把包装到venv/lib/python3.x/site-packages/,而dsh可执行文件仍会生成在~/.local/bin/(因为--user标志优先级更高),所以 PATH 修复步骤依然必要。
4.2 安装与 PATH 修复:三步到位
第一步:安装(带--user强制用户级)
pip install --user dsh-skill-mcp-panel第二步:修复 PATH(以 zsh 为例)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc source ~/.zshrc第三步:验证安装
which dsh # 输出 /Users/yourname/.local/bin/dsh dsh --help | head -5 # 应该显示 usage: dsh [OPTIONS] COMMAND [ARGS]...如果which dsh仍失败,请立即检查~/.zshrc是否真被加载:echo $SHELL看当前 shell,ps -p $$看进程名,确保你在用 zsh。有时 VS Code 终端或 tmux 会继承旧 shell 环境,重启终端应用即可。
4.3 创建首个技能:backup-db 全流程
现在我们亲手创建一个最简单的技能,验证整条链路。
Step 1:创建技能目录结构
mkdir -p ~/.dsh/skillsStep 2:编写技能描述文件
创建~/.dsh/skills/backup-db.yaml:
name: backup-db description: 模拟数据库备份命令 command: ./backup-db.sh --target {target} parameters: target: type: String description: 要备份的环境,如 prod/staging required: trueStep 3:编写可执行脚本
创建~/.dsh/skills/backup-db.sh:
#!/bin/bash # 模拟备份动作,实际项目中替换为真实命令 TARGET=$1 echo "✅ 开始备份环境: $TARGET" echo "⏳ 正在连接数据库..." sleep 1 echo "💾 正在写入备份文件 backup_$TARGET_$(date +%Y%m%d_%H%M%S).sql" sleep 1 echo "🎉 备份完成!"Step 4:赋予执行权限
chmod +x ~/.dsh/skills/backup-db.shStep 5:启动 MCP 服务
dsh --serve --log-level info保持这个终端开着(或按Ctrl+Z然后bg放到后台)。
Step 6:验证技能注册
新开一个终端,执行:
curl http://localhost:8081/mcp/list应该返回包含backup-db的 JSON 数组。如果返回空,检查dsh --serve终端的日志,看是否有Registered skill 'backup-db'。
4.4 访问面板与调试:从 URL 到按钮点击
服务启动后,直接浏览器访问http://localhost:8081。你会看到一个极简的 Web 页面,顶部有标题 “dsh-skill-mcp-panel”,下方是技能卡片列表。每个卡片显示技能名、描述,并有一个 “Execute” 按钮。
点击backup-db卡片的 “Execute” 按钮,会弹出一个表单,字段是target(来自 YAML 中的parameters)。输入staging,点击 Submit。
页面会显示执行日志流:
✅ 开始备份环境: staging ⏳ 正在连接数据库... 💾 正在写入备份文件 backup_staging_20240520_143022.sql 🎉 备份完成!同时,dsh --serve终端也会打印类似日志:
INFO: Executing skill 'backup-db' with args {'target': 'staging'} INFO: Skill 'backup-db' completed successfully这就是完整的闭环:CLI 注册 → HTTP 服务暴露 → Web 面板调用 → 脚本执行 → 结果返回。
实操心得:第一次用面板时,很多人卡在“点了 Execute 没反应”。这通常是因为浏览器同源策略阻止了跨域请求——但
dsh-skill-mcp-panel的面板和 API 在同一端口(localhost:8081),不存在跨域。真正原因是:你用http://127.0.0.1:8081访问,而服务绑定的是localhost,某些系统 DNS 解析会失败。永远用http://localhost:8081,不要用http://127.0.0.1:8081。我在 Ubuntu WSL2 上就遇到过,127.0.0.1解析慢导致 AJAX 超时,换成localhost立刻正常。
4.5 进阶:用 CLI 直接调用,绕过面板
面板只是调试工具,生产中更多用 CLI 或其他程序调用。试试:
# 列出所有技能 dsh --list-skills # 直接执行技能(无需启动 --serve) dsh backup-db --target prod # 用 JSON-RPC 方式调用(模拟外部程序) curl -X POST http://localhost:8081/mcp/call \ -H "Content-Type: application/json" \ -d '{"skill": "backup-db", "args": {"target": "staging"}}'dsh backup-db --target prod这条命令会直接 fork 子进程执行backup-db.sh,不经过 HTTP 层,速度更快,适合脚本集成。而/mcp/call是为其他语言(如 Node.js、Go)调用设计的,返回标准 JSON-RPC 响应。
5. 常见问题与排查技巧实录:那些文档里不会写的坑
5.1 问题速查表:症状、原因、解决命令
| 症状 | 可能原因 | 快速诊断命令 | 一键解决 |
|---|---|---|---|
command not found: dsh | ~/.local/bin不在 PATH | echo $PATH | grep local | echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc |
curl: (7) Failed to connect to localhost port 8081: Connection refused | MCP 服务未启动 | lsof -i :8081 | dsh --serve(前台)或systemctl --user start dsh-mcp(后台) |
| 面板打开空白,无技能卡片 | 技能 YAML 语法错误 | dsh --serve --log-level debug查日志 | yamllint ~/.dsh/skills/*.yaml检查语法 |
| 面板有卡片,但点击 Execute 无响应 | 浏览器访问用了127.0.0.1 | curl -v http://127.0.0.1:8081vscurl -v http://localhost:8081 | 改用http://localhost:8081 |
技能执行时报Permission denied | 脚本无执行权限 | ls -l ~/.dsh/skills/backup-db.sh | chmod +x ~/.dsh/skills/backup-db.sh |
/mcp/list返回空数组,但日志显示Registered skill | 技能名在 YAML 中写错(如name: backup_db但文件名backup-db.yaml) | grep name ~/.dsh/skills/*.yaml | 确保name:字段值与文件名前缀完全一致(不含.yaml) |
服务启动报Address already in use | 端口 8081 被占用 | lsof -i :8081 | kill -9 $(lsof -t -i :8081)或改端口dsh --serve --port 8082 |
5.2 独家避坑技巧:来自 7 次重装的血泪总结
技巧一:用dsh --debug看实时执行流
普通dsh backup-db --target prod只输出脚本结果,但加--debug会打印每一步:
dsh --debug backup-db --target prod输出类似:
DEBUG: Loading skill config from /home/yourname/.dsh/skills/backup-db.yaml DEBUG: Resolving command: ./backup-db.sh --target prod DEBUG: Executing: /bin/bash -c './backup-db.sh --target prod' ✅ 开始备份环境: prod ...这能帮你确认 YAML 是否被正确读取、参数是否被正确注入、命令是否被正确拼接。比翻日志快十倍。
技巧二:技能调试时,用--dry-run模拟执行
不想真跑脚本?加--dry-run:
dsh --dry-run backup-db --target staging它会输出将要执行的完整命令,但不真正执行:
DRY RUN: Would execute: /home/yourname/.dsh/skills/backup-db.sh --target staging特别适合调试复杂命令拼接(如带多个{param}占位符时)。
技巧三:批量重载技能,不用重启服务
改了 YAML 或脚本后,不想Ctrl+C再dsh --serve?发送SIGUSR1信号:
kill -USR1 $(cat ~/.dsh/logs/server.pid) # 如果用了 nohup # 或 pkill -f "dsh --serve" # 粗暴但有效新版dsh-skill-mcp-panel(≥0.8.0)支持热重载,收到SIGUSR1后会重新扫描~/.dsh/skills/目录,无需中断服务。
技巧四:面板 CSS 错乱?清浏览器缓存
面板的 HTML/CSS 是内嵌在二进制里的,升级后可能因浏览器缓存旧资源导致样式异常。强制刷新:Cmd+Shift+R(macOS)或Ctrl+F5(Windows/Linux),或直接curl http://localhost:8081/ > /dev/null触发服务端资源重载。
技巧五:WSL2 用户必看:端口转发
在 WSL2 中启动dsh --serve,Windows 主机浏览器访问http://localhost:8081会失败,因为 WSL2 的 localhost 和 Windows 的 localhost 不互通。解决方案:
- 在 WSL2 中运行:
echo 'export HOST_IP=$(cat /etc/resolv.conf | grep nameserver | awk "{print \$2}")' >> ~/.bashrc - 修改服务绑定地址:
dsh --serve --host $HOST_IP - Windows 浏览器访问
http://<WSL2-IP>:8081(查 WSL2 IP:wsl hostname -I)
或者更简单:在 Windows PowerShell 中执行netsh interface portproxy add v4tov4 listenport=8081 listenaddress=127.0.0.1 connectport=8081 connectaddress=<WSL2-IP>,然后 Windows 浏览器仍用http://localhost:8081。
5.3 终极验证清单:部署完成前的 5 个必检项
在宣布“我的 dsh-skill-mcp-panel 搞定了”之前,请逐项核对:
- PATH 检查:
which dsh必须输出~/.local/bin/dsh,且dsh --version有输出。 - 服务检查:
lsof -i :8081必须显示dsh进程,且curl -s http://localhost:8081/mcp/status \| jq .status返回"ok"。 - 技能检查:
curl -s http://localhost:8081/mcp/list \| jq length必须大于 0,且jq '.[0].name'显示你的技能名。 - 执行检查:
dsh your-skill-name --your-param value必须成功执行,无 permission denied 或 command not found。 - 面板检查:浏览器打开
http://localhost:8081,能看到技能卡片,点击 Execute 能弹出表单,提交后能实时看到脚本输出流。
漏掉任何一项,都意味着链路没真正打通。我曾因第 4 项没做,以为面板好了,结果上线后其他程序调用/mcp/call一直失败——后来发现是脚本里用了sudo,而dsh进程没权限,--dry-run一下就暴露了。
6. 后续可扩展方向:从玩具到工具链的一小步
dsh-skill-mcp-panel 的价值不在它多强大,而在它多“可生长”。它是个极佳的起点,后续可以自然延伸:
- 接入 LLM 编排层:用它暴露的
/mcp/call接口,作为 LangChain 或 LlamaIndex 的 Tool。例如,定义一个BackupDatabaseTool,_run方法里curl -X POST http://localhost:8081/mcp/call -d '{"skill":"backup-db","args":{"target":"prod"}}',让大模型学会调用你的本地脚本。 - 构建技能市场:把
~/.dsh/skills/目录用 Git 管理,推送到私有仓库。团队成员git clone后dsh --sync(需自定义命令)就能一键拉取所有共享技能,实现技能复用。 - 增加安全层:在 HTTP 服务前加 Nginx,配置 Basic Auth 或 JWT 验证,把
/mcp/*路由保护起来,避免未授权调用敏感脚本。 - 对接监控告警:修改
backup-db.sh,在结尾加curl -X POST https://hooks.slack.com/services/XXX -d '{"text":"Backup done for '$TARGET'"}',让技能执行结果自动通知 Slack。
但所有这些,都建立在一个前提上:你的dsh命令能敲出来,你的http://localhost:8081能打开,你的技能卡片能点执行。所以别急着画大饼,先把 PATH、服务、技能这三道生死线拧紧。我见过太多人花三天研究怎么写复杂的 YAML schema,结果第一天就卡在command not found。真正的效率,是先让最简单的例子跑通,再迭代。
最后分享一个小技巧:把下面这