@oevortex/ddg_search 1.2.0 → 1.2.1

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/CHANGELOG.md CHANGED
@@ -1,29 +1,39 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
- ## [1.2.0] - 2025-12-21
5
- ### Added
6
- - Comprehensive Jest testing framework with ES module support
7
- - Complete unit test suite for all utility functions (search, user_agents, search_iask, search_monica)
8
- - Integration tests for MCP server functionality and tool routing
9
- - Test infrastructure with mocking for all external dependencies
10
- - Input validation across all search modules and tools
11
- - Enhanced error handling with specific network error types
12
- - Performance optimizations with timeout management and caching
13
- - Improved logging and monitoring capabilities
14
- - Fixed JSON parsing error in searchTool handler (1.1.9 regression)
15
- - Updated package.json with comprehensive test scripts
16
- - Added Babel configuration for test compatibility
17
-
18
- ### Improved
19
- - Search module robustness with AbortController and timeout management
20
- - IAsk AI WebSocket connection handling with enhanced error reporting
21
- - Monica AI stream processing with improved validation
22
- - Tool schema validation with comprehensive parameter checking
23
- - User agent rotation consistency and logging
24
- - Cache management with hit detection and size controls
25
-
26
- ## [1.1.9] - 2025-12-21
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ ## [1.2.1] - 2026-01-19
5
+ ### Added
6
+ - Brave AI Search provider and tool with research mode toggle
7
+ - Brave AI search utility with streaming response parsing
8
+ - Brave AI tool tests and MCP integration coverage
9
+ - Updated CLI help text and README documentation for Brave AI
10
+
11
+ ### Changed
12
+ - Server and CLI tool registry to include brave-search
13
+
14
+ ## [1.2.0] - 2025-12-21
15
+ ### Added
16
+ - Comprehensive Jest testing framework with ES module support
17
+ - Complete unit test suite for all utility functions (search, user_agents, search_iask, search_monica)
18
+ - Integration tests for MCP server functionality and tool routing
19
+ - Test infrastructure with mocking for all external dependencies
20
+ - Input validation across all search modules and tools
21
+ - Enhanced error handling with specific network error types
22
+ - Performance optimizations with timeout management and caching
23
+ - Improved logging and monitoring capabilities
24
+ - Fixed JSON parsing error in searchTool handler (1.1.9 regression)
25
+ - Updated package.json with comprehensive test scripts
26
+ - Added Babel configuration for test compatibility
27
+
28
+ ### Improved
29
+ - Search module robustness with AbortController and timeout management
30
+ - IAsk AI WebSocket connection handling with enhanced error reporting
31
+ - Monica AI stream processing with improved validation
32
+ - Tool schema validation with comprehensive parameter checking
33
+ - User agent rotation consistency and logging
34
+ - Cache management with hit detection and size controls
35
+
36
+ ## [1.1.9] - 2025-12-21
27
37
  ### Added
28
38
  - Added new `getRandomUserAgent` function to rotate user agents
29
39
  - Added new `src/utils/user_agents.js` file containing list of user agents
package/README.md CHANGED
@@ -8,10 +8,10 @@
8
8
  <a href="https://youtube.com/@OEvortex">
9
9
  <img src="https://img.shields.io/badge/YouTube-%40OEvortex-red.svg" alt="YouTube Channel" />
10
10
  </a>
11
- <h1>DuckDuckGo, IAsk AI & Monica Search MCP <span style="font-size:2.2rem;">🔍🧠</span></h1>
11
+ <h1>DuckDuckGo, IAsk AI, Monica & Brave AI Search MCP <span style="font-size:2.2rem;">🔍🧠</span></h1>
12
12
  <p style="font-size:1.15rem; max-width:600px; margin:0 auto;">
13
13
  <strong>Lightning-fast, privacy-first Model Context Protocol (MCP) server for web search and AI-powered answers.<br>
14
- Powered by DuckDuckGo, IAsk AI and Monica.</strong>
14
+ Powered by DuckDuckGo, IAsk AI, Monica, and Brave AI.</strong>
15
15
  </p>
16
16
  <a href="https://glama.ai/mcp/servers/@OEvortex/ddg_search">
17
17
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@OEvortex/ddg_search/badge" alt="DuckDuckGo Search MCP server" />
@@ -30,7 +30,7 @@
30
30
  ## ✨ Features
31
31
 
32
32
  <div style="display: flex; flex-wrap: wrap; gap: 1.5em; margin-bottom: 1.5em;"> <div><b>🌐 Web search</b> using DuckDuckGo HTML</div>
33
- <div><b>🧠 AI search</b> using IAsk AI & Monica</div>
33
+ <div><b>🧠 AI search</b> using IAsk AI, Monica & Brave AI</div>
34
34
  <div><b>⚡ Performance optimized</b> with caching</div>
35
35
  <div><b>🛡️ Security features</b> including rate limiting and rotating user agents</div>
36
36
  <div><b>🔌 MCP-compliant</b> server implementation</div>
@@ -211,6 +211,15 @@ Or if installed globally:
211
211
  </ul>
212
212
  <i>Example: Search Monica AI for "Latest advancements in AI"</i>
213
213
  </div>
214
+ <div style="margin-bottom: 1.5em;">
215
+ <b>🛡️ Brave AI Search Tool</b><br/>
216
+ <code>brave-search</code><br/>
217
+ <ul>
218
+ <li><b>query</b> (string, required): The search query or question</li>
219
+ <li><b>enableResearch</b> (boolean, optional, default: false): Enable deep research mode</li>
220
+ </ul>
221
+ <i>Example: Search Brave AI for "Summarize the latest AI safety research"</i>
222
+ </div>
214
223
  </div>
215
224
 
216
225
  ---
@@ -226,11 +235,13 @@ src/
226
235
  searchTool.js
227
236
  iaskTool.js
228
237
  monicaTool.js
238
+ braveTool.js
229
239
  utils/
230
240
  search.js # Search and URL utilities
231
241
  user_agents.js
232
242
  search_monica.js
233
243
  search_iask.js # IAsk AI search utilities
244
+ search_brave_ai.js
234
245
  package.json
235
246
  README.md
236
247
  ```
package/babel.config.js CHANGED
@@ -1,12 +1,12 @@
1
- module.exports = {
2
- presets: [
3
- [
4
- '@babel/preset-env',
5
- {
6
- targets: {
7
- node: 'current'
8
- }
9
- }
10
- ]
11
- ]
1
+ module.exports = {
2
+ presets: [
3
+ [
4
+ '@babel/preset-env',
5
+ {
6
+ targets: {
7
+ node: 'current'
8
+ }
9
+ }
10
+ ]
11
+ ]
12
12
  };
package/bin/cli.js CHANGED
@@ -14,12 +14,13 @@ async function startServer() {
14
14
  const { searchToolDefinition, searchToolHandler } = await import(`${modulePath}/tools/searchTool.js`);
15
15
  const { iaskToolDefinition, iaskToolHandler } = await import(`${modulePath}/tools/iaskTool.js`);
16
16
  const { monicaToolDefinition, monicaToolHandler } = await import(`${modulePath}/tools/monicaTool.js`);
17
+ const { braveToolDefinition, braveToolHandler } = await import(`${modulePath}/tools/braveTool.js`);
17
18
 
18
19
  // Create the MCP server
19
20
  const server = new Server({
20
21
  id: 'ddg-search-mcp',
21
- name: 'DuckDuckGo, IAsk AI & Monica Search MCP',
22
- description: 'A Model Context Protocol server for web search using DuckDuckGo, IAsk AI and Monica',
22
+ name: 'DuckDuckGo, IAsk AI, Monica & Brave AI Search MCP',
23
+ description: 'A Model Context Protocol server for web search using DuckDuckGo, IAsk AI, Monica, and Brave AI',
23
24
  version: '1.1.8'
24
25
  }, {
25
26
  capabilities: {
@@ -33,7 +34,8 @@ async function startServer() {
33
34
  let availableTools = [
34
35
  searchToolDefinition,
35
36
  iaskToolDefinition,
36
- monicaToolDefinition
37
+ monicaToolDefinition,
38
+ braveToolDefinition
37
39
  ];
38
40
 
39
41
  // Define available tools
@@ -56,7 +58,7 @@ async function startServer() {
56
58
  const { name, arguments: args } = request.params;
57
59
 
58
60
  // Validate tool name
59
- const validTools = ['web-search', 'iask-search', 'monica-search'];
61
+ const validTools = ['web-search', 'iask-search', 'monica-search', 'brave-search'];
60
62
  if (!validTools.includes(name)) {
61
63
  throw new Error(`Unknown tool: ${name}`);
62
64
  }
@@ -72,6 +74,9 @@ async function startServer() {
72
74
  case 'monica-search':
73
75
  return await monicaToolHandler(args);
74
76
 
77
+ case 'brave-search':
78
+ return await braveToolHandler(args);
79
+
75
80
  default:
76
81
  throw new Error(`Tool not found: ${name}`);
77
82
  }
@@ -92,7 +97,7 @@ async function startServer() {
92
97
  }); // Display promotional message
93
98
  console.error('\n\x1b[36m╔════════════════════════════════════════════════════════════╗');
94
99
  console.error('║ ║');
95
- console.error('║ \x1b[1m\x1b[31mDuckDuckGo & IAsk AI Search MCP\x1b[0m\x1b[36m by \x1b[1m\x1b[33m@OEvortex\x1b[0m\x1b[36m ║');
100
+ console.error('║ \x1b[1m\x1b[31mDuckDuckGo & AI Search MCP\x1b[0m\x1b[36m by \x1b[1m\x1b[33m@OEvortex\x1b[0m\x1b[36m ║');
96
101
  console.error('║ ║');
97
102
  console.error('║ \x1b[0m👉 Subscribe to \x1b[1m\x1b[37myoutube.com/@OEvortex\x1b[0m\x1b[36m for more tools! ║');
98
103
  console.error('║ ║');
@@ -101,7 +106,7 @@ async function startServer() {
101
106
  // Start the server with stdio transport
102
107
  const transport = new StdioServerTransport();
103
108
  await server.connect(transport);
104
- console.error('DuckDuckGo, IAsk AI & Monica Search MCP server started and listening on stdio');
109
+ console.error('DuckDuckGo, IAsk AI, Monica & Brave AI Search MCP server started and listening on stdio');
105
110
  } catch (error) {
106
111
  console.error('Failed to start server:', error);
107
112
  process.exit(1);
@@ -115,7 +120,7 @@ const versionFlag = args.includes('--version') || args.includes('-v');
115
120
 
116
121
  if (helpFlag) {
117
122
  console.log(`
118
- DuckDuckGo, IAsk AI & Monica Search MCP - A Model Context Protocol server for web search
123
+ DuckDuckGo, IAsk AI, Monica & Brave AI Search MCP - A Model Context Protocol server for web search
119
124
 
120
125
  Usage:
121
126
  npx -y @oevortex/ddg_search@latest [options]
@@ -128,6 +133,7 @@ This MCP server provides the following tools:
128
133
  - web-search: Search the web using DuckDuckGo
129
134
  - iask-search: Search using IAsk AI for AI-generated responses
130
135
  - monica-search: Search using Monica AI for AI-generated responses
136
+ - brave-search: Search using Brave AI for AI-generated responses
131
137
 
132
138
  Created by @OEvortex
133
139
  Subscribe to youtube.com/@OEvortex for more tools and tutorials!
@@ -145,7 +151,7 @@ if (versionFlag) {
145
151
  const packageJson = JSON.parse(
146
152
  await readFile(new URL('../package.json', import.meta.url), 'utf8')
147
153
  );
148
- console.log(`DuckDuckGo & IAsk AI Search MCP v${packageJson.version}\nCreated by @OEvortex - Subscribe to youtube.com/@OEvortex!`);
154
+ console.log(`DuckDuckGo & AI Search MCP v${packageJson.version}\nCreated by @OEvortex - Subscribe to youtube.com/@OEvortex!`);
149
155
  process.exit(0);
150
156
  } catch (err) {
151
157
  console.error('Error reading version information:', err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oevortex/ddg_search",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "A Model Context Protocol server for web search using DuckDuckGo and IAsk AI",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.ts",
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
5
5
  import { searchToolDefinition, searchToolHandler } from './tools/searchTool.js';
6
6
  import { iaskToolDefinition, iaskToolHandler } from './tools/iaskTool.js';
7
7
  import { monicaToolDefinition, monicaToolHandler } from './tools/monicaTool.js';
8
+ import { braveToolDefinition, braveToolHandler } from './tools/braveTool.js';
8
9
 
9
10
  // Required: Export default createServer function for Smithery
10
11
  export default function createServer({ config } = {}) {
@@ -14,7 +15,8 @@ export default function createServer({ config } = {}) {
14
15
  const availableTools = [
15
16
  searchToolDefinition,
16
17
  iaskToolDefinition,
17
- monicaToolDefinition
18
+ monicaToolDefinition,
19
+ braveToolDefinition
18
20
  ];
19
21
 
20
22
  console.log('Available tools:', availableTools.map(t => t.name));
@@ -56,6 +58,9 @@ export default function createServer({ config } = {}) {
56
58
  case 'monica-search':
57
59
  return await monicaToolHandler(args);
58
60
 
61
+ case 'brave-search':
62
+ return await braveToolHandler(args);
63
+
59
64
  default:
60
65
  throw new Error(`Tool not found: ${name}`);
61
66
  }
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
5
5
  import { searchToolDefinition, searchToolHandler } from './tools/searchTool.js';
6
6
  import { iaskToolDefinition, iaskToolHandler } from './tools/iaskTool.js';
7
7
  import { monicaToolDefinition, monicaToolHandler } from './tools/monicaTool.js';
8
+ import { braveToolDefinition, braveToolHandler } from './tools/braveTool.js';
8
9
 
9
10
  // Required: Export default createServer function for Smithery
10
11
  export default function createServer({ config }: { config?: any } = {}) {
@@ -14,7 +15,8 @@ export default function createServer({ config }: { config?: any } = {}) {
14
15
  const availableTools = [
15
16
  searchToolDefinition,
16
17
  iaskToolDefinition,
17
- monicaToolDefinition
18
+ monicaToolDefinition,
19
+ braveToolDefinition
18
20
  ];
19
21
 
20
22
  console.log('Available tools:', availableTools.map(t => t.name));
@@ -56,6 +58,9 @@ export default function createServer({ config }: { config?: any } = {}) {
56
58
  case 'monica-search':
57
59
  return await monicaToolHandler(args);
58
60
 
61
+ case 'brave-search':
62
+ return await braveToolHandler(args);
63
+
59
64
  default:
60
65
  throw new Error(`Tool not found: ${name}`);
61
66
  }
@@ -0,0 +1,63 @@
1
+ import { searchBraveAI } from '../utils/search_brave_ai.js';
2
+
3
+ /**
4
+ * Brave AI search tool definition
5
+ */
6
+ export const braveToolDefinition = {
7
+ name: 'brave-search',
8
+ title: 'Brave AI Search',
9
+ description: 'AI-powered search using Brave Search AI Chat. Returns AI-generated responses based on web content.',
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ query: {
14
+ type: 'string',
15
+ description: 'The search query or question.'
16
+ },
17
+ enableResearch: {
18
+ type: 'boolean',
19
+ description: 'Enable deep research mode for more comprehensive responses.',
20
+ default: false
21
+ }
22
+ },
23
+ required: ['query']
24
+ },
25
+ annotations: {
26
+ readOnlyHint: true,
27
+ openWorldHint: false
28
+ }
29
+ };
30
+
31
+ /**
32
+ * Brave AI search tool handler
33
+ * @param {Object} params - The tool parameters
34
+ * @returns {Promise<Object>} - The tool result
35
+ */
36
+ export async function braveToolHandler(params) {
37
+ const { query, enableResearch = false } = params;
38
+
39
+ console.log(`Searching Brave AI for: "${query}" (research: ${enableResearch})`);
40
+
41
+ try {
42
+ const result = await searchBraveAI(query, { enableResearch });
43
+ return {
44
+ content: [
45
+ {
46
+ type: 'text',
47
+ text: result || 'No results found.'
48
+ }
49
+ ]
50
+ };
51
+ } catch (error) {
52
+ console.error(`Error in Brave AI search: ${error.message}`);
53
+ return {
54
+ isError: true,
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: `Error searching Brave AI: ${error.message}`
59
+ }
60
+ ]
61
+ };
62
+ }
63
+ }
@@ -37,43 +37,43 @@ export const searchToolDefinition = {
37
37
  * @param {Object} params - The tool parameters
38
38
  * @returns {Promise<Object>} - The tool result
39
39
  */
40
- export async function searchToolHandler(params) {
41
- const { query, numResults = 3, mode = 'short' } = params;
42
- console.log(`Searching for: ${query} (${numResults} results, mode: ${mode})`);
43
-
44
- const results = await searchDuckDuckGo(query, numResults, mode);
45
- console.log(`Found ${results.length} results`);
46
-
47
- // Format results as readable text, similar to other search tools
48
- const formattedResults = results.map((result, index) => {
49
- let formatted = `${index + 1}. **${result.title}**\n`;
50
- formatted += `URL: ${result.url}\n`;
51
-
52
- if (result.displayUrl) {
53
- formatted += `Display URL: ${result.displayUrl}\n`;
54
- }
55
-
56
- if (result.snippet) {
57
- formatted += `Snippet: ${result.snippet}\n`;
58
- }
59
-
60
- if (mode === 'detailed' && result.description) {
61
- formatted += `Content: ${result.description}\n`;
62
- }
63
-
64
- if (result.favicon) {
65
- formatted += `Favicon: ${result.favicon}\n`;
66
- }
67
-
68
- return formatted;
69
- }).join('\n');
70
-
71
- return {
72
- content: [
73
- {
74
- type: 'text',
75
- text: formattedResults || 'No results found.'
76
- }
77
- ]
78
- };
79
- }
40
+ export async function searchToolHandler(params) {
41
+ const { query, numResults = 3, mode = 'short' } = params;
42
+ console.log(`Searching for: ${query} (${numResults} results, mode: ${mode})`);
43
+
44
+ const results = await searchDuckDuckGo(query, numResults, mode);
45
+ console.log(`Found ${results.length} results`);
46
+
47
+ // Format results as readable text, similar to other search tools
48
+ const formattedResults = results.map((result, index) => {
49
+ let formatted = `${index + 1}. **${result.title}**\n`;
50
+ formatted += `URL: ${result.url}\n`;
51
+
52
+ if (result.displayUrl) {
53
+ formatted += `Display URL: ${result.displayUrl}\n`;
54
+ }
55
+
56
+ if (result.snippet) {
57
+ formatted += `Snippet: ${result.snippet}\n`;
58
+ }
59
+
60
+ if (mode === 'detailed' && result.description) {
61
+ formatted += `Content: ${result.description}\n`;
62
+ }
63
+
64
+ if (result.favicon) {
65
+ formatted += `Favicon: ${result.favicon}\n`;
66
+ }
67
+
68
+ return formatted;
69
+ }).join('\n');
70
+
71
+ return {
72
+ content: [
73
+ {
74
+ type: 'text',
75
+ text: formattedResults || 'No results found.'
76
+ }
77
+ ]
78
+ };
79
+ }