Doramagic 项目包 · 项目说明书
justoneapi-mcp 项目
生成时间:2026-05-15 01:49:03 UTC
项目概述
justoneapi-mcp 是一个基于 Model Context Protocol (MCP) 协议构建的服务器应用程序,专门用于在中国社交媒体平台和新闻网站上进行统一搜索和数据采集。该项目作为 MCP 主机(如 Claude Desktop、Cursor 等)与 JustOneAPI 之间的桥梁,使 AI 助手能够直接访问和分析中国主流社交媒体的内容。资料来源:[RE...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
项目简介
justoneapi-mcp 是一个基于 Model Context Protocol (MCP) 协议构建的服务器应用程序,专门用于在中国社交媒体平台和新闻网站上进行统一搜索和数据采集。该项目作为 MCP 主机(如 Claude Desktop、Cursor 等)与 JustOneAPI 之间的桥梁,使 AI 助手能够直接访问和分析中国主流社交媒体的内容。资料来源:README.md:1
该项目的核心设计理念是"传输而非转换"(Transport, not transformation),强调数据的稳定性和原始保真度,返回未经修改的上游 API 响应。资料来源:README.md:180
技术架构
系统架构图
graph TD
subgraph MCP主机 ["MCP 主机"]
A[Claude Desktop / Cursor]
end
subgraph justoneapi-mcp ["justoneapi-mcp 服务器"]
B[入口模块 src/index.ts]
C[工具注册模块]
D[HTTP 请求模块]
E[错误处理模块]
F[配置管理模块]
G[统一搜索工具]
H[快手搜索工具]
end
subgraph JustOneAPI ["JustOneAPI 服务"]
I[API 网关]
J[上游数据源]
end
A -->|MCP 协议| B
B --> C
C --> G
C --> H
G --> D
H --> D
D --> F
D -->|HTTP 请求| I
I --> J
J -->|微博| K[WEIBO]
J -->|微信| L[WEIXIN]
J -->|知乎| M[ZHIHU]
J -->|抖音| N[DOUYIN]
J -->|小红书| O[XIAOHONGSHU]
J -->|哔哩哔哩| P[BILIBILI]
J -->|快手| Q[KUAISHOU]
J -->|新闻| R[NEWS]技术栈
| 技术组件 | 版本要求 | 用途说明 |
|---|---|---|
| Node.js | >=18.0.0 | 运行时环境 |
| TypeScript | ^5.9.3 | 开发语言 |
| @modelcontextprotocol/sdk | ^1.25.1 | MCP 协议实现 |
| Zod | ^4.3.4 | 参数验证与 schema 定义 |
| dotenv | ^17.2.3 | 环境变量管理 |
资料来源:package.json:7-18
核心模块设计
模块职责说明
graph LR
subgraph 核心模块
A[config.ts]
B[http.ts]
C[errors.ts]
end
subgraph 工具模块
D[unified_search_v1.ts]
E[search_video_v2.ts]
end
subgraph 入口模块
F[index.ts]
end
F --> A
F --> D
F --> E
D --> B
E --> B
B --> C配置管理模块
src/common/config.ts 负责管理和验证环境变量配置。资料来源:src/common/config.ts:1
| 配置项 | 默认值 | 必填 | 说明 |
|---|---|---|---|
JUSTONEAPI_TOKEN | - | 是 | JustOneAPI 访问令牌 |
JUSTONEAPI_BASE_URL | https://api.justoneapi.com | 否 | API 端点地址 |
JUSTONEAPI_TIMEOUT_MS | 20000 | 否 | 请求超时时间(毫秒) |
JUSTONEAPI_RETRY | 1 | 否 | 失败后重试次数 |
JUSTONEAPI_DEBUG | false | 否 | 启用调试日志 |
资料来源:README.md:195-202
配置模块还提供令牌掩码功能,用于日志输出时保护敏感信息:
export function toSafeUrlForLog(fullUrl: string): string {
// 移除或掩码 token 查询参数
}
资料来源:src/common/config.ts:27-39
HTTP 请求模块
src/common/http.ts 实现统一的 HTTP 请求处理机制,具备以下特性:资料来源:src/common/http.ts:1
重试机制:
- 仅对以下情况触发重试:
- 请求超时(AbortError)
- HTTP 5xx 状态码
- 网络连接重置(ECONNRESET)
- 连接被拒绝(ECONNREFUSED)
- DNS 解析失败(ENOTFOUND)
退避策略:每次重试间隔为 250 * attempt 毫秒。资料来源:src/common/http.ts:28-29
graph TD
A[发起请求] --> B{请求成功?}
B -->|是| C[返回 JSON 响应]
B -->|否| D{可重试错误?}
D -->|超时/5xx/网络错误| E[等待退避时间]
D -->|其他错误| F[抛出异常]
E --> G[重试]
G --> A
D -->|达到最大重试次数| F错误处理模块
src/common/errors.ts 实现标准化的 MCP 错误码映射系统。资料来源:src/common/errors.ts:1
错误码映射表:
| 上游错误码 | MCP 错误码 | 描述 | 用户操作 |
|---|---|---|---|
| 302 | RATE_LIMITED | 请求频率超限 | 降低请求频率后重试 |
| - | INVALID_TOKEN | 令牌无效或未激活 | 更新 JUSTONEAPI_TOKEN |
| - | COLLECT_FAILED | 数据采集失败 | 短暂延迟后重试 |
| - | DAILY_QUOTA_EXCEEDED | 日用量超限 | 等待明天或升级套餐 |
| - | INSUFFICIENT_BALANCE | 账户余额不足 | 充值账户 |
| - | PERMISSION_DENIED | 无权访问资源 | 联系客服 |
| - | VALIDATION_ERROR | 请求参数无效 | 检查输入值 |
| - | INTERNAL_ERROR | 服务器内部错误 | 稍后重试 |
| - | NETWORK_TIMEOUT | 请求超时 | 检查网络或重试 |
| - | NETWORK_ERROR | 网络连接失败 | 检查网络连接 |
| - | UPSTREAM_ERROR | 上游未指明错误 | 重试或联系客服 |
资料来源:README.md:152-169
错误输出格式:
ERROR[ERROR_CODE] (upstream=XXX): Human-readable message
示例:ERROR[RATE_LIMITED] (upstream=302): Rate limit exceeded. Please slow down and retry later. 资料来源:README.md:170-174
可用工具
工具清单
| 工具名称 | 版本 | 功能描述 |
|---|---|---|
unified_search_v1 | v1 | 跨平台统一搜索 |
kuaishou_search_video_v2 | v2 | 快手视频搜索 |
资料来源:TOOLS.md:15-19
统一搜索工具 (unified_search_v1)
统一搜索工具支持在多个中国社交媒体和新闻平台上一站式搜索。资料来源:src/tools/search/unified_search_v1.ts:1
支持的平台:
ALL- 全部平台(默认)NEWS- 新闻WEIBO- 微博WEIXIN- 微信ZHIHU- 知乎DOUYIN- 抖音XIAOHONGSHU- 小红书BILIBILI- 哔哩哔哩KUAISHOU- 快手
资料来源:README.md:30-38
参数定义:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
keyword | string | 是 | 搜索关键词,支持高级语法 |
source | string | 否 | 平台过滤器,默认 ALL |
start | string | 首次请求必填 | 开始时间 yyyy-MM-dd HH:mm:ss (UTC+8),范围不超过 84 天 |
end | string | 首次请求必填 | 结束时间 yyyy-MM-dd HH:mm:ss (UTC+8),必须晚于开始时间 |
nextCursor | string | 分页时使用 | 来自上一页响应的游标 |
资料来源:src/tools/search/unified_search_v1.ts:14-35
搜索语法:
| 语法类型 | 格式 | 示例 | 说明 |
|---|---|---|---|
| 单关键词 | word | deepseek | 搜索单个关键词 |
| AND 搜索 | word1 word2 | deepseek chatgpt | 两个关键词必须同时出现 |
| OR 搜索 | word1~word2 | deepseek~chatgpt | 任一关键词出现即可 |
| NOT 搜索 | word -excluded | deepseek -chatgpt | 排除指定关键词 |
资料来源:README.md:122-127
API 调用示例:
{
"keyword": "AI",
"source": "ALL",
"start": "2025-01-01 00:00:00",
"end": "2025-01-02 23:59:59"
}
快手视频搜索工具 (kuaishou_search_video_v2)
快手视频搜索是平台特定的工具,专注于快手平台的视频内容搜索。资料来源:src/tools/kuaishou/search_video_v2.ts:1
参数定义:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
keyword | string | 是 | - | 搜索关键词,如 dance |
page | number | 否 | 1 | 页码,从 1 开始 |
资料来源:src/tools/kuaishou/search_video_v2.ts:5-8
输出契约
成功响应格式
所有工具返回原始 JSON 响应,设计原则是"最大数据保真度、无字段解析、无数据重组"。资料来源:README.md:149-152
{
"code": 0,
"message": null,
"recordTime": "2025-12-31T14:55:21Z",
"data": {
// 平台特定数据结构
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
code | integer | 0 表示成功,非 0 表示错误 |
message | string/null | 错误信息,成功时为 null |
recordTime | string | 响应记录时间(ISO 8601 格式) |
data | object | 平台特定数据内容 |
分页机制
当搜索结果存在更多页面时,响应会包含 nextCursor 字段。用户可以通过以下方式继续获取下一页:
- "显示更多结果"
- "继续获取上一页的更多结果"
- "继续下一页"
系统会自动从上一条响应中提取 nextCursor 并用于后续请求。资料来源:README.md:128-141
graph LR
A[首次请求] -->|无 nextCursor| B[返回第一页 + nextCursor]
B --> C[请求第二页]
C -->|携带 nextCursor| D[返回第二页 + nextCursor]
D --> E[继续...直到无 nextCursor]安装与配置
安装方式
推荐方式:npx(无需安装)
直接使用 npx 运行,无需本地安装:
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_token_here"
}
}
}
}
资料来源:README.md:70-80
Claude Desktop 配置
配置文件位置:
| 操作系统 | 配置文件路径 |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
自定义配置示例
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_token_here",
"JUSTONEAPI_TIMEOUT_MS": "30000",
"JUSTONEAPI_DEBUG": "true"
}
}
}
}
版本管理
项目使用动态版本管理机制,从 package.json 读取版本号:资料来源:src/version.ts:1
const packageJsonPath = join(__dirname, "../package.json");
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
version = packageJson.version || "0.0.0";
项目结构
justoneapi-mcp/
├── src/
│ ├── index.ts # 入口模块
│ ├── version.ts # 版本管理
│ ├── common/
│ │ ├── config.ts # 配置管理
│ │ ├── http.ts # HTTP 请求处理
│ │ └── errors.ts # 错误处理
│ └── tools/
│ ├── search/
│ │ └── unified_search_v1.ts # 统一搜索工具
│ └── kuaishou/
│ └── search_video_v2.ts # 快手搜索工具
├── package.json
├── eslint.config.js
├── README.md
├── TOOLS.md
└── LICENSE
设计哲学
传输,而非转换
该 MCP 服务器的设计优先级为:资料来源:README.md:179-182
- 稳定性:确保服务可靠运行
- 透明度:返回原始数据,不隐藏上游信息
- 数据保真度:返回未修改的上游 API 响应
这一设计理念确保了长期兼容性和最大化的数据完整性,用户可以直接访问底层数据并进行自定义分析。
许可证
本项目采用 MIT 许可证开源授权。资料来源:README.md:206
资料来源:[package.json:7-18]()
安装部署
本文档详细说明 justoneapi-mcp 的安装、配置和部署流程。justoneapi-mcp 是一个基于 Model Context Protocol (MCP) 的服务器,用于连接 JustOneAPI 社交媒体数据搜索服务。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
系统要求
运行环境
| 组件 | 最低版本要求 |
|---|---|
| Node.js | >= 18.0.0 |
资料来源:package.json:28
依赖包
| 依赖包 | 版本 | 用途 |
|---|---|---|
| @modelcontextprotocol/sdk | ^1.25.1 | MCP 协议实现 |
| zod | ^4.3.4 | 参数验证与 Schema 定义 |
| dotenv | ^17.2.3 | 环境变量管理 |
资料来源:package.json:33-36
安装方式
方式一:npx 方式(推荐)
使用 npx 可以直接运行,无需预先安装:
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_actual_token_here"
}
}
}
}
这种方式的优势在于:
- 无需手动安装
- 始终使用最新版本
- 配置简单快捷
资料来源:README.md:71-79
方式二:本地安装
如果需要特定版本或离线部署:
npm install -g justoneapi-mcp
或项目依赖方式:
npm install justoneapi-mcp
MCP 主机配置
Claude Desktop 配置
#### macOS
配置文件路径:~/Library/Application Support/Claude/claude_desktop_config.json
#### Windows
配置文件路径:%APPDATA%\Claude\claude_desktop_config.json
#### Linux
配置文件路径:~/.config/Claude/claude_desktop_config.json
完整配置示例
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_actual_token_here",
"JUSTJUSTONEAPI_TIMEOUT_MS": "30000",
"JUSTONEAPI_DEBUG": "true"
}
}
}
}
资料来源:README.md:64-89
环境变量配置
必需配置
| 变量名 | 说明 | 默认值 |
|---|---|---|
| JUSTONEAPI_TOKEN | JustOneAPI 访问令牌 | 必需 |
可选配置
| 变量名 | 默认值 | 说明 |
|---|---|---|
| JUSTONEAPI_BASE_URL | https://api.justoneapi.com | API 端点地址 |
| JUSTONEAPI_TIMEOUT_MS | 20000 | 请求超时时间(毫秒) |
| JUSTONEAPI_RETRY | 1 | 首次请求失败后的重试次数 |
| JUSTONEAPI_DEBUG | false | 是否启用调试日志 |
资料来源:README.md:91-100
令牌获取
访问 JustOneAPI Dashboard 注册并获取 API 令牌。
配置模块详解
配置加载流程
graph TD
A[启动 MCP Server] --> B[检查 JUSTONEAPI_TOKEN]
B --> C{Token 是否存在且非空?}
C -->|是| D[加载可选配置]
C -->|否| E[输出错误信息并退出]
D --> F[配置加载完成]
F --> G[注册工具并启动服务]
E --> H[进程终止]配置模块负责在服务启动时验证必要参数,核心逻辑位于 src/common/config.ts。
资料来源:src/common/config.ts
令牌验证
export function requireToken(): string {
const token = process.env.JUSTONEAPI_TOKEN;
if (!token?.trim()) {
throw new Error("JUSTONEAPI_TOKEN is required");
}
return token;
}
该函数在所有 API 请求前被调用,确保令牌有效。
资料来源:src/common/config.ts
安全日志处理
配置模块提供令牌脱敏功能,避免在日志中泄露敏感信息:
export function toSafeUrlForLog(fullUrl: string): string {
try {
const u = new URL(fullUrl);
if (u.searchParams.has("token")) {
u.searchParams.set("token", maskToken(u.searchParams.get("token") ?? ""));
}
return u.toString();
} catch {
return fullUrl.replace(/token=([^&]+)/g, (_m, g1) => `token=${maskToken(g1)}`);
}
}
资料来源:src/common/config.ts
HTTP 请求机制
请求流程
graph TD
A[发起请求] --> B{重试次数 < maxRetries?}
B -->|是| C[创建 AbortController]
C --> D[设置超时定时器]
D --> E[发送 GET 请求]
E --> F{响应状态码 < 500?}
F -->|是| G[解析 JSON 响应]
G --> H{业务代码 == 0?}
H -->|是| I[返回响应数据]
H -->|否| J[抛出业务错误]
F -->|否| K{可重试错误?}
K -->|是| L[等待后重试]
K -->|否| M[抛出错误]
J --> N[返回错误响应]
B -->|否| M
L --> B重试策略
请求失败时,HTTP 模块会自动重试以下情况:
| 错误类型 | 是否重试 |
|---|---|
| AbortError(超时) | ✅ 重试 |
| HTTP 5xx 错误 | ✅ 重试 |
| ECONNRESET | ✅ 重试 |
| ECONNREFUSED | ✅ 重试 |
| ENOTFOUND | ✅ 重试 |
| HTTP 4xx 错误 | ❌ 不重试 |
| 业务代码 != 0 | ❌ 不重试 |
重试间隔采用简单退避策略:250ms * attempt。
超时配置
默认超时时间为 20 秒,可通过 JUSTONEAPI_TIMEOUT_MS 环境变量自定义:
const timer = setTimeout(() => controller.abort(), config.timeoutMs);
服务启动流程
启动时验证
graph TD
A[main 函数入口] --> B[检查环境变量]
B --> C{JUSTONEAPI_TOKEN 是否设置?}
C -->|否| D[输出错误信息]
D --> E[进程终止]
C -->|是| F[创建 MCP Server]
F --> G[注册 unified_search_v1 工具]
G --> H[注册 kuaishou_search_video_v2 工具]
H --> I[连接 stdio 传输]
I --> J[服务就绪]主入口代码
async function main() {
if (!process.env.JUSTONEAPI_TOKEN?.trim()) {
console.error(
"[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.\n" +
"Please set the JUSTONEAPI_TOKEN environment variable..."
);
process.exit(1);
}
// ... 启动服务
}
资料来源:src/index.ts:58-65
TypeScript 编译配置
项目配置
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
exclude": ["node_modules", "dist"]
}
编译产物输出至 dist 目录,包含以下文件:
| 目录 | 内容 |
|---|---|
| dist/common/ | 通用模块(config、http、errors) |
| dist/tools/ | 工具模块 |
| dist/index.js | 主入口 |
| dist/*.d.ts | 类型声明文件 |
资料来源:tsconfig.json
开发环境搭建
克隆项目
git clone https://github.com/justoneapi/justoneapi-mcp.git
cd justoneapi-mcp
安装依赖
npm install
TypeScript 类型检查
npm run typecheck
代码格式化
npm run format
ESLint 检查
npm run lint
构建项目
npm run build
启动服务(开发模式)
npm run start
项目文件结构
justoneapi-mcp/
├── src/
│ ├── index.ts # 主入口文件
│ ├── version.ts # 版本信息
│ ├── common/
│ │ ├── config.ts # 配置管理
│ │ ├── http.ts # HTTP 请求封装
│ │ └── errors.ts # 错误处理
│ └── tools/
│ └── search/
│ └── unified_search_v1.ts # 统一搜索工具
├── dist/ # 编译输出
├── package.json # 项目配置
├── tsconfig.json # TypeScript 配置
└── eslint.config.js # ESLint 配置
故障排查
常见问题
#### 1. Token 未设置错误
[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.
解决方案:确保在 MCP 主机配置中正确设置 JUSTONEAPI_TOKEN 环境变量。
#### 2. 请求超时
ERROR[NETWORK_TIMEOUT]: Request timed out
解决方案:增加 JUSTONEAPI_TIMEOUT_MS 配置值(默认 20000ms)。
#### 3. 速率限制
ERROR[RATE_LIMITED]: Rate limit exceeded
解决方案:降低请求频率,等待一段时间后重试。
调试模式
启用调试日志以排查问题:
{
"env": {
"JUSTONEAPI_DEBUG": "true"
}
}
调试模式下会输出所有 HTTP 请求详情(令牌已脱敏)。
相关资源
资料来源:[package.json:28]()
配置管理
justoneapi-mcp 采用简洁而健壮的环境变量配置方案。配置管理系统负责验证必需参数、管理可选行为、确保敏感信息安全性,并在服务启动时进行完整性检查。资料来源:[README.md:108-120]()
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
justoneapi-mcp 采用简洁而健壮的环境变量配置方案。配置管理系统负责验证必需参数、管理可选行为、确保敏感信息安全性,并在服务启动时进行完整性检查。资料来源:README.md:108-120
核心配置架构
配置系统围绕环境变量构建,遵循"约定优于配置"的设计原则。所有配置项通过 process.env 访问,核心 token 验证在服务初始化阶段强制执行。
graph TD
A[服务启动] --> B[检查 JUSTONEAPI_TOKEN]
B --> C{Token 是否存在且非空?}
C -->|是| D[配置验证通过]
C -->|否| E[输出错误信息并退出]
D --> F[初始化 MCP Server]
F --> G[注册工具集]
E --> H[进程终止]
I[运行时配置] --> J[HTTP 请求]
J --> K[Token 注入]
K --> L[URL 安全日志]
D --> I资料来源:src/index.ts:55-68
环境变量配置项
必需配置
| 配置变量 | 类型 | 说明 |
|---|---|---|
JUSTONEAPI_TOKEN | string | API 访问令牌,用于认证上游 JustOneAPI 服务 |
服务启动时,若 JUSTONEAPI_TOKEN 未设置或为空字符串,将输出错误信息并终止进程。资料来源:src/index.ts:55-68
// 启动验证逻辑
if (!process.env.JUSTONEAPI_TOKEN?.trim()) {
console.error(
"[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.\n" +
"Please set the JUSTONEAPI_TOKEN environment variable in your MCP host configuration"
);
process.exit(1);
}
可选配置
| 配置变量 | 默认值 | 类型 | 说明 |
|---|---|---|---|
JUSTONEAPI_BASE_URL | https://api.justoneapi.com | string | API 端点地址 |
JUSTONEAPI_TIMEOUT_MS | 20000 | number | 请求超时时间(毫秒) |
JUSTONEAPI_RETRY | 1 | number | 首次请求失败后的重试次数 |
JUSTONEAPI_DEBUG | false | boolean | 启用调试日志输出到 stderr |
资料来源:README.md:114-119
Token 管理机制
Token 验证函数
requireToken() 函数封装了 token 的获取与验证逻辑,确保在所有需要认证的 API 调用前进行校验。资料来源:src/common/config.ts:1-20
export function requireToken(): string {
const token = process.env.JUSTONEAPI_TOKEN;
if (!token?.trim()) {
throw new Error("JUSTONEAPI_TOKEN environment variable is not set or is empty");
}
return token;
}
Token 掩码处理
为防止敏感信息在日志中泄露,系统提供了 Token 掩码功能。对于长度为 12 位以内的 Token,保留首尾各 2 位字符,中间用 * 替换;超过 12 位的 Token 保留前 6 位和后 4 位。资料来源:src/common/config.ts:26-35
function maskToken(token: string): string {
if (token.length <= 12) {
return token.slice(0, 2) + "*".repeat(token.length - 4) + token.slice(-2);
}
return token.slice(0, 6) + "*".repeat(8) + token.slice(-4);
}
URL 安全日志
在 HTTP 请求处理过程中,敏感 Token 参数会被自动掩码处理后再输出日志,确保生产环境中不会泄露认证凭据。资料来源:src/common/config.ts:40-55
sequenceDiagram
participant Client as 调用方
participant HTTP as HTTP 模块
participant Config as 配置模块
participant Log as 日志输出
Client->>HTTP: 发起 API 请求
HTTP->>Config: 调用 toSafeUrlForLog()
Config->>Config: 检测 URL 中的 token 参数
Config->>Config: 执行 maskToken() 掩码
Config-->>Log: 返回安全 URL
HTTP-->>Client: 返回响应HTTP 请求与配置联动
超时控制
超时时间通过 JUSTONEAPI_TIMEOUT_MS 配置控制,内部使用 AbortController 实现。超时错误会被映射为 NETWORK_TIMEOUT 错误码。资料来源:src/common/http.ts:35-45
重试机制
JUSTONEAPI_RETRY 配置指定初始请求失败后的重试次数。重试策略包含 250 毫秒的指数退避延迟。资料来源:src/common/http.ts:50-60
graph TD
A[发送请求] --> B{成功?}
B -->|是| C[返回结果]
B -->|否| D{可重试错误?}
D -->|AbortError| E[重试]
D -->|5xx 错误| E
D -->|ECONNRESET| E
D -->|ECONNREFUSED| E
D -->|ENOTFOUND| E
D -->|否| F[抛出异常]
E -->|attempt < retry| A
E -->|attempt >= retry| F重试条件判断逻辑:资料来源:src/common/http.ts:20-35
版本配置
版本信息从项目根目录的 package.json 动态读取,确保版本号与发布的包保持同步。若读取失败,默认回退至 0.0.0。资料来源:src/version.ts:1-22
错误处理与配置
配置相关的错误会被规范化为 MCP 错误码,提供可操作的错误信息和明确的错误来源。
| 错误码 | 触发条件 | 建议操作 |
|---|---|---|
INVALID_TOKEN | Token 无效或未激活 | 更新 JUSTONEAPI_TOKEN |
RATE_LIMITED | 请求频率超限 | 减慢请求速度 |
DAILY_QUOTA_EXCEEDED | 日配额用尽 | 等待次日或升级套餐 |
INSUFFICIENT_BALANCE | 账户余额不足 | 充值账户 |
NETWORK_TIMEOUT | 请求超时 | 检查网络或重试 |
NETWORK_ERROR | 网络连接失败 | 检查网络连接 |
资料来源:src/common/errors.ts:25-65
配置验证流程
flowchart TD
A[进程启动] --> B[加载环境变量]
B --> C[验证 JUSTONEAPI_TOKEN]
C --> D{验证结果}
D -->|通过| E[初始化 Zod Schema]
D -->|失败| K[输出错误并退出]
E --> F[注册 MCP 工具]
F --> G[启动服务监听]
G --> H[等待请求]
H --> I{收到请求}
I -->|unified_search_v1| J1[执行统一搜索]
I -->|kuaishou_search_video_v2| J2[执行快手搜索]
J1 --> L[注入 token 并调用 API]
J2 --> L
L --> M[返回原始 JSON]配置文件示例
Claude Desktop 配置
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_actual_token_here",
"JUSTONEAPI_TIMEOUT_MS": "30000",
"JUSTONEAPI_DEBUG": "true"
}
}
}
}
资料来源:README.md:80-96
最佳实践
- Token 安全:始终通过环境变量传递 Token,避免硬编码在配置文件中
- 超时设置:根据网络环境调整
JUSTONEAPI_TIMEOUT_MS,默认 20 秒适合大多数场景 - 重试策略:在不稳定网络环境下可适当增加
JUSTONEAPI_RETRY值 - 调试模式:生产环境应保持
JUSTONEAPI_DEBUG为false,仅在排查问题时启用
资料来源:[src/index.ts:55-68]()
工具概览
JustOneAPI MCP(Model Context Protocol)是一个 MCP 服务器项目,旨在为 Claude Desktop、Cursor 等 MCP 主机提供对中国社交媒体和新闻平台的数据搜索能力。该项目采用"传输而非转换"(Transport, not transformation)的设计理念,优先保证数据的稳定性和原始性 资料来源:[README.md...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 概述
JustOneAPI MCP(Model Context Protocol)是一个 MCP 服务器项目,旨在为 Claude Desktop、Cursor 等 MCP 主机提供对中国社交媒体和新闻平台的数据搜索能力。该项目采用"传输而非转换"(Transport, not transformation)的设计理念,优先保证数据的稳定性和原始性 资料来源:README.md:1。
工具(Tools)是 MCP 协议中的核心概念,每个工具代表一个可调用的功能单元。在 justoneapi-mcp 中,工具通过 @modelcontextprotocol/sdk 框架注册到 MCP 主机,用户可以通过自然语言或结构化参数调用这些工具 资料来源:src/index.ts:1-30。
2. 架构设计
2.1 整体架构
graph TD
subgraph MCP主机
A[Claude Desktop / Cursor]
end
subgraph justoneapi-mcp
B[工具注册层<br/>src/index.ts]
C[工具实现层<br/>src/tools/]
D[公共组件层<br/>src/common/]
end
subgraph 外部依赖
E[JustOneAPI 服务端]
end
A -->|MCP 协议调用| B
B --> C
C --> D
D -->|HTTP 请求| E
style A fill:#e1f5fe
style E fill:#fff3e02.2 请求处理流程
sequenceDiagram
participant U as 用户
participant M as MCP主机
participant S as justoneapi-mcp
participant A as JustOneAPI
U->>M: 自然语言请求
M->>S: 调用工具
S->>S: 参数验证<br/>Zod Schema
S->>A: HTTP GET请求
A->>S: JSON响应
S->>S: 错误映射
S->>M: 结构化结果
M->>U: 返回结果3. 可用工具列表
3.1 当前版本工具
| 工具名称 | 版本 | 功能描述 | 平台支持 |
|---|---|---|---|
unified_search_v1 | v1 | 统一多平台搜索 | Weibo、WeChat、Zhihu、Douyin、Xiaohongshu、Bilibili、Kuaishou、News |
kuaishou_search_video_v2 | v2 | 快手视频搜索 | 快手平台专用 |
资料来源:TOOLS.md:1-25
3.2 工具命名规范
所有工具遵循统一的命名约定:{platform}_{action}_{version} 资料来源:README.md:45-46
- 平台前缀(platform):指定目标平台,如
kuaishou、unified - 动作名称(action):表示操作类型,如
search_video、search - 版本号(version):使用语义化版本,如
v1、v2
4. 统一搜索工具(unified_search_v1)
4.1 工具描述
unified_search_v1 是该 MCP 服务器的核心工具,支持跨多个中国社交媒体和新闻平台进行联合搜索。用户可以通过单一请求同时查询微博、微信、知乎、抖音、小红书、B站、快手和新闻平台的数据 资料来源:src/index.ts:31-40。
4.2 参数说明
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
keyword | string | 是 | - | 搜索关键词,支持高级语法 |
source | string | 否 | ALL | 平台筛选器 |
start | string | 条件必填 | - | 开始时间(UTC+8),格式:yyyy-MM-dd HH:mm:ss |
end | string | 条件必填 | - | 结束时间(UTC+8),格式:yyyy-MM-dd HH:mm:ss |
nextCursor | string | 否 | - | 分页游标,用于获取后续页面 |
资料来源:src/tools/search/unified_search_v1.ts:15-42
4.3 平台选项
| 平台标识 | 描述 |
|---|---|
ALL | 全部平台(默认) |
NEWS | 新闻 |
WEIBO | 微博 |
WEIXIN | 微信 |
ZHIHU | 知乎 |
DOUYIN | 抖音 |
XIAOHONGSHU | 小红书 |
BILIBILI | B站(哔哩哔哩) |
KUAISHOU | 快手 |
资料来源:src/tools/search/unified_search_v1.ts:10-13
4.4 搜索语法
| 语法类型 | 语法格式 | 示例 | 说明 |
|---|---|---|---|
| 单关键词 | keyword | deepseek | 搜索包含指定关键词的内容 |
| AND 搜索 | word1 word2 | deepseek chatgpt | 同时包含两个关键词 |
| OR 搜索 | word1~word2 | deepseek~chatgpt | 包含任一关键词 |
| NOT 搜索 | word1 -word2 | deepseek -chatgpt | 包含前者,排除后者 |
资料来源:TOOLS.md:43-51
4.5 参数验证逻辑
graph TD
A[输入参数] --> B{keyword 是否为空?}
B -->|是| C[抛出错误]
B -->|否| D{是否使用分页?}
D -->|是 nextCursor| E[使用 nextCursor]
D -->|否 首頁| F{start 和 end 都存在?}
F -->|是| G[构建查询参数]
F -->|否| H[抛出错误:需要 start 和 end]
C --> I[返回 INVALID 请求]
H --> I
E --> J[构建查询参数<br/>含 nextCursor]
G --> K[调用 getJson]
J --> K首次请求时,start 和 end 参数必须提供,且时间范围不能超过 84 天。使用分页时,只需提供 nextCursor 即可 资料来源:src/tools/search/unified_search_v1.ts:30-37。
5. 错误处理机制
5.1 错误码映射表
| 错误码 | 描述 | 用户操作建议 |
|---|---|---|
INVALID_TOKEN | Token 无效或未激活 | 更新 JUSTONEAPI_TOKEN |
COLLECT_FAILED | 数据采集失败 | 稍后重试 |
RATE_LIMITED | 请求过于频繁 | 降低请求频率,稍后重试 |
DAILY_QUOTA_EXCEEDED | 达到每日使用限额 | 等待明天或升级套餐 |
INSUFFICIENT_BALANCE | 账户余额不足 | 充值账户 |
PERMISSION_DENIED | 无权访问该资源 | 联系技术支持 |
VALIDATION_ERROR | 请求参数无效 | 检查输入值 |
INTERNAL_ERROR | 服务器内部错误 | 稍后重试 |
NETWORK_TIMEOUT | 请求超时 | 检查网络或重试 |
NETWORK_ERROR | 网络连接失败 | 检查网络连接 |
UPSTREAM_ERROR | 上游服务未指明错误 | 重试或联系支持 |
资料来源:README.md:88-108
5.2 错误格式
所有错误均以统一格式返回:
ERROR[ERROR_CODE] (upstream=XXX): Human-readable message
示例:
ERROR[RATE_LIMITED] (upstream=302): Rate limit exceeded. Please slow down and retry later.
资料来源:src/common/errors.ts:1-30
5.3 错误处理流程
graph TD
A[HTTP 响应] --> B{HTTP 状态码}
B -->|200| C{业务 code}
B -->|非 200| D[抛出 NETWORK_ERROR]
C -->|0| E[返回成功响应]
C -->|非 0| F[映射错误码]
F --> G[构建 MCP 错误格式]
D --> G
E --> H[返回 JSON 数据]
G --> I[返回错误信息]错误映射逻辑会自动识别超时、HTTP 状态码、网络错误等不同类型的故障,并将其转换为用户友好的错误信息 资料来源:src/common/errors.ts:35-70。
6. HTTP 请求机制
6.1 重试策略
graph TD
A[请求发起] --> B{尝试次数 <= 最大重试次数?}
B -->|是| C[发起 HTTP 请求]
C --> D{请求成功?}
D -->|是| E[返回响应]
D -->|否| F{可重试错误?}
F -->|是| G[等待 250ms * 尝试次数]
F -->|否| H[抛出错误]
G --> B
B -->|否| H可重试的错误类型包括:
- 超时错误(
AbortError) - HTTP 5xx 错误
- 网络连接重置(
ECONNRESET) - 连接被拒绝(
ECONNREFUSED) - DNS 解析失败(
ENOTFOUND)
6.2 超时配置
| 配置项 | 默认值 | 说明 |
|---|---|---|
JUSTONEAPI_TIMEOUT_MS | 20000ms | 单次请求超时时间 |
7. 认证与配置
7.1 环境变量配置
| 变量名 | 必填 | 默认值 | 描述 |
|---|---|---|---|
JUSTONEAPI_TOKEN | 是 | - | JustOneAPI 访问令牌 |
JUSTONEAPI_BASE_URL | 否 | https://api.justoneapi.com | API 端点 |
JUSTONEAPI_TIMEOUT_MS | 否 | 20000 | 请求超时(毫秒) |
JUSTONEAPI_RETRY | 否 | 1 | 首次失败后的重试次数 |
JUSTONEAPI_DEBUG | 否 | false | 启用调试日志输出到 stderr |
资料来源:README.md:119-130
7.2 Token 安全处理
系统内置 Token 脱敏功能,在日志输出时会自动将 Token 替换为掩码格式(显示前 4 位和后 4 位) 资料来源:src/common/config.ts:1-20。
示例:
原始 Token: sk-abc123def456ghi789
日志显示: sk-abc***ghi789
8. 分页机制
8.1 分页流程
当搜索结果存在多页时,响应中会包含 nextCursor 字段。用户可以通过以下方式继续获取更多结果:
- "Show me the next page of results"
- "Get more results from the previous search"
- "Continue with the next page"
graph LR
A[首页请求<br/>start + end] --> B[返回结果<br/>+ nextCursor]
B --> C{需要更多结果?}
C -->|是| D[下一页请求<br/>nextCursor]
C -->|否| E[结束]
D --> B使用 nextCursor 分页时,无需再次提供 start、end 或 source 参数,因为游标中已包含这些信息 资料来源:README.md:64-70。
8.2 分页参数限制
- 时间范围:首屏请求的时间跨度不能超过 84 天
- 分页响应:每次返回 10-20 条结果
9. 快速入门
9.1 Claude Desktop 配置示例
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_actual_token_here"
}
}
}
}
9.2 常用调用示例
跨平台搜索:
使用 unified_search_v1 工具搜索"AI",覆盖所有平台,时间范围为最近一个月。
单平台搜索:
搜索"chatgpt"相关内容,仅限微博平台,时间范围为2024年12月1日至2025年1月2日。
分页获取:
Show me more results
10. 输出格式
10.1 成功响应
{
"code": 0,
"message": null,
"recordTime": "2025-12-31T14:55:21Z",
"data": {
// 平台特定数据结构
}
}
10.2 错误响应
{
"isError": true,
"content": [
{
"type": "text",
"text": "ERROR[ERROR_CODE] (upstream=XXX): Human-readable message"
}
]
}
11. 项目依赖
| 依赖包 | 版本 | 用途 |
|---|---|---|
@modelcontextprotocol/sdk | ^1.25.1 | MCP 协议 SDK |
zod | ^4.3.4 | 参数验证与 Schema 定义 |
dotenv | ^17.2.3 | 环境变量管理 |
资料来源:package.json:1-50
资料来源:[TOOLS.md:1-25]()
统一搜索工具
统一搜索工具(unifiedsearchv1)是 justoneapi-mcp 项目提供的核心功能,旨在为用户提供跨多个中国社交媒体和新闻平台的统一搜索能力。通过单一接口,用户可以同时检索微博、微信、知乎、抖音、小红书、B站、快手和新闻等多个平台的内容,无需逐个平台调用不同的 API。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
统一搜索工具(unified_search_v1)是 justoneapi-mcp 项目提供的核心功能,旨在为用户提供跨多个中国社交媒体和新闻平台的统一搜索能力。通过单一接口,用户可以同时检索微博、微信、知乎、抖音、小红书、B站、快手和新闻等多个平台的内容,无需逐个平台调用不同的 API。
该工具遵循项目的核心设计理念——传输而非转换,即保持原始数据的完整性和保真度,不对上游响应进行字段解析或数据重组。资料来源:README.md
架构设计
技术栈
统一搜索工具基于以下技术组件构建:
| 组件 | 技术选型 | 作用 |
|---|---|---|
| MCP SDK | @modelcontextprotocol/sdk ^1.25.1 | 提供 MCP 服务器基础设施 |
| 参数验证 | Zod ^4.3.4 | Schema 定义与输入验证 |
| HTTP 客户端 | Node.js 内置 fetch | API 请求处理 |
| 配置管理 | dotenv ^17.2.3 | 环境变量加载 |
资料来源:package.json
模块依赖关系
graph TD
A[unified_search_v1] --> B[requireToken]
A --> C[getJson]
A --> D[UnifiedSearchV1Input]
B --> E[config.ts - token验证]
C --> F[http.ts - HTTP请求]
F --> G[API Endpoint]
D --> H[Zod Schema验证]工具注册与入口
统一搜索工具通过 MCP SDK 的 server.registerTool() 方法注册到 MCP 服务器。工具注册时需要提供工具名称、描述和输入模式。资料来源:src/index.ts:22-42
server.registerTool(
"unified_search_v1",
{
description:
"Unified search across multiple platforms (Weibo, WeChat, Zhihu, Douyin, Xiaohongshu, Bilibili, Kuaishou, News). Search by keyword with time range. Supports AND/OR/NOT operators and pagination. Returns raw JSON response.",
inputSchema: UnifiedSearchV1Input.shape,
},
async (input) => {
// 处理逻辑
}
);
错误处理机制
工具执行过程中捕获所有异常,并通过 toMcpErrorPayload() 函数将错误转换为标准化的 MCP 错误格式返回。错误消息格式为:ERROR[ERROR_CODE] (upstream=XXX): Human-readable message。资料来源:src/index.ts:31-39
输入参数定义
UnifiedSearchV1Input 是统一搜索工具的 Zod Schema,定义了所有合法的输入参数及其验证规则。资料来源:src/tools/search/unified_search_v1.ts:10-32
参数一览
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| keyword | string | 是 | - | 搜索关键词,支持高级语法 |
| source | PlatformType | 否 | ALL | 平台筛选器 |
| start | string | 条件必填 | - | 开始时间(UTC+8),首页必需 |
| end | string | 条件必填 | - | 结束时间(UTC+8),首页必需 |
| nextCursor | string | 否 | - | 分页游标,用于后续页面 |
平台类型枚举
统一搜索支持以下平台类型:
export const PlatformType = z.enum([
"ALL",
"NEWS",
"WEIBO",
"WEIXIN",
"ZHIHU",
"DOUYIN",
"XIAOHONGSHU",
"BILIBILI",
"KUAISHOU",
]);
资料来源:src/tools/search/unified_search_v1.ts:7-18
| 枚举值 | 平台名称 |
|---|---|
| ALL | 所有平台(默认) |
| NEWS | 新闻 |
| 微博 | |
| WEIXIN | 微信 |
| ZHIHU | 知乎 |
| DOUYIN | 抖音 |
| XIAOHONGSHU | 小红书 |
| BILIBILI | B站 |
| KUAISHOU | 快手 |
参数验证规则
- keyword:最短长度 1 个字符,不允许空字符串
- start/end:首次请求时必须提供,且结束时间必须晚于开始时间
- 时间范围:查询时间跨度必须在 84 天以内
- nextCursor:用于分页时,必须替代 start/end 参数使用
搜索语法
统一搜索工具支持丰富的高级搜索语法,允许用户精确表达搜索意图。资料来源:TOOLS.md
语法类型
| 语法类型 | 示例 | 说明 |
|---|---|---|
| 单关键词 | deepseek | 搜索包含该关键词的所有内容 |
| AND 搜索 | deepseek chatgpt | 两个关键词必须同时出现 |
| OR 搜索 | deepseek~chatgpt | 两个关键词任一出现即可 |
| NOT 搜索 | deepseek -chatgpt | 包含第一个词但排除第二个词 |
使用示例
{
"keyword": "AI",
"source": "ALL",
"start": "2025-01-01 00:00:00",
"end": "2025-01-02 23:59:59"
}
请求处理流程
sequenceDiagram
participant User as 用户
participant MCP as MCP服务器
participant Handler as unifiedSearchV1
participant HTTP as getJson
participant API as JustOneAPI
User->>MCP: unified_search_v1 调用
MCP->>Handler: 传入输入参数
Handler->>Handler: Zod Schema 验证
Handler->>Handler: 构建 URL 参数
Handler->>HTTP: 发起 GET 请求
HTTP->>API: GET /api/search/v1
API-->>HTTP: JSON 响应
HTTP-->>Handler: 解析后的 JSON
Handler-->>MCP: 返回内容数组
MCP-->>User: 格式化输出分页机制
统一搜索工具采用游标式分页机制,与传统的页码分页方式不同。当搜索结果存在后续页面时,响应中会包含 nextCursor 字段。资料来源:README.md
分页流程
graph TD
A[首次搜索请求] --> B{提供 start/end?}
B -->|是| C[发起首页请求]
B -->|否| D[使用 nextCursor]
C --> E[获取响应]
D --> E
E --> F{存在 nextCursor?}
F -->|是| G[返回 nextCursor 给用户]
F -->|否| H[搜索完成]
G --> I[用户请求下一页]
I --> D分页使用方式
用户获取下一页结果时,无需再次提供 start、end 或 source 参数,因为游标中已包含这些信息:
Show me the next page of results
Get more results from the previous search
Continue with the next page
HTTP 请求处理
getJson 函数
统一搜索工具内部使用 getJson() 函数处理所有 HTTP 请求,该函数位于 src/common/http.ts。资料来源:src/common/http.ts
重试策略
getJson() 实现了智能重试机制,仅在以下情况下进行重试:
| 重试条件 | 触发场景 |
|---|---|
| 请求超时 | AbortError 异常 |
| HTTP 5xx 错误 | 服务器内部错误 |
| 网络连接重置 | ECONNRESET |
| 连接被拒绝 | ECONNREFUSED |
| DNS 解析失败 | ENOTFOUND |
重试逻辑采用指数退避策略,每次重试间隔为 250 * attempt 毫秒。
请求超时
默认请求超时时间为 20000 毫秒(20秒),可通过 JUSTONEAPI_TIMEOUT_MS 环境变量配置。资料来源:README.md
错误处理
错误码映射
项目维护了一套标准化的错误码体系,所有错误最终都会映射到这些代码。资料来源:src/common/errors.ts
| 错误码 | 含义 | 建议操作 |
|---|---|---|
| INVALID_TOKEN | Token 无效或已失效 | 更新 JUSTONEAPI_TOKEN |
| COLLECT_FAILED | 数据采集失败 | 稍后重试 |
| RATE_LIMITED | 请求过于频繁 | 降低请求频率 |
| DAILY_QUOTA_EXCEEDED | 达到日使用限额 | 等待次日或升级套餐 |
| INSUFFICIENT_BALANCE | 账户余额不足 | 充值账户 |
| PERMISSION_DENIED | 无权访问该资源 | 联系客服 |
| VALIDATION_ERROR | 请求参数无效 | 检查输入值 |
| INTERNAL_ERROR | 服务器内部错误 | 稍后重试 |
| NETWORK_TIMEOUT | 请求超时 | 检查网络或重试 |
| NETWORK_ERROR | 网络连接失败 | 检查网络连接 |
| UPSTREAM_ERROR | 上游未指明错误 | 重试或联系客服 |
错误响应格式
所有错误均以统一格式返回:
ERROR[ERROR_CODE] (upstream=XXX): Human-readable message
其中 upstream 字段表示上游 API 返回的原始错误码。
配置管理
环境变量
统一搜索工具使用以下环境变量进行配置:资料来源:README.md
| 变量名 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| JUSTONEAPI_TOKEN | 是 | - | 您的 JustOneAPI 令牌 |
| JUSTONEAPI_BASE_URL | 否 | https://api.justoneapi.com | API 端点 |
| JUSTONEAPI_TIMEOUT_MS | 否 | 20000 | 请求超时(毫秒) |
| JUSTONEAPI_RETRY | 否 | 1 | 首次失败后的重试次数 |
| JUSTONEAPI_DEBUG | 否 | false | 启用调试日志输出 |
Token 安全
配置模块实现了 Token 脱敏功能,在日志记录时会自动将 Token 遮蔽,防止敏感信息泄露。资料来源:src/common/config.ts
输出格式
统一搜索工具返回原始 JSON 响应,不进行任何字段标准化或数据结构重组。这是项目"传输而非转换"设计理念的体现。资料来源:TOOLS.md
成功响应结构
{
"code": 0,
"message": null,
"recordTime": "2025-12-31T14:55:00",
"data": {
// 平台特定的数据结构
}
}
code: 0表示成功code != 0表示错误(参见错误处理章节)
使用示例
基础搜索
使用自然语言请求统一搜索:
Search for AI discussions on Chinese social media from last week
Claude 会自动转换为正确的 API 格式,处理日期格式化(UTC+8 时区),并返回聚合结果。
高级搜索
平台特定搜索:
Search for "chatgpt" on Weibo only, from December 1st to January 2nd
复杂查询:
Search for posts containing "AI" OR "机器学习" but NOT "广告" on Zhihu,
from the last 30 days
配置示例
在 Claude Desktop 的 mcpServers 配置中添加:
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_token_here",
"JUSTONEAPI_TIMEOUT_MS": "30000",
"JUSTONEAPI_DEBUG": "true"
}
}
}
}
与其他工具的关系
justoneapi-mcp 项目中,除了统一搜索工具外,还提供了平台特定搜索工具,如 kuaishou_search_video_v2。两者都基于相同的底层 HTTP 和错误处理机制,但面向不同的使用场景。资料来源:src/tools/kuaishou/search_video_v2.ts
| 工具名称 | 搜索范围 | 适用场景 |
|---|---|---|
| unified_search_v1 | 多平台聚合搜索 | 跨平台舆情分析、品牌监控 |
| kuaishou_search_video_v2 | 快手平台 | 快手视频专项研究 |
资料来源:[package.json](https://github.com/justoneapi/justoneapi-mcp/blob/main/package.json)
平台专用工具
平台专用工具(Platform-Specific Tools)是 justoneapi-mcp 项目中针对特定社交媒体平台提供深度搜索能力的功能模块。与统一搜索工具 unifiedsearchv1 不同,平台专用工具针对单个平台进行优化,提供更精细的参数控制和平台特定的功能实现。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
平台专用工具(Platform-Specific Tools)是 justoneapi-mcp 项目中针对特定社交媒体平台提供深度搜索能力的功能模块。与统一搜索工具 unified_search_v1 不同,平台专用工具针对单个平台进行优化,提供更精细的参数控制和平台特定的功能实现。
当前已实现的平台专用工具包括:
| 工具名称 | 平台 | 版本 | 功能描述 |
|---|---|---|---|
kuaishou_search_video_v2 | 快手 | v2 | 快手视频关键词搜索 |
资料来源:src/index.ts:9
架构设计
工具注册机制
平台专用工具通过 MCP SDK 的 registerTool 方法注册到服务器中。每个工具包含三个核心组成部分:工具名称、描述信息(含 Zod 输入验证 schema)和异步处理函数。
graph TD
A[MCP 主机发送请求] --> B[服务器接收工具调用]
B --> C[匹配工具名称]
C --> D{找到对应工具?}
D -->|是| E[执行异步处理函数]
D -->|否| F[返回错误]
E --> G[调用平台 API]
G --> H{请求成功?}
H -->|是| I[返回原始 JSON]
H -->|否| J[错误处理]
J --> K[转换为 MCP 错误格式]资料来源:src/index.ts:18-40
目录结构
平台专用工具遵循统一的目录组织规范:
src/tools/
├── kuaishou/
│ └── search_video_v2.ts # 快手视频搜索 v2
└── search/
└── unified_search_v1.ts # 统一搜索 v1
这种结构确保了代码的模块化组织和可维护性,每个平台拥有独立的子目录,便于后续扩展更多平台工具。
快手视频搜索工具
功能介绍
kuaishou_search_video_v2 是专门用于在快手平台搜索视频内容的工具。该工具通过快手开放 API 获取视频搜索结果,返回未经处理的原始 JSON 数据,确保数据完整性。
资料来源:src/tools/kuaishou/search_video_v2.ts:1-4
输入参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
keyword | string | 是 | - | 搜索关键词,如 "dance" |
page | number | 否 | 1 | 页码,必须为正整数 |
输入验证由 Zod 库提供支持,确保参数类型的正确性:
export const KuaishouSearchVideoV2Input = z.object({
keyword: z.string().min(1).describe("Search keyword, e.g. 'dance'"),
page: z.number().int().min(1).default(1).describe("Page number, default 1"),
});
资料来源:src/tools/kuaishou/search_video_v2.ts:6-9
API 请求构建
工具将输入参数转换为 URL 查询参数并调用内部 HTTP 模块:
export async function kuaishouSearchVideoV2(input: z.infer<typeof KuaishouSearchVideoV2Input>) {
const token = encodeURIComponent(requireToken());
const keyword = encodeURIComponent(input.keyword);
const page = input.page;
return await getJson(
`/api/kuaishou/search-video/v2?token=${token}&keyword=${keyword}&page=${page}`
);
}
请求流程:
- 从环境配置获取 API Token 并进行 URL 编码
- 对搜索关键词进行 URL 编码处理
- 构建完整的 API 端点 URL
- 调用
getJson函数发起 HTTP GET 请求
资料来源:src/tools/kuaishou/search_video_v2.ts:11-18
工具注册流程
注册代码示例
在主入口文件中,工具通过标准化的注册流程添加到 MCP 服务器:
server.registerTool(
"kuaishou_search_video_v2",
{
description:
"Search Kuaishou videos by keyword. Returns the original raw JSON response from upstream without field normalization.",
inputSchema: KuaishouSearchVideoV2Input.shape,
},
async (input) => {
try {
const data = await kuaishouSearchVideoV2(input);
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} catch (e: unknown) {
const m = toMcpErrorPayload(e);
return {
isError: true,
content: [
{
type: "text",
text: `ERROR[${m.code}] (upstream=${m.upstreamCode ?? "N/A"}): ${m.message}`,
},
],
};
}
}
);
资料来源:src/index.ts:18-40
注册参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| 工具名称 | string | MCP 协议中调用该工具的标识符,遵循 {platform}_{action}_{version} 命名规范 |
| description | string | 工具功能描述,供 MCP 主机(如 Claude Desktop)展示给用户 |
| inputSchema | ZodObject | 使用 Zod 库定义的输入验证模式,包含参数类型、默认值和描述 |
| 处理函数 | async function | 接收验证后的输入参数,执行工具逻辑并返回结果 |
错误处理机制
错误转换流程
平台专用工具使用统一的错误处理机制 toMcpErrorPayload 将各类错误转换为标准化的 MCP 错误格式:
graph TD
A[异常发生] --> B{错误类型判断}
B -->|AbortError| C[NETWORK_TIMEOUT]
B -->|upstreamCode| D[业务错误码映射]
B -->|httpStatus| E[UPSTREAM_ERROR]
B -->|cause/code| F[NETWORK_ERROR]
B -->|其他| G[UPSTREAM_ERROR]
D --> H[返回 MCP 错误对象]
C --> H
E --> H
F --> H
G --> H
H --> I[格式化错误消息]
I --> J[ERROR[CODE] (upstream=X): message]资料来源:src/common/errors.ts:30-60
错误码映射表
| 上游错误码 | MCP 错误码 | 说明 |
|---|---|---|
| 100 | INVALID_TOKEN | Token 无效或已失效 |
| 301 | COLLECT_FAILED | 数据采集失败 |
| 302 | RATE_LIMITED | 请求频率超限 |
| 303 | DAILY_QUOTA_EXCEEDED | 每日配额已用尽 |
| 400 | VALIDATION_ERROR | 参数验证错误 |
| 500 | INTERNAL_ERROR | 服务器内部错误 |
| 600 | PERMISSION_DENIED | 无权限访问 |
| 601 | INSUFFICIENT_BALANCE | 账户余额不足 |
资料来源:src/common/errors.ts:68-85
底层支持模块
HTTP 请求模块
平台专用工具通过 getJson 函数发起 API 请求,该函数具备以下特性:
- 自动重试机制:对超时、5xx 错误和网络连接错误进行自动重试
- 可配置超时:支持通过
JUSTONEAPI_TIMEOUT_MS环境变量配置请求超时时间,默认 20000ms - 请求重试次数:可通过
JUSTONEAPI_RETRY环境变量配置,默认 1 次重试 - Token 注入:自动将认证 Token 添加到请求头
const retryable =
error.name === "AbortError" ||
(typeof httpStatus === "number" && httpStatus >= 500) ||
error.code === "ECONNRESET" ||
error.code === "ECONNREFUSED" ||
error.code === "ENOTFOUND";
配置管理模块
工具通过 requireToken 函数获取环境变量中配置的 API Token:
export function requireToken(): string {
const token = process.env.JUSTONEAPI_TOKEN;
if (!token?.trim()) {
throw new Error("JUSTONEAPI_TOKEN is required");
}
return token;
}
资料来源:src/common/config.ts
工具命名规范
平台专用工具遵循统一的命名约定:
{platform}_{action}_{version}
| 组成部分 | 说明 | 示例 |
|---|---|---|
| platform | 目标平台标识(小写) | kuaishou、douyin、weibo |
| action | 操作类型 | search_video、get_user |
| version | API 版本号 | v1、v2 |
当前已实现的工具:
| 工具名称 | 平台 | 版本 | 状态 |
|---|---|---|---|
| kuaishou_search_video_v2 | 快手 | v2 | ✅ 已实现 |
| unified_search_v1 | 统一搜索 | v1 | ✅ 已实现 |
资料来源:README.md
扩展指南
添加新平台工具的步骤
- 创建工具目录:在
src/tools/下创建平台专属目录 - 定义输入模式:使用 Zod 定义输入参数验证 schema
- 实现工具函数:调用
getJson发起 API 请求 - 注册工具:在
src/index.ts中使用server.registerTool注册 - 更新文档:在 README.md 和 TOOLS.md 中添加工具说明
依赖要求
项目使用以下核心依赖实现平台专用工具功能:
| 依赖包 | 版本 | 用途 |
|---|---|---|
| @modelcontextprotocol/sdk | ^1.25.1 | MCP 服务器 SDK |
| zod | ^4.3.4 | 输入参数验证 |
| dotenv | ^17.2.3 | 环境变量管理 |
资料来源:package.json:18-30
与统一搜索工具的对比
| 特性 | 平台专用工具 | 统一搜索工具 |
|---|---|---|
| 覆盖范围 | 单平台 | 多平台聚合 |
| 参数设计 | 平台特定参数 | 通用参数 |
| 使用场景 | 深度平台分析 | 跨平台概览 |
| 实现复杂度 | 较高 | 较低 |
| 扩展方式 | 按平台添加 | 通用扩展 |
资料来源:src/tools/search/unified_search_v1.ts
未来规划
根据项目规划,以下平台专用工具即将推出:
- 抖音视频搜索
- 微博帖子搜索
- Bilibili 视频搜索
- 微信内容搜索
- 知乎内容搜索
- 小红书内容搜索
- 新闻聚合搜索
资料来源:TOOLS.md
资料来源:[src/index.ts:9]()
错误处理
justoneapi-mcp 采用统一的错误处理机制,将上游 API 的原始响应转换为标准化的 MCP 错误格式。该项目遵循"传输而非转换"(Transport, not transformation)的设计理念,在保持数据完整性的同时,为用户提供清晰、可操作的错误信息。 资料来源:README.md
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
justoneapi-mcp 采用统一的错误处理机制,将上游 API 的原始响应转换为标准化的 MCP 错误格式。该项目遵循"传输而非转换"(Transport, not transformation)的设计理念,在保持数据完整性的同时,为用户提供清晰、可操作的错误信息。 资料来源:README.md
错误处理模块位于 src/common/errors.ts,负责以下核心功能:
- 定义标准化错误码体系(
JOAErrorCode) - 映射上游 API 错误码到 MCP 错误码
- 构建用户友好的错误消息
- 将各类异常转换为统一的 MCP 错误负载
错误码体系
JOAErrorCode 类型定义
项目定义了 11 种标准化错误码,涵盖认证失败、网络问题、配额限制等各种场景。 资料来源:src/common/errors.ts:58-69
export type JOAErrorCode =
| "INVALID_TOKEN"
| "COLLECT_FAILED"
| "RATE_LIMITED"
| "DAILY_QUOTA_EXCEEDED"
| "VALIDATION_ERROR"
| "INTERNAL_ERROR"
| "PERMISSION_DENIED"
| "INSUFFICIENT_BALANCE"
| "NETWORK_TIMEOUT"
| "NETWORK_ERROR"
| "UPSTREAM_ERROR";
错误码对照表
| 错误码 | 说明 | 用户操作 |
|---|---|---|
INVALID_TOKEN | Token 无效或未激活 | 更新 JUSTONEAPI_TOKEN |
COLLECT_FAILED | 数据采集失败 | 稍后重试 |
RATE_LIMITED | 请求频率超限 | 降低请求频率后重试 |
DAILY_QUOTA_EXCEEDED | 达到每日用量限制 | 明天重试或升级套餐 |
VALIDATION_ERROR | 请求参数无效 | 检查输入值 |
INTERNAL_ERROR | 服务器内部错误 | 稍后重试 |
PERMISSION_DENIED | 无权访问该资源 | 联系客服 |
INSUFFICIENT_BALANCE | 账户余额不足 | 充值账户 |
NETWORK_TIMEOUT | 请求超时 | 检查网络或重试 |
NETWORK_ERROR | 网络连接失败 | 检查网络连接 |
UPSTREAM_ERROR | 上游未指定错误 | 重试或联系客服 |
资料来源:README.md
错误映射机制
上游错误码到 MCP 错误码的转换
mapUpstreamCode() 函数将上游 API 返回的数字错误码映射为标准化的 JOA 错误码。 资料来源:src/common/errors.ts:77-94
export function mapUpstreamCode(code: number | undefined): JOAErrorCode {
switch (code) {
case 100:
return "INVALID_TOKEN";
case 301:
return "COLLECT_FAILED";
case 302:
return "RATE_LIMITED";
case 303:
return "DAILY_QUOTA_EXCEEDED";
case 400:
return "VALIDATION_ERROR";
case 500:
return "INTERNAL_ERROR";
case 600:
return "PERMISSION_DENIED";
case 601:
return "INSUFFICIENT_BALANCE";
default:
return "UPSTREAM_ERROR";
}
}
映射关系图
graph LR
A["上游错误码"] --> B{"code 值"}
B -->|100| C["INVALID_TOKEN"]
B -->|301| D["COLLECT_FAILED"]
B -->|302| E["RATE_LIMITED"]
B -->|303| F["DAILY_QUOTA_EXCEEDED"]
B -->|400| G["VALIDATION_ERROR"]
B -->|500| H["INTERNAL_ERROR"]
B -->|600| I["PERMISSION_DENIED"]
B -->|601| J["INSUFFICIENT_BALANCE"]
B -->|其他| K["UPSTREAM_ERROR"]用户消息构建
buildUserMessage 函数
buildUserMessage() 函数为每种错误码生成用户友好的错误消息。当上游返回消息时,优先使用上游消息;否则使用默认消息。 资料来源:src/common/errors.ts:96-128
export function buildUserMessage(mcpCode: JOAErrorCode, upstreamMessage?: string | null): string {
const base = upstreamMessage && upstreamMessage.trim() ? upstreamMessage.trim() : undefined;
switch (mcpCode) {
case "INVALID_TOKEN":
return base ?? "Invalid or inactive token. Please update JUSTONEAPI_TOKEN.";
case "COLLECT_FAILED":
return base ?? "Collection failed. Please retry after a short delay.";
case "RATE_LIMITED":
return base ?? "Rate limit exceeded. Please slow down and retry later.";
case "DAILY_QUOTA_EXCEEDED":
return base ?? "Daily quota exceeded. Please try again tomorrow or upgrade your plan.";
case "VALIDATION_ERROR":
return base ?? "Invalid parameters. Please check the input values.";
case "PERMISSION_DENIED":
return base ?? "Permission denied. Please verify your account permissions.";
case "INSUFFICIENT_BALANCE":
return base ?? "Insufficient balance. Please top up your account.";
case "INTERNAL_ERROR":
return base ?? "Internal server error. Please retry later.";
case "NETWORK_TIMEOUT":
return base ?? "Network timeout. Please retry later.";
case "NETWORK_ERROR":
return base ?? "Network error. Please retry later.";
default:
return base ?? "Upstream error. Please retry later.";
}
}
错误转换
toMcpErrorPayload 函数
toMcpErrorPayload() 是核心错误转换函数,将各种类型的异常统一转换为 MCP 错误负载格式。 资料来源:src/common/errors.ts:130-173
export function toMcpErrorPayload(e: unknown): {
code: JOAErrorCode;
message: string;
upstreamCode?: number;
httpStatus?: number;
} {
const error = e as {
name?: string;
message?: string;
upstreamCode?: number;
httpStatus?: number;
code?: string;
cause?: unknown;
};
// AbortController 超时
if (error.name === "AbortError") {
return { code: "NETWORK_TIMEOUT", message: buildUserMessage("NETWORK_TIMEOUT") };
}
// 业务错误码
if (error.upstreamCode !== undefined) {
const upstreamCode = Number(error.upstreamCode);
const mcpCode = mapUpstreamCode(upstreamCode);
return {
code: mcpCode,
message: buildUserMessage(mcpCode, error.message),
upstreamCode,
httpStatus: typeof error.httpStatus === "number" ? error.httpStatus : undefined,
};
}
// HTTP 级别错误
if (typeof error.httpStatus === "number") {
return {
code: "UPSTREAM_ERROR",
message: error.message ?? `HTTP error ${error.httpStatus}`,
httpStatus: error.httpStatus,
};
}
// 网络连接错误
if (error.cause || error.code === "ECONNREFUSED" || error.code === "ENOTFOUND") {
return {
code: "NETWORK_ERROR",
message: error.message ?? buildUserMessage("NETWORK_ERROR"),
};
}
return { code: "UPSTREAM_ERROR", message: error.message ?? "Unknown error" };
}
错误转换流程图
graph TD
A["捕获异常 e"] --> B{"error.name === 'AbortError'?"}
B -->|是| C["返回 NETWORK_TIMEOUT"]
B -->|否| D{"error.upstreamCode !== undefined?"}
D -->|是| E["mapUpstreamCode + buildUserMessage"]
D -->|否| F{"typeof error.httpStatus === 'number'?"}
F -->|是| G["返回 UPSTREAM_ERROR"]
F -->|否| H{"error.cause || ECONNREFUSED || ENOTFOUND?"}
H -->|是| I["返回 NETWORK_ERROR"]
H -->|否| J["返回 UPSTREAM_ERROR + Unknown error"]上游响应验证
isUpstreamOk 函数
用于判断上游 API 响应是否成功。 资料来源:src/common/errors.ts:71-75
export type UpstreamResponse = {
code?: number;
message?: string | null;
recordTime?: string;
data?: unknown;
};
export function isUpstreamOk(resp: UpstreamResponse): boolean {
return Number(resp?.code) === 0;
}
UpstreamResponse 类型定义
| 字段 | 类型 | 说明 | |
|---|---|---|---|
code | number | 响应状态码,0 表示成功 | |
message | string \ | null | 响应消息 |
recordTime | string | 记录时间 | |
data | unknown | 响应数据 |
资料来源:src/common/errors.ts:54-56
HTTP 请求重试机制
getJson 函数中的重试逻辑
src/common/http.ts 中的 getJson() 函数实现了智能重试机制,针对特定错误进行自动重试。 资料来源:src/common/http.ts
重试条件:
AbortError(超时)- HTTP 5xx 错误
ECONNRESETECONNREFUSEDENOTFOUND
graph TD
A["发起 HTTP 请求"] --> B{"请求成功?"}
B -->|是| C["返回响应 JSON"]
B -->|否| D{"可重试错误?"}
D -->|否| E["抛出异常"]
D -->|是| F{"尝试次数 < 最大次数?"}
F -->|是| G["等待 250ms * attempt"]
G --> H["重新发起请求"]
H --> B
F -->|否| EMCP 工具中的错误处理
统一搜索工具示例
在 src/index.ts 中,所有工具都使用统一的错误处理模式: 资料来源:src/index.ts
async (input) => {
try {
const data = await unifiedSearchV1(input);
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} catch (e: unknown) {
const m = toMcpErrorPayload(e);
return {
isError: true,
content: [
{
type: "text",
text: `ERROR[${m.code}] (upstream=${m.upstreamCode ?? "N/A"}): ${m.message}`,
},
],
};
}
}
错误输出格式
错误格式规范
所有错误按照统一格式返回:
ERROR[ERROR_CODE] (upstream=XXX): Human-readable message
示例
| 场景 | 错误输出 |
|---|---|
| Token 无效 | ERROR[INVALID_TOKEN] (upstream=100): Invalid or inactive token. Please update JUSTONEAPI_TOKEN. |
| 频率限制 | ERROR[RATE_LIMITED] (upstream=302): Rate limit exceeded. Please slow down and retry later. |
| 网络超时 | ERROR[NETWORK_TIMEOUT] (upstream=N/A): Network timeout. Please retry later. |
资料来源:README.md
MCP 工具返回格式
当工具调用出错时,返回包含 isError: true 的响应:
{
"isError": true,
"content": [
{
"type": "text",
"text": "ERROR[RATE_LIMITED] (upstream=302): Rate limit exceeded. Please slow down and retry later."
}
]
}
配置与环境变量
错误处理相关配置
| 变量 | 默认值 | 说明 |
|---|---|---|
JUSTONEAPI_TOKEN | *(必填)* | API 认证令牌 |
JUSTONEAPI_BASE_URL | https://api.justoneapi.com | API 端点 |
JUSTONEAPI_TIMEOUT_MS | 20000 | 请求超时(毫秒) |
JUSTONEAPI_RETRY | 1 | 首次失败后的重试次数 |
JUSTONEAPI_DEBUG | false | 启用调试日志输出到 stderr |
资料来源:README.md
设计理念
Transport, not transformation
该项目坚持"传输而非转换"的设计哲学:
- 返回上游 API 的原始 JSON 响应
- 不进行字段解析或数据规范化
- 不重构数据结构
- 确保长期兼容性
错误处理模块在保持数据完整性的同时,提供了必要的错误信息翻译层,使用户能够快速定位和解决问题。 资料来源:README.md
相关文件
| 文件路径 | 说明 |
|---|---|
src/common/errors.ts | 核心错误处理模块 |
src/common/http.ts | HTTP 请求与重试机制 |
src/common/config.ts | 配置管理(含 URL 安全日志) |
src/index.ts | MCP 工具注册与错误处理集成 |
README.md | 错误处理文档 |
TOOLS.md | 工具文档中的错误处理说明 |
资料来源:[README.md](https://github.com/justoneapi/justoneapi-mcp/blob/main/README.md)
认证授权
justoneapi-mcp 采用基于令牌(Token)的简洁认证机制。所有 API 请求必须携带有效的 JustOneAPI 令牌才能访问上游服务。该设计遵循 "Transport, not transformation" 原则,在令牌验证通过后直接透传请求,不进行额外的数据转换或协议转换。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
justoneapi-mcp 采用基于令牌(Token)的简洁认证机制。所有 API 请求必须携带有效的 JustOneAPI 令牌才能访问上游服务。该设计遵循 "Transport, not transformation" 原则,在令牌验证通过后直接透传请求,不进行额外的数据转换或协议转换。
认证流程的核心组件位于 src/common/config.ts 模块中,负责令牌的读取、验证和安全传输。
核心配置
环境变量配置
| 变量名 | 必填 | 默认值 | 说明 |
|---|---|---|---|
JUSTONEAPI_TOKEN | 是 | 无 | 用户的 JustOneAPI 访问令牌 |
JUSTONEAPI_BASE_URL | 否 | https://api.justoneapi.com | API 端点地址 |
JUSTONEAPI_TIMEOUT_MS | 否 | 20000 | 请求超时时间(毫秒) |
JUSTONEAPI_RETRY | 否 | 1 | 首次失败后的重试次数 |
JUSTONEAPI_DEBUG | 否 | false | 是否启用调试日志输出 |
令牌获取
用户需访问 justoneapi.com 注册账号并获取 API 令牌。令牌将作为查询参数附加到每个 API 请求中。
认证流程
sequenceDiagram
participant MCP as MCP Server
participant Config as config.ts
participant HTTP as http.ts
participant API as JustOneAPI
Note over MCP: 服务启动
MCP->>Config: 读取 JUSTONEAPI_TOKEN
alt Token 为空或空白
Config-->>MCP: 抛出配置错误
MCP->>MCP: 终止启动并输出错误信息
end
Note over MCP: 用户发起工具调用
MCP->>Config: requireToken()
Config->>Config: 验证令牌存在
MCP->>HTTP: 构建请求(含令牌)
HTTP->>API: GET /api/xxx?token=xxx
API-->>HTTP: 响应 (code=0 或 code!=0)
alt 认证失败
API-->>HTTP: code != 0
HTTP-->>MCP: 抛出 UpstreamError
MCP-->>用户: ERROR[INVALID_TOKEN]
end令牌验证实现
requireToken 函数
src/common/config.ts 中实现了令牌验证函数:
export function requireToken(): string {
const token = process.env.JUSTONEAPI_TOKEN?.trim();
if (!token) {
throw new Error(
"[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.\n" +
"Please set the JUSTONEAPI_TOKEN environment variable in your MCP host configuration."
);
}
return token;
}
资料来源:src/common/config.ts:1-50
启动时验证
服务启动时会在 src/index.ts 中进行强制验证:
async function main() {
if (!process.env.JUSTONEAPI_TOKEN?.trim()) {
console.error(
"[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.\n" +
"Please set the JUSTONEAPI_TOKEN environment variable in your MCP host configuration"
);
process.exit(1);
}
// ... 继续初始化
}
资料来源:src/index.ts
令牌在请求中的传递
所有工具实现都遵循统一的令牌传递模式。以统一搜索为例:
export async function unifiedSearchV1(input: z.infer<typeof UnifiedSearchV1Input>) {
const token = encodeURIComponent(requireToken());
const keyword = encodeURIComponent(input.keyword);
const params = new URLSearchParams();
params.append("token", token);
params.append("keyword", keyword);
// ...
return await getJson(`/api/search/v1?${params.toString()}`);
}
资料来源:src/tools/search/unified_search_v1.ts:30-50
令牌安全处理
URL 安全日志
为防止令牌在日志中泄露,系统提供了安全 URL 构建函数:
export function toSafeUrlForLog(fullUrl: string): string {
try {
const u = new URL(fullUrl);
if (u.searchParams.has("token")) {
u.searchParams.set("token", maskToken(u.searchParams.get("token") ?? ""));
}
return u.toString();
} catch {
return fullUrl.replace(/token=([^&]+)/g, (_m, g1) => `token=${maskToken(g1)}`);
}
}
该函数会在调试模式下将日志输出中的令牌进行脱敏处理,仅保留首尾字符。
资料来源:src/common/config.ts:60-80
认证错误处理
错误码映射
src/common/errors.ts 负责将上游错误码映射为统一的 MCP 错误码:
| 上游错误码 | MCP 错误码 | 说明 | 用户操作 |
|---|---|---|---|
| - | INVALID_TOKEN | 令牌无效或未激活 | 更新 JUSTONEAPI_TOKEN |
| 302 | RATE_LIMITED | 请求过于频繁 | 减缓请求频率 |
| - | INSUFFICIENT_BALANCE | 账户余额不足 | 充值账户 |
| - | PERMISSION_DENIED | 无权访问该资源 | 联系客服支持 |
资料来源:src/common/errors.ts:1-60
错误响应格式
认证错误以统一格式返回:
ERROR[INVALID_TOKEN] (upstream=N/A): Token is invalid or inactive. Please update your JUSTONEAPI_TOKEN environment variable.
请求重试与超时
重试机制
HTTP 客户端在以下情况会进行重试:
AbortError(请求超时)- HTTP 5xx 状态码
- 网络错误(
ECONNRESET、ECONNREFUSED、ENOTFOUND)
重试间隔采用指数退避策略:
// small backoff
await new Promise((r) => setTimeout(r, 250 * attempt));
超时配置
默认超时时间为 20 秒(20000 毫秒),可通过 JUSTONEAPI_TIMEOUT_MS 环境变量自定义。
MCP Host 配置示例
Claude Desktop 配置
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_actual_token_here"
}
}
}
}
自定义配置
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_token_here",
"JUSTONEAPI_TIMEOUT_MS": "30000",
"JUSTONEAPI_DEBUG": "true"
}
}
}
}
最佳实践
- 令牌安全:不要将令牌硬编码在代码中,使用环境变量传递
- 调试模式:生产环境建议关闭
JUSTONEAPI_DEBUG - 超时设置:根据网络环境调整
JUSTONEAPI_TIMEOUT_MS - 错误处理:捕获
INVALID_TOKEN错误并提示用户更新令牌
资料来源:[src/common/config.ts:1-50]()
系统架构
justoneapi-mcp 是一个基于 Model Context Protocol (MCP) 的服务器实现,旨在为 AI 助手(如 Claude Desktop、Cursor 等)提供统一的中国社交媒体和新闻平台搜索能力。该项目采用"传输而非转换"(Transport, not transformation)的设计理念,直接返回上游 API 的原始 JSON 数据,确...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
justoneapi-mcp 是一个基于 Model Context Protocol (MCP) 的服务器实现,旨在为 AI 助手(如 Claude Desktop、Cursor 等)提供统一的中国社交媒体和新闻平台搜索能力。该项目采用"传输而非转换"(Transport, not transformation)的设计理念,直接返回上游 API 的原始 JSON 数据,确保最大程度的数据保真度。资料来源:README.md
架构分层
系统采用模块化分层架构,主要分为以下四层:
graph TD
A[MCP Host<br/>Claude Desktop/Cursor] --> B[工具注册层<br/>src/index.ts]
B --> C[业务逻辑层<br/>src/tools/]
C --> D[公共基础设施层<br/>src/common/]
D --> E[外部服务<br/>JustOneAPI]
C --> C1[unified_search_v1]
C --> C2[kuaishou_search_video_v2]
D --> D1[config.ts<br/>配置管理]
D --> D2[http.ts<br/>HTTP客户端]
D --> D3[errors.ts<br/>错误处理]| 层级 | 文件路径 | 职责 |
|---|---|---|
| 工具注册层 | src/index.ts | MCP 工具注册、请求路由、错误格式化 |
| 业务逻辑层 | src/tools/ | 各个工具的具体实现(搜索、视频等) |
| 公共基础设施层 | src/common/ | 配置管理、HTTP 请求、错误处理 |
| 外部服务层 | JustOneAPI | 第三方数据源 API |
资料来源:src/index.ts:1-80
核心组件
1. 工具注册层 (src/index.ts)
作为 MCP 服务器的入口点,负责:
- 初始化 MCP SDK 服务器实例
- 注册所有可用工具及其输入 schema
- 统一处理工具执行中的异常
- 格式化错误响应为 MCP 错误格式
sequenceDiagram
participant Host as MCP Host
participant Server as MCP Server
participant Tool as Tool Handler
participant API as JustOneAPI
Host->>Server: 工具调用请求
Server->>Tool: 传递输入参数
Tool->>API: HTTP 请求
API-->>Tool: JSON 响应
Tool-->>Server: 返回数据
Server-->>Host: MCP 响应格式
Note over Tool,API: 异常时返回错误格式
Tool-->>Server: ERROR[CODE]: message
Server-->>Host: isError: true关键代码结构:
// 工具注册示例
server.registerTool(
"unified_search_v1",
{
description: "Unified search across multiple platforms...",
inputSchema: UnifiedSearchV1Input.shape,
},
async (input) => {
try {
const data = await unifiedSearchV1(input);
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
} catch (e: unknown) {
const m = toMcpErrorPayload(e);
return {
isError: true,
content: [{
type: "text",
text: `ERROR[${m.code}] (upstream=${m.upstreamCode ?? "N/A"}): ${m.message}`,
}],
};
}
}
);
资料来源:src/index.ts:40-65
2. 配置管理 (src/common/config.ts)
负责管理和验证环境变量配置:
| 配置项 | 必填 | 默认值 | 说明 |
|---|---|---|---|
JUSTONEAPI_TOKEN | 是 | - | API 访问令牌 |
JUSTONEAPI_BASE_URL | 否 | https://api.justoneapi.com | API 端点 |
JUSTONEAPI_TIMEOUT_MS | 否 | 20000 | 请求超时(毫秒) |
JUSTONEAPI_RETRY | 否 | 1 | 首次尝试后的重试次数 |
JUSTONEAPI_DEBUG | 否 | false | 启用调试日志 |
配置验证在服务器启动时执行:
async function main() {
if (!process.env.JUSTONEAPI_TOKEN?.trim()) {
console.error(
"[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.\n" +
"Please set the JUSTONEAPI_TOKEN environment variable..."
);
process.exit(1);
}
// ...
}
资料来源:src/common/config.ts:1-30 和 src/index.ts:75-85
3. HTTP 客户端 (src/common/http.ts)
封装 HTTP 请求逻辑,提供重试机制:
graph TD
A[发起请求] --> B{attempt < attempts?}
B -->|是| C[发送 HTTP 请求]
C --> D{响应状态?}
D -->|成功 2xx| E[返回 JSON]
D -->|超时/5xx/网络错误| F[等待 backoff]
F --> G[attempt++]
G --> B
D -->|其他错误| H[立即抛出异常]
B -->|否| I[抛出最后一次错误]可重试的错误类型:
| 错误类型 | 条件 |
|---|---|
| 超时 | error.name === "AbortError" |
| HTTP 5xx | httpStatus >= 500 |
| 连接重置 | error.code === "ECONNRESET" |
| 连接被拒绝 | error.code === "ECONNREFUSED" |
| 主机未找到 | error.code === "ENOTFOUND" |
重试策略:指数退避,每次重试间隔 250 * attempt 毫秒。
4. 错误处理 (src/common/errors.ts)
统一错误码映射和用户友好消息生成:
graph TD
A[原始错误] --> B{错误类型判断}
B -->|AbortError| C[NETWORK_TIMEOUT]
B -->|upstreamCode| D[mapUpstreamCode]
B -->|httpStatus| E[UPSTREAM_ERROR]
B -->|cause/code| F[NETWORK_ERROR]
B -->|其他| G[UPSTREAM_ERROR]
D --> H[错误码映射表]
H --> H1[INVALID_TOKEN<br/>302]
H --> H2[COLLECT_FAILED<br/>500]
H --> H3[RATE_LIMITED<br/>429]
H --> H4[DAILY_QUOTA_EXCEEDED<br/>403]
H --> H5[INSUFFICIENT_BALANCE<br/>402]
H --> H6[PERMISSION_DENIED<br/>401]
H --> H7[VALIDATION_ERROR<br/>400]MCP 错误码对照表:
| MCP 错误码 | 说明 | 上游响应码 | 用户操作建议 |
|---|---|---|---|
INVALID_TOKEN | Token 无效或未激活 | 302 | 更新 JUSTONEAPI_TOKEN |
COLLECT_FAILED | 数据采集失败 | 500 | 稍后重试 |
RATE_LIMITED | 请求过于频繁 | 429 | 降低请求频率 |
DAILY_QUOTA_EXCEEDED | 达到日用量限额 | 403 | 等待明天或升级套餐 |
INSUFFICIENT_BALANCE | 账户余额不足 | 402 | 充值账户 |
PERMISSION_DENIED | 无权访问该资源 | 401 | 联系客服 |
VALIDATION_ERROR | 请求参数无效 | 400 | 检查输入值 |
INTERNAL_ERROR | 服务器内部错误 | 其他 5xx | 稍后重试 |
NETWORK_TIMEOUT | 请求超时 | - | 检查网络或重试 |
NETWORK_ERROR | 网络连接失败 | - | 检查网络连接 |
UPSTREAM_ERROR | 未指定的上游错误 | - | 重试或联系客服 |
错误输出格式:
ERROR[ERROR_CODE] (upstream=XXX): Human-readable message
资料来源:src/common/errors.ts:1-80
工具实现
统一搜索 (unified_search_v1)
支持跨多个平台进行搜索,返回统一的 JSON 响应:
graph LR
A[keyword] --> B[参数构建]
B --> C{分页?}
C -->|首页| D[start, end]
C -->|后续页| E[nextCursor]
D --> F[URLSearchParams]
E --> F
F --> G[/api/search/v1]
G --> H[getJson]输入参数 Schema:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
keyword | string | 是 | 搜索关键词,支持 AND/OR/NOT 语法 |
source | enum | 否 | 平台筛选:ALL(默认)、NEWS、WEIBO、WEIXIN、ZHIHU、DOUYIN、XIAOHONGSHU、BILIBILI、KUAISHOU |
start | string | 首页必填 | 开始时间 yyyy-MM-dd HH:mm:ss(UTC+8),需在 84 天内 |
end | string | 首页必填 | 结束时间,需晚于开始时间 |
nextCursor | string | 分页用 | 上一页返回的游标 |
搜索语法:
- 单关键词:
deepseek - AND 搜索(同时包含):
deepseek chatgpt - OR 搜索(任一包含):
deepseek~chatgpt - NOT 搜索(排除):
deepseek -chatgpt
资料来源:src/tools/search/unified_search_v1.ts:1-60
快手视频搜索 (kuaishou_search_video_v2)
针对快手平台的专用视频搜索工具:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
keyword | string | 是 | - | 搜索关键词,如 'dance' |
page | number | 否 | 1 | 页码,从 1 开始 |
资料来源:src/tools/kuaishou/search_video_v2.ts:1-25
数据流
sequenceDiagram
participant User as 用户
participant MCP as MCP Host
participant Server as justoneapi-mcp
participant HTTP as HTTP Client
participant API as JustOneAPI
User->>MCP: 自然语言搜索请求
MCP->>Server: unified_search_v1(keyword, source, start, end)
Server->>HTTP: getJson(url)
HTTP->>HTTP: Token 编码
HTTP->>HTTP: 参数序列化
HTTP->>API: GET /api/search/v1?...
API-->>HTTP: JSON 响应
HTTP-->>Server: 原始 JSON 数据
Server-->>MCP: { content: [{type:"text", text: JSON}] }
MCP-->>User: 搜索结果摘要
Note over API: code=0 表示成功<br/>code≠0 表示错误依赖关系
项目依赖项及其版本:
| 依赖类型 | 包名 | 版本要求 | 用途 |
|---|---|---|---|
| 生产依赖 | @modelcontextprotocol/sdk | ^1.25.1 | MCP 协议实现 |
| 生产依赖 | zod | ^4.3.4 | 输入验证和 Schema 定义 |
| 生产依赖 | dotenv | ^17.2.3 | 环境变量管理 |
| 开发依赖 | typescript | ^5.9.3 | TypeScript 编译 |
| 开发依赖 | eslint | ^9.39.2 | 代码检查 |
| 开发依赖 | prettier | ^3.7.4 | 代码格式化 |
运行环境要求:Node.js >= 18.0.0
资料来源:package.json:1-50
启动验证流程
graph TD
A[服务器启动] --> B{检查 JUSTONEAPI_TOKEN}
B -->|未设置| C[输出错误信息]
C --> D[进程退出]
B -->|已设置| E[服务器就绪]
E --> F[注册所有工具]
F --> G[等待 MCP Host 调用]
G --> H{收到工具调用}
H -->|unified_search_v1| I[执行统一搜索]
H -->|kuaishou_search_video_v2| J[执行快手搜索]
I --> K[返回结果或错误]
J --> K设计原则
- 传输而非转换:直接返回上游 API 的原始响应,不进行字段解析或数据重组,确保长期兼容性。
- 透明性:错误信息包含上游错误码,便于调试和问题定位。
- 稳定性:通过 HTTP 重试机制和超时控制提高系统可靠性。
- 模块化:各功能模块职责清晰,便于维护和扩展。
扩展性
项目采用插件化架构添加新工具:
- 在
src/tools/下创建新的工具目录 - 定义 Zod 输入 Schema
- 实现工具逻辑函数
- 在
src/index.ts中注册工具
即将支持的工具:
- Douyin 视频搜索
- Weibo 帖子搜索
- Bilibili 视频搜索
资料来源:[src/index.ts:1-80]()
开发指南
本开发指南旨在帮助开发者快速上手 justoneapi-mcp 项目的开发工作,涵盖项目结构、环境配置、代码规范、工具开发以及构建发布等核心内容。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
项目概述
justoneapi-mcp 是一个基于 Model Context Protocol (MCP) 的服务器实现,用于连接 Claude 等 AI 助手与中国主流社交媒体平台的数据搜索接口。该项目支持统一搜索、快手视频搜索等多个工具,为用户提供跨平台社交媒体数据分析能力。
核心设计理念:Transport, not transformation — 即优先保证数据传输的稳定性、透明性和原始数据完整性,而非对数据进行转换或处理。
资料来源:README.md
项目结构
justoneapi-mcp/
├── src/
│ ├── index.ts # MCP 服务器主入口
│ ├── version.ts # 版本管理模块
│ ├── common/
│ │ ├── config.ts # 配置管理
│ │ ├── errors.ts # 错误处理
│ │ └── http.ts # HTTP 请求封装
│ └── tools/
│ ├── search/
│ │ └── unified_search_v1.ts # 统一搜索工具
│ └── kuaishou/
│ └── search_video_v2.ts # 快手视频搜索工具
├── eslint.config.js # ESLint 配置
├── tsconfig.json # TypeScript 配置
├── package.json # 项目依赖配置
└── README.md # 项目文档
目录职责说明
| 目录/文件 | 职责 | 关键依赖 |
|---|---|---|
src/index.ts | MCP 服务器启动、工具注册、错误处理 | @modelcontextprotocol/sdk |
src/common/ | 公共基础设施模块 | zod, dotenv |
src/tools/ | 具体业务工具实现 | 继承 common 模块 |
资料来源:src/index.ts:1-50
环境配置
运行时要求
项目要求 Node.js 版本不低于 18.0.0。
资料来源:package.json:22
必需环境变量
| 变量名 | 必填 | 默认值 | 说明 |
|---|---|---|---|
JUSTONEAPI_TOKEN | 是 | 无 | JustOneAPI 访问令牌 |
JUSTONEAPI_BASE_URL | 否 | https://api.justoneapi.com | API 端点地址 |
JUSTONEAPI_TIMEOUT_MS | 否 | 20000 | 请求超时时间(毫秒) |
JUSTONEAPI_RETRY | 否 | 1 | 首次请求后的重试次数 |
JUSTONEAPI_DEBUG | 否 | false | 是否启用调试日志 |
资料来源:README.md
配置验证机制
项目在启动时(src/index.ts 的 main() 函数)会验证 JUSTONEAPI_TOKEN 是否已设置。若未设置,服务器将输出错误信息并终止运行:
if (!process.env.JUSTONEAPI_TOKEN?.trim()) {
console.error(
"[justoneapi-mcp] ERROR: JUSTONEAPI_TOKEN is required but not set.\n" +
"Please set the JUSTONEAPI_TOKEN environment variable..."
);
process.exit(1);
}
资料来源:src/index.ts
开发工具配置
TypeScript 配置
项目使用 TypeScript 5.9.3,编译配置位于 tsconfig.json。关键配置项包括:
- target: ES2022
- module: ESNext (ES 模块系统)
- moduleResolution: bundler
- strict mode: 启用严格类型检查
资料来源:package.json:29-31
ESLint 配置
ESLint 配置集成了 TypeScript ESLint 插件和 Prettier 配置:
rules: {
...tseslint.configs.recommended.rules,
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"no-console": ["warn", { allow: ["error", "warn"] }],
}
规则说明:
| 规则 | 级别 | 说明 |
|---|---|---|
no-explicit-any | warn | 允许使用 any 类型但会警告 |
no-unused-vars | error | 未使用的变量报错,下划线开头的参数除外 |
no-console | warn | 禁止使用 console.log,允许 error 和 warn |
资料来源:eslint.config.js
项目依赖
生产依赖:
| 依赖包 | 版本 | 用途 |
|---|---|---|
| @modelcontextprotocol/sdk | ^1.25.1 | MCP 协议实现 |
| dotenv | ^17.2.3 | 环境变量加载 |
| zod | ^4.3.4 | 输入验证与 Schema 定义 |
开发依赖:
| 依赖包 | 版本 | 用途 |
|---|---|---|
| typescript | ^5.9.3 | TypeScript 编译器 |
| eslint | ^9.39.2 | 代码检查 |
| prettier | ^3.7.4 | 代码格式化 |
| ts-node | ^10.9.2 | TypeScript 执行环境 |
资料来源:package.json:24-45
工具开发
工具注册流程
MCP 服务器通过 server.registerTool() 方法注册工具。注册时需提供工具名称、描述和输入 Schema:
server.registerTool(
"tool_name_v1",
{
description: "工具描述字符串",
inputSchema: ToolInputSchema.shape,
},
async (input) => {
// 工具实现逻辑
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
资料来源:src/index.ts
工具命名规范
项目采用统一的工具命名规范:{platform}_{action}_{version}
| 示例 | 含义 |
|---|---|
unified_search_v1 | 统一搜索工具,第一版本 |
kuaishou_search_video_v2 | 快手平台视频搜索,第二版本 |
资料来源:README.md
输入验证
项目使用 Zod v4 进行输入验证。每个工具需要定义 InputSchema:
import { z } from "zod";
export const UnifiedSearchV1Input = z.object({
keyword: z.string().min(1).describe("搜索关键词"),
source: PlatformType.optional().describe("平台来源"),
start: z.string().optional().describe("开始时间"),
end: z.string().optional().describe("结束时间"),
nextCursor: z.string().optional().describe("分页游标"),
});
Zod Schema 特性说明:
| 方法 | 用途 |
|---|---|
z.string().min(1) | 非空字符串验证 |
.optional() | 可选字段 |
.default(value) | 默认值 |
.describe("...") | 字段描述(用于 MCP 文档生成) |
资料来源:src/tools/search/unified_search_v1.ts
工具实现模板
import { z } from "zod";
import { requireToken } from "../../common/config.js";
import { getJson } from "../../common/http.js";
// 1. 定义输入 Schema
export const ToolInput = z.object({
param1: z.string().min(1).describe("参数描述"),
param2: z.number().int().min(1).default(1).describe("可选参数"),
});
// 2. 实现工具函数
export async function toolFunction(input: z.infer<typeof ToolInput>) {
const token = encodeURIComponent(requireToken());
const param = encodeURIComponent(input.param1);
const page = input.param2;
return await getJson(
`/api/path?token=${token}¶m=${param}&page=${page}`
);
}
资料来源:src/tools/kuaishou/search_video_v2.ts
HTTP 请求封装
请求重试机制
getJson() 函数封装了带重试逻辑的 HTTP 请求:
graph TD
A[发起请求] --> B{成功?}
B -->|是| C[返回响应]
B -->|否| D{可重试?}
D -->|超时/5xx/网络错误| E[等待 250ms × attempt]
E --> F[重试]
F --> A
D -->|不可重试| G[抛出异常]
G --> H[错误处理]
C --> H可重试条件:
| 条件 | 说明 |
|---|---|
AbortError | 请求超时 |
| HTTP 5xx | 服务器内部错误 |
ECONNRESET | 连接被重置 |
ECONNREFUSED | 连接被拒绝 |
ENOTFOUND | DNS 解析失败 |
资料来源:src/common/http.ts
错误处理机制
错误代码映射
项目定义了一套标准化的 MCP 错误代码:
| 错误代码 | 上游代码 | 说明 | 处理建议 |
|---|---|---|---|
INVALID_TOKEN | - | Token 无效或未激活 | 更新 JUSTONEAPI_TOKEN |
COLLECT_FAILED | - | 数据采集失败 | 稍后重试 |
RATE_LIMITED | 302 | 请求过于频繁 | 降低请求频率 |
DAILY_QUOTA_EXCEEDED | - | 达到日配额限制 | 等待明天或升级套餐 |
INSUFFICIENT_BALANCE | - | 账户余额不足 | 充值账户 |
PERMISSION_DENIED | - | 无权访问该资源 | 联系支持 |
VALIDATION_ERROR | - | 请求参数无效 | 检查输入值 |
INTERNAL_ERROR | - | 服务器内部错误 | 稍后重试 |
NETWORK_TIMEOUT | - | 请求超时 | 检查网络或重试 |
NETWORK_ERROR | - | 网络连接失败 | 检查网络连接 |
UPSTREAM_ERROR | - | 未指定的上游错误 | 重试或联系支持 |
错误格式
错误以以下格式返回:
ERROR[ERROR_CODE] (upstream=XXX): Human-readable message
错误处理流程
graph TD
A[捕获异常] --> B{AbortError?}
B -->|是| C[返回 NETWORK_TIMEOUT]
B -->|否| D{upstreamCode 存在?}
D -->|是| E[映射上游错误码]
E --> F[返回业务错误]
D -->|否| G{httpStatus 存在?}
G -->|是| H[返回 UPSTREAM_ERROR]
G -->|否| I{网络错误?}
I -->|是| J[返回 NETWORK_ERROR]
I -->|否| K[返回 UPSTREAM_ERROR]资料来源:src/common/errors.ts
版本管理
项目使用动态版本读取机制,从 package.json 中提取版本号:
const packageJsonPath = join(__dirname, "../package.json");
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
version = packageJson.version || "0.0.0";
此设计确保构建产物中的版本号与 package.json 保持同步。
资料来源:src/version.ts
构建和发布
安装依赖
npm install
代码检查
npm run lint # ESLint 检查
npm run format # Prettier 格式化
构建
npm run build # TypeScript 编译到 dist/
发布配置
package.json 中的发布文件配置:
{
"files": ["dist", "README.md", "LICENSE"]
}
仅 dist 目录(编译产物)、README.md 和 LICENSE 会被发布到 npm。
资料来源:package.json:19-22
Claude Desktop 集成
配置示例
在 Claude Desktop 配置文件中添加以下内容:
{
"mcpServers": {
"justoneapi": {
"command": "npx",
"args": ["-y", "justoneapi-mcp"],
"env": {
"JUSTONEAPI_TOKEN": "your_token_here",
"JUSTONEAPI_TIMEOUT_MS": "30000",
"JUSTONEAPI_DEBUG": "true"
}
}
}
}
配置文件位置
| 操作系统 | 路径 |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
资料来源:README.md
开发工作流程
graph LR
A[创建工具文件] --> B[定义 Zod Schema]
B --> C[实现工具函数]
C --> D[注册工具到服务器]
D --> E[配置环境变量]
E --> F[本地测试]
F --> G[代码检查]
G --> H{通过?}
H -->|否| I[修复问题]
I --> G
H -->|是| J[构建发布]
J --> K[end]常见问题
Token 配置问题
问题: 服务器启动时报错 JUSTONEAPI_TOKEN is required but not set
解决: 确保在 MCP host 配置中正确设置了 JUSTONEAPI_TOKEN 环境变量
请求超时
问题: 请求返回 NETWORK_TIMEOUT
解决: 增加 JUSTONEAPI_TIMEOUT_MS 配置值(默认 20000ms)
调试模式
启用调试模式可查看详细的请求日志:
{
"env": {
"JUSTONEAPI_DEBUG": "true"
}
}
资料来源:src/common/config.ts
资料来源:[README.md](https://github.com/justoneapi/justoneapi-mcp/blob/main/README.md)
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
假设不成立时,用户拿不到承诺的能力。
可能增加新用户试用和生产接入成本。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
下游已经要求复核,不能在页面中弱化。
Pitfall Log / 踩坑日志
项目:justoneapi/justoneapi-mcp
摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:能力坑 - 能力判断依赖假设。
1. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 建议检查:将假设转成下游验证清单。
- 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
- 证据:capability.assumptions | github_repo:1125683257 | https://github.com/justoneapi/justoneapi-mcp | README/documentation is current enough for a first validation pass.
2. 运行坑 · 来源证据:Clawhub skill family: 6 SKILL.md files have description-vs-body operation count mismatches (claim vs documented gap of…
- 严重度:medium
- 证据强度:source_linked
- 发现:GitHub 社区证据显示该项目存在一个运行相关的待验证问题:Clawhub skill family: 6 SKILL.md files have description-vs-body operation count mismatches (claim vs documented gap of 2-39)
- 对用户的影响:可能增加新用户试用和生产接入成本。
- 建议检查:来源问题仍为 open,Pack Agent 需要复核是否仍影响当前版本。
- 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
- 证据:community_evidence:github | cevd_3b8110f2a2a84250a1da5b96b5573463 | https://github.com/justoneapi/justoneapi-mcp/issues/2 | 来源类型 github_issue 暴露的待验证使用条件。
3. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
- 证据:evidence.maintainer_signals | github_repo:1125683257 | https://github.com/justoneapi/justoneapi-mcp | last_activity_observed missing
4. 安全/权限坑 · 下游验证发现风险项
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:下游已经要求复核,不能在页面中弱化。
- 建议检查:进入安全/权限治理复核队列。
- 防护动作:下游风险存在时必须保持 review/recommendation 降级。
- 证据:downstream_validation.risk_items | github_repo:1125683257 | https://github.com/justoneapi/justoneapi-mcp | no_demo; severity=medium
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 建议检查:把风险写入边界卡,并确认是否需要人工复核。
- 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
- 证据:risks.scoring_risks | github_repo:1125683257 | https://github.com/justoneapi/justoneapi-mcp | no_demo; severity=medium
6. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
- 防护动作:issue/PR 响应未知时,必须提示维护风险。
- 证据:evidence.maintainer_signals | github_repo:1125683257 | https://github.com/justoneapi/justoneapi-mcp | issue_or_pr_quality=unknown
7. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
- 证据:evidence.maintainer_signals | github_repo:1125683257 | https://github.com/justoneapi/justoneapi-mcp | release_recency=unknown
来源:Doramagic 发现、验证与编译记录