@yyaylt/zhipu-web-search-mcp-server 1.0.4 → 1.0.5
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/README.md +10 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -3
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -20
- package/dist/index.js.map +1 -1
- package/dist/schemas/webSearch.d.ts +80 -2
- package/dist/schemas/webSearch.d.ts.map +1 -1
- package/dist/schemas/webSearch.js +20 -3
- package/dist/schemas/webSearch.js.map +1 -1
- package/package.json +2 -2
- package/src/constants.ts +1 -3
- package/src/index.ts +30 -20
- package/src/schemas/webSearch.ts +22 -3
package/README.md
CHANGED
|
@@ -67,12 +67,20 @@ opencode mcp add zhipu-web-search -- node D:\path\to\zhipu-web-search-mcp-server
|
|
|
67
67
|
| search_query | string | 必填 | 搜索内容,不超过 70 字符 |
|
|
68
68
|
| search_engine | string | search_std | 搜索引擎:search_std / search_pro / search_pro_sogou / search_pro_quark |
|
|
69
69
|
| search_intent | boolean | false | 是否执行搜索意图识别 |
|
|
70
|
-
| count | number | 10 |
|
|
70
|
+
| count | number | 支持的引擎默认 10 | search_std / search_pro:1-50 的整数;search_pro_sogou:仅 10/20/30/40/50;search_pro_quark:不支持,不能指定 |
|
|
71
71
|
| search_domain_filter | string | - | 白名单域名过滤(search_std / search_pro / search_pro_sogou 支持) |
|
|
72
72
|
| search_recency_filter | string | noLimit | 时间过滤:oneDay / oneWeek / oneMonth / oneYear / noLimit |
|
|
73
73
|
| content_size | string | medium | 内容长短:medium / high |
|
|
74
74
|
| user_id | string | - | 终端用户 ID,6-128 字符 |
|
|
75
75
|
|
|
76
|
+
条数行为依据 [Web Search API 官方参数文档](https://docs.bigmodel.cn/api-reference/工具-api/网络搜索):
|
|
77
|
+
|
|
78
|
+
- `count` 是请求条数,输出 JSON 的 `count` 是实际收到的 `results.length`,不能将两者视为必然相等。
|
|
79
|
+
- 官网在搜狗枚举说明后注明同时指定 `search_domain_filter` 和 `search_recency_filter` 时 `count` 不生效,未明确此备注对其他引擎的适用范围。项目保留用户的具体过滤条件并提示此限制。
|
|
80
|
+
- `search_recency_filter` 为 `noLimit` 时省略该请求字段,避免默认值导致同时携带域名和时间过滤;官网未明确服务端是否将显式 `noLimit` 计入上述限制。
|
|
81
|
+
- 夸克不发送 `count`;显式指定会返回参数错误。搜狗的非法条数也会在发送请求前拒绝。
|
|
82
|
+
- Markdown 按约 25,000 字符的条目预算截断,截断标题显示“展示 X 条,共 Y 条”;结构化结果始终保留完整列表,文本同时说明请求与实际返回数量。
|
|
83
|
+
|
|
76
84
|
## 隐私与安全提示
|
|
77
85
|
|
|
78
86
|
- `ZHIPU_API_KEY` 仅通过环境变量注入,请勿将其写入代码、配置仓库或提交到 Git 历史。
|
|
@@ -118,4 +126,4 @@ It includes third-party packages with the following licenses (updated at build t
|
|
|
118
126
|
- BSD-3-Clause (2 packages)
|
|
119
127
|
- BSD-2-Clause (1 package)
|
|
120
128
|
|
|
121
|
-
> 提示:以上数量为生成本文档时的快照。依赖升级后可用 `npx license-checker --summary` 重新生成核对。
|
|
129
|
+
> 提示:以上数量为生成本文档时的快照。依赖升级后可用 `npx license-checker --summary` 重新生成核对。
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,oDAAoD,CAAC;AAG9E,eAAO,MAAM,eAAe,QAAQ,CAAC;AAGrC,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAGX,eAAO,MAAM,eAAe;;;;;;CAMlB,CAAC;AAGX,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAGX,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,oDAAoD,CAAC;AAG9E,eAAO,MAAM,eAAe,QAAQ,CAAC;AAGrC,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAGX,eAAO,MAAM,eAAe;;;;;;CAMlB,CAAC;AAGX,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAGX,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAEpD,CAAC;AAGF,eAAO,MAAM,kBAAkB,QAAQ,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -24,10 +24,8 @@ export const CONTENT_SIZES = {
|
|
|
24
24
|
MEDIUM: "medium",
|
|
25
25
|
HIGH: "high"
|
|
26
26
|
};
|
|
27
|
-
//
|
|
27
|
+
// 仅搜狗限制为枚举;基础版和高阶版支持 1-50 的整数。
|
|
28
28
|
export const COUNT_BY_ENGINE = {
|
|
29
|
-
[SEARCH_ENGINES.STORE]: [10, 20, 30, 40, 50],
|
|
30
|
-
[SEARCH_ENGINES.PRO]: [10, 20, 30, 40, 50],
|
|
31
29
|
[SEARCH_ENGINES.PRO_SOGOU]: [10, 20, 30, 40, 50]
|
|
32
30
|
};
|
|
33
31
|
// 请求超时时间(毫秒)
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2BAA2B;AAE3B,mBAAmB;AACnB,MAAM,CAAC,MAAM,YAAY,GAAG,iDAAiD,CAAC;AAE9E,wBAAwB;AACxB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,YAAY;AACZ,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,YAAY;IACnB,GAAG,EAAE,YAAY;IACjB,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,kBAAkB;CACrB,CAAC;AAEX,YAAY;AACZ,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,QAAQ;IACjB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;CACX,CAAC;AAEX,SAAS;AACT,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;CACJ,CAAC;AAEX
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2BAA2B;AAE3B,mBAAmB;AACnB,MAAM,CAAC,MAAM,YAAY,GAAG,iDAAiD,CAAC;AAE9E,wBAAwB;AACxB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,YAAY;AACZ,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,YAAY;IACnB,GAAG,EAAE,YAAY;IACjB,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,kBAAkB;CACrB,CAAC;AAEX,YAAY;AACZ,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,QAAQ;IACjB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;CACX,CAAC;AAEX,SAAS;AACT,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;CACJ,CAAC;AAEX,+BAA+B;AAC/B,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;CACjD,CAAC;AAEF,aAAa;AACb,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* 环境变量:
|
|
9
9
|
* ZHIPU_API_KEY - 智谱 API Key(必填),从 https://bigmodel.cn/usercenter/proj-mgmt/apikeys 获取
|
|
10
10
|
*/
|
|
11
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
12
|
import type { WebSearchToolOutput } from "./types.js";
|
|
13
|
+
export declare const server: McpServer;
|
|
12
14
|
export declare function formatResultsMarkdown(output: WebSearchToolOutput, charLimit?: number): {
|
|
13
15
|
text: string;
|
|
14
16
|
truncated: boolean;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAItD,eAAO,MAAM,MAAM,WAGjB,CAAC;AAMH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,mBAAmB,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAwDtC"}
|
package/dist/index.js
CHANGED
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
13
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
14
14
|
import { callWebSearch, handleApiError } from "./services/webSearchApi.js";
|
|
15
|
-
import { WebSearchInputSchema } from "./schemas/webSearch.js";
|
|
15
|
+
import { WebSearchInputSchema, WebSearchRequestSchema } from "./schemas/webSearch.js";
|
|
16
16
|
import { CHARACTER_LIMIT } from "./constants.js";
|
|
17
17
|
import { pathToFileURL } from "node:url";
|
|
18
18
|
// 创建 MCP 服务器实例
|
|
19
|
-
const server = new McpServer({
|
|
19
|
+
export const server = new McpServer({
|
|
20
20
|
name: "zhipu-web-search-mcp-server",
|
|
21
21
|
version: "1.0.0"
|
|
22
22
|
});
|
|
@@ -40,9 +40,11 @@ export function formatResultsMarkdown(output, charLimit) {
|
|
|
40
40
|
if (output.results.length === 0) {
|
|
41
41
|
return { text: "未找到相关搜索结果。", truncated: false };
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
const headingIndex = lines.length;
|
|
44
|
+
lines.push(`# 搜索结果 (${output.results.length})`);
|
|
44
45
|
lines.push("");
|
|
45
46
|
let truncated = false;
|
|
47
|
+
let displayedCount = 0;
|
|
46
48
|
for (let index = 0; index < output.results.length; index++) {
|
|
47
49
|
const item = output.results[index];
|
|
48
50
|
const itemLines = [`## ${index + 1}. ${item.title}`];
|
|
@@ -66,6 +68,10 @@ export function formatResultsMarkdown(output, charLimit) {
|
|
|
66
68
|
}
|
|
67
69
|
lines.push(itemText);
|
|
68
70
|
charCount += itemText.length + 1;
|
|
71
|
+
displayedCount++;
|
|
72
|
+
}
|
|
73
|
+
if (truncated) {
|
|
74
|
+
lines[headingIndex] = `# 搜索结果(展示 ${displayedCount} 条,共 ${output.results.length} 条)`;
|
|
69
75
|
}
|
|
70
76
|
return { text: lines.join("\n"), truncated };
|
|
71
77
|
}
|
|
@@ -80,7 +86,7 @@ Args:
|
|
|
80
86
|
- search_query (string): 需要搜索的内容,建议不超过 70 个字符
|
|
81
87
|
- search_engine (string): 搜索引擎编码(默认 search_std)
|
|
82
88
|
- search_intent (boolean): 是否执行搜索意图识别(默认 false)
|
|
83
|
-
- count (number):
|
|
89
|
+
- count (number): 请求条数,search_std/search_pro 支持 1-50,搜狗仅支持 10/20/30/40/50(默认 10);夸克不支持,请勿指定。官网注明同时指定域名和时间过滤时 count 不生效
|
|
84
90
|
- search_domain_filter (string): 白名单域名过滤,仅返回指定域名内容(可选)
|
|
85
91
|
- search_recency_filter (string): 时间范围过滤:oneDay/oneWeek/oneMonth/oneYear/noLimit(默认 noLimit)
|
|
86
92
|
- content_size (string): 返回内容长短:medium/high(默认 medium)
|
|
@@ -88,7 +94,7 @@ Args:
|
|
|
88
94
|
|
|
89
95
|
Returns:
|
|
90
96
|
Markdown 文本:搜索意图识别结果 + 搜索结果列表(标题、发布时间、来源、链接、摘要)
|
|
91
|
-
|
|
97
|
+
同时返回完整结构化 JSON 数据,count 表示实际返回条数;Markdown 超长时显示展示条数和总条数。
|
|
92
98
|
|
|
93
99
|
Examples:
|
|
94
100
|
- "帮我搜索今天的天气" -> search_query="今天北京天气"
|
|
@@ -107,6 +113,13 @@ Error Handling:
|
|
|
107
113
|
openWorldHint: true
|
|
108
114
|
}
|
|
109
115
|
}, async (params) => {
|
|
116
|
+
const request = WebSearchRequestSchema.safeParse(params);
|
|
117
|
+
if (!request.success) {
|
|
118
|
+
return {
|
|
119
|
+
isError: true,
|
|
120
|
+
content: [{ type: "text", text: request.error.issues.map((issue) => issue.message).join("\n") }]
|
|
121
|
+
};
|
|
122
|
+
}
|
|
110
123
|
const apiKey = process.env.ZHIPU_API_KEY;
|
|
111
124
|
if (!apiKey) {
|
|
112
125
|
return {
|
|
@@ -120,18 +133,7 @@ Error Handling:
|
|
|
120
133
|
};
|
|
121
134
|
}
|
|
122
135
|
try {
|
|
123
|
-
const data = await callWebSearch(apiKey,
|
|
124
|
-
search_query: params.search_query,
|
|
125
|
-
search_engine: params.search_engine,
|
|
126
|
-
search_intent: params.search_intent,
|
|
127
|
-
count: params.count,
|
|
128
|
-
...(params.search_domain_filter
|
|
129
|
-
? { search_domain_filter: params.search_domain_filter }
|
|
130
|
-
: {}),
|
|
131
|
-
search_recency_filter: params.search_recency_filter,
|
|
132
|
-
content_size: params.content_size,
|
|
133
|
-
...(params.user_id ? { user_id: params.user_id } : {})
|
|
134
|
-
});
|
|
136
|
+
const data = await callWebSearch(apiKey, request.data);
|
|
135
137
|
const results = data.search_result ?? [];
|
|
136
138
|
const output = {
|
|
137
139
|
id: data.id,
|
|
@@ -143,9 +145,17 @@ Error Handling:
|
|
|
143
145
|
};
|
|
144
146
|
// 一次性限长构建 Markdown,超限即截断,避免先构建完整文本再二次格式化的内存峰值
|
|
145
147
|
const { text, truncated } = formatResultsMarkdown(output, CHARACTER_LIMIT);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
const notes = [];
|
|
149
|
+
if (request.data.count !== undefined) {
|
|
150
|
+
notes.push(`请求 ${request.data.count} 条,实际返回 ${results.length} 条。`);
|
|
151
|
+
}
|
|
152
|
+
if (request.data.count !== undefined && request.data.search_domain_filter && request.data.search_recency_filter) {
|
|
153
|
+
notes.push("官网注明同时指定域名和时间过滤时 count 不生效;请以实际返回条数为准。");
|
|
154
|
+
}
|
|
155
|
+
if (truncated) {
|
|
156
|
+
notes.push(`文本因过长被截断,完整 ${results.length} 条结果保留在 structuredContent.results 中。`);
|
|
157
|
+
}
|
|
158
|
+
const finalText = notes.length ? `${text}\n\n> ${notes.join("\n> ")}` : text;
|
|
149
159
|
return {
|
|
150
160
|
content: [{ type: "text", text: finalText }],
|
|
151
161
|
structuredContent: output
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,+BAA+B;AAC/B;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ export declare const WebSearchInputSchema: z.ZodObject<{
|
|
|
8
8
|
readonly PRO_QUARK: "search_pro_quark";
|
|
9
9
|
}>>;
|
|
10
10
|
search_intent: z.ZodDefault<z.ZodBoolean>;
|
|
11
|
-
count: z.
|
|
11
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
12
12
|
search_domain_filter: z.ZodOptional<z.ZodString>;
|
|
13
13
|
search_recency_filter: z.ZodDefault<z.ZodNativeEnum<{
|
|
14
14
|
readonly ONE_DAY: "oneDay";
|
|
@@ -26,9 +26,9 @@ export declare const WebSearchInputSchema: z.ZodObject<{
|
|
|
26
26
|
search_query: string;
|
|
27
27
|
search_engine: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark";
|
|
28
28
|
search_intent: boolean;
|
|
29
|
-
count: number;
|
|
30
29
|
search_recency_filter: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | "noLimit";
|
|
31
30
|
content_size: "medium" | "high";
|
|
31
|
+
count?: number | undefined;
|
|
32
32
|
search_domain_filter?: string | undefined;
|
|
33
33
|
user_id?: string | undefined;
|
|
34
34
|
}, {
|
|
@@ -42,4 +42,82 @@ export declare const WebSearchInputSchema: z.ZodObject<{
|
|
|
42
42
|
user_id?: string | undefined;
|
|
43
43
|
}>;
|
|
44
44
|
export type WebSearchInput = z.infer<typeof WebSearchInputSchema>;
|
|
45
|
+
export declare const WebSearchRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObject<{
|
|
46
|
+
search_query: z.ZodString;
|
|
47
|
+
search_engine: z.ZodDefault<z.ZodNativeEnum<{
|
|
48
|
+
readonly STORE: "search_std";
|
|
49
|
+
readonly PRO: "search_pro";
|
|
50
|
+
readonly PRO_SOGOU: "search_pro_sogou";
|
|
51
|
+
readonly PRO_QUARK: "search_pro_quark";
|
|
52
|
+
}>>;
|
|
53
|
+
search_intent: z.ZodDefault<z.ZodBoolean>;
|
|
54
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
search_domain_filter: z.ZodOptional<z.ZodString>;
|
|
56
|
+
search_recency_filter: z.ZodDefault<z.ZodNativeEnum<{
|
|
57
|
+
readonly ONE_DAY: "oneDay";
|
|
58
|
+
readonly ONE_WEEK: "oneWeek";
|
|
59
|
+
readonly ONE_MONTH: "oneMonth";
|
|
60
|
+
readonly ONE_YEAR: "oneYear";
|
|
61
|
+
readonly NO_LIMIT: "noLimit";
|
|
62
|
+
}>>;
|
|
63
|
+
content_size: z.ZodDefault<z.ZodNativeEnum<{
|
|
64
|
+
readonly MEDIUM: "medium";
|
|
65
|
+
readonly HIGH: "high";
|
|
66
|
+
}>>;
|
|
67
|
+
user_id: z.ZodOptional<z.ZodString>;
|
|
68
|
+
}, "strict", z.ZodTypeAny, {
|
|
69
|
+
search_query: string;
|
|
70
|
+
search_engine: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark";
|
|
71
|
+
search_intent: boolean;
|
|
72
|
+
search_recency_filter: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | "noLimit";
|
|
73
|
+
content_size: "medium" | "high";
|
|
74
|
+
count?: number | undefined;
|
|
75
|
+
search_domain_filter?: string | undefined;
|
|
76
|
+
user_id?: string | undefined;
|
|
77
|
+
}, {
|
|
78
|
+
search_query: string;
|
|
79
|
+
search_engine?: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark" | undefined;
|
|
80
|
+
search_intent?: boolean | undefined;
|
|
81
|
+
count?: number | undefined;
|
|
82
|
+
search_domain_filter?: string | undefined;
|
|
83
|
+
search_recency_filter?: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | "noLimit" | undefined;
|
|
84
|
+
content_size?: "medium" | "high" | undefined;
|
|
85
|
+
user_id?: string | undefined;
|
|
86
|
+
}>, {
|
|
87
|
+
search_query: string;
|
|
88
|
+
search_engine: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark";
|
|
89
|
+
search_intent: boolean;
|
|
90
|
+
search_recency_filter: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | "noLimit";
|
|
91
|
+
content_size: "medium" | "high";
|
|
92
|
+
count?: number | undefined;
|
|
93
|
+
search_domain_filter?: string | undefined;
|
|
94
|
+
user_id?: string | undefined;
|
|
95
|
+
}, {
|
|
96
|
+
search_query: string;
|
|
97
|
+
search_engine?: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark" | undefined;
|
|
98
|
+
search_intent?: boolean | undefined;
|
|
99
|
+
count?: number | undefined;
|
|
100
|
+
search_domain_filter?: string | undefined;
|
|
101
|
+
search_recency_filter?: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | "noLimit" | undefined;
|
|
102
|
+
content_size?: "medium" | "high" | undefined;
|
|
103
|
+
user_id?: string | undefined;
|
|
104
|
+
}>, {
|
|
105
|
+
search_recency_filter?: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | undefined;
|
|
106
|
+
search_domain_filter?: string | undefined;
|
|
107
|
+
count?: number | undefined;
|
|
108
|
+
search_query: string;
|
|
109
|
+
search_engine: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark";
|
|
110
|
+
search_intent: boolean;
|
|
111
|
+
content_size: "medium" | "high";
|
|
112
|
+
user_id?: string | undefined;
|
|
113
|
+
}, {
|
|
114
|
+
search_query: string;
|
|
115
|
+
search_engine?: "search_std" | "search_pro" | "search_pro_sogou" | "search_pro_quark" | undefined;
|
|
116
|
+
search_intent?: boolean | undefined;
|
|
117
|
+
count?: number | undefined;
|
|
118
|
+
search_domain_filter?: string | undefined;
|
|
119
|
+
search_recency_filter?: "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | "noLimit" | undefined;
|
|
120
|
+
content_size?: "medium" | "high" | undefined;
|
|
121
|
+
user_id?: string | undefined;
|
|
122
|
+
}>;
|
|
45
123
|
//# sourceMappingURL=webSearch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webSearch.d.ts","sourceRoot":"","sources":["../../src/schemas/webSearch.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"webSearch.d.ts","sourceRoot":"","sources":["../../src/schemas/webSearch.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DtB,CAAC;AAEZ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAchC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
// Web Search 工具的 Zod 输入校验 schema
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { SEARCH_ENGINES, RECENCY_FILTERS, CONTENT_SIZES } from "../constants.js";
|
|
4
|
+
import { SEARCH_ENGINES, RECENCY_FILTERS, CONTENT_SIZES, COUNT_BY_ENGINE } from "../constants.js";
|
|
5
5
|
export const WebSearchInputSchema = z
|
|
6
6
|
.object({
|
|
7
7
|
search_query: z
|
|
@@ -22,8 +22,8 @@ export const WebSearchInputSchema = z
|
|
|
22
22
|
.int()
|
|
23
23
|
.min(1)
|
|
24
24
|
.max(50)
|
|
25
|
-
.
|
|
26
|
-
.describe("
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("请求结果条数:search_std、search_pro 支持 1-50,默认 10;search_pro_sogou 仅支持 10/20/30/40/50,默认 10;search_pro_quark 不支持,请勿指定。官网注明同时指定域名和时间过滤时 count 不生效,实际条数以返回结果为准"),
|
|
27
27
|
search_domain_filter: z
|
|
28
28
|
.string()
|
|
29
29
|
.optional()
|
|
@@ -44,4 +44,21 @@ export const WebSearchInputSchema = z
|
|
|
44
44
|
.describe("终端用户的唯一 ID,用于平台对非法活动的干预,长度 6-128 个字符")
|
|
45
45
|
})
|
|
46
46
|
.strict();
|
|
47
|
+
// 保留工具输入为普通对象 schema,避免跨字段校验影响 MCP 的 JSON Schema 展示。
|
|
48
|
+
// 请求前单独校验:count 不提前填默认值,才能区分夸克的省略与显式指定。
|
|
49
|
+
export const WebSearchRequestSchema = WebSearchInputSchema.superRefine((params, ctx) => {
|
|
50
|
+
if (params.search_engine === SEARCH_ENGINES.PRO_QUARK && params.count !== undefined) {
|
|
51
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["count"], message: "search_pro_quark 不支持 count,请移除此参数。" });
|
|
52
|
+
}
|
|
53
|
+
const counts = COUNT_BY_ENGINE[params.search_engine];
|
|
54
|
+
if (counts && !counts.includes(params.count ?? 10)) {
|
|
55
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["count"], message: "search_pro_sogou 的 count 仅支持 10/20/30/40/50。" });
|
|
56
|
+
}
|
|
57
|
+
}).transform(({ count, search_recency_filter, search_domain_filter, ...params }) => ({
|
|
58
|
+
...params,
|
|
59
|
+
...(params.search_engine === SEARCH_ENGINES.PRO_QUARK ? {} : { count: count ?? 10 }),
|
|
60
|
+
...(search_domain_filter ? { search_domain_filter } : {}),
|
|
61
|
+
// noLimit 与省略均表示不限时间;省略可避免无意中同时指定域名和时间字段。
|
|
62
|
+
...(search_recency_filter === RECENCY_FILTERS.NO_LIMIT ? {} : { search_recency_filter })
|
|
63
|
+
}));
|
|
47
64
|
//# sourceMappingURL=webSearch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webSearch.js","sourceRoot":"","sources":["../../src/schemas/webSearch.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,iCAAiC;AAEjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,cAAc,EACd,eAAe,EACf,aAAa,
|
|
1
|
+
{"version":3,"file":"webSearch.js","sourceRoot":"","sources":["../../src/schemas/webSearch.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.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "MCP server for ZHIPU AI Web Search API integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zhipu",
|
|
@@ -57,4 +57,4 @@
|
|
|
57
57
|
"LICENSE",
|
|
58
58
|
"package.json"
|
|
59
59
|
]
|
|
60
|
-
}
|
|
60
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -30,10 +30,8 @@ export const CONTENT_SIZES = {
|
|
|
30
30
|
HIGH: "high"
|
|
31
31
|
} as const;
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// 仅搜狗限制为枚举;基础版和高阶版支持 1-50 的整数。
|
|
34
34
|
export const COUNT_BY_ENGINE: Record<string, number[]> = {
|
|
35
|
-
[SEARCH_ENGINES.STORE]: [10, 20, 30, 40, 50],
|
|
36
|
-
[SEARCH_ENGINES.PRO]: [10, 20, 30, 40, 50],
|
|
37
35
|
[SEARCH_ENGINES.PRO_SOGOU]: [10, 20, 30, 40, 50]
|
|
38
36
|
};
|
|
39
37
|
|
package/src/index.ts
CHANGED
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
15
|
import { callWebSearch, handleApiError } from "./services/webSearchApi.js";
|
|
16
|
-
import { WebSearchInputSchema } from "./schemas/webSearch.js";
|
|
16
|
+
import { WebSearchInputSchema, WebSearchRequestSchema } from "./schemas/webSearch.js";
|
|
17
17
|
import { CHARACTER_LIMIT } from "./constants.js";
|
|
18
18
|
import type { WebSearchToolOutput } from "./types.js";
|
|
19
19
|
import { pathToFileURL } from "node:url";
|
|
20
20
|
|
|
21
21
|
// 创建 MCP 服务器实例
|
|
22
|
-
const server = new McpServer({
|
|
22
|
+
export const server = new McpServer({
|
|
23
23
|
name: "zhipu-web-search-mcp-server",
|
|
24
24
|
version: "1.0.0"
|
|
25
25
|
});
|
|
@@ -50,10 +50,12 @@ export function formatResultsMarkdown(
|
|
|
50
50
|
return { text: "未找到相关搜索结果。", truncated: false };
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
const headingIndex = lines.length;
|
|
54
|
+
lines.push(`# 搜索结果 (${output.results.length})`);
|
|
54
55
|
lines.push("");
|
|
55
56
|
|
|
56
57
|
let truncated = false;
|
|
58
|
+
let displayedCount = 0;
|
|
57
59
|
for (let index = 0; index < output.results.length; index++) {
|
|
58
60
|
const item = output.results[index];
|
|
59
61
|
const itemLines = [`## ${index + 1}. ${item.title}`];
|
|
@@ -78,8 +80,12 @@ export function formatResultsMarkdown(
|
|
|
78
80
|
}
|
|
79
81
|
lines.push(itemText);
|
|
80
82
|
charCount += itemText.length + 1;
|
|
83
|
+
displayedCount++;
|
|
81
84
|
}
|
|
82
85
|
|
|
86
|
+
if (truncated) {
|
|
87
|
+
lines[headingIndex] = `# 搜索结果(展示 ${displayedCount} 条,共 ${output.results.length} 条)`;
|
|
88
|
+
}
|
|
83
89
|
return { text: lines.join("\n"), truncated };
|
|
84
90
|
}
|
|
85
91
|
|
|
@@ -96,7 +102,7 @@ Args:
|
|
|
96
102
|
- search_query (string): 需要搜索的内容,建议不超过 70 个字符
|
|
97
103
|
- search_engine (string): 搜索引擎编码(默认 search_std)
|
|
98
104
|
- search_intent (boolean): 是否执行搜索意图识别(默认 false)
|
|
99
|
-
- count (number):
|
|
105
|
+
- count (number): 请求条数,search_std/search_pro 支持 1-50,搜狗仅支持 10/20/30/40/50(默认 10);夸克不支持,请勿指定。官网注明同时指定域名和时间过滤时 count 不生效
|
|
100
106
|
- search_domain_filter (string): 白名单域名过滤,仅返回指定域名内容(可选)
|
|
101
107
|
- search_recency_filter (string): 时间范围过滤:oneDay/oneWeek/oneMonth/oneYear/noLimit(默认 noLimit)
|
|
102
108
|
- content_size (string): 返回内容长短:medium/high(默认 medium)
|
|
@@ -104,7 +110,7 @@ Args:
|
|
|
104
110
|
|
|
105
111
|
Returns:
|
|
106
112
|
Markdown 文本:搜索意图识别结果 + 搜索结果列表(标题、发布时间、来源、链接、摘要)
|
|
107
|
-
|
|
113
|
+
同时返回完整结构化 JSON 数据,count 表示实际返回条数;Markdown 超长时显示展示条数和总条数。
|
|
108
114
|
|
|
109
115
|
Examples:
|
|
110
116
|
- "帮我搜索今天的天气" -> search_query="今天北京天气"
|
|
@@ -124,6 +130,13 @@ Error Handling:
|
|
|
124
130
|
}
|
|
125
131
|
},
|
|
126
132
|
async (params) => {
|
|
133
|
+
const request = WebSearchRequestSchema.safeParse(params);
|
|
134
|
+
if (!request.success) {
|
|
135
|
+
return {
|
|
136
|
+
isError: true,
|
|
137
|
+
content: [{ type: "text" as const, text: request.error.issues.map((issue) => issue.message).join("\n") }]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
127
140
|
const apiKey = process.env.ZHIPU_API_KEY;
|
|
128
141
|
if (!apiKey) {
|
|
129
142
|
return {
|
|
@@ -138,18 +151,7 @@ Error Handling:
|
|
|
138
151
|
}
|
|
139
152
|
|
|
140
153
|
try {
|
|
141
|
-
const data = await callWebSearch(apiKey,
|
|
142
|
-
search_query: params.search_query,
|
|
143
|
-
search_engine: params.search_engine,
|
|
144
|
-
search_intent: params.search_intent,
|
|
145
|
-
count: params.count,
|
|
146
|
-
...(params.search_domain_filter
|
|
147
|
-
? { search_domain_filter: params.search_domain_filter }
|
|
148
|
-
: {}),
|
|
149
|
-
search_recency_filter: params.search_recency_filter,
|
|
150
|
-
content_size: params.content_size,
|
|
151
|
-
...(params.user_id ? { user_id: params.user_id } : {})
|
|
152
|
-
});
|
|
154
|
+
const data = await callWebSearch(apiKey, request.data);
|
|
153
155
|
|
|
154
156
|
const results = data.search_result ?? [];
|
|
155
157
|
const output: WebSearchToolOutput = {
|
|
@@ -163,9 +165,17 @@ Error Handling:
|
|
|
163
165
|
|
|
164
166
|
// 一次性限长构建 Markdown,超限即截断,避免先构建完整文本再二次格式化的内存峰值
|
|
165
167
|
const { text, truncated } = formatResultsMarkdown(output, CHARACTER_LIMIT);
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
const notes: string[] = [];
|
|
169
|
+
if (request.data.count !== undefined) {
|
|
170
|
+
notes.push(`请求 ${request.data.count} 条,实际返回 ${results.length} 条。`);
|
|
171
|
+
}
|
|
172
|
+
if (request.data.count !== undefined && request.data.search_domain_filter && request.data.search_recency_filter) {
|
|
173
|
+
notes.push("官网注明同时指定域名和时间过滤时 count 不生效;请以实际返回条数为准。");
|
|
174
|
+
}
|
|
175
|
+
if (truncated) {
|
|
176
|
+
notes.push(`文本因过长被截断,完整 ${results.length} 条结果保留在 structuredContent.results 中。`);
|
|
177
|
+
}
|
|
178
|
+
const finalText = notes.length ? `${text}\n\n> ${notes.join("\n> ")}` : text;
|
|
169
179
|
|
|
170
180
|
return {
|
|
171
181
|
content: [{ type: "text" as const, text: finalText }],
|
package/src/schemas/webSearch.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { z } from "zod";
|
|
|
5
5
|
import {
|
|
6
6
|
SEARCH_ENGINES,
|
|
7
7
|
RECENCY_FILTERS,
|
|
8
|
-
CONTENT_SIZES
|
|
8
|
+
CONTENT_SIZES,
|
|
9
|
+
COUNT_BY_ENGINE
|
|
9
10
|
} from "../constants.js";
|
|
10
11
|
|
|
11
12
|
export const WebSearchInputSchema = z
|
|
@@ -35,9 +36,9 @@ export const WebSearchInputSchema = z
|
|
|
35
36
|
.int()
|
|
36
37
|
.min(1)
|
|
37
38
|
.max(50)
|
|
38
|
-
.
|
|
39
|
+
.optional()
|
|
39
40
|
.describe(
|
|
40
|
-
"
|
|
41
|
+
"请求结果条数:search_std、search_pro 支持 1-50,默认 10;search_pro_sogou 仅支持 10/20/30/40/50,默认 10;search_pro_quark 不支持,请勿指定。官网注明同时指定域名和时间过滤时 count 不生效,实际条数以返回结果为准"
|
|
41
42
|
),
|
|
42
43
|
|
|
43
44
|
search_domain_filter: z
|
|
@@ -71,3 +72,21 @@ export const WebSearchInputSchema = z
|
|
|
71
72
|
.strict();
|
|
72
73
|
|
|
73
74
|
export type WebSearchInput = z.infer<typeof WebSearchInputSchema>;
|
|
75
|
+
|
|
76
|
+
// 保留工具输入为普通对象 schema,避免跨字段校验影响 MCP 的 JSON Schema 展示。
|
|
77
|
+
// 请求前单独校验:count 不提前填默认值,才能区分夸克的省略与显式指定。
|
|
78
|
+
export const WebSearchRequestSchema = WebSearchInputSchema.superRefine((params, ctx) => {
|
|
79
|
+
if (params.search_engine === SEARCH_ENGINES.PRO_QUARK && params.count !== undefined) {
|
|
80
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["count"], message: "search_pro_quark 不支持 count,请移除此参数。" });
|
|
81
|
+
}
|
|
82
|
+
const counts = COUNT_BY_ENGINE[params.search_engine];
|
|
83
|
+
if (counts && !counts.includes(params.count ?? 10)) {
|
|
84
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["count"], message: "search_pro_sogou 的 count 仅支持 10/20/30/40/50。" });
|
|
85
|
+
}
|
|
86
|
+
}).transform(({ count, search_recency_filter, search_domain_filter, ...params }) => ({
|
|
87
|
+
...params,
|
|
88
|
+
...(params.search_engine === SEARCH_ENGINES.PRO_QUARK ? {} : { count: count ?? 10 }),
|
|
89
|
+
...(search_domain_filter ? { search_domain_filter } : {}),
|
|
90
|
+
// noLimit 与省略均表示不限时间;省略可避免无意中同时指定域名和时间字段。
|
|
91
|
+
...(search_recency_filter === RECENCY_FILTERS.NO_LIMIT ? {} : { search_recency_filter })
|
|
92
|
+
}));
|