@asiainfo-sdd/skillshub-mcp
v0.0.5
Published
SkillsHub MCP server — 对接亚信 SkillsHub 后台的本地 MCP 客户端,支持技能批量下载到 .trae/.qoder 等智能体目录,token 过期自动续期。
Maintainers
Readme
@asiainfo-sdd/skillshub-mcp
对接亚信 SkillsHub 后台的本地 MCP(Model Context Protocol)客户端。支持技能批量下载到
.trae/.qoder等智能体目录,token 过期自动续期并重试,开箱即用。
技能平台 token 有效期较短(约 1 小时),本服务在任意接口收到 401 时会自动重新获取 token 并重试一次,对调用方完全透明,无需手动处理鉴权过期。
✨ 核心能力
- 技能批量下载(核心):按
skillIds精确下载,或按名称/业务类型模糊批量下载,按技能原始目录层级落盘。 - 多智能体目录:默认写入
.trae与.qoder,可通过dirs参数扩展到.claude/.cursor等任意智能体目录。 - token 自动续期:401 自动刷新 + 重试,并发请求自动去重只刷新一次。
- 只读安全:仅保留获取 token / 查询 / 下载,共 6 个 MCP 工具,不暴露任何会修改后台技能的接口(无增删改 / 发布 / 导入导出)。
- 零构建:纯 Node.js ESM,无编译步骤;
npx直接运行。
🚀 快速开始
方式一:npx 直接运行(推荐,无需安装)
自
0.0.4起,团队共享凭证(SKILLHUB_BASIC_AUTH/SKILLHUB_TEAM_ID/SKILLHUB_INSECURE)已内置在代码中,无需在 MCP 配置里再通过 env 传递。这样在 Trae 等智能体里共享 MCP 配置时,不会再出现敏感值被平台用******掩码导致团队成员无法使用的问题。
在智能体的 MCP 配置中加入:
{
"mcpServers": {
"skillshub": {
"command": "npx",
"args": ["-y", "@asiainfo-sdd/skillshub-mcp@latest"]
}
}
}不需要任何
env字段,开箱即用。如需覆盖默认的 base URL / 下载目录等可选项,仍可通过 env 设置。
方式二:全局安装
npm install -g @asiainfo-sdd/skillshub-mcp{
"mcpServers": {
"skillshub": {
"command": "skillshub-mcp"
}
}
}各智能体配置文件位置
| 智能体 | 配置文件 |
|--------|----------|
| Trae | .trae/mcp_config.json(项目级)或设置 → MCP |
| Qoder | Qoder 设置 → MCP Servers |
| Claude Code / Claude Desktop | claude_desktop_config.json |
| Cursor | .cursor/mcp.json 或 ~/.cursor/mcp.json |
配置格式均为上面的
mcpServers结构,可通用。
⚙️ 环境变量
凭证类配置已内置:自
0.0.4起,SKILLHUB_BASIC_AUTH/SKILLHUB_TEAM_ID/SKILLHUB_INSECURE三项团队共享凭证已直接写入代码(见 src/config.js),不再从 env 读取。这样 Trae 等智能体在团队内共享 MCP 配置时,不会再因env字段被掩码为******而失效。下表仅列出可选覆盖项:
| 变量 | 说明 | 默认值 |
|------|------|--------|
| SKILLHUB_BASE_URL | 技能接口基础地址 | https://aido.asiainfo.com/maas-mgmt |
| SKILLHUB_TOKEN_URL | OAuth2 取 token 地址 | https://aido.asiainfo.com/maas-sso/oauth2/token |
| SKILLHUB_DOWNLOAD_DIRS | 默认下载目录,逗号分隔 | .trae,.qoder |
| SKILLHUB_PAGE_SIZE | 分页默认每页条数 | 100 |
| SKILLHUB_TIMEOUT_MS | 单次 HTTP 超时毫秒 | 30000 |
| SKILLHUB_TOKEN_MARGIN_MS | token 提前刷新余量毫秒 | 60000 |
内置凭证(不通过 env 读取):
basicAuth= 团队 OAuth2 应用接入密钥;teamId=1851529412143517698;insecure=true(内网自签证书,固定开启)。如需更换团队或密钥,请直接修改 src/config.js 顶部的常量后重新发布。
关于 TLS:该后台证书无法被 Node 默认信任库校验(
UNABLE_TO_VERIFY_LEAF_SIGNATURE)。内网环境可设SKILLHUB_INSECURE=1快速放通;生产环境更推荐NODE_EXTRA_CA_CERTS=/path/to/enterprise-ca.pem导入企业 CA。关于 base URL:技能 REST 接口位于
/maas-mgmt网关下(根路径/skill/...返回 nginx 404,/maas-skill等是 MinIO 对象存储桶而非接口)。默认值已设为…/maas-mgmt。若你的网关前缀不同,用SKILLHUB_BASE_URL覆盖即可。关于后台响应结构:后台真实响应为
{ success:true, code:"bizSuccess", data:..., count:N }(code为字符串、分页总数字段为count),与接口文档描述的整数 code /total不同,本服务已做兼容。技能文件以fileTrees返回,路径带skill/<uuid>/存储前缀、目录以dir:false+ 末尾/表示——下载时已自动剥离存储前缀并正确识别目录。
🧰 工具一览
本服务只读:仅保留获取 token / 查询 / 下载 / token 自动续期,不暴露任何会修改后台技能的接口(无增删改 / 发布 / 导入导出),保证对外安全。
| 工具 | 类别 | 说明 |
|------|------|------|
| ping | 获取 token | 验证连通性,主动取一次 token,返回过期时间。排查鉴权/网络问题首选。 |
| list_skills | 查询 | 分页查询技能列表(可按状态/名称/业务类型过滤)。 |
| list_published_skills | 查询 | 分页查询已发布技能列表。 |
| get_skill_detail | 查询 | 按 skillId 查询技能详情(含文件树)。 |
| get_published_skill_detail | 查询 | 按 skillId 查询已发布技能详情。 |
| download_skills | 下载 | ⭐ 批量下载技能到本地智能体目录(顺序,适合小批量)。 |
| download_skills_parallel | 下载 | 🚀 多线程批量下载(async 并发池,适合大批量)。 |
多线程说明:
download_skills_parallel在接口内启动多个并发任务(concurrency控制并发度,默认 5),每个任务独立完成 拉详情→写盘,技能间真正并行下载。Node 通过 async I/O + libuv 线程池在系统层并行执行 socket 读写,且所有并发请求共享同一个 TokenManager——任一请求遇 401 自动续 token 一次,全部受益(若改用 OS worker_threads 反而会破坏统一的 token 管理)。实测 6 技能:顺序 ~1.2s / 并发(6) ~0.2s。token 过期自动续期不是独立工具,而是内置机制:任意接口收到 401 时自动刷新 token 并重试一次(见 client.js),对调用方透明。
⭐ download_skills 详解
功能:把一个或多个技能按其原始目录层级,批量写入本地智能体目录。
参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| skillIds | string[] | 二选一 | 要下载的技能 ID 列表 |
| filter | object | 二选一 | { skillName?, busType?, skillStatus?, teamId? },自动翻页收集全部匹配项 |
| dirs | string[] | 否 | 目标智能体目录,默认读配置 [.trae, .qoder],可传 [".claude", ".cursor"] 等 |
| baseDir | string | 否 | 基准目录,默认当前工作目录(智能体工作区根) |
| subDir | string | 否 | 每个智能体目录下的子目录,默认 skills;传 "" 则直接写到 <dir>/<skillName> |
| overwrite | boolean | 否 | 是否覆盖已存在文件,默认 false(跳过) |
| published | boolean | 否 | 使用已发布技能详情,默认 false |
| dryRun | boolean | 否 | 只预览不落盘,默认 false |
落地结构:<baseDir>/<dir>/<subDir?>/<skillName>/<原始文件层级>
示例(让 AI 这样调用)
下载指定技能到默认的 .trae / .qoder:
{
"skillIds": ["101", "102"],
"overwrite": true
}按名称模糊批量下载,并额外写入 .claude 目录:
{
"filter": { "skillName": "报表", "busType": "data" },
"dirs": [".trae", ".qoder", ".claude"]
}只预览不写盘:
{ "filter": { "skillName": "登录" }, "dryRun": true }技能名中的文件系统非法字符(
/ \ : * ? " < > |等)会被清洗为_;所有相对路径都会做路径穿越拦截,确保文件不会写到目标目录之外。
🔑 Token 自动续期机制
调用任意接口
│
├─ 200/2xx ──▶ 正常返回
│
└─ 401(token 过期)
│
├─ TokenManager 强制刷新(fetchToken)
│ · 并发请求自动去重,只刷新一次
│
└─ 用新 token 重试一次原请求 ──▶ 返回结果- token 在到期前
SKILLHUB_TOKEN_MARGIN_MS(默认 60s)即视为临期,下一次调用前主动刷新。 - 即便如此仍可能撞上 401,此时由 HTTP 客户端兜底:刷新 + 重试一次。
- 对所有工具完全透明,调用方无需感知。
📦 发布到 npm
本项目为 scoped 包(@asiainfo-sdd/skillshub-mcp),首次发布需以 public 可见性发布:
# 1. 登录(需要 npm 账号,且对 @asiainfo scope 有权限;若无 scope 权限可改用扁平包名)
npm login
# 2. 发布(scoped 包默认私有,必须加 --access public)
npm publish --access public发布内容受 package.json 的 files 字段白名单控制,仅包含 src/、README.md、LICENSE,不会带上 node_modules/ 与 test/。可在发布前预览将上传的文件清单:
npm pack --dry-run升级版本:修改 package.json 的 version 后再次 npm publish。
🛠️ 本地开发与测试
环境要求:Node.js ≥ 18.17(内置 fetch / FormData / Blob)。
npm install # 安装依赖
npm start # 启动 MCP server(stdio)
node test/smoke.mjs # 启动握手 + 工具注册校验(断言恰好 6 个只读工具)
node test/retry.mjs # token 自动续期 + 并发去重 + 业务错误
node test/download.mjs # 文件落盘 + 多目录复制 + 路径穿越拦截
node test/parallel.mjs # 多线程并发下载(真正并行 / 顺序保持 / 错误隔离)
SKILLHUB_INSECURE=1 node test/real-mcp.mjs # 真实后台:ping + list_skills
SKILLHUB_INSECURE=1 node test/real-readonly.mjs # 真实后台:只读全链路 ping→list→detail→download🔧 故障排查
先用 ping 工具自检(它会强制取一次 token 并返回过期时间):
| 现象 | 原因 | 处理 |
|------|------|------|
| UNABLE_TO_VERIFY_LEAF_SIGNATURE / TLS 报错 | 后台证书不被 Node 信任库校验(自签/缺中间证书) | 设 SKILLHUB_INSECURE=1;或 NODE_EXTRA_CA_CERTS 导入企业 CA |
| 获取 token 失败 (HTTP 401) | Basic 密钥错 / 过期 | 用 SKILLHUB_BASIC_AUTH 覆盖正确的密钥 |
| HTTP 404 Not Found (nginx) | base URL 前缀不对(如误用根路径) | 确认 SKILLHUB_BASE_URL 为 …/maas-mgmt |
| HTTP 502 Bad Gateway | 后台技能服务自身宕机(网关上游不可用) | 服务端问题,等待恢复后重试;MCP 侧无需改动 |
| 业务错误 [code=xxx] | 后台返回的业务错误码 | 看 message 字段定位 |
实测结论(2026-07):只读全链路打通 ✅。
ping取 token 成功(749 字符 Bearer,有效期 3599s);list_skills/list_published_skills返回code:"bizSuccess";通过 MCP 协议走ping → list_published_skills → get_published_skill_detail → download_skills,技能正确落盘到.trae/.qoder(下载引擎对含文件技能的落盘由test/download.mjs覆盖)。团队 ID 等大整数以字符串传输,避免Number()精度丢失。
📁 项目结构
src/
index.js # 入口:MCP server + 6 个只读工具注册
config.js # 环境变量配置加载(含 SKILLHUB_INSECURE)
auth.js # TokenManager:取/缓存/刷新 token
client.js # HttpClient:Bearer 鉴权 + 401 自动重试
api.js # 技能接口封装(只读:page / publishedPage / detail / publishedDetail)
download.js # fileTrees 落盘 + 顺序/多线程批量下载
util.js # 响应封装、路径清洗、文件树统计
test/
smoke.mjs # MCP 握手与工具校验(断言恰好 7 个只读工具)
retry.mjs # 鉴权续期逻辑
download.mjs # 下载引擎(顺序)
parallel.mjs # 多线程并发下载验证
real-mcp.mjs # 真实后台 ping + list_skills
real-readonly.mjs # 真实后台只读全链路📄 License
MIT
