one-search-mcp 1.0.1 → 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/README.md CHANGED
@@ -11,6 +11,7 @@ A Model Context Protocol (MCP) server implementation that integrates with Searxn
11
11
  ## Installation
12
12
 
13
13
  ```shell
14
+ # Install globally
14
15
  npm install -g one-search-mcp
15
16
  ```
16
17
 
@@ -19,9 +20,55 @@ npm install -g one-search-mcp
19
20
  env SEARCH_API_KEY=YOUR_API_KEY SEARCH_API_URL=YOUR_API_URL npx -y one-search-mcp
20
21
  ```
21
22
 
23
+ ## Environment Variables
24
+
25
+ - SEARCH_PROVIDER (Optional): The search provider to use, either `searxng` or `tavily`, default is `searxng`.
26
+ - SEARCH_API_URL (Optional): The URL of the SearxNG API, required for `searxng`.
27
+ - SEARCH_API_KEY (Optional): The API key for the search provider, required for `tavily`.
28
+
29
+ ## Running on Cursor
30
+
31
+ Your `mcp.json` file will look like this:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "one-search-mcp": {
37
+ "command": "npx",
38
+ "args": ["-y", "one-search-mcp"],
39
+ "env": {
40
+ "SEARCH_PROVIDER": "searxng",
41
+ "SEARCH_API_URL": "http://127.0.0.1:8080",
42
+ "SEARCH_API_KEY": "YOUR_API_KEY"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Running on Windsurf
50
+
51
+ Add this to your `./codeium/windsurf/model_config.json` file:
52
+
53
+ ```json
54
+ {
55
+ "mcpServers": {
56
+ "one-search-mcp": {
57
+ "command": "npx",
58
+ "args": ["-y", "one-search-mcp"],
59
+ "env": {
60
+ "SEARCH_PROVIDER": "searxng",
61
+ "SEARCH_API_URL": "http://127.0.0.1:8080",
62
+ "SEARCH_API_KEY": "YOUR_API_KEY"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
22
69
  ## Self-host
23
70
 
24
- Local deployment of Searxng and Firecrawl, please refer to [Deploy](./deploy/README.md)
71
+ Local deployment of SearXNG and Firecrawl, please refer to [Deploy](./deploy/README.md)
25
72
 
26
73
  ## License
27
74
 
package/dist/index.cjs CHANGED
@@ -29,11 +29,12 @@ 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);
35
36
  var import_core = require("@tavily/core");
36
- async function searxngSearch(apiUrl, params) {
37
+ async function searxngSearch(params) {
37
38
  try {
38
39
  const {
39
40
  query,
@@ -45,11 +46,15 @@ async function searxngSearch(apiUrl, params) {
45
46
  language = "auto",
46
47
  timeRange = "",
47
48
  timeout = 1e4,
48
- apiKey = ""
49
+ apiKey,
50
+ apiUrl
49
51
  } = params;
52
+ if (!apiUrl) {
53
+ throw new Error("SearxNG API URL is required");
54
+ }
50
55
  const controller = new AbortController();
51
56
  const timeoutId = setTimeout(() => controller.abort(), Number(timeout));
52
- const config2 = {
57
+ const config = {
53
58
  q: query,
54
59
  pageno: limit,
55
60
  categories,
@@ -60,7 +65,7 @@ async function searxngSearch(apiUrl, params) {
60
65
  time_range: timeRange
61
66
  };
62
67
  const endpoint = `${apiUrl}/search`;
63
- const queryParams = import_node_url.default.format({ query: config2 });
68
+ const queryParams = import_node_url.default.format({ query: config });
64
69
  const headers = {
65
70
  "Content-Type": "application/json"
66
71
  };
@@ -104,13 +109,15 @@ async function searxngSearch(apiUrl, params) {
104
109
  success: false
105
110
  };
106
111
  } catch (err) {
107
- process.stdout.write(err?.message ?? "Searxng search error.");
112
+ const msg = err instanceof Error ? err.message : "Searxng search error.";
113
+ process.stdout.write(msg);
108
114
  throw err;
109
115
  }
110
116
  }
111
117
  var tvly = null;
112
- async function tavilySearch(query, options) {
118
+ async function tavilySearch(options) {
113
119
  const {
120
+ query,
114
121
  limit = 10,
115
122
  categories = "general",
116
123
  timeRange,
@@ -141,10 +148,7 @@ async function tavilySearch(query, options) {
141
148
  };
142
149
  }
143
150
 
144
- // src/index.ts
145
- var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
146
- var import_dotenvx = __toESM(require("@dotenvx/dotenvx"), 1);
147
- import_dotenvx.default.config();
151
+ // src/tools.ts
148
152
  var SEARCH_TOOL = {
149
153
  name: "one_search",
150
154
  description: "Search and retrieve content from web pages. Returns SERP results by default (url, title, description).",
@@ -157,11 +161,11 @@ var SEARCH_TOOL = {
157
161
  },
158
162
  limit: {
159
163
  type: "number",
160
- description: "Maximum number of results to return (default: 5)"
164
+ description: "Maximum number of results to return (default: 10)"
161
165
  },
162
166
  language: {
163
167
  type: "string",
164
- description: "Language code for search results (default: en)"
168
+ description: "Language code for search results (default: auto)"
165
169
  },
166
170
  categories: {
167
171
  type: "string",
@@ -364,6 +368,28 @@ var EXTRACT_TOOL = {
364
368
  required: ["urls"]
365
369
  }
366
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
+ });
367
393
  var server = new import_server.Server(
368
394
  {
369
395
  name: "one-search-mcp",
@@ -376,22 +402,7 @@ var server = new import_server.Server(
376
402
  }
377
403
  }
378
404
  );
379
- var SEARCH_API_URL = process.env.SEARCH_API_URL;
380
- var SEARCH_API_KEY = process.env.SEARCH_API_KEY;
381
- var SEARCH_PROVIDER = process.env.SEARCH_PROVIDER ?? "searxng";
382
- if (!SEARCH_API_URL) {
383
- process.stderr.write("SEARCH_API_URL must be set");
384
- process.exit(1);
385
- }
386
- var SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;
387
- var LIMIT = process.env.LIMIT ?? 10;
388
- var CATEGORIES = process.env.CATEGORIES ?? "general";
389
- var ENGINES = process.env.ENGINES ?? "all";
390
- var FORMAT = process.env.FORMAT ?? "json";
391
- var LANGUAGE = process.env.LANGUAGE ?? "auto";
392
- var TIME_RANGE = process.env.TIME_RANGE ?? "";
393
- var DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 1e4;
394
- var config = {
405
+ var searchConfig = {
395
406
  pageno: LIMIT,
396
407
  categories: CATEGORIES,
397
408
  format: FORMAT,
@@ -425,15 +436,26 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
425
436
  throw new Error(`Invalid arguments for tool: [${name}]`);
426
437
  }
427
438
  try {
428
- const { results, success } = await processSearch(SEARCH_API_URL, {
429
- ...config,
439
+ const { results, success } = await processSearch({
440
+ ...searchConfig,
430
441
  ...args,
431
- apiKey: SEARCH_API_KEY ?? ""
442
+ apiKey: SEARCH_API_KEY ?? "",
443
+ apiUrl: SEARCH_API_URL ?? ""
432
444
  });
433
445
  if (!success) {
434
446
  throw new Error("Failed to search");
435
447
  }
448
+ const resultsText = results.map((result) => `Title: ${result.title}
449
+ URL: ${result.url}
450
+ Description: ${result.snippet}
451
+ ${result.markdown ? `Content: ${result.markdown}` : ""}`);
436
452
  return {
453
+ content: [
454
+ {
455
+ type: "text",
456
+ text: resultsText.join("\n\n")
457
+ }
458
+ ],
437
459
  results,
438
460
  success
439
461
  };
@@ -445,12 +467,56 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
445
467
  const msg = error instanceof Error ? error.message : "Unknown error";
446
468
  return {
447
469
  success: false,
448
- error: msg
470
+ content: [
471
+ {
472
+ type: "text",
473
+ text: msg
474
+ }
475
+ ]
449
476
  };
450
477
  }
451
478
  }
452
- 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: {
453
518
  throw new Error(`Unknown tool: ${name}`);
519
+ }
454
520
  }
455
521
  } catch (error) {
456
522
  const msg = error instanceof Error ? error.message : String(error);
@@ -466,7 +532,12 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
466
532
  });
467
533
  return {
468
534
  success: false,
469
- error: error instanceof Error ? error.message : msg
535
+ content: [
536
+ {
537
+ type: "text",
538
+ text: msg
539
+ }
540
+ ]
470
541
  };
471
542
  } finally {
472
543
  server.sendLoggingMessage({
@@ -475,17 +546,17 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
475
546
  });
476
547
  }
477
548
  });
478
- async function processSearch(apiUrl, args) {
549
+ async function processSearch(args) {
479
550
  switch (SEARCH_PROVIDER) {
480
551
  case "searxng":
481
- return await searxngSearch(apiUrl, {
482
- ...config,
552
+ return await searxngSearch({
553
+ ...searchConfig,
483
554
  ...args,
484
555
  apiKey: SEARCH_API_KEY
485
556
  });
486
557
  case "tavily":
487
- return await tavilySearch(apiUrl, {
488
- ...config,
558
+ return await tavilySearch({
559
+ ...searchConfig,
489
560
  ...args,
490
561
  apiKey: SEARCH_API_KEY
491
562
  });
@@ -493,9 +564,49 @@ async function processSearch(apiUrl, args) {
493
564
  throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);
494
565
  }
495
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
+ }
496
604
  function checkSearchArgs(args) {
497
605
  return typeof args === "object" && args !== null && "query" in args && typeof args.query === "string";
498
606
  }
607
+ function checkScrapeArgs(args) {
608
+ return typeof args === "object" && args !== null && "url" in args && typeof args.url === "string";
609
+ }
499
610
  async function runServer() {
500
611
  try {
501
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: 5)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: en)',\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\nif (!SEARCH_API_URL) {\n process.stderr.write('SEARCH_API_URL must be set');\n process.exit(1);\n}\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(SEARCH_API_URL, {\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n return {\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 error: msg,\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 error: error instanceof Error ? error.message : msg,\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(apiUrl: string, args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng':\n return await searxngSearch(apiUrl, {\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n case 'tavily':\n return await tavilySearch(apiUrl, {\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(apiUrl: string, 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 } = params;\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: any) {\n process.stdout.write(err?.message ?? 'Searxng search error.');\n throw err;\n }\n}\n\n\nlet tvly: TavilyClient | null = null;\nexport async function tavilySearch(query: string, options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\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.d.cts CHANGED
@@ -14,11 +14,13 @@ interface ISearchRequestOptions {
14
14
  timeRange?: string;
15
15
  timeout?: number | string;
16
16
  apiKey?: string;
17
+ apiUrl?: string;
17
18
  }
18
19
  interface ISearchResponseResult {
19
20
  title: string;
20
21
  snippet: string;
21
22
  url: string;
23
+ markdown?: string;
22
24
  source?: string;
23
25
  engine?: string;
24
26
  image?: IMediaItem | null;
package/dist/index.d.ts CHANGED
@@ -14,11 +14,13 @@ interface ISearchRequestOptions {
14
14
  timeRange?: string;
15
15
  timeout?: number | string;
16
16
  apiKey?: string;
17
+ apiUrl?: string;
17
18
  }
18
19
  interface ISearchResponseResult {
19
20
  title: string;
20
21
  snippet: string;
21
22
  url: string;
23
+ markdown?: string;
22
24
  source?: string;
23
25
  engine?: string;
24
26
  image?: IMediaItem | null;
package/dist/index.js CHANGED
@@ -3,11 +3,12 @@
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";
9
10
  import { tavily } from "@tavily/core";
10
- async function searxngSearch(apiUrl, params) {
11
+ async function searxngSearch(params) {
11
12
  try {
12
13
  const {
13
14
  query,
@@ -19,11 +20,15 @@ async function searxngSearch(apiUrl, params) {
19
20
  language = "auto",
20
21
  timeRange = "",
21
22
  timeout = 1e4,
22
- apiKey = ""
23
+ apiKey,
24
+ apiUrl
23
25
  } = params;
26
+ if (!apiUrl) {
27
+ throw new Error("SearxNG API URL is required");
28
+ }
24
29
  const controller = new AbortController();
25
30
  const timeoutId = setTimeout(() => controller.abort(), Number(timeout));
26
- const config2 = {
31
+ const config = {
27
32
  q: query,
28
33
  pageno: limit,
29
34
  categories,
@@ -34,7 +39,7 @@ async function searxngSearch(apiUrl, params) {
34
39
  time_range: timeRange
35
40
  };
36
41
  const endpoint = `${apiUrl}/search`;
37
- const queryParams = url.format({ query: config2 });
42
+ const queryParams = url.format({ query: config });
38
43
  const headers = {
39
44
  "Content-Type": "application/json"
40
45
  };
@@ -78,13 +83,15 @@ async function searxngSearch(apiUrl, params) {
78
83
  success: false
79
84
  };
80
85
  } catch (err) {
81
- process.stdout.write(err?.message ?? "Searxng search error.");
86
+ const msg = err instanceof Error ? err.message : "Searxng search error.";
87
+ process.stdout.write(msg);
82
88
  throw err;
83
89
  }
84
90
  }
85
91
  var tvly = null;
86
- async function tavilySearch(query, options) {
92
+ async function tavilySearch(options) {
87
93
  const {
94
+ query,
88
95
  limit = 10,
89
96
  categories = "general",
90
97
  timeRange,
@@ -115,10 +122,7 @@ async function tavilySearch(query, options) {
115
122
  };
116
123
  }
117
124
 
118
- // src/index.ts
119
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
120
- import dotenvx from "@dotenvx/dotenvx";
121
- dotenvx.config();
125
+ // src/tools.ts
122
126
  var SEARCH_TOOL = {
123
127
  name: "one_search",
124
128
  description: "Search and retrieve content from web pages. Returns SERP results by default (url, title, description).",
@@ -131,11 +135,11 @@ var SEARCH_TOOL = {
131
135
  },
132
136
  limit: {
133
137
  type: "number",
134
- description: "Maximum number of results to return (default: 5)"
138
+ description: "Maximum number of results to return (default: 10)"
135
139
  },
136
140
  language: {
137
141
  type: "string",
138
- description: "Language code for search results (default: en)"
142
+ description: "Language code for search results (default: auto)"
139
143
  },
140
144
  categories: {
141
145
  type: "string",
@@ -338,6 +342,28 @@ var EXTRACT_TOOL = {
338
342
  required: ["urls"]
339
343
  }
340
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
+ });
341
367
  var server = new Server(
342
368
  {
343
369
  name: "one-search-mcp",
@@ -350,22 +376,7 @@ var server = new Server(
350
376
  }
351
377
  }
352
378
  );
353
- var SEARCH_API_URL = process.env.SEARCH_API_URL;
354
- var SEARCH_API_KEY = process.env.SEARCH_API_KEY;
355
- var SEARCH_PROVIDER = process.env.SEARCH_PROVIDER ?? "searxng";
356
- if (!SEARCH_API_URL) {
357
- process.stderr.write("SEARCH_API_URL must be set");
358
- process.exit(1);
359
- }
360
- var SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;
361
- var LIMIT = process.env.LIMIT ?? 10;
362
- var CATEGORIES = process.env.CATEGORIES ?? "general";
363
- var ENGINES = process.env.ENGINES ?? "all";
364
- var FORMAT = process.env.FORMAT ?? "json";
365
- var LANGUAGE = process.env.LANGUAGE ?? "auto";
366
- var TIME_RANGE = process.env.TIME_RANGE ?? "";
367
- var DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 1e4;
368
- var config = {
379
+ var searchConfig = {
369
380
  pageno: LIMIT,
370
381
  categories: CATEGORIES,
371
382
  format: FORMAT,
@@ -399,15 +410,26 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
399
410
  throw new Error(`Invalid arguments for tool: [${name}]`);
400
411
  }
401
412
  try {
402
- const { results, success } = await processSearch(SEARCH_API_URL, {
403
- ...config,
413
+ const { results, success } = await processSearch({
414
+ ...searchConfig,
404
415
  ...args,
405
- apiKey: SEARCH_API_KEY ?? ""
416
+ apiKey: SEARCH_API_KEY ?? "",
417
+ apiUrl: SEARCH_API_URL ?? ""
406
418
  });
407
419
  if (!success) {
408
420
  throw new Error("Failed to search");
409
421
  }
422
+ const resultsText = results.map((result) => `Title: ${result.title}
423
+ URL: ${result.url}
424
+ Description: ${result.snippet}
425
+ ${result.markdown ? `Content: ${result.markdown}` : ""}`);
410
426
  return {
427
+ content: [
428
+ {
429
+ type: "text",
430
+ text: resultsText.join("\n\n")
431
+ }
432
+ ],
411
433
  results,
412
434
  success
413
435
  };
@@ -419,12 +441,56 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
419
441
  const msg = error instanceof Error ? error.message : "Unknown error";
420
442
  return {
421
443
  success: false,
422
- error: msg
444
+ content: [
445
+ {
446
+ type: "text",
447
+ text: msg
448
+ }
449
+ ]
423
450
  };
424
451
  }
425
452
  }
426
- 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: {
427
492
  throw new Error(`Unknown tool: ${name}`);
493
+ }
428
494
  }
429
495
  } catch (error) {
430
496
  const msg = error instanceof Error ? error.message : String(error);
@@ -440,7 +506,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
440
506
  });
441
507
  return {
442
508
  success: false,
443
- error: error instanceof Error ? error.message : msg
509
+ content: [
510
+ {
511
+ type: "text",
512
+ text: msg
513
+ }
514
+ ]
444
515
  };
445
516
  } finally {
446
517
  server.sendLoggingMessage({
@@ -449,17 +520,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
449
520
  });
450
521
  }
451
522
  });
452
- async function processSearch(apiUrl, args) {
523
+ async function processSearch(args) {
453
524
  switch (SEARCH_PROVIDER) {
454
525
  case "searxng":
455
- return await searxngSearch(apiUrl, {
456
- ...config,
526
+ return await searxngSearch({
527
+ ...searchConfig,
457
528
  ...args,
458
529
  apiKey: SEARCH_API_KEY
459
530
  });
460
531
  case "tavily":
461
- return await tavilySearch(apiUrl, {
462
- ...config,
532
+ return await tavilySearch({
533
+ ...searchConfig,
463
534
  ...args,
464
535
  apiKey: SEARCH_API_KEY
465
536
  });
@@ -467,9 +538,49 @@ async function processSearch(apiUrl, args) {
467
538
  throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);
468
539
  }
469
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
+ }
470
578
  function checkSearchArgs(args) {
471
579
  return typeof args === "object" && args !== null && "query" in args && typeof args.query === "string";
472
580
  }
581
+ function checkScrapeArgs(args) {
582
+ return typeof args === "object" && args !== null && "url" in args && typeof args.url === "string";
583
+ }
473
584
  async function runServer() {
474
585
  try {
475
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: 5)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: en)',\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\nif (!SEARCH_API_URL) {\n process.stderr.write('SEARCH_API_URL must be set');\n process.exit(1);\n}\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(SEARCH_API_URL, {\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n return {\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 error: msg,\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 error: error instanceof Error ? error.message : msg,\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(apiUrl: string, args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng':\n return await searxngSearch(apiUrl, {\n ...config,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n case 'tavily':\n return await tavilySearch(apiUrl, {\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(apiUrl: string, 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 } = params;\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: any) {\n process.stdout.write(err?.message ?? 'Searxng search error.');\n throw err;\n }\n}\n\n\nlet tvly: TavilyClient | null = null;\nexport async function tavilySearch(query: string, options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\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":"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","names":["startTime","url"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-search-mcp",
3
- "version": "1.0.1",
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",
@@ -43,7 +43,7 @@
43
43
  "start": "node dist/index.js",
44
44
  "lint": "eslint src",
45
45
  "lint:fix": "eslint src --fix",
46
- "publish": "npm run build && npm publish --registry=https://registry.npmjs.org/"
46
+ "publish": "npm publish --registry=https://registry.npmjs.org/"
47
47
  },
48
48
  "tsup": {
49
49
  "entry": [
@@ -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
  }