random-video-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/README.md +126 -0
- package/example-config.json +11 -0
- package/index.js +186 -0
- package/package.json +37 -0
package/.env.example
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Random Video MCP Server
|
|
2
|
+
|
|
3
|
+
一个支持 webhook 日志记录的 MCP 服务器,用于生成随机视频。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 🎬 获取随机视频(支持多种类型:明星/热舞/风景/游戏/动物/动漫)
|
|
8
|
+
- 📊 Webhook 日志记录 - 自动将所有调用信息 POST 到你配置的接口
|
|
9
|
+
- 🚀 支持 npx 直接运行
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g random-video-mcp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
或使用 npx 直接运行(无需安装):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx random-video-mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 配置 Webhook(可选)
|
|
24
|
+
|
|
25
|
+
如果你想监控所有调用信息,可以通过环境变量 `MCP_WEBHOOK_URL` 配置你的 webhook 接口地址。每次工具被调用时,服务器会自动将以下信息 POST 到你的接口:
|
|
26
|
+
|
|
27
|
+
### Webhook 数据格式
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"timestamp": "2026-02-04T10:00:00.000Z",
|
|
32
|
+
"server": "random-video-mcp",
|
|
33
|
+
"event": "tool_call",
|
|
34
|
+
"tool_name": "get_random_video",
|
|
35
|
+
"arguments": {
|
|
36
|
+
"msg": "动漫",
|
|
37
|
+
"type": "json"
|
|
38
|
+
},
|
|
39
|
+
"full_request": { ... },
|
|
40
|
+
"meta": { ... }
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 在 Cursor 中配置
|
|
45
|
+
|
|
46
|
+
在 Cursor 的 MCP 设置中添加:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"random-video": {
|
|
52
|
+
"command": "npx",
|
|
53
|
+
"args": ["-y", "random-video-mcp"],
|
|
54
|
+
"env": {
|
|
55
|
+
"MCP_WEBHOOK_URL": "https://your-webhook-url.com/api/log"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 使用本地路径
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"mcpServers": {
|
|
67
|
+
"random-video": {
|
|
68
|
+
"command": "node",
|
|
69
|
+
"args": ["/path/to/random-video-mcp/index.js"],
|
|
70
|
+
"env": {
|
|
71
|
+
"MCP_WEBHOOK_URL": "https://your-webhook-url.com/api/log"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 工具说明
|
|
79
|
+
|
|
80
|
+
### get_random_video
|
|
81
|
+
|
|
82
|
+
获取随机视频。
|
|
83
|
+
|
|
84
|
+
**参数:**
|
|
85
|
+
- `msg` (可选): 视频类型
|
|
86
|
+
- 可选值:`明星` | `热舞` | `风景` | `游戏` | `动物` | `动漫`
|
|
87
|
+
- 默认值:`动漫`
|
|
88
|
+
- `type` (可选): 输出格式
|
|
89
|
+
- 可选值:`json` | `text`
|
|
90
|
+
- 默认值:`json`
|
|
91
|
+
|
|
92
|
+
**返回示例(JSON):**
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"code": 1,
|
|
96
|
+
"text": "获取成功",
|
|
97
|
+
"data": {
|
|
98
|
+
"img": "http://cdn.video.picasso.dandanjiang.tv/xxx.jpg",
|
|
99
|
+
"mold": "#标签1 #标签2",
|
|
100
|
+
"url": "http://cdn.video.picasso.dandanjiang.tv/xxx.mp4"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 发布到 NPM
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# 1. 登录 npm
|
|
109
|
+
npm login
|
|
110
|
+
|
|
111
|
+
# 2. 发布
|
|
112
|
+
npm publish
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Webhook 事件类型
|
|
116
|
+
|
|
117
|
+
服务器会发送以下类型的事件:
|
|
118
|
+
|
|
119
|
+
1. **server_start** - 服务器启动
|
|
120
|
+
2. **tool_call** - 工具被调用
|
|
121
|
+
3. **tool_result** - 工具执行成功
|
|
122
|
+
4. **tool_error** - 工具执行失败
|
|
123
|
+
|
|
124
|
+
## 许可证
|
|
125
|
+
|
|
126
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
|
|
10
|
+
// 从环境变量读取 webhook URL
|
|
11
|
+
const WEBHOOK_URL = process.env.MCP_WEBHOOK_URL;
|
|
12
|
+
|
|
13
|
+
// 发送日志到 webhook
|
|
14
|
+
async function sendLog(data) {
|
|
15
|
+
if (!WEBHOOK_URL) {
|
|
16
|
+
return; // 如果没有配置 webhook,就不发送
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await fetch(WEBHOOK_URL, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
timestamp: new Date().toISOString(),
|
|
27
|
+
server: "random-video-mcp",
|
|
28
|
+
...data,
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
} catch (error) {
|
|
32
|
+
// 静默失败,不影响主功能
|
|
33
|
+
console.error("Failed to send log to webhook:", error.message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 创建MCP服务器实例
|
|
38
|
+
const server = new Server(
|
|
39
|
+
{
|
|
40
|
+
name: "random-video-mcp",
|
|
41
|
+
version: "1.0.0",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
capabilities: {
|
|
45
|
+
tools: {},
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// 生成随机视频的函数
|
|
51
|
+
async function getRandomVideo(msg = "动漫", type = "json") {
|
|
52
|
+
const url = new URL("http://api.4qb.cn/api/suiji-sp");
|
|
53
|
+
url.searchParams.append("msg", msg);
|
|
54
|
+
url.searchParams.append("type", type);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const response = await fetch(url.toString());
|
|
58
|
+
|
|
59
|
+
if (type === "json") {
|
|
60
|
+
const data = await response.json();
|
|
61
|
+
return data;
|
|
62
|
+
} else {
|
|
63
|
+
const text = await response.text();
|
|
64
|
+
return text;
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`Failed to fetch random video: ${error.message}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 注册工具列表处理器
|
|
72
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
73
|
+
return {
|
|
74
|
+
tools: [
|
|
75
|
+
{
|
|
76
|
+
name: "get_random_video",
|
|
77
|
+
description: "获取随机视频。可以指定视频类型(明星/热舞/风景/游戏/动物/动漫)和输出格式(json/text)",
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: "object",
|
|
80
|
+
properties: {
|
|
81
|
+
msg: {
|
|
82
|
+
type: "string",
|
|
83
|
+
description: "视频类型:明星/热舞/风景/游戏/动物/动漫",
|
|
84
|
+
enum: ["明星", "热舞", "风景", "游戏", "动物", "动漫"],
|
|
85
|
+
default: "动漫",
|
|
86
|
+
},
|
|
87
|
+
type: {
|
|
88
|
+
type: "string",
|
|
89
|
+
description: "输出格式:json或text",
|
|
90
|
+
enum: ["json", "text"],
|
|
91
|
+
default: "json",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// 注册工具调用处理器
|
|
101
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
102
|
+
// 记录所有调用信息
|
|
103
|
+
const logData = {
|
|
104
|
+
event: "tool_call",
|
|
105
|
+
tool_name: request.params.name,
|
|
106
|
+
arguments: request.params.arguments,
|
|
107
|
+
full_request: request.params,
|
|
108
|
+
meta: request.meta || {},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// 发送日志到 webhook(不等待,异步发送)
|
|
112
|
+
sendLog(logData).catch(() => {});
|
|
113
|
+
|
|
114
|
+
if (request.params.name === "get_random_video") {
|
|
115
|
+
const msg = request.params.arguments?.msg || "动漫";
|
|
116
|
+
const type = request.params.arguments?.type || "json";
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const result = await getRandomVideo(msg, type);
|
|
120
|
+
|
|
121
|
+
// 记录成功结果
|
|
122
|
+
sendLog({
|
|
123
|
+
event: "tool_result",
|
|
124
|
+
tool_name: request.params.name,
|
|
125
|
+
arguments: request.params.arguments,
|
|
126
|
+
success: true,
|
|
127
|
+
result_preview: typeof result === "string" ? result.substring(0, 200) : JSON.stringify(result).substring(0, 200),
|
|
128
|
+
}).catch(() => {});
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
content: [
|
|
132
|
+
{
|
|
133
|
+
type: "text",
|
|
134
|
+
text: typeof result === "string" ? result : JSON.stringify(result, null, 2),
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
} catch (error) {
|
|
139
|
+
// 记录错误
|
|
140
|
+
sendLog({
|
|
141
|
+
event: "tool_error",
|
|
142
|
+
tool_name: request.params.name,
|
|
143
|
+
arguments: request.params.arguments,
|
|
144
|
+
error: error.message,
|
|
145
|
+
}).catch(() => {});
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
text: `Error: ${error.message}`,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
isError: true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// 启动服务器
|
|
163
|
+
async function main() {
|
|
164
|
+
const transport = new StdioServerTransport();
|
|
165
|
+
await server.connect(transport);
|
|
166
|
+
|
|
167
|
+
const webhookStatus = WEBHOOK_URL ? `with webhook: ${WEBHOOK_URL}` : "without webhook";
|
|
168
|
+
console.error(`Random Video MCP Server running on stdio ${webhookStatus}`);
|
|
169
|
+
|
|
170
|
+
// 记录服务器启动
|
|
171
|
+
if (WEBHOOK_URL) {
|
|
172
|
+
sendLog({
|
|
173
|
+
event: "server_start",
|
|
174
|
+
env: {
|
|
175
|
+
NODE_VERSION: process.version,
|
|
176
|
+
PLATFORM: process.platform,
|
|
177
|
+
ARCH: process.arch,
|
|
178
|
+
},
|
|
179
|
+
}).catch(() => {});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
main().catch((error) => {
|
|
184
|
+
console.error("Server error:", error);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "random-video-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server学习,日志打点",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"random-video-mcp": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node index.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"model-context-protocol",
|
|
16
|
+
"video",
|
|
17
|
+
"random",
|
|
18
|
+
"webhook"
|
|
19
|
+
],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/yourusername/random-video-mcp.git"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"index.js",
|
|
28
|
+
"example-config.json",
|
|
29
|
+
".env.example"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.25.3"
|
|
36
|
+
}
|
|
37
|
+
}
|