@yyaylt/zhipu-web-search-mcp-server 1.0.1 → 1.0.2

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/dist/index.d.ts CHANGED
@@ -8,5 +8,9 @@
8
8
  * 环境变量:
9
9
  * ZHIPU_API_KEY - 智谱 API Key(必填),从 https://bigmodel.cn/usercenter/proj-mgmt/apikeys 获取
10
10
  */
11
- export {};
11
+ import type { WebSearchToolOutput } from "./types.js";
12
+ export declare function formatResultsMarkdown(output: WebSearchToolOutput, charLimit?: number): {
13
+ text: string;
14
+ truncated: boolean;
15
+ };
12
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAatD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,mBAAmB,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAkDtC"}
package/dist/index.js CHANGED
@@ -13,14 +13,19 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
13
13
  import { callWebSearch, handleApiError } from "./services/webSearchApi.js";
14
14
  import { WebSearchInputSchema } from "./schemas/webSearch.js";
15
15
  import { CHARACTER_LIMIT } from "./constants.js";
16
+ import { pathToFileURL } from "node:url";
16
17
  // 创建 MCP 服务器实例
17
18
  const server = new McpServer({
18
19
  name: "zhipu-web-search-mcp-server",
19
20
  version: "1.0.0"
20
21
  });
21
- // 将搜索结果格式化为 Markdown 文本
22
- function formatResultsMarkdown(output) {
22
+ // 将搜索结果格式化为 Markdown 文本。
23
+ // 支持传入 charLimit:构建时逐条累计字符数,一旦加入下一条会超限则立即停止,
24
+ // 避免先构建完整大字符串再截断所造成的一次性峰值内存占用。
25
+ // 返回 { text, truncated }:text 为最终文本,truncated 标记是否因超限被截断。
26
+ export function formatResultsMarkdown(output, charLimit) {
23
27
  const lines = [];
28
+ let charCount = 0;
24
29
  if (output.search_intent && output.search_intent.length > 0) {
25
30
  const intent = output.search_intent[0];
26
31
  lines.push(`## 搜索意图识别`);
@@ -32,27 +37,36 @@ function formatResultsMarkdown(output) {
32
37
  lines.push("");
33
38
  }
34
39
  if (output.results.length === 0) {
35
- lines.push("未找到相关搜索结果。");
36
- return lines.join("\n");
40
+ return { text: "未找到相关搜索结果。", truncated: false };
37
41
  }
38
42
  lines.push(`# 搜索结果 (${output.count})`);
39
43
  lines.push("");
40
- output.results.forEach((item, index) => {
41
- lines.push(`## ${index + 1}. ${item.title}`);
44
+ let truncated = false;
45
+ for (let index = 0; index < output.results.length; index++) {
46
+ const item = output.results[index];
47
+ const itemLines = [`## ${index + 1}. ${item.title}`];
42
48
  if (item.publish_date) {
43
- lines.push(`**发布时间:** ${item.publish_date}`);
49
+ itemLines.push(`**发布时间:** ${item.publish_date}`);
44
50
  }
45
51
  if (item.media) {
46
- lines.push(`**来源:** ${item.media}`);
52
+ itemLines.push(`**来源:** ${item.media}`);
47
53
  }
48
54
  if (item.link) {
49
- lines.push(`**链接:** ${item.link}`);
55
+ itemLines.push(`**链接:** ${item.link}`);
50
56
  }
51
- lines.push("");
52
- lines.push(item.content || "(无摘要)");
53
- lines.push("");
54
- });
55
- return lines.join("\n");
57
+ itemLines.push("");
58
+ itemLines.push(item.content || "(无摘要)");
59
+ itemLines.push("");
60
+ const itemText = itemLines.join("\n");
61
+ // 若加入本条将超出字符上限,则停止构建并标记截断(+1 计入条目间的换行分隔符)
62
+ if (charLimit !== undefined && charCount + itemText.length + 1 > charLimit) {
63
+ truncated = true;
64
+ break;
65
+ }
66
+ lines.push(itemText);
67
+ charCount += itemText.length + 1;
68
+ }
69
+ return { text: lines.join("\n"), truncated };
56
70
  }
57
71
  // 注册网络搜索工具
58
72
  server.registerTool("zhipu_web_search", {
@@ -126,18 +140,13 @@ Error Handling:
126
140
  count: results.length,
127
141
  results
128
142
  };
129
- let text = formatResultsMarkdown(output);
130
- // 超长截断,防止响应过大
131
- if (text.length > CHARACTER_LIMIT) {
132
- const keepItems = Math.max(1, Math.floor(results.length / 2));
133
- const truncated = {
134
- ...output,
135
- results: results.slice(0, keepItems)
136
- };
137
- text = `${formatResultsMarkdown(truncated)}\n\n> 响应因过长被截断(原 ${results.length} 条),可减少 count 或增加关键词精度以查看更多结果。`;
138
- }
143
+ // 一次性限长构建 Markdown,超限即截断,避免先构建完整文本再二次格式化的内存峰值
144
+ const { text, truncated } = formatResultsMarkdown(output, CHARACTER_LIMIT);
145
+ const finalText = truncated
146
+ ? `${text}\n\n> 响应因过长被截断(原 ${results.length} 条),可减少 count 或增加关键词精度以查看更多结果。`
147
+ : text;
139
148
  return {
140
- content: [{ type: "text", text }],
149
+ content: [{ type: "text", text: finalText }],
141
150
  structuredContent: output
142
151
  };
143
152
  }
@@ -163,8 +172,11 @@ async function main() {
163
172
  await server.connect(transport);
164
173
  console.error("智谱 Web Search MCP server 正在运行 (stdio)");
165
174
  }
166
- main().catch((error) => {
167
- console.error("服务器启动失败:", error);
168
- process.exit(1);
169
- });
175
+ // 仅当作为主入口被直接执行时才启动服务器;被测试 import 时不启动
176
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
177
+ main().catch((error) => {
178
+ console.error("服务器启动失败:", error);
179
+ process.exit(1);
180
+ });
181
+ }
170
182
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yyaylt/zhipu-web-search-mcp-server",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "MCP server for ZHIPU AI Web Search API integration",
5
5
  "keywords": [
6
6
  "zhipu",
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ import { callWebSearch, handleApiError } from "./services/webSearchApi.js";
15
15
  import { WebSearchInputSchema } from "./schemas/webSearch.js";
16
16
  import { CHARACTER_LIMIT } from "./constants.js";
17
17
  import type { WebSearchToolOutput } from "./types.js";
18
+ import { pathToFileURL } from "node:url";
18
19
 
19
20
  // 创建 MCP 服务器实例
20
21
  const server = new McpServer({
@@ -22,9 +23,16 @@ const server = new McpServer({
22
23
  version: "1.0.0"
23
24
  });
24
25
 
25
- // 将搜索结果格式化为 Markdown 文本
26
- function formatResultsMarkdown(output: WebSearchToolOutput): string {
26
+ // 将搜索结果格式化为 Markdown 文本。
27
+ // 支持传入 charLimit:构建时逐条累计字符数,一旦加入下一条会超限则立即停止,
28
+ // 避免先构建完整大字符串再截断所造成的一次性峰值内存占用。
29
+ // 返回 { text, truncated }:text 为最终文本,truncated 标记是否因超限被截断。
30
+ export function formatResultsMarkdown(
31
+ output: WebSearchToolOutput,
32
+ charLimit?: number
33
+ ): { text: string; truncated: boolean } {
27
34
  const lines: string[] = [];
35
+ let charCount = 0;
28
36
 
29
37
  if (output.search_intent && output.search_intent.length > 0) {
30
38
  const intent = output.search_intent[0];
@@ -38,28 +46,40 @@ function formatResultsMarkdown(output: WebSearchToolOutput): string {
38
46
  }
39
47
 
40
48
  if (output.results.length === 0) {
41
- lines.push("未找到相关搜索结果。");
42
- return lines.join("\n");
49
+ return { text: "未找到相关搜索结果。", truncated: false };
43
50
  }
44
51
 
45
52
  lines.push(`# 搜索结果 (${output.count})`);
46
53
  lines.push("");
47
- output.results.forEach((item, index) => {
48
- lines.push(`## ${index + 1}. ${item.title}`);
54
+
55
+ let truncated = false;
56
+ for (let index = 0; index < output.results.length; index++) {
57
+ const item = output.results[index];
58
+ const itemLines = [`## ${index + 1}. ${item.title}`];
49
59
  if (item.publish_date) {
50
- lines.push(`**发布时间:** ${item.publish_date}`);
60
+ itemLines.push(`**发布时间:** ${item.publish_date}`);
51
61
  }
52
62
  if (item.media) {
53
- lines.push(`**来源:** ${item.media}`);
63
+ itemLines.push(`**来源:** ${item.media}`);
54
64
  }
55
65
  if (item.link) {
56
- lines.push(`**链接:** ${item.link}`);
66
+ itemLines.push(`**链接:** ${item.link}`);
57
67
  }
58
- lines.push("");
59
- lines.push(item.content || "(无摘要)");
60
- lines.push("");
61
- });
62
- return lines.join("\n");
68
+ itemLines.push("");
69
+ itemLines.push(item.content || "(无摘要)");
70
+ itemLines.push("");
71
+
72
+ const itemText = itemLines.join("\n");
73
+ // 若加入本条将超出字符上限,则停止构建并标记截断(+1 计入条目间的换行分隔符)
74
+ if (charLimit !== undefined && charCount + itemText.length + 1 > charLimit) {
75
+ truncated = true;
76
+ break;
77
+ }
78
+ lines.push(itemText);
79
+ charCount += itemText.length + 1;
80
+ }
81
+
82
+ return { text: lines.join("\n"), truncated };
63
83
  }
64
84
 
65
85
  // 注册网络搜索工具
@@ -140,20 +160,14 @@ Error Handling:
140
160
  results
141
161
  };
142
162
 
143
- let text = formatResultsMarkdown(output);
144
-
145
- // 超长截断,防止响应过大
146
- if (text.length > CHARACTER_LIMIT) {
147
- const keepItems = Math.max(1, Math.floor(results.length / 2));
148
- const truncated = {
149
- ...output,
150
- results: results.slice(0, keepItems)
151
- };
152
- text = `${formatResultsMarkdown(truncated)}\n\n> 响应因过长被截断(原 ${results.length} 条),可减少 count 或增加关键词精度以查看更多结果。`;
153
- }
163
+ // 一次性限长构建 Markdown,超限即截断,避免先构建完整文本再二次格式化的内存峰值
164
+ const { text, truncated } = formatResultsMarkdown(output, CHARACTER_LIMIT);
165
+ const finalText = truncated
166
+ ? `${text}\n\n> 响应因过长被截断(原 ${results.length} 条),可减少 count 或增加关键词精度以查看更多结果。`
167
+ : text;
154
168
 
155
169
  return {
156
- content: [{ type: "text" as const, text }],
170
+ content: [{ type: "text" as const, text: finalText }],
157
171
  structuredContent: output
158
172
  };
159
173
  } catch (error) {
@@ -182,7 +196,10 @@ async function main() {
182
196
  console.error("智谱 Web Search MCP server 正在运行 (stdio)");
183
197
  }
184
198
 
185
- main().catch((error) => {
186
- console.error("服务器启动失败:", error);
187
- process.exit(1);
188
- });
199
+ // 仅当作为主入口被直接执行时才启动服务器;被测试 import 时不启动
200
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
201
+ main().catch((error) => {
202
+ console.error("服务器启动失败:", error);
203
+ process.exit(1);
204
+ });
205
+ }