@oevortex/ddg_search 1.1.9 → 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 +36 -10
- package/README.md +14 -3
- package/babel.config.js +12 -0
- package/bin/cli.js +14 -8
- package/package.json +14 -3
- package/src/index.js +6 -1
- package/src/index.ts +6 -1
- package/src/tools/braveTool.js +63 -0
- package/src/tools/searchTool.js +40 -40
- package/src/utils/search.js +175 -120
- package/src/utils/search_brave_ai.js +167 -0
- package/src/utils/search_iask.js +170 -116
- package/src/utils/search_monica.js +127 -16
- package/test.setup.js +120 -0
- package/oevortex-ddg_search-1.1.9.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,39 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
## [1.1
|
|
5
|
-
###
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
11
37
|
### Added
|
|
12
38
|
- Added new `getRandomUserAgent` function to rotate user agents
|
|
13
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 &
|
|
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
|
|
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 &
|
|
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
ADDED
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 &
|
|
22
|
-
description: 'A Model Context Protocol server for web search using DuckDuckGo, IAsk AI and
|
|
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 &
|
|
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 &
|
|
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 &
|
|
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 &
|
|
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.1
|
|
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",
|
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
"oevortex-ddg-search": "bin/cli.js"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
|
-
"test": "
|
|
18
|
+
"test": "jest",
|
|
19
|
+
"test:watch": "jest --watch",
|
|
20
|
+
"test:coverage": "jest --coverage",
|
|
21
|
+
"test:unit": "jest --testPathPattern=src/__tests__/utils",
|
|
22
|
+
"test:integration": "jest --testPathPattern=src/__tests__/mcp-integration",
|
|
23
|
+
"test:tools": "jest --testPathPattern=src/__tests__/tools",
|
|
24
|
+
"test:all": "jest --coverage --verbose",
|
|
19
25
|
"start": "node bin/cli.js",
|
|
20
26
|
"prepublishOnly": "npm run lint",
|
|
21
27
|
"lint": "echo \"No linting configured\"",
|
|
@@ -51,8 +57,13 @@
|
|
|
51
57
|
"ws": "^8.18.3"
|
|
52
58
|
},
|
|
53
59
|
"devDependencies": {
|
|
60
|
+
"@babel/core": "^7.28.5",
|
|
61
|
+
"@babel/preset-env": "^7.28.5",
|
|
62
|
+
"@jest/globals": "^29.7.0",
|
|
54
63
|
"@types/node": "^24.3.0",
|
|
64
|
+
"babel-jest": "^29.7.0",
|
|
65
|
+
"jest": "^29.7.0",
|
|
55
66
|
"tsx": "^4.20.4",
|
|
56
67
|
"typescript": "^5.9.2"
|
|
57
68
|
}
|
|
58
|
-
}
|
|
69
|
+
}
|
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
|
+
}
|
package/src/tools/searchTool.js
CHANGED
|
@@ -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
|
+
}
|