UNPKG

websearch-mcp

Version:

A Model Context Protocol (MCP) server implementation that provides real-time web search capabilities through a simple API

146 lines (145 loc) 7.16 kB
#!/usr/bin/env node "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const zod_1 = require("zod"); const axios_1 = __importDefault(require("axios")); // Configuration const API_URL = process.env.API_URL || "http://localhost:3001"; const MAX_SEARCH_RESULT = parseInt(process.env.MAX_SEARCH_RESULT || "5", 10); // Main function to set up and run the MCP server function main() { return __awaiter(this, void 0, void 0, function* () { // Create an MCP server const server = new mcp_js_1.McpServer({ name: "WebSearch-MCP", version: "1.0.0", }); // Add a web_search tool server.tool("web_search", "Search the web for information.\n" + "Use this tool when you need to search the web for information.\n" + "You can use this tool to search for news, blogs, or all types of information.\n" + "You can also use this tool to search for information about a specific company or product.\n" + "You can also use this tool to search for information about a specific person.\n" + "You can also use this tool to search for information about a specific product.\n" + "You can also use this tool to search for information about a specific company.\n" + "You can also use this tool to search for information about a specific event.\n" + "You can also use this tool to search for information about a specific location.\n" + "You can also use this tool to search for information about a specific thing.\n" + "If you request search with 1 result number and failed, retry with bigger results number.", { query: zod_1.z.string().describe("The search query to look up"), numResults: zod_1.z .number() .optional() .describe(`Number of results to return (default: ${MAX_SEARCH_RESULT})`), language: zod_1.z .string() .optional() .describe("Language code for search results (e.g., 'en')"), region: zod_1.z .string() .optional() .describe("Region code for search results (e.g., 'us')"), excludeDomains: zod_1.z .array(zod_1.z.string()) .optional() .describe("Domains to exclude from results"), includeDomains: zod_1.z .array(zod_1.z.string()) .optional() .describe("Only include these domains in results"), excludeTerms: zod_1.z .array(zod_1.z.string()) .optional() .describe("Terms to exclude from results"), resultType: zod_1.z .enum(["all", "news", "blogs"]) .optional() .describe("Type of results to return"), }, (params) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; try { console.error(`Performing web search for: ${params.query}`); // Prepare request payload for crawler API const requestPayload = { query: params.query, numResults: (_a = params.numResults) !== null && _a !== void 0 ? _a : MAX_SEARCH_RESULT, language: params.language, region: params.region, filters: { excludeDomains: params.excludeDomains, includeDomains: params.includeDomains, excludeTerms: params.excludeTerms, resultType: params.resultType, }, }; // Call the crawler API console.error(`Sending request to ${API_URL}/crawl`); const response = yield axios_1.default.post(`${API_URL}/crawl`, requestPayload); // Format the response for the MCP client const results = response.data.results.map((result) => ({ title: result.title, snippet: result.excerpt, text: result.text, url: result.url, siteName: result.siteName || "", byline: result.byline || "", })); return { content: [ { type: "text", text: JSON.stringify({ query: response.data.query, results: results, }, null, 2), }, ], }; } catch (error) { console.error("Error performing web search:", error); if (axios_1.default.isAxiosError(error)) { const errorMessage = ((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) || error.message; return { content: [{ type: "text", text: `Error: ${errorMessage}` }], isError: true, }; } return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], isError: true, }; } })); // Start receiving messages on stdin and sending messages on stdout console.error("Starting WebSearch MCP server..."); console.error(`Using API_URL: ${API_URL}`); const transport = new stdio_js_1.StdioServerTransport(); yield server.connect(transport); console.error("WebSearch MCP server started"); }); } // Start the server main().catch((error) => { console.error("Failed to start WebSearch MCP server:", error); process.exit(1); });