one-search-mcp 1.0.2 → 1.0.3

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.cjs CHANGED
@@ -29,6 +29,7 @@ var index_exports = {};
29
29
  module.exports = __toCommonJS(index_exports);
30
30
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
31
31
  var import_types = require("@modelcontextprotocol/sdk/types.js");
32
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
32
33
 
33
34
  // src/search.ts
34
35
  var import_node_url = __toESM(require("url"), 1);
@@ -53,7 +54,7 @@ async function searxngSearch(params) {
53
54
  }
54
55
  const controller = new AbortController();
55
56
  const timeoutId = setTimeout(() => controller.abort(), Number(timeout));
56
- const config2 = {
57
+ const config = {
57
58
  q: query,
58
59
  pageno: limit,
59
60
  categories,
@@ -64,7 +65,7 @@ async function searxngSearch(params) {
64
65
  time_range: timeRange
65
66
  };
66
67
  const endpoint = `${apiUrl}/search`;
67
- const queryParams = import_node_url.default.format({ query: config2 });
68
+ const queryParams = import_node_url.default.format({ query: config });
68
69
  const headers = {
69
70
  "Content-Type": "application/json"
70
71
  };
@@ -147,10 +148,7 @@ async function tavilySearch(options) {
147
148
  };
148
149
  }
149
150
 
150
- // src/index.ts
151
- var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
152
- var import_dotenvx = __toESM(require("@dotenvx/dotenvx"), 1);
153
- import_dotenvx.default.config();
151
+ // src/tools.ts
154
152
  var SEARCH_TOOL = {
155
153
  name: "one_search",
156
154
  description: "Search and retrieve content from web pages. Returns SERP results by default (url, title, description).",
@@ -370,6 +368,28 @@ var EXTRACT_TOOL = {
370
368
  required: ["urls"]
371
369
  }
372
370
  };
371
+
372
+ // src/index.ts
373
+ var import_firecrawl_js = __toESM(require("@mendable/firecrawl-js"), 1);
374
+ var import_dotenvx = __toESM(require("@dotenvx/dotenvx"), 1);
375
+ import_dotenvx.default.config();
376
+ var SEARCH_API_URL = process.env.SEARCH_API_URL;
377
+ var SEARCH_API_KEY = process.env.SEARCH_API_KEY;
378
+ var SEARCH_PROVIDER = process.env.SEARCH_PROVIDER ?? "searxng";
379
+ var SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;
380
+ var LIMIT = process.env.LIMIT ?? 10;
381
+ var CATEGORIES = process.env.CATEGORIES ?? "general";
382
+ var ENGINES = process.env.ENGINES ?? "all";
383
+ var FORMAT = process.env.FORMAT ?? "json";
384
+ var LANGUAGE = process.env.LANGUAGE ?? "auto";
385
+ var TIME_RANGE = process.env.TIME_RANGE ?? "";
386
+ var DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 1e4;
387
+ var FIRECRAWL_API_KEY = process.env.FIRECRAWL_API_KEY;
388
+ var FIRECRAWL_API_URL = process.env.FIRECRAWL_API_URL;
389
+ var firecrawl = new import_firecrawl_js.default({
390
+ apiKey: FIRECRAWL_API_KEY ?? "",
391
+ ...FIRECRAWL_API_URL ? { apiUrl: FIRECRAWL_API_URL } : {}
392
+ });
373
393
  var server = new import_server.Server(
374
394
  {
375
395
  name: "one-search-mcp",
@@ -382,18 +402,7 @@ var server = new import_server.Server(
382
402
  }
383
403
  }
384
404
  );
385
- var SEARCH_API_URL = process.env.SEARCH_API_URL;
386
- var SEARCH_API_KEY = process.env.SEARCH_API_KEY;
387
- var SEARCH_PROVIDER = process.env.SEARCH_PROVIDER ?? "searxng";
388
- var SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;
389
- var LIMIT = process.env.LIMIT ?? 10;
390
- var CATEGORIES = process.env.CATEGORIES ?? "general";
391
- var ENGINES = process.env.ENGINES ?? "all";
392
- var FORMAT = process.env.FORMAT ?? "json";
393
- var LANGUAGE = process.env.LANGUAGE ?? "auto";
394
- var TIME_RANGE = process.env.TIME_RANGE ?? "";
395
- var DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 1e4;
396
- var config = {
405
+ var searchConfig = {
397
406
  pageno: LIMIT,
398
407
  categories: CATEGORIES,
399
408
  format: FORMAT,
@@ -428,7 +437,7 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
428
437
  }
429
438
  try {
430
439
  const { results, success } = await processSearch({
431
- ...config,
440
+ ...searchConfig,
432
441
  ...args,
433
442
  apiKey: SEARCH_API_KEY ?? "",
434
443
  apiUrl: SEARCH_API_URL ?? ""
@@ -437,9 +446,9 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
437
446
  throw new Error("Failed to search");
438
447
  }
439
448
  const resultsText = results.map((result) => `Title: ${result.title}
440
- URL: ${result.url}
441
- Description: ${result.snippet}
442
- ${result.markdown ? `Content: ${result.markdown}` : ""}`);
449
+ URL: ${result.url}
450
+ Description: ${result.snippet}
451
+ ${result.markdown ? `Content: ${result.markdown}` : ""}`);
443
452
  return {
444
453
  content: [
445
454
  {
@@ -467,8 +476,47 @@ ${result.markdown ? `Content: ${result.markdown}` : ""}`);
467
476
  };
468
477
  }
469
478
  }
470
- default:
479
+ case "one_scrape": {
480
+ if (!checkScrapeArgs(args)) {
481
+ throw new Error(`Invalid arguments for tool: [${name}]`);
482
+ }
483
+ try {
484
+ const startTime2 = Date.now();
485
+ server.sendLoggingMessage({
486
+ level: "info",
487
+ data: `[${(/* @__PURE__ */ new Date()).toISOString()}] Scraping started for url: [${args.url}]`
488
+ });
489
+ const { url: url2, ...scrapeArgs } = args;
490
+ const { content, success, result } = await processScrape(url2, scrapeArgs);
491
+ server.sendLoggingMessage({
492
+ level: "info",
493
+ data: `[${(/* @__PURE__ */ new Date()).toISOString()}] Scraping completed in ${Date.now() - startTime2}ms`
494
+ });
495
+ return {
496
+ content,
497
+ result,
498
+ success
499
+ };
500
+ } catch (error) {
501
+ server.sendLoggingMessage({
502
+ level: "error",
503
+ data: `[${(/* @__PURE__ */ new Date()).toISOString()}] Error scraping: ${error}`
504
+ });
505
+ const msg = error instanceof Error ? error.message : "Unknown error";
506
+ return {
507
+ success: false,
508
+ content: [
509
+ {
510
+ type: "text",
511
+ text: msg
512
+ }
513
+ ]
514
+ };
515
+ }
516
+ }
517
+ default: {
471
518
  throw new Error(`Unknown tool: ${name}`);
519
+ }
472
520
  }
473
521
  } catch (error) {
474
522
  const msg = error instanceof Error ? error.message : String(error);
@@ -502,13 +550,13 @@ async function processSearch(args) {
502
550
  switch (SEARCH_PROVIDER) {
503
551
  case "searxng":
504
552
  return await searxngSearch({
505
- ...config,
553
+ ...searchConfig,
506
554
  ...args,
507
555
  apiKey: SEARCH_API_KEY
508
556
  });
509
557
  case "tavily":
510
558
  return await tavilySearch({
511
- ...config,
559
+ ...searchConfig,
512
560
  ...args,
513
561
  apiKey: SEARCH_API_KEY
514
562
  });
@@ -516,9 +564,49 @@ async function processSearch(args) {
516
564
  throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);
517
565
  }
518
566
  }
567
+ async function processScrape(url2, args) {
568
+ const res = await firecrawl.scrapeUrl(url2, {
569
+ ...args
570
+ });
571
+ if (!res.success) {
572
+ throw new Error(`Failed to scrape: ${res.error}`);
573
+ }
574
+ const content = [];
575
+ if (res.markdown) {
576
+ content.push(res.markdown);
577
+ }
578
+ if (res.rawHtml) {
579
+ content.push(res.rawHtml);
580
+ }
581
+ if (res.links) {
582
+ content.push(res.links.join("\n"));
583
+ }
584
+ if (res.screenshot) {
585
+ content.push(res.screenshot);
586
+ }
587
+ if (res.html) {
588
+ content.push(res.html);
589
+ }
590
+ if (res.extract) {
591
+ content.push(res.extract);
592
+ }
593
+ return {
594
+ content: [
595
+ {
596
+ type: "text",
597
+ text: content.join("\n\n") || "No content found"
598
+ }
599
+ ],
600
+ result: res,
601
+ success: true
602
+ };
603
+ }
519
604
  function checkSearchArgs(args) {
520
605
  return typeof args === "object" && args !== null && "query" in args && typeof args.query === "string";
521
606
  }
607
+ function checkScrapeArgs(args) {
608
+ return typeof args === "object" && args !== null && "url" in args && typeof args.url === "string";
609
+ }
522
610
  async function runServer() {
523
611
  try {
524
612
  process.stdout.write("Starting OneSearch MCP server...\n");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/search.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema, Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { ISearchRequestOptions, ISearchResponse, Provider } from './interface.js';\nimport { searxngSearch, tavilySearch } from './search.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport dotenvx from '@dotenvx/dotenvx';\n\ndotenvx.config();\n\n// tools definition\nconst SEARCH_TOOL: Tool = {\n name: 'one_search',\n description:\n 'Search and retrieve content from web pages. ' +\n 'Returns SERP results by default (url, title, description).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 10)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: auto)',\n },\n categories: {\n type: 'string',\n description: 'Categories to search for (default: general)',\n },\n timeRange: {\n type: 'string',\n description: 'Time range for search results (default: all)',\n },\n },\n required: ['query'],\n },\n};\n\nconst SCRAPE_TOOL: Tool = {\n name: 'one_scrape',\n description:\n 'Scrape a single webpage with advanced options for content extraction. ' +\n 'Supports various formats including markdown, HTML, and screenshots. ' +\n 'Can execute custom actions like clicking or scrolling before scraping.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to scrape',\n },\n formats: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'markdown',\n 'html',\n 'rawHtml',\n 'screenshot',\n 'links',\n 'screenshot@fullPage',\n 'extract',\n ],\n },\n description: \"Content formats to extract (default: ['markdown'])\",\n },\n onlyMainContent: {\n type: 'boolean',\n description:\n 'Extract only the main content, filtering out navigation, footers, etc.',\n },\n includeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to specifically include in extraction',\n },\n excludeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to exclude from extraction',\n },\n waitFor: {\n type: 'number',\n description: 'Time in milliseconds to wait for dynamic content to load',\n },\n timeout: {\n type: 'number',\n description:\n 'Maximum time in milliseconds to wait for the page to load',\n },\n actions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'wait',\n 'click',\n 'screenshot',\n 'write',\n 'press',\n 'scroll',\n 'scrape',\n 'executeJavascript',\n ],\n description: 'Type of action to perform',\n },\n selector: {\n type: 'string',\n description: 'CSS selector for the target element',\n },\n milliseconds: {\n type: 'number',\n description: 'Time to wait in milliseconds (for wait action)',\n },\n text: {\n type: 'string',\n description: 'Text to write (for write action)',\n },\n key: {\n type: 'string',\n description: 'Key to press (for press action)',\n },\n direction: {\n type: 'string',\n enum: ['up', 'down'],\n description: 'Scroll direction',\n },\n script: {\n type: 'string',\n description: 'JavaScript code to execute',\n },\n fullPage: {\n type: 'boolean',\n description: 'Take full page screenshot',\n },\n },\n required: ['type'],\n },\n description: 'List of actions to perform before scraping',\n },\n extract: {\n type: 'object',\n properties: {\n schema: {\n type: 'object',\n description: 'Schema for structured data extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n prompt: {\n type: 'string',\n description: 'User prompt for LLM extraction',\n },\n },\n description: 'Configuration for structured data extraction',\n },\n mobile: {\n type: 'boolean',\n description: 'Use mobile viewport',\n },\n skipTlsVerification: {\n type: 'boolean',\n description: 'Skip TLS certificate verification',\n },\n removeBase64Images: {\n type: 'boolean',\n description: 'Remove base64 encoded images from output',\n },\n location: {\n type: 'object',\n properties: {\n country: {\n type: 'string',\n description: 'Country code for geolocation',\n },\n languages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Language codes for content',\n },\n },\n description: 'Location settings for scraping',\n },\n },\n required: ['url'],\n },\n};\n\nconst EXTRACT_TOOL: Tool = {\n name: 'one_extract',\n description:\n 'Extract structured information from web pages using LLM. ' +\n 'Supports both cloud AI and self-hosted LLM extraction.',\n inputSchema: {\n type: 'object',\n properties: {\n urls: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of URLs to extract information from',\n },\n prompt: {\n type: 'string',\n description: 'Prompt for the LLM extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n schema: {\n type: 'object',\n description: 'JSON schema for structured data extraction',\n },\n allowExternalLinks: {\n type: 'boolean',\n description: 'Allow extraction from external links',\n },\n enableWebSearch: {\n type: 'boolean',\n description: 'Enable web search for additional context',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include subdomains in extraction',\n },\n },\n required: ['urls'],\n },\n};\n\n// Server implementation\nconst server = new Server(\n {\n name: 'one-search-mcp',\n version: '0.0.1',\n },\n {\n capabilities: {\n tools: {},\n logging: {},\n },\n },\n);\n\n// searxng api\nconst SEARCH_API_URL = process.env.SEARCH_API_URL;\nconst SEARCH_API_KEY = process.env.SEARCH_API_KEY;\nconst SEARCH_PROVIDER: Provider = process.env.SEARCH_PROVIDER as Provider ?? 'searxng';\n\n// query params\nconst SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;\nconst LIMIT = process.env.LIMIT ?? 10;\nconst CATEGORIES = process.env.CATEGORIES ?? 'general';\nconst ENGINES = process.env.ENGINES ?? 'all';\nconst FORMAT = process.env.FORMAT ?? 'json';\nconst LANGUAGE = process.env.LANGUAGE ?? 'auto';\nconst TIME_RANGE = process.env.TIME_RANGE ?? '';\nconst DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 10000;\n\nconst config = {\n pageno: LIMIT,\n categories: CATEGORIES,\n format: FORMAT,\n safesearch: SAFE_SEARCH,\n language: LANGUAGE,\n engines: ENGINES,\n time_range: TIME_RANGE,\n timeout: DEFAULT_TIMEOUT,\n};\n\n// Tool handlers\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n SEARCH_TOOL,\n EXTRACT_TOOL,\n SCRAPE_TOOL,\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const startTime = Date.now();\n\n try {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('No arguments provided');\n }\n \n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Received request for tool: [${name}]`,\n });\n \n switch (name) {\n case 'one_search': {\n // check args.\n if (!checkSearchArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { results, success } = await processSearch({\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n apiUrl: SEARCH_API_URL ?? '',\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n const resultsText = results.map((result) => (\n `Title: ${result.title}\nURL: ${result.url}\nDescription: ${result.snippet}\n${result.markdown ? `Content: ${result.markdown}` : ''}`\n ));\n return {\n content: [\n {\n type: 'text',\n text: resultsText.join('\\n\\n'),\n },\n ],\n results,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error searching: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch(error) {\n const msg = error instanceof Error ? error.message : String(error);\n server.sendLoggingMessage({\n level: 'error',\n data: {\n message: `[${new Date().toISOString()}] Error processing request: ${msg}`,\n tool: request.params.name,\n arguments: request.params.arguments,\n timestamp: new Date().toISOString(),\n duration: Date.now() - startTime,\n },\n });\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n } finally {\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Request completed in ${Date.now() - startTime}ms`,\n });\n }\n});\n\nasync function processSearch(args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng':\n return await searxngSearch({\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n case 'tavily':\n return await tavilySearch({\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n default:\n throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);\n }\n}\n\nfunction checkSearchArgs(args: unknown): args is ISearchRequestOptions {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'query' in args &&\n typeof args.query === 'string'\n );\n}\n\nasync function runServer() {\n try {\n process.stdout.write('Starting OneSearch MCP server...\\n');\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n server.sendLoggingMessage({\n level: 'info',\n data: 'OneSearch MCP server started',\n });\n\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error starting server: ${msg}\\n`);\n process.exit(1);\n }\n}\n\n// run server\nrunServer().catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error running server: ${msg}\\n`);\n process.exit(1);\n});\n\n// export types\nexport * from './interface.js';\n","import url from 'node:url';\nimport { tavily, TavilyClient, TavilySearchOptions } from '@tavily/core';\nimport { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from './interface.js';\n\n/**\n * SearxNG Search API\n * - https://docs.searxng.org/dev/search_api.html\n */\nexport async function searxngSearch(params: ISearchRequestOptions): Promise<ISearchResponse> {\n try {\n const {\n query,\n limit = 10,\n categories = 'general',\n engines = 'all',\n safeSearch = 0,\n format = 'json',\n language = 'auto',\n timeRange = '',\n timeout = 10000,\n apiKey,\n apiUrl,\n } = params;\n\n if (!apiUrl) {\n throw new Error('SearxNG API URL is required');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), Number(timeout));\n\n const config = {\n q: query,\n pageno: limit,\n categories,\n format,\n safesearch: safeSearch,\n language,\n engines,\n time_range: timeRange,\n };\n\n const endpoint = `${apiUrl}/search`;\n\n const queryParams = url.format({ query: config });\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const res = await fetch(`${endpoint}${queryParams}`, {\n method: 'POST',\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const result = await res.json();\n if (result.results) {\n const results: ISearchResponseResult[] = result.results.map((item: Record<string, unknown>) => {\n const image = item.img_src ? {\n thumbnail: item.thumbnail_src,\n src: item.img_src,\n } : null;\n const video = item.iframe_src ? {\n thumbnail: item.thumbnail_src,\n src: item.iframe_src,\n } : null;\n return {\n title: item.title,\n snippet: item.content,\n url: item.url,\n source: item.source,\n image,\n video,\n engine: item.engine,\n };\n });\n return {\n results,\n success: true,\n };\n }\n return {\n results: [],\n success: false,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Searxng search error.';\n process.stdout.write(msg);\n throw err;\n }\n}\n\n\nlet tvly: TavilyClient | null = null;\nexport async function tavilySearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\n query,\n limit = 10,\n categories = 'general',\n timeRange,\n apiKey,\n } = options;\n\n if (!apiKey) {\n throw new Error('Tavily API key is required');\n }\n\n if (!tvly) {\n tvly = tavily({\n apiKey,\n });\n }\n\n const params: TavilySearchOptions = {\n topic: categories as TavilySearchOptions['topic'],\n timeRange: timeRange as TavilySearchOptions['timeRange'],\n maxResults: limit,\n };\n\n const res = await tvly.search(query, params);\n const results = res.results.map(item => ({\n title: item.title,\n url: item.url,\n snippet: item.content,\n }));\n\n return {\n results,\n success: true,\n };\n}\n"],"mappings":"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","names":["config","url","dotenvx"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/search.ts","../src/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { ISearchRequestOptions, ISearchResponse, Provider } from './interface.js';\nimport { searxngSearch, tavilySearch } from './search.js';\nimport { SEARCH_TOOL, EXTRACT_TOOL, SCRAPE_TOOL } from './tools.js';\nimport FirecrawlApp, { ScrapeParams } from '@mendable/firecrawl-js';\nimport dotenvx from '@dotenvx/dotenvx';\n\ndotenvx.config();\n\n\n// search api\nconst SEARCH_API_URL = process.env.SEARCH_API_URL;\nconst SEARCH_API_KEY = process.env.SEARCH_API_KEY;\nconst SEARCH_PROVIDER: Provider = process.env.SEARCH_PROVIDER as Provider ?? 'searxng';\n\n// search query params\nconst SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;\nconst LIMIT = process.env.LIMIT ?? 10;\nconst CATEGORIES = process.env.CATEGORIES ?? 'general';\nconst ENGINES = process.env.ENGINES ?? 'all';\nconst FORMAT = process.env.FORMAT ?? 'json';\nconst LANGUAGE = process.env.LANGUAGE ?? 'auto';\nconst TIME_RANGE = process.env.TIME_RANGE ?? '';\nconst DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 10000;\n\n// firecrawl api\nconst FIRECRAWL_API_KEY = process.env.FIRECRAWL_API_KEY;\nconst FIRECRAWL_API_URL = process.env.FIRECRAWL_API_URL;\n\n// firecrawl client\nconst firecrawl = new FirecrawlApp({\n apiKey: FIRECRAWL_API_KEY ?? '',\n ...(FIRECRAWL_API_URL ? { apiUrl: FIRECRAWL_API_URL } : {}),\n});\n\n// Server implementation\nconst server = new Server(\n {\n name: 'one-search-mcp',\n version: '0.0.1',\n },\n {\n capabilities: {\n tools: {},\n logging: {},\n },\n },\n);\n\nconst searchConfig = {\n pageno: LIMIT,\n categories: CATEGORIES,\n format: FORMAT,\n safesearch: SAFE_SEARCH,\n language: LANGUAGE,\n engines: ENGINES,\n time_range: TIME_RANGE,\n timeout: DEFAULT_TIMEOUT,\n};\n\n// Tool handlers\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n SEARCH_TOOL,\n EXTRACT_TOOL,\n SCRAPE_TOOL,\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const startTime = Date.now();\n\n try {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('No arguments provided');\n }\n \n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Received request for tool: [${name}]`,\n });\n \n switch (name) {\n case 'one_search': {\n // check args.\n if (!checkSearchArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { results, success } = await processSearch({\n ...searchConfig,\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n apiUrl: SEARCH_API_URL ?? '',\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n const resultsText = results.map((result) => (\n `Title: ${result.title}\n URL: ${result.url}\n Description: ${result.snippet}\n ${result.markdown ? `Content: ${result.markdown}` : ''}`\n ));\n return {\n content: [\n {\n type: 'text',\n text: resultsText.join('\\n\\n'),\n },\n ],\n results,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error searching: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n case 'one_scrape': {\n if (!checkScrapeArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const startTime = Date.now();\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping started for url: [${args.url}]`,\n });\n\n const { url, ...scrapeArgs } = args;\n const { content, success, result } = await processScrape(url, scrapeArgs);\n\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping completed in ${Date.now() - startTime}ms`,\n });\n\n return {\n content,\n result,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error scraping: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n default: {\n throw new Error(`Unknown tool: ${name}`);\n }\n }\n } catch(error) {\n const msg = error instanceof Error ? error.message : String(error);\n server.sendLoggingMessage({\n level: 'error',\n data: {\n message: `[${new Date().toISOString()}] Error processing request: ${msg}`,\n tool: request.params.name,\n arguments: request.params.arguments,\n timestamp: new Date().toISOString(),\n duration: Date.now() - startTime,\n },\n });\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n } finally {\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Request completed in ${Date.now() - startTime}ms`,\n });\n }\n});\n\nasync function processSearch(args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng':\n return await searxngSearch({\n ...searchConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n case 'tavily':\n return await tavilySearch({\n ...searchConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n default:\n throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);\n }\n}\n\nasync function processScrape(url: string, args: ScrapeParams) {\n const res = await firecrawl.scrapeUrl(url, {\n ...args,\n });\n\n if (!res.success) {\n throw new Error(`Failed to scrape: ${res.error}`);\n }\n\n const content: string[] = [];\n\n if (res.markdown) {\n content.push(res.markdown);\n }\n\n if (res.rawHtml) {\n content.push(res.rawHtml);\n }\n\n if (res.links) {\n content.push(res.links.join('\\n'));\n }\n\n if (res.screenshot) {\n content.push(res.screenshot);\n }\n\n if (res.html) {\n content.push(res.html);\n }\n\n if (res.extract) {\n content.push(res.extract);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: content.join('\\n\\n') || 'No content found',\n },\n ],\n result: res,\n success: true,\n };\n}\n\nfunction checkSearchArgs(args: unknown): args is ISearchRequestOptions {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'query' in args &&\n typeof args.query === 'string'\n );\n}\n\nfunction checkScrapeArgs(args: unknown): args is ScrapeParams & { url: string } {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'url' in args &&\n typeof args.url === 'string'\n );\n}\n\nasync function runServer() {\n try {\n process.stdout.write('Starting OneSearch MCP server...\\n');\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n server.sendLoggingMessage({\n level: 'info',\n data: 'OneSearch MCP server started',\n });\n\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error starting server: ${msg}\\n`);\n process.exit(1);\n }\n}\n\n// run server\nrunServer().catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error running server: ${msg}\\n`);\n process.exit(1);\n});\n\n// export types\nexport * from './interface.js';\n","import url from 'node:url';\nimport { tavily, TavilyClient, TavilySearchOptions } from '@tavily/core';\nimport { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from './interface.js';\n\n/**\n * SearxNG Search API\n * - https://docs.searxng.org/dev/search_api.html\n */\nexport async function searxngSearch(params: ISearchRequestOptions): Promise<ISearchResponse> {\n try {\n const {\n query,\n limit = 10,\n categories = 'general',\n engines = 'all',\n safeSearch = 0,\n format = 'json',\n language = 'auto',\n timeRange = '',\n timeout = 10000,\n apiKey,\n apiUrl,\n } = params;\n\n if (!apiUrl) {\n throw new Error('SearxNG API URL is required');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), Number(timeout));\n\n const config = {\n q: query,\n pageno: limit,\n categories,\n format,\n safesearch: safeSearch,\n language,\n engines,\n time_range: timeRange,\n };\n\n const endpoint = `${apiUrl}/search`;\n\n const queryParams = url.format({ query: config });\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const res = await fetch(`${endpoint}${queryParams}`, {\n method: 'POST',\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const result = await res.json();\n if (result.results) {\n const results: ISearchResponseResult[] = result.results.map((item: Record<string, unknown>) => {\n const image = item.img_src ? {\n thumbnail: item.thumbnail_src,\n src: item.img_src,\n } : null;\n const video = item.iframe_src ? {\n thumbnail: item.thumbnail_src,\n src: item.iframe_src,\n } : null;\n return {\n title: item.title,\n snippet: item.content,\n url: item.url,\n source: item.source,\n image,\n video,\n engine: item.engine,\n };\n });\n return {\n results,\n success: true,\n };\n }\n return {\n results: [],\n success: false,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Searxng search error.';\n process.stdout.write(msg);\n throw err;\n }\n}\n\n\nlet tvly: TavilyClient | null = null;\nexport async function tavilySearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\n query,\n limit = 10,\n categories = 'general',\n timeRange,\n apiKey,\n } = options;\n\n if (!apiKey) {\n throw new Error('Tavily API key is required');\n }\n\n if (!tvly) {\n tvly = tavily({\n apiKey,\n });\n }\n\n const params: TavilySearchOptions = {\n topic: categories as TavilySearchOptions['topic'],\n timeRange: timeRange as TavilySearchOptions['timeRange'],\n maxResults: limit,\n };\n\n const res = await tvly.search(query, params);\n const results = res.results.map(item => ({\n title: item.title,\n url: item.url,\n snippet: item.content,\n }));\n\n return {\n results,\n success: true,\n };\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n// tools definition\nexport const SEARCH_TOOL: Tool = {\n name: 'one_search',\n description:\n 'Search and retrieve content from web pages. ' +\n 'Returns SERP results by default (url, title, description).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 10)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: auto)',\n },\n categories: {\n type: 'string',\n description: 'Categories to search for (default: general)',\n },\n timeRange: {\n type: 'string',\n description: 'Time range for search results (default: all)',\n },\n },\n required: ['query'],\n },\n};\n\nexport const SCRAPE_TOOL: Tool = {\n name: 'one_scrape',\n description:\n 'Scrape a single webpage with advanced options for content extraction. ' +\n 'Supports various formats including markdown, HTML, and screenshots. ' +\n 'Can execute custom actions like clicking or scrolling before scraping.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to scrape',\n },\n formats: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'markdown',\n 'html',\n 'rawHtml',\n 'screenshot',\n 'links',\n 'screenshot@fullPage',\n 'extract',\n ],\n },\n description: \"Content formats to extract (default: ['markdown'])\",\n },\n onlyMainContent: {\n type: 'boolean',\n description:\n 'Extract only the main content, filtering out navigation, footers, etc.',\n },\n includeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to specifically include in extraction',\n },\n excludeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to exclude from extraction',\n },\n waitFor: {\n type: 'number',\n description: 'Time in milliseconds to wait for dynamic content to load',\n },\n timeout: {\n type: 'number',\n description:\n 'Maximum time in milliseconds to wait for the page to load',\n },\n actions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'wait',\n 'click',\n 'screenshot',\n 'write',\n 'press',\n 'scroll',\n 'scrape',\n 'executeJavascript',\n ],\n description: 'Type of action to perform',\n },\n selector: {\n type: 'string',\n description: 'CSS selector for the target element',\n },\n milliseconds: {\n type: 'number',\n description: 'Time to wait in milliseconds (for wait action)',\n },\n text: {\n type: 'string',\n description: 'Text to write (for write action)',\n },\n key: {\n type: 'string',\n description: 'Key to press (for press action)',\n },\n direction: {\n type: 'string',\n enum: ['up', 'down'],\n description: 'Scroll direction',\n },\n script: {\n type: 'string',\n description: 'JavaScript code to execute',\n },\n fullPage: {\n type: 'boolean',\n description: 'Take full page screenshot',\n },\n },\n required: ['type'],\n },\n description: 'List of actions to perform before scraping',\n },\n extract: {\n type: 'object',\n properties: {\n schema: {\n type: 'object',\n description: 'Schema for structured data extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n prompt: {\n type: 'string',\n description: 'User prompt for LLM extraction',\n },\n },\n description: 'Configuration for structured data extraction',\n },\n mobile: {\n type: 'boolean',\n description: 'Use mobile viewport',\n },\n skipTlsVerification: {\n type: 'boolean',\n description: 'Skip TLS certificate verification',\n },\n removeBase64Images: {\n type: 'boolean',\n description: 'Remove base64 encoded images from output',\n },\n location: {\n type: 'object',\n properties: {\n country: {\n type: 'string',\n description: 'Country code for geolocation',\n },\n languages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Language codes for content',\n },\n },\n description: 'Location settings for scraping',\n },\n },\n required: ['url'],\n },\n};\n\nexport const EXTRACT_TOOL: Tool = {\n name: 'one_extract',\n description:\n 'Extract structured information from web pages using LLM. ' +\n 'Supports both cloud AI and self-hosted LLM extraction.',\n inputSchema: {\n type: 'object',\n properties: {\n urls: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of URLs to extract information from',\n },\n prompt: {\n type: 'string',\n description: 'Prompt for the LLM extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n schema: {\n type: 'object',\n description: 'JSON schema for structured data extraction',\n },\n allowExternalLinks: {\n type: 'boolean',\n description: 'Allow extraction from external links',\n },\n enableWebSearch: {\n type: 'boolean',\n description: 'Enable web search for additional context',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include subdomains in extraction',\n },\n },\n required: ['urls'],\n },\n};\n"],"mappings":"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","names":["url","dotenvx","FirecrawlApp","startTime","url"]}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // src/index.ts
4
4
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
5
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
7
 
7
8
  // src/search.ts
8
9
  import url from "node:url";
@@ -27,7 +28,7 @@ async function searxngSearch(params) {
27
28
  }
28
29
  const controller = new AbortController();
29
30
  const timeoutId = setTimeout(() => controller.abort(), Number(timeout));
30
- const config2 = {
31
+ const config = {
31
32
  q: query,
32
33
  pageno: limit,
33
34
  categories,
@@ -38,7 +39,7 @@ async function searxngSearch(params) {
38
39
  time_range: timeRange
39
40
  };
40
41
  const endpoint = `${apiUrl}/search`;
41
- const queryParams = url.format({ query: config2 });
42
+ const queryParams = url.format({ query: config });
42
43
  const headers = {
43
44
  "Content-Type": "application/json"
44
45
  };
@@ -121,10 +122,7 @@ async function tavilySearch(options) {
121
122
  };
122
123
  }
123
124
 
124
- // src/index.ts
125
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
126
- import dotenvx from "@dotenvx/dotenvx";
127
- dotenvx.config();
125
+ // src/tools.ts
128
126
  var SEARCH_TOOL = {
129
127
  name: "one_search",
130
128
  description: "Search and retrieve content from web pages. Returns SERP results by default (url, title, description).",
@@ -344,6 +342,28 @@ var EXTRACT_TOOL = {
344
342
  required: ["urls"]
345
343
  }
346
344
  };
345
+
346
+ // src/index.ts
347
+ import FirecrawlApp from "@mendable/firecrawl-js";
348
+ import dotenvx from "@dotenvx/dotenvx";
349
+ dotenvx.config();
350
+ var SEARCH_API_URL = process.env.SEARCH_API_URL;
351
+ var SEARCH_API_KEY = process.env.SEARCH_API_KEY;
352
+ var SEARCH_PROVIDER = process.env.SEARCH_PROVIDER ?? "searxng";
353
+ var SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;
354
+ var LIMIT = process.env.LIMIT ?? 10;
355
+ var CATEGORIES = process.env.CATEGORIES ?? "general";
356
+ var ENGINES = process.env.ENGINES ?? "all";
357
+ var FORMAT = process.env.FORMAT ?? "json";
358
+ var LANGUAGE = process.env.LANGUAGE ?? "auto";
359
+ var TIME_RANGE = process.env.TIME_RANGE ?? "";
360
+ var DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 1e4;
361
+ var FIRECRAWL_API_KEY = process.env.FIRECRAWL_API_KEY;
362
+ var FIRECRAWL_API_URL = process.env.FIRECRAWL_API_URL;
363
+ var firecrawl = new FirecrawlApp({
364
+ apiKey: FIRECRAWL_API_KEY ?? "",
365
+ ...FIRECRAWL_API_URL ? { apiUrl: FIRECRAWL_API_URL } : {}
366
+ });
347
367
  var server = new Server(
348
368
  {
349
369
  name: "one-search-mcp",
@@ -356,18 +376,7 @@ var server = new Server(
356
376
  }
357
377
  }
358
378
  );
359
- var SEARCH_API_URL = process.env.SEARCH_API_URL;
360
- var SEARCH_API_KEY = process.env.SEARCH_API_KEY;
361
- var SEARCH_PROVIDER = process.env.SEARCH_PROVIDER ?? "searxng";
362
- var SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;
363
- var LIMIT = process.env.LIMIT ?? 10;
364
- var CATEGORIES = process.env.CATEGORIES ?? "general";
365
- var ENGINES = process.env.ENGINES ?? "all";
366
- var FORMAT = process.env.FORMAT ?? "json";
367
- var LANGUAGE = process.env.LANGUAGE ?? "auto";
368
- var TIME_RANGE = process.env.TIME_RANGE ?? "";
369
- var DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 1e4;
370
- var config = {
379
+ var searchConfig = {
371
380
  pageno: LIMIT,
372
381
  categories: CATEGORIES,
373
382
  format: FORMAT,
@@ -402,7 +411,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
402
411
  }
403
412
  try {
404
413
  const { results, success } = await processSearch({
405
- ...config,
414
+ ...searchConfig,
406
415
  ...args,
407
416
  apiKey: SEARCH_API_KEY ?? "",
408
417
  apiUrl: SEARCH_API_URL ?? ""
@@ -411,9 +420,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
411
420
  throw new Error("Failed to search");
412
421
  }
413
422
  const resultsText = results.map((result) => `Title: ${result.title}
414
- URL: ${result.url}
415
- Description: ${result.snippet}
416
- ${result.markdown ? `Content: ${result.markdown}` : ""}`);
423
+ URL: ${result.url}
424
+ Description: ${result.snippet}
425
+ ${result.markdown ? `Content: ${result.markdown}` : ""}`);
417
426
  return {
418
427
  content: [
419
428
  {
@@ -441,8 +450,47 @@ ${result.markdown ? `Content: ${result.markdown}` : ""}`);
441
450
  };
442
451
  }
443
452
  }
444
- default:
453
+ case "one_scrape": {
454
+ if (!checkScrapeArgs(args)) {
455
+ throw new Error(`Invalid arguments for tool: [${name}]`);
456
+ }
457
+ try {
458
+ const startTime2 = Date.now();
459
+ server.sendLoggingMessage({
460
+ level: "info",
461
+ data: `[${(/* @__PURE__ */ new Date()).toISOString()}] Scraping started for url: [${args.url}]`
462
+ });
463
+ const { url: url2, ...scrapeArgs } = args;
464
+ const { content, success, result } = await processScrape(url2, scrapeArgs);
465
+ server.sendLoggingMessage({
466
+ level: "info",
467
+ data: `[${(/* @__PURE__ */ new Date()).toISOString()}] Scraping completed in ${Date.now() - startTime2}ms`
468
+ });
469
+ return {
470
+ content,
471
+ result,
472
+ success
473
+ };
474
+ } catch (error) {
475
+ server.sendLoggingMessage({
476
+ level: "error",
477
+ data: `[${(/* @__PURE__ */ new Date()).toISOString()}] Error scraping: ${error}`
478
+ });
479
+ const msg = error instanceof Error ? error.message : "Unknown error";
480
+ return {
481
+ success: false,
482
+ content: [
483
+ {
484
+ type: "text",
485
+ text: msg
486
+ }
487
+ ]
488
+ };
489
+ }
490
+ }
491
+ default: {
445
492
  throw new Error(`Unknown tool: ${name}`);
493
+ }
446
494
  }
447
495
  } catch (error) {
448
496
  const msg = error instanceof Error ? error.message : String(error);
@@ -476,13 +524,13 @@ async function processSearch(args) {
476
524
  switch (SEARCH_PROVIDER) {
477
525
  case "searxng":
478
526
  return await searxngSearch({
479
- ...config,
527
+ ...searchConfig,
480
528
  ...args,
481
529
  apiKey: SEARCH_API_KEY
482
530
  });
483
531
  case "tavily":
484
532
  return await tavilySearch({
485
- ...config,
533
+ ...searchConfig,
486
534
  ...args,
487
535
  apiKey: SEARCH_API_KEY
488
536
  });
@@ -490,9 +538,49 @@ async function processSearch(args) {
490
538
  throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);
491
539
  }
492
540
  }
541
+ async function processScrape(url2, args) {
542
+ const res = await firecrawl.scrapeUrl(url2, {
543
+ ...args
544
+ });
545
+ if (!res.success) {
546
+ throw new Error(`Failed to scrape: ${res.error}`);
547
+ }
548
+ const content = [];
549
+ if (res.markdown) {
550
+ content.push(res.markdown);
551
+ }
552
+ if (res.rawHtml) {
553
+ content.push(res.rawHtml);
554
+ }
555
+ if (res.links) {
556
+ content.push(res.links.join("\n"));
557
+ }
558
+ if (res.screenshot) {
559
+ content.push(res.screenshot);
560
+ }
561
+ if (res.html) {
562
+ content.push(res.html);
563
+ }
564
+ if (res.extract) {
565
+ content.push(res.extract);
566
+ }
567
+ return {
568
+ content: [
569
+ {
570
+ type: "text",
571
+ text: content.join("\n\n") || "No content found"
572
+ }
573
+ ],
574
+ result: res,
575
+ success: true
576
+ };
577
+ }
493
578
  function checkSearchArgs(args) {
494
579
  return typeof args === "object" && args !== null && "query" in args && typeof args.query === "string";
495
580
  }
581
+ function checkScrapeArgs(args) {
582
+ return typeof args === "object" && args !== null && "url" in args && typeof args.url === "string";
583
+ }
496
584
  async function runServer() {
497
585
  try {
498
586
  process.stdout.write("Starting OneSearch MCP server...\n");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/search.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema, Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { ISearchRequestOptions, ISearchResponse, Provider } from './interface.js';\nimport { searxngSearch, tavilySearch } from './search.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport dotenvx from '@dotenvx/dotenvx';\n\ndotenvx.config();\n\n// tools definition\nconst SEARCH_TOOL: Tool = {\n name: 'one_search',\n description:\n 'Search and retrieve content from web pages. ' +\n 'Returns SERP results by default (url, title, description).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 10)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: auto)',\n },\n categories: {\n type: 'string',\n description: 'Categories to search for (default: general)',\n },\n timeRange: {\n type: 'string',\n description: 'Time range for search results (default: all)',\n },\n },\n required: ['query'],\n },\n};\n\nconst SCRAPE_TOOL: Tool = {\n name: 'one_scrape',\n description:\n 'Scrape a single webpage with advanced options for content extraction. ' +\n 'Supports various formats including markdown, HTML, and screenshots. ' +\n 'Can execute custom actions like clicking or scrolling before scraping.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to scrape',\n },\n formats: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'markdown',\n 'html',\n 'rawHtml',\n 'screenshot',\n 'links',\n 'screenshot@fullPage',\n 'extract',\n ],\n },\n description: \"Content formats to extract (default: ['markdown'])\",\n },\n onlyMainContent: {\n type: 'boolean',\n description:\n 'Extract only the main content, filtering out navigation, footers, etc.',\n },\n includeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to specifically include in extraction',\n },\n excludeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to exclude from extraction',\n },\n waitFor: {\n type: 'number',\n description: 'Time in milliseconds to wait for dynamic content to load',\n },\n timeout: {\n type: 'number',\n description:\n 'Maximum time in milliseconds to wait for the page to load',\n },\n actions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'wait',\n 'click',\n 'screenshot',\n 'write',\n 'press',\n 'scroll',\n 'scrape',\n 'executeJavascript',\n ],\n description: 'Type of action to perform',\n },\n selector: {\n type: 'string',\n description: 'CSS selector for the target element',\n },\n milliseconds: {\n type: 'number',\n description: 'Time to wait in milliseconds (for wait action)',\n },\n text: {\n type: 'string',\n description: 'Text to write (for write action)',\n },\n key: {\n type: 'string',\n description: 'Key to press (for press action)',\n },\n direction: {\n type: 'string',\n enum: ['up', 'down'],\n description: 'Scroll direction',\n },\n script: {\n type: 'string',\n description: 'JavaScript code to execute',\n },\n fullPage: {\n type: 'boolean',\n description: 'Take full page screenshot',\n },\n },\n required: ['type'],\n },\n description: 'List of actions to perform before scraping',\n },\n extract: {\n type: 'object',\n properties: {\n schema: {\n type: 'object',\n description: 'Schema for structured data extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n prompt: {\n type: 'string',\n description: 'User prompt for LLM extraction',\n },\n },\n description: 'Configuration for structured data extraction',\n },\n mobile: {\n type: 'boolean',\n description: 'Use mobile viewport',\n },\n skipTlsVerification: {\n type: 'boolean',\n description: 'Skip TLS certificate verification',\n },\n removeBase64Images: {\n type: 'boolean',\n description: 'Remove base64 encoded images from output',\n },\n location: {\n type: 'object',\n properties: {\n country: {\n type: 'string',\n description: 'Country code for geolocation',\n },\n languages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Language codes for content',\n },\n },\n description: 'Location settings for scraping',\n },\n },\n required: ['url'],\n },\n};\n\nconst EXTRACT_TOOL: Tool = {\n name: 'one_extract',\n description:\n 'Extract structured information from web pages using LLM. ' +\n 'Supports both cloud AI and self-hosted LLM extraction.',\n inputSchema: {\n type: 'object',\n properties: {\n urls: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of URLs to extract information from',\n },\n prompt: {\n type: 'string',\n description: 'Prompt for the LLM extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n schema: {\n type: 'object',\n description: 'JSON schema for structured data extraction',\n },\n allowExternalLinks: {\n type: 'boolean',\n description: 'Allow extraction from external links',\n },\n enableWebSearch: {\n type: 'boolean',\n description: 'Enable web search for additional context',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include subdomains in extraction',\n },\n },\n required: ['urls'],\n },\n};\n\n// Server implementation\nconst server = new Server(\n {\n name: 'one-search-mcp',\n version: '0.0.1',\n },\n {\n capabilities: {\n tools: {},\n logging: {},\n },\n },\n);\n\n// searxng api\nconst SEARCH_API_URL = process.env.SEARCH_API_URL;\nconst SEARCH_API_KEY = process.env.SEARCH_API_KEY;\nconst SEARCH_PROVIDER: Provider = process.env.SEARCH_PROVIDER as Provider ?? 'searxng';\n\n// query params\nconst SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;\nconst LIMIT = process.env.LIMIT ?? 10;\nconst CATEGORIES = process.env.CATEGORIES ?? 'general';\nconst ENGINES = process.env.ENGINES ?? 'all';\nconst FORMAT = process.env.FORMAT ?? 'json';\nconst LANGUAGE = process.env.LANGUAGE ?? 'auto';\nconst TIME_RANGE = process.env.TIME_RANGE ?? '';\nconst DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 10000;\n\nconst config = {\n pageno: LIMIT,\n categories: CATEGORIES,\n format: FORMAT,\n safesearch: SAFE_SEARCH,\n language: LANGUAGE,\n engines: ENGINES,\n time_range: TIME_RANGE,\n timeout: DEFAULT_TIMEOUT,\n};\n\n// Tool handlers\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n SEARCH_TOOL,\n EXTRACT_TOOL,\n SCRAPE_TOOL,\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const startTime = Date.now();\n\n try {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('No arguments provided');\n }\n \n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Received request for tool: [${name}]`,\n });\n \n switch (name) {\n case 'one_search': {\n // check args.\n if (!checkSearchArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { results, success } = await processSearch({\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n apiUrl: SEARCH_API_URL ?? '',\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n const resultsText = results.map((result) => (\n `Title: ${result.title}\nURL: ${result.url}\nDescription: ${result.snippet}\n${result.markdown ? `Content: ${result.markdown}` : ''}`\n ));\n return {\n content: [\n {\n type: 'text',\n text: resultsText.join('\\n\\n'),\n },\n ],\n results,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error searching: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch(error) {\n const msg = error instanceof Error ? error.message : String(error);\n server.sendLoggingMessage({\n level: 'error',\n data: {\n message: `[${new Date().toISOString()}] Error processing request: ${msg}`,\n tool: request.params.name,\n arguments: request.params.arguments,\n timestamp: new Date().toISOString(),\n duration: Date.now() - startTime,\n },\n });\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n } finally {\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Request completed in ${Date.now() - startTime}ms`,\n });\n }\n});\n\nasync function processSearch(args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng':\n return await searxngSearch({\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n case 'tavily':\n return await tavilySearch({\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n default:\n throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);\n }\n}\n\nfunction checkSearchArgs(args: unknown): args is ISearchRequestOptions {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'query' in args &&\n typeof args.query === 'string'\n );\n}\n\nasync function runServer() {\n try {\n process.stdout.write('Starting OneSearch MCP server...\\n');\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n server.sendLoggingMessage({\n level: 'info',\n data: 'OneSearch MCP server started',\n });\n\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error starting server: ${msg}\\n`);\n process.exit(1);\n }\n}\n\n// run server\nrunServer().catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error running server: ${msg}\\n`);\n process.exit(1);\n});\n\n// export types\nexport * from './interface.js';\n","import url from 'node:url';\nimport { tavily, TavilyClient, TavilySearchOptions } from '@tavily/core';\nimport { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from './interface.js';\n\n/**\n * SearxNG Search API\n * - https://docs.searxng.org/dev/search_api.html\n */\nexport async function searxngSearch(params: ISearchRequestOptions): Promise<ISearchResponse> {\n try {\n const {\n query,\n limit = 10,\n categories = 'general',\n engines = 'all',\n safeSearch = 0,\n format = 'json',\n language = 'auto',\n timeRange = '',\n timeout = 10000,\n apiKey,\n apiUrl,\n } = params;\n\n if (!apiUrl) {\n throw new Error('SearxNG API URL is required');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), Number(timeout));\n\n const config = {\n q: query,\n pageno: limit,\n categories,\n format,\n safesearch: safeSearch,\n language,\n engines,\n time_range: timeRange,\n };\n\n const endpoint = `${apiUrl}/search`;\n\n const queryParams = url.format({ query: config });\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const res = await fetch(`${endpoint}${queryParams}`, {\n method: 'POST',\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const result = await res.json();\n if (result.results) {\n const results: ISearchResponseResult[] = result.results.map((item: Record<string, unknown>) => {\n const image = item.img_src ? {\n thumbnail: item.thumbnail_src,\n src: item.img_src,\n } : null;\n const video = item.iframe_src ? {\n thumbnail: item.thumbnail_src,\n src: item.iframe_src,\n } : null;\n return {\n title: item.title,\n snippet: item.content,\n url: item.url,\n source: item.source,\n image,\n video,\n engine: item.engine,\n };\n });\n return {\n results,\n success: true,\n };\n }\n return {\n results: [],\n success: false,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Searxng search error.';\n process.stdout.write(msg);\n throw err;\n }\n}\n\n\nlet tvly: TavilyClient | null = null;\nexport async function tavilySearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\n query,\n limit = 10,\n categories = 'general',\n timeRange,\n apiKey,\n } = options;\n\n if (!apiKey) {\n throw new Error('Tavily API key is required');\n }\n\n if (!tvly) {\n tvly = tavily({\n apiKey,\n });\n }\n\n const params: TavilySearchOptions = {\n topic: categories as TavilySearchOptions['topic'],\n timeRange: timeRange as TavilySearchOptions['timeRange'],\n maxResults: limit,\n };\n\n const res = await tvly.search(query, params);\n const results = res.results.map(item => ({\n title: item.title,\n url: item.url,\n snippet: item.content,\n }));\n\n return {\n results,\n success: true,\n };\n}\n"],"mappings":"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","names":["config"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/search.ts","../src/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { ISearchRequestOptions, ISearchResponse, Provider } from './interface.js';\nimport { searxngSearch, tavilySearch } from './search.js';\nimport { SEARCH_TOOL, EXTRACT_TOOL, SCRAPE_TOOL } from './tools.js';\nimport FirecrawlApp, { ScrapeParams } from '@mendable/firecrawl-js';\nimport dotenvx from '@dotenvx/dotenvx';\n\ndotenvx.config();\n\n\n// search api\nconst SEARCH_API_URL = process.env.SEARCH_API_URL;\nconst SEARCH_API_KEY = process.env.SEARCH_API_KEY;\nconst SEARCH_PROVIDER: Provider = process.env.SEARCH_PROVIDER as Provider ?? 'searxng';\n\n// search query params\nconst SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;\nconst LIMIT = process.env.LIMIT ?? 10;\nconst CATEGORIES = process.env.CATEGORIES ?? 'general';\nconst ENGINES = process.env.ENGINES ?? 'all';\nconst FORMAT = process.env.FORMAT ?? 'json';\nconst LANGUAGE = process.env.LANGUAGE ?? 'auto';\nconst TIME_RANGE = process.env.TIME_RANGE ?? '';\nconst DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 10000;\n\n// firecrawl api\nconst FIRECRAWL_API_KEY = process.env.FIRECRAWL_API_KEY;\nconst FIRECRAWL_API_URL = process.env.FIRECRAWL_API_URL;\n\n// firecrawl client\nconst firecrawl = new FirecrawlApp({\n apiKey: FIRECRAWL_API_KEY ?? '',\n ...(FIRECRAWL_API_URL ? { apiUrl: FIRECRAWL_API_URL } : {}),\n});\n\n// Server implementation\nconst server = new Server(\n {\n name: 'one-search-mcp',\n version: '0.0.1',\n },\n {\n capabilities: {\n tools: {},\n logging: {},\n },\n },\n);\n\nconst searchConfig = {\n pageno: LIMIT,\n categories: CATEGORIES,\n format: FORMAT,\n safesearch: SAFE_SEARCH,\n language: LANGUAGE,\n engines: ENGINES,\n time_range: TIME_RANGE,\n timeout: DEFAULT_TIMEOUT,\n};\n\n// Tool handlers\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n SEARCH_TOOL,\n EXTRACT_TOOL,\n SCRAPE_TOOL,\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const startTime = Date.now();\n\n try {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('No arguments provided');\n }\n \n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Received request for tool: [${name}]`,\n });\n \n switch (name) {\n case 'one_search': {\n // check args.\n if (!checkSearchArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { results, success } = await processSearch({\n ...searchConfig,\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n apiUrl: SEARCH_API_URL ?? '',\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n const resultsText = results.map((result) => (\n `Title: ${result.title}\n URL: ${result.url}\n Description: ${result.snippet}\n ${result.markdown ? `Content: ${result.markdown}` : ''}`\n ));\n return {\n content: [\n {\n type: 'text',\n text: resultsText.join('\\n\\n'),\n },\n ],\n results,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error searching: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n case 'one_scrape': {\n if (!checkScrapeArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const startTime = Date.now();\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping started for url: [${args.url}]`,\n });\n\n const { url, ...scrapeArgs } = args;\n const { content, success, result } = await processScrape(url, scrapeArgs);\n\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping completed in ${Date.now() - startTime}ms`,\n });\n\n return {\n content,\n result,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error scraping: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n default: {\n throw new Error(`Unknown tool: ${name}`);\n }\n }\n } catch(error) {\n const msg = error instanceof Error ? error.message : String(error);\n server.sendLoggingMessage({\n level: 'error',\n data: {\n message: `[${new Date().toISOString()}] Error processing request: ${msg}`,\n tool: request.params.name,\n arguments: request.params.arguments,\n timestamp: new Date().toISOString(),\n duration: Date.now() - startTime,\n },\n });\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n } finally {\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Request completed in ${Date.now() - startTime}ms`,\n });\n }\n});\n\nasync function processSearch(args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng':\n return await searxngSearch({\n ...searchConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n case 'tavily':\n return await tavilySearch({\n ...searchConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n default:\n throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);\n }\n}\n\nasync function processScrape(url: string, args: ScrapeParams) {\n const res = await firecrawl.scrapeUrl(url, {\n ...args,\n });\n\n if (!res.success) {\n throw new Error(`Failed to scrape: ${res.error}`);\n }\n\n const content: string[] = [];\n\n if (res.markdown) {\n content.push(res.markdown);\n }\n\n if (res.rawHtml) {\n content.push(res.rawHtml);\n }\n\n if (res.links) {\n content.push(res.links.join('\\n'));\n }\n\n if (res.screenshot) {\n content.push(res.screenshot);\n }\n\n if (res.html) {\n content.push(res.html);\n }\n\n if (res.extract) {\n content.push(res.extract);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: content.join('\\n\\n') || 'No content found',\n },\n ],\n result: res,\n success: true,\n };\n}\n\nfunction checkSearchArgs(args: unknown): args is ISearchRequestOptions {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'query' in args &&\n typeof args.query === 'string'\n );\n}\n\nfunction checkScrapeArgs(args: unknown): args is ScrapeParams & { url: string } {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'url' in args &&\n typeof args.url === 'string'\n );\n}\n\nasync function runServer() {\n try {\n process.stdout.write('Starting OneSearch MCP server...\\n');\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n server.sendLoggingMessage({\n level: 'info',\n data: 'OneSearch MCP server started',\n });\n\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error starting server: ${msg}\\n`);\n process.exit(1);\n }\n}\n\n// run server\nrunServer().catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error running server: ${msg}\\n`);\n process.exit(1);\n});\n\n// export types\nexport * from './interface.js';\n","import url from 'node:url';\nimport { tavily, TavilyClient, TavilySearchOptions } from '@tavily/core';\nimport { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from './interface.js';\n\n/**\n * SearxNG Search API\n * - https://docs.searxng.org/dev/search_api.html\n */\nexport async function searxngSearch(params: ISearchRequestOptions): Promise<ISearchResponse> {\n try {\n const {\n query,\n limit = 10,\n categories = 'general',\n engines = 'all',\n safeSearch = 0,\n format = 'json',\n language = 'auto',\n timeRange = '',\n timeout = 10000,\n apiKey,\n apiUrl,\n } = params;\n\n if (!apiUrl) {\n throw new Error('SearxNG API URL is required');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), Number(timeout));\n\n const config = {\n q: query,\n pageno: limit,\n categories,\n format,\n safesearch: safeSearch,\n language,\n engines,\n time_range: timeRange,\n };\n\n const endpoint = `${apiUrl}/search`;\n\n const queryParams = url.format({ query: config });\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const res = await fetch(`${endpoint}${queryParams}`, {\n method: 'POST',\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const result = await res.json();\n if (result.results) {\n const results: ISearchResponseResult[] = result.results.map((item: Record<string, unknown>) => {\n const image = item.img_src ? {\n thumbnail: item.thumbnail_src,\n src: item.img_src,\n } : null;\n const video = item.iframe_src ? {\n thumbnail: item.thumbnail_src,\n src: item.iframe_src,\n } : null;\n return {\n title: item.title,\n snippet: item.content,\n url: item.url,\n source: item.source,\n image,\n video,\n engine: item.engine,\n };\n });\n return {\n results,\n success: true,\n };\n }\n return {\n results: [],\n success: false,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Searxng search error.';\n process.stdout.write(msg);\n throw err;\n }\n}\n\n\nlet tvly: TavilyClient | null = null;\nexport async function tavilySearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\n query,\n limit = 10,\n categories = 'general',\n timeRange,\n apiKey,\n } = options;\n\n if (!apiKey) {\n throw new Error('Tavily API key is required');\n }\n\n if (!tvly) {\n tvly = tavily({\n apiKey,\n });\n }\n\n const params: TavilySearchOptions = {\n topic: categories as TavilySearchOptions['topic'],\n timeRange: timeRange as TavilySearchOptions['timeRange'],\n maxResults: limit,\n };\n\n const res = await tvly.search(query, params);\n const results = res.results.map(item => ({\n title: item.title,\n url: item.url,\n snippet: item.content,\n }));\n\n return {\n results,\n success: true,\n };\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n// tools definition\nexport const SEARCH_TOOL: Tool = {\n name: 'one_search',\n description:\n 'Search and retrieve content from web pages. ' +\n 'Returns SERP results by default (url, title, description).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 10)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: auto)',\n },\n categories: {\n type: 'string',\n description: 'Categories to search for (default: general)',\n },\n timeRange: {\n type: 'string',\n description: 'Time range for search results (default: all)',\n },\n },\n required: ['query'],\n },\n};\n\nexport const SCRAPE_TOOL: Tool = {\n name: 'one_scrape',\n description:\n 'Scrape a single webpage with advanced options for content extraction. ' +\n 'Supports various formats including markdown, HTML, and screenshots. ' +\n 'Can execute custom actions like clicking or scrolling before scraping.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to scrape',\n },\n formats: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'markdown',\n 'html',\n 'rawHtml',\n 'screenshot',\n 'links',\n 'screenshot@fullPage',\n 'extract',\n ],\n },\n description: \"Content formats to extract (default: ['markdown'])\",\n },\n onlyMainContent: {\n type: 'boolean',\n description:\n 'Extract only the main content, filtering out navigation, footers, etc.',\n },\n includeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to specifically include in extraction',\n },\n excludeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to exclude from extraction',\n },\n waitFor: {\n type: 'number',\n description: 'Time in milliseconds to wait for dynamic content to load',\n },\n timeout: {\n type: 'number',\n description:\n 'Maximum time in milliseconds to wait for the page to load',\n },\n actions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'wait',\n 'click',\n 'screenshot',\n 'write',\n 'press',\n 'scroll',\n 'scrape',\n 'executeJavascript',\n ],\n description: 'Type of action to perform',\n },\n selector: {\n type: 'string',\n description: 'CSS selector for the target element',\n },\n milliseconds: {\n type: 'number',\n description: 'Time to wait in milliseconds (for wait action)',\n },\n text: {\n type: 'string',\n description: 'Text to write (for write action)',\n },\n key: {\n type: 'string',\n description: 'Key to press (for press action)',\n },\n direction: {\n type: 'string',\n enum: ['up', 'down'],\n description: 'Scroll direction',\n },\n script: {\n type: 'string',\n description: 'JavaScript code to execute',\n },\n fullPage: {\n type: 'boolean',\n description: 'Take full page screenshot',\n },\n },\n required: ['type'],\n },\n description: 'List of actions to perform before scraping',\n },\n extract: {\n type: 'object',\n properties: {\n schema: {\n type: 'object',\n description: 'Schema for structured data extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n prompt: {\n type: 'string',\n description: 'User prompt for LLM extraction',\n },\n },\n description: 'Configuration for structured data extraction',\n },\n mobile: {\n type: 'boolean',\n description: 'Use mobile viewport',\n },\n skipTlsVerification: {\n type: 'boolean',\n description: 'Skip TLS certificate verification',\n },\n removeBase64Images: {\n type: 'boolean',\n description: 'Remove base64 encoded images from output',\n },\n location: {\n type: 'object',\n properties: {\n country: {\n type: 'string',\n description: 'Country code for geolocation',\n },\n languages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Language codes for content',\n },\n },\n description: 'Location settings for scraping',\n },\n },\n required: ['url'],\n },\n};\n\nexport const EXTRACT_TOOL: Tool = {\n name: 'one_extract',\n description:\n 'Extract structured information from web pages using LLM. ' +\n 'Supports both cloud AI and self-hosted LLM extraction.',\n inputSchema: {\n type: 'object',\n properties: {\n urls: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of URLs to extract information from',\n },\n prompt: {\n type: 'string',\n description: 'Prompt for the LLM extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n schema: {\n type: 'object',\n description: 'JSON schema for structured data extraction',\n },\n allowExternalLinks: {\n type: 'boolean',\n description: 'Allow extraction from external links',\n },\n enableWebSearch: {\n type: 'boolean',\n description: 'Enable web search for additional context',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include subdomains in extraction',\n },\n },\n required: ['urls'],\n },\n};\n"],"mappings":";;;AAEA,SAAS,cAAc;AACvB,SAAU,uBAAuB,8BAA8B;AAC/D,SAAS,4BAA4B;;;ACJrC,OAAO,SAAS;AAChB,SAAS,cAAiD;AAO1D,eAAsB,cAAc,QAAyD;AAC3F,MAAI;AACF,UAAM;AAAA,MACJ;AAAA,MACA,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,UAAU;AAAA,MACV,aAAa;AAAA,MACb,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF,IAAI;AAEJ,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,OAAO,OAAO,CAAC;AAEtE,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IACd;AAEA,UAAM,WAAW,GAAG,MAAM;AAE1B,UAAM,cAAc,IAAI,OAAO,EAAE,OAAO,OAAO,CAAC;AAEhD,UAAM,UAAuB;AAAA,MAC3B,gBAAgB;AAAA,IAClB;AAEA,QAAI,QAAQ;AACV,cAAQ,eAAe,IAAI,UAAU,MAAM;AAAA,IAC7C;AAEA,UAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,WAAW,IAAI;AAAA,MACnD,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,iBAAa,SAAS;AACtB,UAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,QAAI,OAAO,SAAS;AAClB,YAAM,UAAmC,OAAO,QAAQ,IAAI,CAAC,SAAkC;AAC7F,cAAM,QAAQ,KAAK,UAAU;AAAA,UAC3B,WAAW,KAAK;AAAA,UAChB,KAAK,KAAK;AAAA,QACZ,IAAI;AACJ,cAAM,QAAQ,KAAK,aAAa;AAAA,UAC9B,WAAW,KAAK;AAAA,UAChB,KAAK,KAAK;AAAA,QACZ,IAAI;AACJ,eAAO;AAAA,UACL,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK;AAAA,UACd,KAAK,KAAK;AAAA,UACV,QAAQ,KAAK;AAAA,UACb;AAAA,UACA;AAAA,UACA,QAAQ,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AACD,aAAO;AAAA,QACL;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,CAAC;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAc;AACrB,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU;AACjD,YAAQ,OAAO,MAAM,GAAG;AACxB,UAAM;AAAA,EACR;AACF;AAGA,IAAI,OAA4B;AAChC,eAAsB,aAAa,SAA0D;AAC3F,QAAM;AAAA,IACJ;AAAA,IACA,QAAQ;AAAA,IACR,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AAEA,MAAI,CAAC,MAAM;AACT,WAAO,OAAO;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAA8B;AAAA,IAClC,OAAO;AAAA,IACP;AAAA,IACA,YAAY;AAAA,EACd;AAEA,QAAM,MAAM,MAAM,KAAK,OAAO,OAAO,MAAM;AAC3C,QAAM,UAAU,IAAI,QAAQ,IAAI,WAAS;AAAA,IACvC,OAAO,KAAK;AAAA,IACZ,KAAK,KAAK;AAAA,IACV,SAAS,KAAK;AAAA,EAChB,EAAE;AAEF,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,EACX;AACF;;;ACrIO,IAAM,cAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,aACE;AAAA,EAEF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,YAAY;AAAA,QACV,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,WAAW;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,OAAO;AAAA,EACpB;AACF;AAEO,IAAM,cAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,aACE;AAAA,EAGF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,KAAK;AAAA,QACH,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,aAAa;AAAA,MACf;AAAA,MACA,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,aAAa;AAAA,MACf;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,YACV,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,aAAa;AAAA,YACf;AAAA,YACA,UAAU;AAAA,cACR,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,cAAc;AAAA,cACZ,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,KAAK;AAAA,cACH,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,WAAW;AAAA,cACT,MAAM;AAAA,cACN,MAAM,CAAC,MAAM,MAAM;AAAA,cACnB,aAAa;AAAA,YACf;AAAA,YACA,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,UAAU;AAAA,cACR,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA,UAAU,CAAC,MAAM;AAAA,QACnB;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,cAAc;AAAA,YACZ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,qBAAqB;AAAA,QACnB,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,oBAAoB;AAAA,QAClB,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,YACP,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,WAAW;AAAA,YACT,MAAM;AAAA,YACN,OAAO,EAAE,MAAM,SAAS;AAAA,YACxB,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,KAAK;AAAA,EAClB;AACF;AAEO,IAAM,eAAqB;AAAA,EAChC,MAAM;AAAA,EACN,aACE;AAAA,EAEF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,oBAAoB;AAAA,QAClB,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,iBAAiB;AAAA,QACf,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,mBAAmB;AAAA,QACjB,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,MAAM;AAAA,EACnB;AACF;;;AFhOA,OAAO,kBAAoC;AAC3C,OAAO,aAAa;AAEpB,QAAQ,OAAO;AAIf,IAAM,iBAAiB,QAAQ,IAAI;AACnC,IAAM,iBAAiB,QAAQ,IAAI;AACnC,IAAM,kBAA4B,QAAQ,IAAI,mBAA+B;AAG7E,IAAM,cAAc,QAAQ,IAAI,eAAe;AAC/C,IAAM,QAAQ,QAAQ,IAAI,SAAS;AACnC,IAAM,aAAa,QAAQ,IAAI,cAAc;AAC7C,IAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,IAAM,SAAS,QAAQ,IAAI,UAAU;AACrC,IAAM,WAAW,QAAQ,IAAI,YAAY;AACzC,IAAM,aAAa,QAAQ,IAAI,cAAc;AAC7C,IAAM,kBAAkB,QAAQ,IAAI,WAAW;AAG/C,IAAM,oBAAoB,QAAQ,IAAI;AACtC,IAAM,oBAAoB,QAAQ,IAAI;AAGtC,IAAM,YAAY,IAAI,aAAa;AAAA,EACjC,QAAQ,qBAAqB;AAAA,EAC7B,GAAI,oBAAoB,EAAE,QAAQ,kBAAkB,IAAI,CAAC;AAC3D,CAAC;AAGD,IAAM,SAAS,IAAI;AAAA,EACjB;AAAA,IACE,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,cAAc;AAAA,MACZ,OAAO,CAAC;AAAA,MACR,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,eAAe;AAAA,EACnB,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AACX;AAGA,OAAO,kBAAkB,wBAAwB,aAAa;AAAA,EAC5D,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF,EAAE;AAEF,OAAO,kBAAkB,uBAAuB,OAAO,YAAY;AACjE,QAAM,YAAY,KAAK,IAAI;AAE3B,MAAI;AACF,UAAM,EAAE,MAAM,WAAW,KAAK,IAAI,QAAQ;AAE1C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AAEA,WAAO,mBAAmB;AAAA,MACxB,OAAO;AAAA,MACP,MAAM,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,iCAAiC,IAAI;AAAA,IACzE,CAAC;AAED,YAAQ,MAAM;AAAA,MACZ,KAAK,cAAc;AAEjB,YAAI,CAAC,gBAAgB,IAAI,GAAG;AAC1B,gBAAM,IAAI,MAAM,gCAAgC,IAAI,GAAG;AAAA,QACzD;AACA,YAAI;AACF,gBAAM,EAAE,SAAS,QAAQ,IAAI,MAAM,cAAc;AAAA,YAC/C,GAAG;AAAA,YACH,GAAG;AAAA,YACH,QAAQ,kBAAkB;AAAA,YAC1B,QAAQ,kBAAkB;AAAA,UAC5B,CAAC;AACD,cAAI,CAAC,SAAS;AACZ,kBAAM,IAAI,MAAM,kBAAkB;AAAA,UACpC;AACA,gBAAM,cAAc,QAAQ,IAAI,CAAC,WAC/B,UAAU,OAAO,KAAK;AAAA,SACzB,OAAO,GAAG;AAAA,iBACF,OAAO,OAAO;AAAA,IAC3B,OAAO,WAAW,YAAY,OAAO,QAAQ,KAAK,EAAE,EAC7C;AACD,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,YAAY,KAAK,MAAM;AAAA,cAC/B;AAAA,YACF;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,iBAAO,mBAAmB;AAAA,YACxB,OAAO;AAAA,YACP,MAAM,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,sBAAsB,KAAK;AAAA,UAC/D,CAAC;AACD,gBAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU;AACrD,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK,cAAc;AACjB,YAAI,CAAC,gBAAgB,IAAI,GAAG;AAC1B,gBAAM,IAAI,MAAM,gCAAgC,IAAI,GAAG;AAAA,QACzD;AACA,YAAI;AACF,gBAAMA,aAAY,KAAK,IAAI;AAC3B,iBAAO,mBAAmB;AAAA,YACxB,OAAO;AAAA,YACP,MAAM,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,gCAAgC,KAAK,GAAG;AAAA,UAC5E,CAAC;AAED,gBAAM,EAAE,KAAAC,MAAK,GAAG,WAAW,IAAI;AAC/B,gBAAM,EAAE,SAAS,SAAS,OAAO,IAAI,MAAM,cAAcA,MAAK,UAAU;AAExE,iBAAO,mBAAmB;AAAA,YACxB,OAAO;AAAA,YACP,MAAM,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,2BAA2B,KAAK,IAAI,IAAID,UAAS;AAAA,UACrF,CAAC;AAED,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,iBAAO,mBAAmB;AAAA,YACxB,OAAO;AAAA,YACP,MAAM,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,qBAAqB,KAAK;AAAA,UAC9D,CAAC;AACD,gBAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU;AACrD,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,SAAS;AACP,cAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,MACzC;AAAA,IACF;AAAA,EACF,SAAQ,OAAO;AACb,UAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,WAAO,mBAAmB;AAAA,MACxB,OAAO;AAAA,MACP,MAAM;AAAA,QACJ,SAAS,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,+BAA+B,GAAG;AAAA,QACvE,MAAM,QAAQ,OAAO;AAAA,QACrB,WAAW,QAAQ,OAAO;AAAA,QAC1B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,UAAU,KAAK,IAAI,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAE;AACA,WAAO,mBAAmB;AAAA,MACxB,OAAO;AAAA,MACP,MAAM,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,0BAA0B,KAAK,IAAI,IAAI,SAAS;AAAA,IACpF,CAAC;AAAA,EACH;AACF,CAAC;AAED,eAAe,cAAc,MAAuD;AAClF,UAAQ,iBAAiB;AAAA,IACvB,KAAK;AACH,aAAO,MAAM,cAAc;AAAA,QACzB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,KAAK;AACH,aAAO,MAAM,aAAa;AAAA,QACxB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AACE,YAAM,IAAI,MAAM,gCAAgC,eAAe,EAAE;AAAA,EACrE;AACF;AAEA,eAAe,cAAcC,MAAa,MAAoB;AAC5D,QAAM,MAAM,MAAM,UAAU,UAAUA,MAAK;AAAA,IACzC,GAAG;AAAA,EACL,CAAC;AAED,MAAI,CAAC,IAAI,SAAS;AAChB,UAAM,IAAI,MAAM,qBAAqB,IAAI,KAAK,EAAE;AAAA,EAClD;AAEA,QAAM,UAAoB,CAAC;AAE3B,MAAI,IAAI,UAAU;AAChB,YAAQ,KAAK,IAAI,QAAQ;AAAA,EAC3B;AAEA,MAAI,IAAI,SAAS;AACf,YAAQ,KAAK,IAAI,OAAO;AAAA,EAC1B;AAEA,MAAI,IAAI,OAAO;AACb,YAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,CAAC;AAAA,EACnC;AAEA,MAAI,IAAI,YAAY;AAClB,YAAQ,KAAK,IAAI,UAAU;AAAA,EAC7B;AAEA,MAAI,IAAI,MAAM;AACZ,YAAQ,KAAK,IAAI,IAAI;AAAA,EACvB;AAEA,MAAI,IAAI,SAAS;AACf,YAAQ,KAAK,IAAI,OAAO;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,QAAQ,KAAK,MAAM,KAAK;AAAA,MAChC;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AACF;AAEA,SAAS,gBAAgB,MAA8C;AACrE,SACE,OAAO,SAAS,YAChB,SAAS,QACT,WAAW,QACX,OAAO,KAAK,UAAU;AAE1B;AAEA,SAAS,gBAAgB,MAAuD;AAC9E,SACE,OAAO,SAAS,YAChB,SAAS,QACT,SAAS,QACT,OAAO,KAAK,QAAQ;AAExB;AAEA,eAAe,YAAY;AACzB,MAAI;AACF,YAAQ,OAAO,MAAM,oCAAoC;AAEzD,UAAM,YAAY,IAAI,qBAAqB;AAC3C,UAAM,OAAO,QAAQ,SAAS;AAE9B,WAAO,mBAAmB;AAAA,MACxB,OAAO;AAAA,MACP,MAAM;AAAA,IACR,CAAC;AAAA,EAEH,SAAS,OAAO;AACd,UAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,YAAQ,OAAO,MAAM,0BAA0B,GAAG;AAAA,CAAI;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAGA,UAAU,EAAE,MAAM,CAAC,UAAU;AAC3B,QAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,UAAQ,OAAO,MAAM,yBAAyB,GAAG;AAAA,CAAI;AACrD,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["startTime","url"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-search-mcp",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "One Search MCP Server, Web Search & Crawl & Scraper & Extract, support SearXNG, Firecrawl, Tavily, etc.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -79,6 +79,7 @@
79
79
  },
80
80
  "dependencies": {
81
81
  "@dotenvx/dotenvx": "^1.38.5",
82
+ "@mendable/firecrawl-js": "^1.20.1",
82
83
  "@modelcontextprotocol/sdk": "^1.7.0",
83
84
  "@tavily/core": "^0.3.1"
84
85
  }