remote-skill-mcp
by Congenital
README.md
# remote-skill-mcp
> 把**远程 HTTP 服务**上的技能文件(`skill.md` 及其子文件)动态暴露为 **MCP(Model Context Protocol)** 工具、资源与提示词,让任意 MCP 客户端(Claude Desktop、Cursor、LobeHub 等)通过 stdio 直接读取远程技能文档。
[](https://www.python.org/)
[](https://github.com/modelcontextprotocol/python-sdk)
[]()
[](./LICENSE)
> 📖 **English documentation / 英文文档:** [README.en.md](./README.en.md)
基于**标准 MCP SDK** 的 `FastMCP` 运行时实现(非手写 JSON-RPC 协议层),完全符合 MCP 规范,可直接被任意 MCP 客户端接入,并已适配 **LobeHub MCP 市场**(见 [`lhm.plugin.json`](./lhm.plugin.json))。
---
## 工作原理(懒加载,省上下文)
```
┌─────────────┐ stdio (newline-delimited JSON-RPC) ┌──────────────────┐
│ MCP 客户端 │ ◄────────────────────────────────────► │ server.py │
│ (Claude等) │ initialize / tools/* / │ (本仓库) │
└─────────────┘ resources/* / prompts/* └────────┬─────────┘
│ HTTP GET/HEAD
▼
┌─────────────────────┐
│ 远程 SimpleHTTP 服务 │
│ /skill.md │
│ /image/*.md 等子文件│
└─────────────────────┘
```
启动时(lifespan,懒加载):
1. 从 `REMOTE_SKILL_BASE_URL` 拉取 `skill.md`(轻量能力目录,描述有哪些技能方向);
2. 解析其中的 **markdown 链接 / 图片 / 裸文件 token / 目录名**,对每个引用做 **HEAD 探测**(不下载正文):
- 引用是**文件** → 记录路径 + mime/size;
- 引用是**目录** → GET 其 HTML 列表页,把列出的文件记录进来(不递归下载文件正文);
- 404 的裸文件名会在已知目录中自动重试;
3. 动态生成 MCP 暴露物(description 只含**路径清单**,不含正文,避免上下文膨胀):
- **工具** `get_skill_file(path)` —— 按路径**按需**取文件内容;
- **资源** `skill://<相对路径>` —— 每个发现的文件一个资源(`read` 时才下载;文本内联,二进制转 base64);
- **提示词** `skill` / `list_skills` —— 返回 `skill.md` 全文 / 能力目录摘要。
> 这样 agent 平时只看到"有哪些能力方向",真正用到某个技能时才拉取详细文档,
> 避免一次性把所有技能详情灌进上下文。若 `skill.md` 不直接列全所有文件、需要钻取目录,
> 可设 `MCP_DISCOVER_DEPTH>=1` 递归 N 层(会下载中间层正文以解析更多引用)。
---
## 特性
- ✅ 基于**标准 MCP SDK**(`FastMCP`)实现,完全符合 MCP 规范,stdio 传输
- ✅ **懒加载**:启动只读 `skill.md`,子文件仅记录路径,正文按需下载(省上下文)
- ✅ 动态发现:HEAD 探测文件 + GET 目录列表页,解析 `skill.md` 的链接/图片/裸文件/目录名
- ✅ 404 重试:对失败路径在已知目录中自动重试
- ✅ MIME 推断:`content-type` 为 `application/octet-stream` 时按扩展名回退(`.md` 等仍按文本)
- ✅ 三种暴露方式:工具 / 资源 / 提示词(description 只含路径清单,不含正文)
- ✅ 大文件保护:超过 `MCP_MAX_FILE_BYTES` 拒绝读取
- ✅ 日志只走 stderr,stdout 仅用于协议消息
- ✅ 工具错误用 `isError=True` 返回(符合 MCP 约定,客户端不抛异常)
- ✅ 适配 **LobeHub MCP 市场**:含 `lhm.plugin.json` 清单、`pyproject.toml` 元数据、MIT 许可
---
## 提供的 MCP 能力
| 类型 | 名称 | 说明 |
|------|------|------|
| 工具 | `get_skill_file(path)` | 按路径读取文件内容(文本/图片/二进制 base64) |
| 资源 | `skill://<相对路径>` | 每个发现的文件一个资源 URI,可 `resources/read` |
| 提示词 | `skill` | 返回 `skill.md` 全文(可用 `file` 参数指定子文件) |
| 提示词 | `list_skills` | 返回可用技能方向摘要(文件清单) |
---
## 安装
```bash
cd remote_skill_mcp
pip install -r requirements.txt
```
依赖:`mcp`(协议类型 + stdio 传输 + FastMCP 运行时)、`httpx`(HTTP 客户端)。
---
## 配置(环境变量)
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `REMOTE_SKILL_BASE_URL` | `http://192.168.2.6:4000` | 远程服务根地址 |
| `SKILL_FILE` | `skill.md` | 技能入口文件(相对 BASE_URL) |
| `MCP_MAX_FILE_BYTES` | `524288`(512KB) | 单文件最大字节,超过则拒绝 |
| `MCP_MAX_FILES` | `200` | 记录文件数上限 |
| `MCP_TIMEOUT` | `30` | 单次 HTTP 超时(秒) |
| `MCP_DISCOVER_DEPTH` | `0` | 发现深度:`0`=只读 `skill.md`(默认,最省);`>=1` 递归 N 层 |
| `MCP_CACHE_READS` | `false` | 是否缓存已读取文件内容(省重复请求,但占内存) |
---
## 运行
### 直接运行(调试)
```bash
export REMOTE_SKILL_BASE_URL=http://192.168.2.6:4000
python server.py
```
服务启动后会阻塞等待 stdio 输入。
### 接入 MCP 客户端
**Claude Desktop**(`claude_desktop_config.json`):
```json
{
"mcpServers": {
"remote-skill": {
"command": "python",
"args": ["/绝对路径/remote_skill_mcp/server.py"],
"env": {
"REMOTE_SKILL_BASE_URL": "http://192.168.2.6:4000"
}
}
}
}
```
**Cursor / 其他支持 stdio MCP 的客户端**同理,把 `server.py` 作为子进程启动即可。
---
## 发布到 LobeHub MCP 市场
本仓库已包含市场清单 [`lhm.plugin.json`](./lhm.plugin.json)(`identifier`/`name`/`version`/`author`/`homepage`/`icon`/`category`/`tags`/`description`/`tools`/`prompts`/`resources` 齐全)。
1. 确保仓库已 push 到 GitHub(`origin` = `git@github.com:Congenital/remote_skill_mcp.git`);
2. 安装市场 CLI(需 Node.js ≥ 22)并登录:
```bash
npx -y @lobehub/market-cli login
npx -y @lobehub/market-cli github connect
```
3. 发布(读取本仓库根目录的 `lhm.plugin.json`):
```bash
npx -y @lobehub/market-cli plugin publish https://github.com/Congenital/remote_skill_mcp
```
后续版本更新:`npx -y @lobehub/market-cli plugin update`(改 `lhm.plugin.json` 的 `version` 即可)。
> 市场按 活跃度 / 稳定性 / 社区反馈 等维度排名。本清单已补齐 作者、主页、图标、分类、标签、工具/提示词/资源 等字段以提升完整度评分。
---
## 测试
```bash
python tests/e2e_test.py
```
端到端测试通过 `mcp.ClientSession` 启动 server,验证 `initialize` / `tools/list` / `tools/call`(含非法路径报错)/ `resources/list` / `resources/read` / `prompts/list` / `prompts/get`(`skill` + `list_skills`)全链路。
---
## 目录结构
```
remote_skill_mcp/
├── server.py # MCP 服务(FastMCP 运行时 + 发现 + 工具/资源/提示词)
├── lhm.plugin.json # LobeHub MCP 市场清单
├── pyproject.toml # 项目元数据(名称/版本/作者/许可/入口点)
├── LICENSE # MIT 许可
├── requirements.txt
├── README.md # 中文文档
├── README.en.md # 英文文档
└── tests/
└── e2e_test.py # 端到端测试
```
---
## 远程服务要求
- 一个可静态列出/下载文件的 HTTP 服务(如 `python -m http.server`);
- 根目录下有 `skill.md`(或用 `SKILL_FILE` 指定入口);
- 子文件用相对路径引用(支持 markdown 链接、图片、裸文件名、`目录名:` 形式)。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues