@lmcc-dev/mult-fetch-mcp-server 1.0.1

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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/README.zh.md +510 -0
  4. package/dist/index.js +21 -0
  5. package/dist/src/cli-language.js +78 -0
  6. package/dist/src/client.js +284 -0
  7. package/dist/src/index.js +21 -0
  8. package/dist/src/lib/BrowserFetcher.js +753 -0
  9. package/dist/src/lib/NodeFetcher.js +428 -0
  10. package/dist/src/lib/example.js +93 -0
  11. package/dist/src/lib/i18n/index.js +36 -0
  12. package/dist/src/lib/i18n/locales/en/browser.js +53 -0
  13. package/dist/src/lib/i18n/locales/en/client.js +40 -0
  14. package/dist/src/lib/i18n/locales/en/errors.js +18 -0
  15. package/dist/src/lib/i18n/locales/en/fetcher.js +67 -0
  16. package/dist/src/lib/i18n/locales/en/index.js +26 -0
  17. package/dist/src/lib/i18n/locales/en/node.js +42 -0
  18. package/dist/src/lib/i18n/locales/en/prompts.js +72 -0
  19. package/dist/src/lib/i18n/locales/en/resources.js +47 -0
  20. package/dist/src/lib/i18n/locales/en/server.js +32 -0
  21. package/dist/src/lib/i18n/locales/en/tools.js +25 -0
  22. package/dist/src/lib/i18n/locales/zh/browser.js +53 -0
  23. package/dist/src/lib/i18n/locales/zh/client.js +39 -0
  24. package/dist/src/lib/i18n/locales/zh/errors.js +18 -0
  25. package/dist/src/lib/i18n/locales/zh/fetcher.js +67 -0
  26. package/dist/src/lib/i18n/locales/zh/index.js +26 -0
  27. package/dist/src/lib/i18n/locales/zh/node.js +42 -0
  28. package/dist/src/lib/i18n/locales/zh/prompts.js +72 -0
  29. package/dist/src/lib/i18n/locales/zh/resources.js +47 -0
  30. package/dist/src/lib/i18n/locales/zh/server.js +32 -0
  31. package/dist/src/lib/i18n/locales/zh/tools.js +25 -0
  32. package/dist/src/lib/i18n/logger.js +57 -0
  33. package/dist/src/lib/logger.js +126 -0
  34. package/dist/src/lib/server/browser.js +86 -0
  35. package/dist/src/lib/server/fetcher.js +130 -0
  36. package/dist/src/lib/server/index.js +73 -0
  37. package/dist/src/lib/server/logger.js +23 -0
  38. package/dist/src/lib/server/prompts.js +207 -0
  39. package/dist/src/lib/server/resources.js +171 -0
  40. package/dist/src/lib/server/tools.js +346 -0
  41. package/dist/src/lib/server/types.js +6 -0
  42. package/dist/src/lib/types.js +35 -0
  43. package/dist/src/mcp-server.js +22 -0
  44. package/dist/tests/test-direct-client.js +129 -0
  45. package/dist/tests/test-mcp-methods.js +114 -0
  46. package/dist/tests/test-mcp.js +145 -0
  47. package/dist/tests/test-mini4k.js +147 -0
  48. package/images/example_en.png +0 -0
  49. package/images/example_zh.png +0 -0
  50. package/package.json +80 -0
@@ -0,0 +1,346 @@
1
+ /**
2
+ * Author: Martin <lmccc.dev@gmail.com>
3
+ * Co-Author: AI Assistant (Claude)
4
+ * Description: This code was collaboratively developed by Martin and AI Assistant.
5
+ */
6
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
7
+ import { log, COMPONENTS } from '../logger.js';
8
+ import { fetchWithAutoDetect } from './fetcher.js';
9
+ /**
10
+ * 注册工具到服务器 (Register tools to server)
11
+ * 设置工具列表和处理程序 (Set up tool list and handlers)
12
+ * @param server MCP服务器实例 (MCP server instance)
13
+ */
14
+ export function registerTools(server) {
15
+ // 注册工具列表处理程序
16
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
17
+ return {
18
+ tools: [
19
+ {
20
+ name: "fetch_html",
21
+ description: "Fetch a website and return the content as HTML",
22
+ inputSchema: {
23
+ type: "object",
24
+ properties: {
25
+ url: {
26
+ type: "string",
27
+ description: "URL of the website to fetch",
28
+ },
29
+ headers: {
30
+ type: "object",
31
+ description: "Optional headers to include in the request",
32
+ },
33
+ proxy: {
34
+ type: "string",
35
+ description: "Optional proxy server to use (format: http://host:port or https://host:port)",
36
+ },
37
+ noDelay: {
38
+ type: "boolean",
39
+ description: "Optional flag to disable random delay between requests (default: false)",
40
+ },
41
+ timeout: {
42
+ type: "number",
43
+ description: "Optional timeout in milliseconds (default: 30000)",
44
+ },
45
+ maxRedirects: {
46
+ type: "number",
47
+ description: "Optional maximum number of redirects to follow (default: 10)",
48
+ },
49
+ useSystemProxy: {
50
+ type: "boolean",
51
+ description: "Optional flag to use system proxy environment variables (default: true)",
52
+ },
53
+ debug: {
54
+ type: "boolean",
55
+ description: "Optional flag to enable detailed debug logging (default: false)",
56
+ },
57
+ useBrowser: {
58
+ type: "boolean",
59
+ description: "Optional flag to use headless browser for fetching (default: false)",
60
+ },
61
+ autoDetectMode: {
62
+ type: "boolean",
63
+ description: "Optional flag to automatically switch to browser mode if standard fetch fails (default: true)",
64
+ },
65
+ waitForSelector: {
66
+ type: "string",
67
+ description: "Optional CSS selector to wait for when using browser mode",
68
+ },
69
+ waitForTimeout: {
70
+ type: "number",
71
+ description: "Optional timeout to wait after page load in browser mode (default: 5000)",
72
+ },
73
+ scrollToBottom: {
74
+ type: "boolean",
75
+ description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
76
+ },
77
+ saveCookies: {
78
+ type: "boolean",
79
+ description: "Optional flag to save cookies for future requests to the same domain (default: true)",
80
+ },
81
+ closeBrowser: {
82
+ type: "boolean",
83
+ description: "Optional flag to close the browser after fetching (default: false)",
84
+ },
85
+ },
86
+ required: ["url"],
87
+ },
88
+ },
89
+ {
90
+ name: "fetch_json",
91
+ description: "Fetch a JSON file from a URL",
92
+ inputSchema: {
93
+ type: "object",
94
+ properties: {
95
+ url: {
96
+ type: "string",
97
+ description: "URL of the JSON to fetch",
98
+ },
99
+ headers: {
100
+ type: "object",
101
+ description: "Optional headers to include in the request",
102
+ },
103
+ proxy: {
104
+ type: "string",
105
+ description: "Optional proxy server to use (format: http://host:port or https://host:port)",
106
+ },
107
+ noDelay: {
108
+ type: "boolean",
109
+ description: "Optional flag to disable random delay between requests (default: false)",
110
+ },
111
+ timeout: {
112
+ type: "number",
113
+ description: "Optional timeout in milliseconds (default: 30000)",
114
+ },
115
+ maxRedirects: {
116
+ type: "number",
117
+ description: "Optional maximum number of redirects to follow (default: 10)",
118
+ },
119
+ useSystemProxy: {
120
+ type: "boolean",
121
+ description: "Optional flag to use system proxy environment variables (default: true)",
122
+ },
123
+ debug: {
124
+ type: "boolean",
125
+ description: "Optional flag to enable detailed debug logging (default: false)",
126
+ },
127
+ useBrowser: {
128
+ type: "boolean",
129
+ description: "Optional flag to use headless browser for fetching (default: false)",
130
+ },
131
+ waitForSelector: {
132
+ type: "string",
133
+ description: "Optional CSS selector to wait for when using browser mode",
134
+ },
135
+ waitForTimeout: {
136
+ type: "number",
137
+ description: "Optional timeout to wait after page load in browser mode (default: 5000)",
138
+ },
139
+ closeBrowser: {
140
+ type: "boolean",
141
+ description: "Optional flag to close the browser after fetching (default: false)",
142
+ },
143
+ },
144
+ required: ["url"],
145
+ },
146
+ },
147
+ {
148
+ name: "fetch_txt",
149
+ description: "Fetch a website, return the content as plain text (no HTML)",
150
+ inputSchema: {
151
+ type: "object",
152
+ properties: {
153
+ url: {
154
+ type: "string",
155
+ description: "URL of the website to fetch",
156
+ },
157
+ headers: {
158
+ type: "object",
159
+ description: "Optional headers to include in the request",
160
+ },
161
+ proxy: {
162
+ type: "string",
163
+ description: "Optional proxy server to use (format: http://host:port or https://host:port)",
164
+ },
165
+ noDelay: {
166
+ type: "boolean",
167
+ description: "Optional flag to disable random delay between requests (default: false)",
168
+ },
169
+ timeout: {
170
+ type: "number",
171
+ description: "Optional timeout in milliseconds (default: 30000)",
172
+ },
173
+ maxRedirects: {
174
+ type: "number",
175
+ description: "Optional maximum number of redirects to follow (default: 10)",
176
+ },
177
+ useSystemProxy: {
178
+ type: "boolean",
179
+ description: "Optional flag to use system proxy environment variables (default: true)",
180
+ },
181
+ debug: {
182
+ type: "boolean",
183
+ description: "Optional flag to enable detailed debug logging (default: false)",
184
+ },
185
+ useBrowser: {
186
+ type: "boolean",
187
+ description: "Optional flag to use headless browser for fetching (default: false)",
188
+ },
189
+ waitForSelector: {
190
+ type: "string",
191
+ description: "Optional CSS selector to wait for when using browser mode",
192
+ },
193
+ waitForTimeout: {
194
+ type: "number",
195
+ description: "Optional timeout to wait after page load in browser mode (default: 5000)",
196
+ },
197
+ scrollToBottom: {
198
+ type: "boolean",
199
+ description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
200
+ },
201
+ closeBrowser: {
202
+ type: "boolean",
203
+ description: "Optional flag to close the browser after fetching (default: false)",
204
+ },
205
+ },
206
+ required: ["url"],
207
+ },
208
+ },
209
+ {
210
+ name: "fetch_markdown",
211
+ description: "Fetch a website and return the content as Markdown",
212
+ inputSchema: {
213
+ type: "object",
214
+ properties: {
215
+ url: {
216
+ type: "string",
217
+ description: "URL of the website to fetch",
218
+ },
219
+ headers: {
220
+ type: "object",
221
+ description: "Optional headers to include in the request",
222
+ },
223
+ proxy: {
224
+ type: "string",
225
+ description: "Optional proxy server to use (format: http://host:port or https://host:port)",
226
+ },
227
+ noDelay: {
228
+ type: "boolean",
229
+ description: "Optional flag to disable random delay between requests (default: false)",
230
+ },
231
+ timeout: {
232
+ type: "number",
233
+ description: "Optional timeout in milliseconds (default: 30000)",
234
+ },
235
+ maxRedirects: {
236
+ type: "number",
237
+ description: "Optional maximum number of redirects to follow (default: 10)",
238
+ },
239
+ useSystemProxy: {
240
+ type: "boolean",
241
+ description: "Optional flag to use system proxy environment variables (default: true)",
242
+ },
243
+ debug: {
244
+ type: "boolean",
245
+ description: "Optional flag to enable detailed debug logging (default: false)",
246
+ },
247
+ useBrowser: {
248
+ type: "boolean",
249
+ description: "Optional flag to use headless browser for fetching (default: false)",
250
+ },
251
+ waitForSelector: {
252
+ type: "string",
253
+ description: "Optional CSS selector to wait for when using browser mode",
254
+ },
255
+ waitForTimeout: {
256
+ type: "number",
257
+ description: "Optional timeout to wait after page load in browser mode (default: 5000)",
258
+ },
259
+ scrollToBottom: {
260
+ type: "boolean",
261
+ description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
262
+ },
263
+ closeBrowser: {
264
+ type: "boolean",
265
+ description: "Optional flag to close the browser after fetching (default: false)",
266
+ },
267
+ },
268
+ required: ["url"],
269
+ },
270
+ },
271
+ ],
272
+ };
273
+ });
274
+ // 注册工具调用处理程序
275
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
276
+ const name = request.params.name;
277
+ const parameters = request.params.arguments;
278
+ const params = parameters;
279
+ try {
280
+ // 记录工具请求
281
+ log('server.receivedToolRequest', params.debug === true, { name, url: params.url }, COMPONENTS.TOOLS);
282
+ if (name === "fetch_html") {
283
+ const result = await fetchWithAutoDetect(params, 'html');
284
+ return {
285
+ content: [
286
+ {
287
+ type: "text",
288
+ text: result.content[0].text
289
+ }
290
+ ],
291
+ isError: result.isError
292
+ };
293
+ }
294
+ else if (name === "fetch_json") {
295
+ const result = await fetchWithAutoDetect(params, 'json');
296
+ return {
297
+ content: [
298
+ {
299
+ type: "text",
300
+ text: result.content[0].text
301
+ }
302
+ ],
303
+ isError: result.isError
304
+ };
305
+ }
306
+ else if (name === "fetch_txt") {
307
+ const result = await fetchWithAutoDetect(params, 'txt');
308
+ return {
309
+ content: [
310
+ {
311
+ type: "text",
312
+ text: result.content[0].text
313
+ }
314
+ ],
315
+ isError: result.isError
316
+ };
317
+ }
318
+ else if (name === "fetch_markdown") {
319
+ const result = await fetchWithAutoDetect(params, 'markdown');
320
+ return {
321
+ content: [
322
+ {
323
+ type: "text",
324
+ text: result.content[0].text
325
+ }
326
+ ],
327
+ isError: result.isError
328
+ };
329
+ }
330
+ throw new Error(`Unknown tool name: ${name}`);
331
+ }
332
+ catch (error) {
333
+ // 记录错误
334
+ log('server.processingToolRequestError', params.debug === true, { name, error: error instanceof Error ? error.message : String(error) }, COMPONENTS.TOOLS);
335
+ return {
336
+ isError: true,
337
+ content: [
338
+ {
339
+ type: "text",
340
+ text: `Error processing request: ${error instanceof Error ? error.message : String(error)}`
341
+ }
342
+ ]
343
+ };
344
+ }
345
+ });
346
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Author: Martin <lmccc.dev@gmail.com>
3
+ * Co-Author: AI Assistant (Claude)
4
+ * Description: This code was collaboratively developed by Martin and AI Assistant.
5
+ */
6
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Author: Martin <lmccc.dev@gmail.com>
3
+ * Co-Author: AI Assistant (Claude)
4
+ * Description: This code was collaboratively developed by Martin and AI Assistant.
5
+ */
6
+ import { z } from "zod";
7
+ // 浏览器特定参数
8
+ export const BrowserParamsSchema = z.object({
9
+ waitForSelector: z.string().optional(),
10
+ waitForTimeout: z.number().optional(),
11
+ scrollToBottom: z.boolean().optional(),
12
+ saveCookies: z.boolean().optional(),
13
+ useBrowser: z.boolean().optional(),
14
+ useNodeFetch: z.boolean().optional(),
15
+ autoDetectMode: z.boolean().optional(),
16
+ closeBrowser: z.boolean().optional(),
17
+ });
18
+ export const RequestPayloadSchema = z.object({
19
+ url: z.string(),
20
+ method: z.string().optional(),
21
+ headers: z.record(z.string()).optional(),
22
+ proxy: z.string().optional(),
23
+ noDelay: z.boolean().optional(),
24
+ timeout: z.number().optional(),
25
+ maxRedirects: z.number().optional(),
26
+ useSystemProxy: z.boolean().optional(),
27
+ debug: z.boolean().optional(),
28
+ useBrowser: z.boolean().optional(),
29
+ useNodeFetch: z.boolean().optional(),
30
+ autoDetectMode: z.boolean().optional(),
31
+ waitForSelector: z.string().optional(),
32
+ waitForTimeout: z.number().optional(),
33
+ scrollToBottom: z.boolean().optional(),
34
+ closeBrowser: z.boolean().optional(),
35
+ }).merge(BrowserParamsSchema);
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Author: Martin <lmccc.dev@gmail.com>
3
+ * Co-Author: AI Assistant (Claude)
4
+ * Description: This code was collaboratively developed by Martin and AI Assistant.
5
+ */
6
+ import { startServer } from './lib/server/index.js';
7
+ import { log, COMPONENTS } from './lib/logger.js';
8
+ /**
9
+ * 主函数 (Main function)
10
+ * 统一处理debug和MCP_LANG的获取方式 (Unified handling of debug and MCP_LANG acquisition)
11
+ */
12
+ async function main() {
13
+ // MCP_LANG从环境变量获取,已在i18n/index.ts中处理
14
+ // debug将从调用参数获取,不需要在这里处理
15
+ // 启动服务器
16
+ await startServer();
17
+ }
18
+ // 启动服务器
19
+ main().catch(async (error) => {
20
+ log('server.startupError', true, { error: error instanceof Error ? error.message : String(error) }, COMPONENTS.SERVER);
21
+ process.exit(1);
22
+ });
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Author: Martin <lmccc.dev@gmail.com>
3
+ * Co-Author: AI Assistant (Claude)
4
+ * Description: This code was collaboratively developed by Martin and AI Assistant.
5
+ */
6
+ import { spawn } from 'child_process';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ // 获取当前文件的目录路径 (Get the directory path of the current file)
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+ // 获取项目根目录 (Get the project root directory)
13
+ const rootDir = process.cwd();
14
+ /**
15
+ * 直接调用客户端脚本进行测试 (Directly call client script for testing)
16
+ * 不通过MCP协议,直接测试客户端功能 (Test client functionality directly without going through MCP protocol)
17
+ */
18
+ async function testDirectClient() {
19
+ console.log('开始直接调用客户端脚本进行测试...');
20
+ // 测试用例列表
21
+ const testCases = [
22
+ {
23
+ name: 'HTML 获取测试',
24
+ method: 'fetch_html',
25
+ params: {
26
+ url: 'https://example.com',
27
+ debug: true
28
+ }
29
+ },
30
+ {
31
+ name: 'JSON 获取测试',
32
+ method: 'fetch_json',
33
+ params: {
34
+ url: 'https://jsonplaceholder.typicode.com/todos/1',
35
+ debug: true
36
+ }
37
+ },
38
+ {
39
+ name: 'TXT 获取测试',
40
+ method: 'fetch_txt',
41
+ params: {
42
+ url: 'https://example.com',
43
+ debug: true
44
+ }
45
+ },
46
+ {
47
+ name: 'Markdown 获取测试',
48
+ method: 'fetch_markdown',
49
+ params: {
50
+ url: 'https://example.com',
51
+ debug: true
52
+ }
53
+ },
54
+ {
55
+ name: '错误处理测试 - 无效URL',
56
+ method: 'fetch_html',
57
+ params: {
58
+ url: 'https://this-domain-does-not-exist-123456789.com',
59
+ debug: true,
60
+ timeout: 5000
61
+ }
62
+ }
63
+ ];
64
+ // 依次执行每个测试用例
65
+ for (const testCase of testCases) {
66
+ console.log(`\n执行测试: ${testCase.name}`);
67
+ // 构建命令行参数
68
+ const clientPath = path.resolve(rootDir, 'dist/src/client.js');
69
+ const args = [
70
+ clientPath,
71
+ testCase.method,
72
+ JSON.stringify(testCase.params)
73
+ ];
74
+ console.log(`运行命令: node ${args.join(' ')}`);
75
+ // 执行命令
76
+ const result = await new Promise((resolve) => {
77
+ const childProcess = spawn('node', args, {
78
+ stdio: ['ignore', 'pipe', 'pipe']
79
+ });
80
+ let stdout = '';
81
+ let stderr = '';
82
+ childProcess.stdout.on('data', (data) => {
83
+ stdout += data.toString();
84
+ });
85
+ childProcess.stderr.on('data', (data) => {
86
+ stderr += data.toString();
87
+ });
88
+ childProcess.on('close', (code) => {
89
+ resolve({
90
+ code: code || 0,
91
+ stdout,
92
+ stderr
93
+ });
94
+ });
95
+ });
96
+ // 输出结果
97
+ console.log(`退出代码: ${result.code}`);
98
+ if (result.code === 0) {
99
+ console.log('测试成功!');
100
+ // 尝试解析JSON结果
101
+ try {
102
+ const jsonResult = JSON.parse(result.stdout);
103
+ console.log('结果类型:', typeof jsonResult);
104
+ if (typeof jsonResult === 'string') {
105
+ console.log('内容长度:', jsonResult.length);
106
+ console.log('内容预览:', jsonResult.substring(0, 200) + '...');
107
+ }
108
+ else {
109
+ console.log('结果:', JSON.stringify(jsonResult, null, 2));
110
+ }
111
+ }
112
+ catch (error) {
113
+ console.log('原始输出:');
114
+ console.log(result.stdout);
115
+ }
116
+ }
117
+ else {
118
+ console.error('测试失败!');
119
+ console.error('错误输出:');
120
+ console.error(result.stderr);
121
+ }
122
+ }
123
+ console.log('\n所有测试完成!');
124
+ }
125
+ // 运行测试
126
+ testDirectClient().catch(error => {
127
+ console.error('运行测试时出错:', error);
128
+ process.exit(1);
129
+ });
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Author: Martin <lmccc.dev@gmail.com>
3
+ * Co-Author: AI Assistant (Claude)
4
+ * Description: This code was collaboratively developed by Martin and AI Assistant.
5
+ */
6
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
7
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
8
+ import path from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ // 获取当前文件的目录路径 (Get the directory path of the current file)
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+ /**
14
+ * 测试 MCP 方法 (Test MCP methods)
15
+ * 测试 resources/list 和 prompts/list 方法 (Test resources/list and prompts/list methods)
16
+ */
17
+ async function testMcpMethods() {
18
+ console.log('开始测试 MCP 方法...\n');
19
+ // 创建服务器进程 (Create server process)
20
+ const serverPath = path.resolve(path.dirname(__dirname), 'index.js');
21
+ console.log(`使用服务器路径: ${serverPath}`);
22
+ // 创建客户端传输层 (Create client transport layer)
23
+ const transport = new StdioClientTransport({
24
+ command: 'node',
25
+ args: [serverPath],
26
+ stderr: 'inherit',
27
+ env: {
28
+ ...process.env, // 传递所有环境变量,包括MCP_LANG
29
+ }
30
+ });
31
+ // 创建客户端 (Create client)
32
+ const client = new Client({
33
+ name: "mcp-methods-test-client",
34
+ version: "1.0.0"
35
+ });
36
+ try {
37
+ // 连接到传输层 (Connect to transport layer)
38
+ console.log('连接到 MCP 服务器...');
39
+ await client.connect(transport);
40
+ console.log('连接成功!\n');
41
+ // 测试 resources/list 方法 (Test resources/list method)
42
+ console.log('测试 resources/list 方法...');
43
+ try {
44
+ const resourcesResult = await client.listResources({});
45
+ console.log('resources/list 结果:');
46
+ console.log(JSON.stringify(resourcesResult, null, 2));
47
+ console.log('resources/list 测试成功!\n');
48
+ }
49
+ catch (error) {
50
+ console.error('resources/list 测试失败:', error);
51
+ }
52
+ // 测试 prompts/list 方法 (Test prompts/list method)
53
+ console.log('测试 prompts/list 方法...');
54
+ try {
55
+ const promptsResult = await client.listPrompts({});
56
+ console.log('prompts/list 结果:');
57
+ console.log(JSON.stringify(promptsResult, null, 2));
58
+ console.log('prompts/list 测试成功!\n');
59
+ }
60
+ catch (error) {
61
+ console.error('prompts/list 测试失败:', error);
62
+ }
63
+ /*
64
+ // 测试 resources/read 方法 (Test resources/read method)
65
+ // 注释掉此部分,因为我们没有找到可用的资源 (Comment out this part because we didn't find available resources)
66
+ console.log('测试 resources/read 方法...');
67
+ try {
68
+ const readResult = await client.readResource({
69
+ uri: 'file:///docs/readme'
70
+ });
71
+ console.log('resources/read 结果 (前100个字符):');
72
+ if (readResult.contents && readResult.contents[0] && readResult.contents[0].text) {
73
+ console.log((readResult.contents[0].text as string).substring(0, 100) + '...');
74
+ } else {
75
+ console.log(readResult);
76
+ }
77
+ console.log('resources/read 测试成功!\n');
78
+ } catch (error) {
79
+ console.error('resources/read 测试失败:', error);
80
+ }
81
+ */
82
+ // 测试 prompts/get 方法 (Test prompts/get method)
83
+ console.log('测试 prompts/get 方法...');
84
+ try {
85
+ const getPromptResult = await client.getPrompt({
86
+ name: 'fetch-website',
87
+ arguments: {
88
+ url: 'https://example.com',
89
+ format: 'html',
90
+ useBrowser: 'false'
91
+ }
92
+ });
93
+ console.log('prompts/get 结果:');
94
+ console.log(JSON.stringify(getPromptResult, null, 2));
95
+ console.log('prompts/get 测试成功!\n');
96
+ }
97
+ catch (error) {
98
+ console.error('prompts/get 测试失败:', error);
99
+ }
100
+ }
101
+ catch (error) {
102
+ console.error('测试过程中发生错误:', error);
103
+ }
104
+ finally {
105
+ // 关闭客户端连接 (Close client connection)
106
+ await client.close();
107
+ console.log('测试完成,客户端连接已关闭');
108
+ }
109
+ }
110
+ // 执行测试 (Execute test)
111
+ testMcpMethods().catch(error => {
112
+ console.error('测试脚本执行失败:', error);
113
+ process.exit(1);
114
+ });