@oevortex/ddg_search 1.1.2 → 1.1.4

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 ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.1.3] - 2025-11-30
6
+ ### Changed
7
+ - Replaced Felo AI tool with IAsk AI tool for advanced AI-powered search
8
+ - Added `src/utils/search_iask.js` implementing IAsk API client
9
+ - Added `src/tools/iaskTool.js` tool definition and handler
10
+ - Updated `src/index.ts` to use IAsk tool instead of Felo
11
+ - Updated `package.json` description, keywords, and dependencies (`turndown`, `ws`)
12
+ - Updated `README.md` to reference IAsk AI and document new tool parameters
13
+ - Removed old Felo tool files (`feloTool.js`, `search_felo.js`)
14
+
15
+ ## [1.1.2] - 2025-11-29
16
+ ### Added
17
+ - Initial release with DuckDuckGo and Felo AI search tools
18
+ - MCP server implementation
19
+ - Caching, rotating user agents, and web scraping features
package/Dockerfile CHANGED
@@ -1,20 +1,26 @@
1
- # Use official Node.js LTS image
2
- FROM node:20-alpine
3
-
4
- # Set working directory
1
+ # Build stage: install dependencies
2
+ FROM node:22-slim AS build
5
3
  WORKDIR /app
6
4
 
7
- # Copy package.json and package-lock.json
8
- COPY package*.json ./
5
+ # Copy package manifests and lockfile first for better caching
6
+ COPY package.json package-lock.json ./
9
7
 
10
- # Install dependencies
11
- RUN npm install --production
8
+ # Install production dependencies (use npm ci when lockfile exists)
9
+ RUN if [ -f package-lock.json ]; then npm ci --production; else npm install --production; fi
12
10
 
13
- # Copy source code
11
+ # Copy application source
14
12
  COPY . .
15
13
 
16
- # Expose port (if your app listens on a port, e.g. 3000)
14
+ # Final minimal runtime image
15
+ FROM node:22-slim AS runtime
16
+ WORKDIR /app
17
+
18
+ # Copy node_modules and built app from build stage
19
+ COPY --from=build /app/node_modules ./node_modules
20
+ COPY --from=build /app .
21
+
22
+ # Expose port in case the MCP server needs it
17
23
  EXPOSE 3000
18
24
 
19
- # Default command (adjust if your entry point is different)
20
- CMD ["node", "src/index.js"]
25
+ # Default command: use the CLI entry which starts the MCP server
26
+ CMD ["node", "bin/cli.js"]
package/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
  <img src="https://img.shields.io/npm/v/@oevortex/ddg_search.svg" alt="npm version" />
3
3
  <img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License: Apache 2.0" />
4
4
  <img src="https://img.shields.io/badge/YouTube-%40OEvortex-red.svg" alt="YouTube Channel" />
5
- <h1>DuckDuckGo & Felo AI Search MCP 🔍🧠</h1>
6
- <p>A blazing-fast, privacy-friendly Model Context Protocol (MCP) server for web search and AI-powered responses using DuckDuckGo and Felo AI.</p>
5
+ <h1>DuckDuckGo & IAsk AI Search MCP 🔍🧠</h1>
6
+ <p>A blazing-fast, privacy-friendly Model Context Protocol (MCP) server for web search and AI-powered responses using DuckDuckGo and IAsk AI.</p>
7
7
  <a href="https://glama.ai/mcp/servers/@OEvortex/ddg_search">
8
8
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@OEvortex/ddg_search/badge" alt="DuckDuckGo Search MCP server" />
9
9
  </a>
@@ -20,9 +20,7 @@
20
20
  ## ✨ Features
21
21
 
22
22
  <div style="display: flex; flex-wrap: wrap; gap: 1.5em; margin-bottom: 1.5em;"> <div><b>🌐 Web search</b> using DuckDuckGo HTML</div>
23
- <div><b>🧠 AI search</b> using Felo AI</div>
24
- <div><b>📄 URL content extraction</b> with smart filtering</div>
25
- <div><b>📊 URL metadata extraction</b> (title, description, images)</div>
23
+ <div><b>🧠 AI search</b> using IAsk AI</div>
26
24
  <div><b>⚡ Performance optimized</b> with caching</div>
27
25
  <div><b>🛡️ Security features</b> including rate limiting and rotating user agents</div>
28
26
  <div><b>🔌 MCP-compliant</b> server implementation</div>
@@ -52,7 +50,7 @@ npx -y @oevortex/ddg_search@latest
52
50
  ## 🛠️ Installation Options
53
51
 
54
52
  <details>
55
- <summary><b>Global Installation</b></summary>
53
+ <summary><b>Global Installation (npm)</b></summary>
56
54
 
57
55
  ```bash
58
56
  npm install -g @oevortex/ddg_search
@@ -66,6 +64,36 @@ ddg-search-mcp
66
64
 
67
65
  </details>
68
66
 
67
+ <details>
68
+ <summary><b>Global Installation (Yarn)</b></summary>
69
+
70
+ ```bash
71
+ yarn global add @oevortex/ddg_search
72
+ ```
73
+
74
+ Run globally:
75
+
76
+ ```bash
77
+ ddg-search-mcp
78
+ ```
79
+
80
+ </details>
81
+
82
+ <details>
83
+ <summary><b>Global Installation (pnpm)</b></summary>
84
+
85
+ ```bash
86
+ pnpm add -g @oevortex/ddg_search
87
+ ```
88
+
89
+ Run globally:
90
+
91
+ ```bash
92
+ ddg-search-mcp
93
+ ```
94
+
95
+ </details>
96
+
69
97
  <details>
70
98
  <summary><b>Local Installation (Development)</b></summary>
71
99
 
@@ -76,6 +104,20 @@ npm install
76
104
  npm start
77
105
  ```
78
106
 
107
+ Or with Yarn:
108
+
109
+ ```bash
110
+ yarn install
111
+ yarn start
112
+ ```
113
+
114
+ Or with pnpm:
115
+
116
+ ```bash
117
+ pnpm install
118
+ pnpm start
119
+ ```
120
+
79
121
  </details>
80
122
 
81
123
  ---
@@ -140,34 +182,15 @@ Or if installed globally:
140
182
  <i>Example: Search the web for "climate change solutions"</i>
141
183
  </div>
142
184
  <div style="margin-bottom: 1.5em;">
143
- <b>🧠 Felo AI Search Tool</b><br/>
144
- <code>felo-search</code><br/>
185
+ <b>🧠 IAsk AI Search Tool</b><br/>
186
+ <code>iask-search</code><br/>
145
187
  <ul>
146
- <li><b>query</b> (string, required): The search query or prompt</li>
188
+ <li><b>query</b> (string, required): The search query or question</li>
189
+ <li><b>mode</b> (string, optional, default: "question"): Search mode - "question", "academic", "forums", "wiki", or "thinking"</li>
190
+ <li><b>detailLevel</b> (string, optional): Response detail level - "concise", "detailed", or "comprehensive"</li>
147
191
  <li><b>stream</b> (boolean, optional, default: false): Whether to stream the response</li>
148
192
  </ul>
149
- <i>Example: Search Felo AI for "Explain quantum computing in simple terms"</i>
150
- </div>
151
- <div style="margin-bottom: 1.5em;">
152
- <b>📄 Fetch URL Tool</b><br/>
153
- <code>fetch-url</code><br/>
154
- <ul>
155
- <li><b>url</b> (string, required): The URL to fetch</li>
156
- <li><b>maxLength</b> (integer, optional, default: 10000): Max content length</li>
157
- <li><b>extractMainContent</b> (boolean, optional, default: true): Extract main content</li>
158
- <li><b>includeLinks</b> (boolean, optional, default: true): Include link text</li>
159
- <li><b>includeImages</b> (boolean, optional, default: true): Include image alt text</li>
160
- <li><b>excludeTags</b> (array, optional): Tags to exclude</li>
161
- </ul>
162
- <i>Example: Fetch the content from "https://example.com"</i>
163
- </div>
164
- <div style="margin-bottom: 1.5em;">
165
- <b>📊 URL Metadata Tool</b><br/>
166
- <code>url-metadata</code><br/>
167
- <ul>
168
- <li><b>url</b> (string, required): The URL to extract metadata from</li>
169
- </ul>
170
- <i>Example: Get metadata for "https://example.com"</i>
193
+ <i>Example: Search IAsk AI for "Explain quantum computing in simple terms"</i>
171
194
  </div>
172
195
  </div>
173
196
 
@@ -182,12 +205,10 @@ src/
182
205
  index.js # Main entry point
183
206
  tools/ # Tool definitions and handlers
184
207
  searchTool.js
185
- fetchUrlTool.js
186
- metadataTool.js
187
- feloTool.js
208
+ iaskTool.js
188
209
  utils/
189
210
  search.js # Search and URL utilities
190
- search_felo.js # Felo AI search utilities
211
+ search_iask.js # IAsk AI search utilities
191
212
  package.json
192
213
  README.md
193
214
  ```
@@ -227,4 +248,4 @@ Apache License 2.0
227
248
 
228
249
  <div align="center">
229
250
  <sub>Made with ❤️ by <a href="https://youtube.com/@OEvortex">@OEvortex</a></sub>
230
- </div>
251
+ </div>
package/bin/cli.js CHANGED
@@ -12,48 +12,58 @@ async function startServer() {
12
12
  try {
13
13
  // Dynamically import the modules
14
14
  const { searchToolDefinition, searchToolHandler } = await import(`${modulePath}/tools/searchTool.js`);
15
- const { fetchUrlToolDefinition, fetchUrlToolHandler } = await import(`${modulePath}/tools/fetchUrlTool.js`);
16
- const { metadataToolDefinition, metadataToolHandler } = await import(`${modulePath}/tools/metadataTool.js`);
17
- const { feloToolDefinition, feloToolHandler } = await import(`${modulePath}/tools/feloTool.js`); // Create the MCP server
15
+ const { feloToolDefinition, feloToolHandler } = await import(`${modulePath}/tools/feloTool.js`);
16
+
17
+ // Create the MCP server
18
18
  const server = new Server({
19
19
  id: 'ddg-search-mcp',
20
20
  name: 'DuckDuckGo & Felo AI Search MCP',
21
21
  description: 'A Model Context Protocol server for web search using DuckDuckGo and Felo AI',
22
- version: '1.1.1'
22
+ version: '1.1.2'
23
23
  }, {
24
24
  capabilities: {
25
- tools: {}
25
+ tools: {
26
+ listChanged: true
27
+ }
26
28
  }
27
29
  });
28
30
 
31
+ // Global variable to track available tools
32
+ let availableTools = [
33
+ searchToolDefinition,
34
+ feloToolDefinition
35
+ ];
36
+
29
37
  // Define available tools
30
38
  server.setRequestHandler(ListToolsRequestSchema, async () => {
31
39
  return {
32
- tools: [
33
- searchToolDefinition,
34
- fetchUrlToolDefinition,
35
- metadataToolDefinition,
36
- feloToolDefinition
37
- ]
40
+ tools: availableTools
38
41
  };
39
42
  });
40
43
 
44
+ // Function to notify clients when tools list changes
45
+ function notifyToolsChanged() {
46
+ server.notification({
47
+ method: 'notifications/tools/list_changed'
48
+ });
49
+ }
50
+
41
51
  // Handle tool execution
42
52
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
43
53
  try {
44
54
  const { name, arguments: args } = request.params;
55
+
56
+ // Validate tool name
57
+ const validTools = ['web-search', 'felo-search'];
58
+ if (!validTools.includes(name)) {
59
+ throw new Error(`Unknown tool: ${name}`);
60
+ }
45
61
 
46
62
  // Route to the appropriate tool handler
47
63
  switch (name) {
48
64
  case 'web-search':
49
65
  return await searchToolHandler(args);
50
66
 
51
- case 'fetch-url':
52
- return await fetchUrlToolHandler(args);
53
-
54
- case 'url-metadata':
55
- return await metadataToolHandler(args);
56
-
57
67
  case 'felo-search':
58
68
  return await feloToolHandler(args);
59
69
 
@@ -61,13 +71,15 @@ async function startServer() {
61
71
  throw new Error(`Tool not found: ${name}`);
62
72
  }
63
73
  } catch (error) {
64
- console.error(`Error handling ${request.params.name} request:`, error);
74
+ console.error(`Error handling ${request.params.name} tool call:`, error);
75
+
76
+ // Return proper tool execution error format
65
77
  return {
66
78
  isError: true,
67
79
  content: [
68
80
  {
69
81
  type: 'text',
70
- text: `Error: ${error.message}`
82
+ text: `Error executing tool '${request.params.name}': ${error.message}`
71
83
  }
72
84
  ]
73
85
  };
@@ -109,8 +121,6 @@ Options:
109
121
 
110
122
  This MCP server provides the following tools:
111
123
  - web-search: Search the web using DuckDuckGo
112
- - fetch-url: Fetch and extract content from a URL
113
- - url-metadata: Extract metadata from a URL
114
124
  - felo-search: Search using Felo AI for AI-generated responses
115
125
 
116
126
  Created by @OEvortex
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@oevortex/ddg_search","version":"1.1.2","description":"A Model Context Protocol server for web search using DuckDuckGo and Felo AI","main":"src/index.js","bin":{"ddg-search-mcp":"bin/cli.js","oevortex-ddg-search":"bin/cli.js"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1","start":"node bin/cli.js","prepublishOnly":"npm run lint","lint":"echo \"No linting configured\""},"publishConfig":{"access":"public"},"keywords":["mcp","model-context-protocol","duckduckgo","felo","search","web-search","ai-search","claude","ai","llm"],"author":"OEvortex","license":"Apache-2.0","type":"module","dependencies":{"@modelcontextprotocol/sdk":"^1.9.0","axios":"^1.8.4","cheerio":"^1.0.0","jsdom":"^26.1.0","uuid":"^9.0.1"}}
1
+ {"name":"@oevortex/ddg_search","version":"1.1.4","description":"A Model Context Protocol server for web search using DuckDuckGo and IAsk AI","main":"src/index.js","module":"src/index.ts","exports":{".":{"import":"./src/index.js","default":"./src/index.js"}},"bin":{"ddg-search-mcp":"bin/cli.js","oevortex-ddg-search":"bin/cli.js"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1","start":"node bin/cli.js","prepublishOnly":"npm run lint","lint":"echo \"No linting configured\"","build":"npx @smithery/cli build","dev":"npx @smithery/cli dev"},"publishConfig":{"access":"public"},"keywords":["mcp","model-context-protocol","duckduckgo","iask","search","web-search","ai-search","claude","ai","llm"],"author":"OEvortex","license":"Apache-2.0","type":"module","dependencies":{"@modelcontextprotocol/sdk":"^1.17.4","axios":"^1.8.4","cheerio":"^1.0.0","jsdom":"^26.1.0","smithery":"^0.5.2","turndown":"^7.2.2","uuid":"^9.0.1","ws":"^8.18.3"},"devDependencies":{"@types/node":"^24.3.0","tsx":"^4.20.4","typescript":"^5.9.2"}}
package/smithery.yaml ADDED
@@ -0,0 +1,12 @@
1
+ runtime: typescript
2
+
3
+ build:
4
+ external:
5
+ - canvas
6
+ - utf-8-validate
7
+ - bufferutil
8
+ esbuild:
9
+ bundle: true
10
+ platform: node
11
+ format: cjs
12
+ target: node18
package/src/index.js CHANGED
@@ -1,82 +1,95 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
2
  import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
3
 
5
4
  // Import tool definitions and handlers
6
5
  import { searchToolDefinition, searchToolHandler } from './tools/searchTool.js';
7
- import { fetchUrlToolDefinition, fetchUrlToolHandler } from './tools/fetchUrlTool.js';
8
- import { metadataToolDefinition, metadataToolHandler } from './tools/metadataTool.js';
9
6
  import { feloToolDefinition, feloToolHandler } from './tools/feloTool.js';
10
7
 
11
- // Create the MCP server
12
- const server = new Server({
13
- id: 'ddg-search-mcp',
14
- name: 'DuckDuckGo & Felo AI Search MCP',
15
- description: 'A Model Context Protocol server for web search using DuckDuckGo and Felo AI',
16
- version: '1.1.1'
17
- }, {
18
- capabilities: {
19
- tools: {}
20
- }
21
- });
8
+ // Required: Export default createServer function for Smithery
9
+ export default function createServer({ config } = {}) {
10
+ console.log('Creating MCP server with latest SDK...');
22
11
 
23
- // Define available tools
24
- server.setRequestHandler(ListToolsRequestSchema, async () => {
25
- return {
26
- tools: [
27
- searchToolDefinition,
28
- fetchUrlToolDefinition,
29
- metadataToolDefinition,
30
- feloToolDefinition
31
- ]
32
- };
33
- });
12
+ // Global variable to track available tools
13
+ const availableTools = [
14
+ searchToolDefinition,
15
+ feloToolDefinition
16
+ ];
17
+
18
+ console.log('Available tools:', availableTools.map(t => t.name));
34
19
 
35
- // Handle tool execution
36
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
37
- try {
38
- const { name, arguments: args } = request.params;
39
- // Route to the appropriate tool handler
40
- switch (name) {
41
- case 'web-search':
42
- return await searchToolHandler(args);
43
-
44
- case 'fetch-url':
45
- return await fetchUrlToolHandler(args);
46
-
47
- case 'url-metadata':
48
- return await metadataToolHandler(args);
49
-
50
- case 'felo-search':
51
- return await feloToolHandler(args);
52
-
53
- default:
54
- throw new Error(`Tool not found: ${name}`);
20
+ // Create the MCP server using the Server class
21
+ const server = new Server({
22
+ name: 'ddg-search-mcp',
23
+ version: '1.1.2'
24
+ }, {
25
+ capabilities: {
26
+ tools: {
27
+ listChanged: true
28
+ }
55
29
  }
56
- } catch (error) {
57
- console.error(`Error handling ${request.params.name} request:`, error);
30
+ });
31
+
32
+ // Define available tools
33
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
34
+ console.log('Tools list requested, returning:', availableTools.length, 'tools');
58
35
  return {
59
- isError: true,
60
- content: [
61
- {
62
- type: 'text',
63
- text: `Error: ${error.message}`
64
- }
65
- ]
36
+ tools: availableTools
66
37
  };
67
- }
68
- });
38
+ });
69
39
 
70
- // Start the server with stdio transport
71
- async function main() {
72
- try {
73
- const transport = new StdioServerTransport();
74
- await server.connect(transport);
75
- console.error('WebSearch MCP server started and listening on stdio');
76
- } catch (error) {
77
- console.error('Failed to start server:', error);
78
- process.exit(1);
79
- }
40
+ // Handle tool execution
41
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
42
+ try {
43
+ const { name, arguments: args } = request.params;
44
+ console.log(`Tool call received: ${name} with args:`, args);
45
+
46
+ // Route to the appropriate tool handler
47
+ switch (name) {
48
+ case 'web-search':
49
+ return await searchToolHandler(args);
50
+
51
+ case 'felo-search':
52
+ return await feloToolHandler(args);
53
+
54
+ default:
55
+ throw new Error(`Tool not found: ${name}`);
56
+ }
57
+ } catch (error) {
58
+ console.error(`Error handling ${request.params.name} tool call:`, error);
59
+
60
+ // Return proper tool execution error format
61
+ return {
62
+ isError: true,
63
+ content: [
64
+ {
65
+ type: 'text',
66
+ text: `Error executing tool '${request.params.name}': ${error.message}`
67
+ }
68
+ ]
69
+ };
70
+ }
71
+ });
72
+
73
+ console.log('MCP server created successfully');
74
+
75
+ // Return the server instance (required for Smithery)
76
+ return server;
80
77
  }
81
78
 
82
- main();
79
+ // Legacy standalone server support (for CLI usage)
80
+ if (import.meta.url === `file://${process.argv[1]}`) {
81
+ async function main() {
82
+ try {
83
+ const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
84
+ const server = createServer();
85
+ const transport = new StdioServerTransport();
86
+ await server.connect(transport);
87
+ console.error('WebSearch MCP server started and listening on stdio');
88
+ } catch (error) {
89
+ console.error('Failed to start server:', error);
90
+ process.exit(1);
91
+ }
92
+ }
93
+
94
+ main();
95
+ }
package/src/index.ts ADDED
@@ -0,0 +1,80 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
3
+
4
+ // Import tool definitions and handlers
5
+ import { searchToolDefinition, searchToolHandler } from './tools/searchTool.js';
6
+ import { iaskToolDefinition, iaskToolHandler } from './tools/iaskTool.js';
7
+
8
+ // Required: Export default createServer function for Smithery
9
+ export default function createServer({ config }: { config?: any } = {}) {
10
+ console.log('Creating MCP server with latest SDK...');
11
+
12
+ // Global variable to track available tools
13
+ const availableTools = [
14
+ searchToolDefinition,
15
+ iaskToolDefinition
16
+ ];
17
+
18
+ console.log('Available tools:', availableTools.map(t => t.name));
19
+
20
+ // Create the MCP server using the Server class
21
+ const server = new Server({
22
+ name: 'ddg-search-mcp',
23
+ version: '1.1.2'
24
+ }, {
25
+ capabilities: {
26
+ tools: {
27
+ listChanged: true
28
+ }
29
+ }
30
+ });
31
+
32
+ // Define available tools
33
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
34
+ console.log('Tools list requested, returning:', availableTools.length, 'tools');
35
+ return {
36
+ tools: availableTools
37
+ };
38
+ });
39
+
40
+ // Handle tool execution
41
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
42
+ try {
43
+ const { name, arguments: args } = request.params;
44
+ console.log(`Tool call received: ${name} with args:`, args);
45
+
46
+ // Route to the appropriate tool handler
47
+ switch (name) {
48
+ case 'web-search':
49
+ return await searchToolHandler(args);
50
+
51
+ case 'iask-search':
52
+ return await iaskToolHandler(args);
53
+
54
+ default:
55
+ throw new Error(`Tool not found: ${name}`);
56
+ }
57
+ } catch (error: any) {
58
+ console.error(`Error handling ${request.params.name} tool call:`, error);
59
+
60
+ // Return proper tool execution error format
61
+ return {
62
+ isError: true,
63
+ content: [
64
+ {
65
+ type: 'text',
66
+ text: `Error executing tool '${request.params.name}': ${error.message}`
67
+ }
68
+ ]
69
+ };
70
+ }
71
+ });
72
+
73
+ console.log('MCP server created successfully');
74
+
75
+ // Return the server instance (required for Smithery)
76
+ return server;
77
+ }
78
+
79
+ // Optional: No configuration schema needed for this server
80
+ // export const configSchema = z.object({});
@@ -0,0 +1,101 @@
1
+ import { searchIAsk, VALID_MODES, VALID_DETAIL_LEVELS } from '../utils/search_iask.js';
2
+
3
+ /**
4
+ * IAsk AI search tool definition
5
+ */
6
+ export const iaskToolDefinition = {
7
+ name: 'iask-search',
8
+ title: 'IAsk AI Search',
9
+ description: 'AI-powered search using IAsk.ai. Retrieves comprehensive, AI-generated responses based on web content. Supports different search modes (question, academic, forums, wiki, thinking) and detail levels (concise, detailed, comprehensive). Ideal for getting well-researched answers to complex questions.',
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ query: {
14
+ type: 'string',
15
+ description: 'The search query or question to ask. Supports natural language questions for comprehensive AI-generated responses.'
16
+ },
17
+ mode: {
18
+ type: 'string',
19
+ description: 'Search mode to use. Options: "question" (general questions), "academic" (scholarly/research), "forums" (community discussions), "wiki" (encyclopedia-style), "thinking" (deep analysis). Default is "question".',
20
+ enum: VALID_MODES,
21
+ default: 'question'
22
+ },
23
+ detailLevel: {
24
+ type: 'string',
25
+ description: 'Level of detail in the response. Options: "concise" (brief), "detailed" (moderate), "comprehensive" (extensive). Default is null (standard response).',
26
+ enum: VALID_DETAIL_LEVELS
27
+ },
28
+ stream: {
29
+ type: 'boolean',
30
+ description: 'Enable streaming mode to receive incremental results. Default is false.',
31
+ default: false
32
+ }
33
+ },
34
+ required: ['query']
35
+ },
36
+ annotations: {
37
+ readOnlyHint: true,
38
+ openWorldHint: false
39
+ }
40
+ };
41
+
42
+ /**
43
+ * IAsk AI search tool handler
44
+ * @param {Object} params - The tool parameters
45
+ * @returns {Promise<Object>} - The tool result
46
+ */
47
+ export async function iaskToolHandler(params) {
48
+ const {
49
+ query,
50
+ mode = 'question',
51
+ detailLevel = null,
52
+ stream = false
53
+ } = params;
54
+
55
+ console.log(`Searching IAsk AI for: "${query}" (mode: ${mode}, detailLevel: ${detailLevel || 'default'}, stream: ${stream})`);
56
+
57
+ try {
58
+ if (stream) {
59
+ // For streaming responses, collect them and return
60
+ let fullResponse = '';
61
+ const chunks = [];
62
+
63
+ for await (const chunk of await searchIAsk(query, true, false, mode, detailLevel)) {
64
+ chunks.push(chunk);
65
+ fullResponse += chunk;
66
+ }
67
+
68
+ return {
69
+ content: [
70
+ {
71
+ type: 'text',
72
+ text: fullResponse || 'No results found.'
73
+ }
74
+ ]
75
+ };
76
+ } else {
77
+ // For non-streaming responses
78
+ const response = await searchIAsk(query, false, false, mode, detailLevel);
79
+
80
+ return {
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: response || 'No results found.'
85
+ }
86
+ ]
87
+ };
88
+ }
89
+ } catch (error) {
90
+ console.error(`Error in IAsk search: ${error.message}`);
91
+ return {
92
+ isError: true,
93
+ content: [
94
+ {
95
+ type: 'text',
96
+ text: `Error searching IAsk: ${error.message}`
97
+ }
98
+ ]
99
+ };
100
+ }
101
+ }