Amiel's picture
Upload folder using huggingface_hub
676fc08 verified
import { z } from "zod";
import { McpServer } from "@/libs/mcp-server/mcp";
import DeepResearch from "@/utils/deep-research";
import { multiApiKeyPolling } from "@/utils/model";
import {
getAIProviderBaseURL,
getAIProviderApiKey,
getSearchProviderBaseURL,
getSearchProviderApiKey,
} from "../utils";
const AI_PROVIDER = process.env.MCP_AI_PROVIDER || "";
const SEARCH_PROVIDER = process.env.MCP_SEARCH_PROVIDER || "model";
const THINKING_MODEL = process.env.MCP_THINKING_MODEL || "";
const TASK_MODEL = process.env.MCP_TASK_MODEL || "";
function initDeepResearchServer({
language,
maxResult,
}: {
language?: string;
maxResult?: number;
}) {
const deepResearch = new DeepResearch({
language,
AIProvider: {
baseURL: getAIProviderBaseURL(AI_PROVIDER),
apiKey: multiApiKeyPolling(getAIProviderApiKey(AI_PROVIDER)),
provider: AI_PROVIDER,
thinkingModel: THINKING_MODEL,
taskModel: TASK_MODEL,
},
searchProvider: {
baseURL: getSearchProviderBaseURL(SEARCH_PROVIDER),
apiKey: multiApiKeyPolling(getSearchProviderApiKey(SEARCH_PROVIDER)),
provider: SEARCH_PROVIDER,
maxResult,
},
onMessage: (event, data) => {
if (event === "progress") {
console.log(
`[${data.step}]: ${data.name ? `"${data.name}" ` : ""}${data.status}`
);
if (data.status === "end" && data.data) {
console.log(data.data);
}
} else if (event === "error") {
console.error(data.message);
throw new Error(data.message);
}
},
});
return deepResearch;
}
export function initMcpServer() {
const deepResearchToolDescription =
"Start deep research on any question, obtain and organize information through search engines, and generate research report.";
const writeResearchPlanDescription =
"Generate research plan based on user query.";
const generateSERPQueryDescription =
"Generate a list of data collection tasks based on the research plan.";
const searchTaskDescription =
"Generate SERP queries based on the research plan.";
const writeFinalReportDescription =
"Write a final research report based on the research plan and the results of the information collection tasks.";
const server = new McpServer(
{
name: "deep-research",
version: "0.1.0",
},
{
capabilities: {
tools: {
"deep-research": {
description: deepResearchToolDescription,
},
"write-research-plan": {
description: writeResearchPlanDescription,
},
"generate-SERP-query": {
description: generateSERPQueryDescription,
},
"search-task": {
description: searchTaskDescription,
},
"write-final-report": {
description: writeFinalReportDescription,
},
},
},
}
);
server.tool(
"deep-research",
deepResearchToolDescription,
{
query: z.string().describe("The topic for deep research."),
language: z
.string()
.optional()
.describe("The final report text language."),
maxResult: z
.number()
.optional()
.default(5)
.describe("Maximum number of search results."),
enableCitationImage: z
.boolean()
.default(true)
.optional()
.describe(
"Whether to include content-related images in the final report."
),
enableReferences: z
.boolean()
.default(true)
.optional()
.describe(
"Whether to include citation links in search results and final reports."
),
},
async (
{ query, language, maxResult, enableCitationImage, enableReferences },
{ signal }
) => {
signal.addEventListener("abort", () => {
throw new Error("The client closed unexpectedly!");
});
try {
const deepResearch = initDeepResearchServer({
language,
maxResult,
});
const result = await deepResearch.start(
query,
enableCitationImage,
enableReferences
);
return {
content: [{ type: "text", text: JSON.stringify(result) }],
};
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error: ${
error instanceof Error ? error.message : "Unknown error"
}`,
},
],
};
}
}
);
server.tool(
"write-research-plan",
writeResearchPlanDescription,
{
query: z.string().describe("The topic for deep research."),
language: z.string().optional().describe("The response Language."),
},
async ({ query, language }, { signal }) => {
signal.addEventListener("abort", () => {
throw new Error("The client closed unexpectedly!");
});
try {
const deepResearch = initDeepResearchServer({ language });
const result = await deepResearch.writeReportPlan(query);
return {
content: [
{ type: "text", text: JSON.stringify({ reportPlan: result }) },
],
};
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error: ${
error instanceof Error ? error.message : "Unknown error"
}`,
},
],
};
}
}
);
server.tool(
"generate-SERP-query",
generateSERPQueryDescription,
{
plan: z.string().describe("Research plan for deep research."),
language: z.string().optional().describe("The response Language."),
},
async ({ plan, language }, { signal }) => {
signal.addEventListener("abort", () => {
throw new Error("The client closed unexpectedly!");
});
try {
const deepResearch = initDeepResearchServer({ language });
const result = await deepResearch.generateSERPQuery(plan);
return {
content: [{ type: "text", text: JSON.stringify(result) }],
};
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error: ${
error instanceof Error ? error.message : "Unknown error"
}`,
},
],
};
}
}
);
server.tool(
"search-task",
searchTaskDescription,
{
tasks: z
.array(
z.object({
query: z.string().describe("Information to be queried."),
researchGoal: z.string().describe("The goal of this query task."),
})
)
.describe("Information Collection Task List."),
language: z.string().optional().describe("The response Language."),
maxResult: z
.number()
.optional()
.default(5)
.describe("Maximum number of search results."),
enableReferences: z
.boolean()
.default(true)
.optional()
.describe(
"Whether to include citation links in search results and final reports."
),
},
async (
{ tasks, language, maxResult, enableReferences = true },
{ signal }
) => {
signal.addEventListener("abort", () => {
throw new Error("The client closed unexpectedly!");
});
try {
const deepResearch = initDeepResearchServer({ language, maxResult });
const result = await deepResearch.runSearchTask(
tasks,
enableReferences
);
return {
content: [{ type: "text", text: JSON.stringify(result) }],
};
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error: ${
error instanceof Error ? error.message : "Unknown error"
}`,
},
],
};
}
}
);
server.tool(
"write-final-report",
writeFinalReportDescription,
{
plan: z.string().describe("Research plan for deep research."),
tasks: z
.array(
z.object({
query: z.string().describe("Information to be queried."),
researchGoal: z.string().describe("The goal of this query task."),
learning: z
.string()
.describe(
"Knowledge learned while performing information gathering tasks."
),
sources: z
.array(
z.object({
url: z.string().describe("Web link."),
title: z.string().optional().describe("Page title."),
})
)
.optional()
.describe(
"Web page information that was queried when performing information collection tasks."
),
images: z
.array(
z.object({
url: z.string().describe("Image link."),
description: z
.string()
.optional()
.describe("Image Description."),
})
)
.optional()
.describe(
"Image resources obtained when performing information collection tasks."
),
})
)
.describe(
"The data information collected during the execution of the query task."
),
language: z
.string()
.optional()
.describe("The final report text language."),
maxResult: z
.number()
.optional()
.default(5)
.describe("Maximum number of search results."),
enableCitationImage: z
.boolean()
.default(true)
.optional()
.describe(
"Whether to include content-related images in the final report."
),
enableReferences: z
.boolean()
.default(true)
.optional()
.describe(
"Whether to include citation links in search results and final reports."
),
},
async (
{
plan,
tasks,
language,
maxResult,
enableCitationImage = true,
enableReferences = true,
},
{ signal }
) => {
signal.addEventListener("abort", () => {
throw new Error("The client closed unexpectedly!");
});
try {
const deepResearch = initDeepResearchServer({ language, maxResult });
const result = await deepResearch.writeFinalReport(
plan,
tasks,
enableCitationImage,
enableReferences
);
return {
content: [{ type: "text", text: JSON.stringify(result) }],
};
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error: ${
error instanceof Error ? error.message : "Unknown error"
}`,
},
],
};
}
}
);
return server;
}