@osqi/mteam-mcp
v0.2.1
Published
MCP server for searching M-Team torrents.
Downloads
605
Maintainers
Readme
@osqi/mteam-mcp
用于查询 M-Team 种子数据的 MCP Server,接口地址为 https://api.m-team.cc。
安装
npm install
npm run build发布到 npm 后,可以通过 mteam-mcp 这个二进制入口启动。
配置
创建 .env 文件:
MTEAM_API_KEY=your_mteam_api_key
MTEAM_CATEGORY_IDS=419,423
MTEAM_SEARCH_MODE=normal
MTEAM_PUSH_FETCH_SIZE=100
MTEAM_API_BASE_URL=https://api.m-team.cc
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
TELEGRAM_CHAT_ID=your_telegram_chat_id
QBITTORRENT_URL=http://127.0.0.1:8080
QBITTORRENT_USERNAME=admin
QBITTORRENT_PASSWORD=your_qbittorrent_password
MTEAM_PUSH_STATE_PATH=.mteam-push-state.jsonMTEAM_API_KEY 会作为 x-api-key 请求头发送,不会进入请求 body。
MTEAM_CATEGORY_IDS 是逗号分隔的分类 ID 列表,会作为每次请求里的 categories 字段。工具入参不接受 categories,分类始终来自这个环境变量。
MTEAM_SEARCH_MODE 是搜索模式,例如 normal。两个搜索工具都不接受 mode 入参,请求始终使用这个环境变量;未配置时默认使用 normal。
MTEAM_PUSH_FETCH_SIZE 是 pushTorrentSearch 每次扫描的记录数,默认及最大值均为 100。工具入参不能覆盖这个值。
TELEGRAM_BOT_TOKEN 用于 pushTorrentSearch 调用 Telegram Bot API 发送消息。
TELEGRAM_CHAT_ID 是 Telegram 推送目标,可以是用户、群组或频道。bot token 只代表机器人本身,不能决定消息发送到哪里,所以这个配置是必须的。
QBITTORRENT_URL、QBITTORRENT_USERNAME 和 QBITTORRENT_PASSWORD 用于登录 qBittorrent WebUI 并添加下载任务。三个参数必须同时配置;配置完整后 Telegram 消息会显示“推送”按钮,并启用 addTorrentToQbittorrent 工具。
按钮回调使用 Telegram 长轮询,由同一个监听器处理所有消息。请使用一个没有配置 webhook 的 Bot,并保持 MCP 进程运行;消息数量不会增加监听器数量。
MTEAM_PUSH_STATE_PATH 用于保存已经成功推送过的种子 ID,避免重复推送。状态记录上限与 MTEAM_PUSH_FETCH_SIZE 相同;成功加入新 ID 后会删除 pushedAt 最早的记录。
MCP 客户端配置
多数 MCP 客户端都支持 command、args、env 这种 stdio server 配置方式。推荐直接通过 npx 运行已发布的 npm 包:
{
"mcpServers": {
"mteam": {
"command": "npx",
"args": ["-y", "@osqi/mteam-mcp"],
"env": {
"MTEAM_API_KEY": "your_mteam_api_key",
"MTEAM_CATEGORY_IDS": "419,423",
"MTEAM_SEARCH_MODE": "normal",
"MTEAM_PUSH_FETCH_SIZE": "100",
"MTEAM_API_BASE_URL": "https://api.m-team.cc",
"TELEGRAM_BOT_TOKEN": "your_telegram_bot_token",
"TELEGRAM_CHAT_ID": "your_telegram_chat_id",
"QBITTORRENT_URL": "http://127.0.0.1:8080",
"QBITTORRENT_USERNAME": "admin",
"QBITTORRENT_PASSWORD": "your_qbittorrent_password",
"MTEAM_PUSH_STATE_PATH": ".mteam-push-state.json"
}
}
}
}opencode
在 opencode 的 MCP 配置中新增一个名为 mteam 的 server,使用上面的 mcpServers.mteam 配置即可。
如果 opencode 使用界面添加 MCP,字段对应关系如下:
- name:
mteam - command:
npx - args:
-y,@osqi/mteam-mcp - env: 填入上方环境变量
Hermes Agent
在 Hermes Agent 的 MCP 配置中新增 mteam server,使用同样的 stdio 配置:
{
"name": "mteam",
"command": "npx",
"args": ["-y", "@osqi/mteam-mcp"],
"env": {
"MTEAM_API_KEY": "your_mteam_api_key",
"MTEAM_CATEGORY_IDS": "419,423",
"MTEAM_SEARCH_MODE": "normal",
"MTEAM_PUSH_FETCH_SIZE": "100",
"MTEAM_API_BASE_URL": "https://api.m-team.cc",
"TELEGRAM_BOT_TOKEN": "your_telegram_bot_token",
"TELEGRAM_CHAT_ID": "your_telegram_chat_id",
"QBITTORRENT_URL": "http://127.0.0.1:8080",
"QBITTORRENT_USERNAME": "admin",
"QBITTORRENT_PASSWORD": "your_qbittorrent_password",
"MTEAM_PUSH_STATE_PATH": ".mteam-push-state.json"
}
}如果客户端支持读取 .env,也可以只配置 command 和 args,把敏感信息放在运行目录的 .env 文件中。
MCP 使用
在 MCP 客户端中配置运行:
npx @osqi/mteam-mcp本地开发时可以运行:
npm run dev工具:torrentSearch
只查询 M-Team 数据,不推送 Telegram。
入参:
{
"visible": 1,
"pageNumber": 1,
"pageSize": 30
}所有字段都是可选的,默认值:
visible:1pageNumber:1pageSize:30
当前版本不支持 keyword。categories 也不是工具入参,它始终来自 MTEAM_CATEGORY_IDS。
发送到 M-Team 的请求 body 示例:
{
"mode": "normal",
"visible": 1,
"categories": ["419", "423"],
"pageNumber": 1,
"pageSize": 30
}请求 body 中的 mode 始终来自 .env:
MTEAM_SEARCH_MODE=normal工具调用者不能传入或覆盖 mode。
请求地址:
POST https://api.m-team.cc/api/torrent/search请求头:
content-type: application/json
x-api-key: <MTEAM_API_KEY>工具:addTorrentToQbittorrent
根据 M-Team 种子 ID 生成临时下载 URL,并提交到 qBittorrent。这个工具适合在 MCP Inspector 中单独调试完整下载链路。
入参:
{
"id": "1167644"
}成功返回:
{
"id": "1167644",
"status": "submitted",
"stages": {
"downloadUrlGenerated": true,
"qbittorrentAuthenticated": true,
"torrentSubmitted": true
}
}失败结果会包含 stage 和经过脱敏的错误信息,不会返回 M-Team 下载 URL、API key、qBittorrent 密码或 SID。
本地构建后可运行 MCP Inspector:
npx @modelcontextprotocol/inspector node dist/index.js在 Inspector 的 Tools 页面选择 addTorrentToQbittorrent,输入种子 ID 后调用。Inspector 的 stdio 启动方式可参考其官方说明。
工具:pushTorrentSearch
查询 M-Team,按创建时间从早到晚排序,跳过已经推送过的 ID,并把最早的未推送记录发送到 Telegram。每次调用最多发送一条。
入参:
{
"visible": 1,
"pageNumber": 1
}所有字段都是可选的,默认值:
visible:1pageNumber:1
读取数量不属于工具入参,固定从 MTEAM_PUSH_FETCH_SIZE 读取。
提取后的数据结构:
{
"id": "123",
"name": "完整种子标题",
"smallDescr": "完整描述",
"cover": "https://example.com/cover.jpg",
"category": "423",
"size": "1073741824",
"discount": "FREE",
"createdDate": "2026-06-26 12:00:00"
}字段来源:
id:item.idname:item.namesmallDescr:item.smallDescrcover:item.imageList?.[0] ?? nullcategory:item.categorysize:item.sizediscount:item.status.discountcreatedDate:item.createdDate
推送文案示例:
📌 完整种子标题(可复制代码样式)
📝 完整描述(正常字体)
🏷️ 类型: 游戏 · 💾 大小: 1.00 GB 🆓 FREE
🔗 ID: 123
🕒 创建时间: 2026-06-26 12:00:00第一行直接显示完整 name,不添加标题前缀。smallDescr 非空时完整显示。当 discount 为 FREE 时,会在大小后面追加 FREE;其他值不显示。已内置常用分类 ID 的中文映射,未知分类会显示原始 ID。
Telegram 消息使用紧凑的 HTML 样式和克制的表情符号:标题使用可复制的代码样式,字段名加粗,描述使用正常字体,类型与大小合并为一行,大小与创建时间使用普通文本,FREE 会以 🆓 FREE 单独强调。smallDescr 最多显示 100 个 Unicode 字符,超出后添加省略号。ID 数字通过 HTML anchor 链接到 https://kp.m-team.cc/detail/{id},点击后可打开对应的 M-Team 详情页。🔗 ID: 不在链接内,只有完整 ID 数字可点击。图文 caption 和纯文本消息都会使用相同样式;长度超限时优先截断描述并保留 ID 链接及其他固定字段。
如果 cover 存在,MCP 会携带 M-Team Referer 将图片下载到内存,检查响应类型和 10 MB 大小限制,再通过 multipart/form-data 调用 Telegram sendPhoto。图片不会写入磁盘,上传完成后由内存自动释放,不会留下临时文件。
如果没有封面,或者封面下载、内容检查、图片上传任一步失败,会自动调用 sendMessage 发送相同文案。纯文本发送成功后仍会标记该 ID,避免坏封面阻塞后续记录;纯文本也失败时才保留未推送状态。
qBittorrent 配置完整时,图文和纯文本消息都会带有“推送”按钮。按钮数据只包含种子 ID;点击后会调用与 addTorrentToQbittorrent 相同的内部下载服务。目标聊天中的用户均可点击,结果通过 Telegram 提示,按钮会保留。
抓取结果会按 createdDate 从早到晚稳定排序;创建时间相同的记录保持接口原顺序,日期缺失或无效的记录排在最后。每次调用只发送排序后的第一条未推送记录,成功后写入状态文件并结束。发送失败时不会标记该 ID,也不会继续发送后面的记录,下次调用会重新尝试。若本次读取的记录全部已经推送,则正常结束且不发送消息。
状态文件最多保留 MTEAM_PUSH_FETCH_SIZE 条记录。成功推送新记录后,如果超过容量,会删除 pushedAt 最早的记录。
返回摘要示例:
{
"fetched": 100,
"alreadyPushed": 12,
"pending": 88,
"sent": 1,
"failed": 0,
"sentIds": ["123"],
"failedItems": []
}开发
npm run typecheck
npm run build
npm test