@phuetz/code-buddy 0.1.0 → 0.1.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/.codebuddy/skills/bundled/brave-search/SKILL.md +490 -0
- package/.codebuddy/skills/bundled/exa-search/SKILL.md +1122 -0
- package/.codebuddy/skills/bundled/perplexity/SKILL.md +748 -0
- package/.codebuddy/skills/bundled/playwright/SKILL.md +520 -0
- package/.codebuddy/skills/bundled/puppeteer/SKILL.md +708 -0
- package/.codebuddy/skills/bundled/web-fetch/SKILL.md +1003 -0
- package/README.md +56 -0
- package/dist/agent/agent-state.d.ts +3 -3
- package/dist/agent/agent-state.js +6 -6
- package/dist/agent/agent-state.js.map +1 -1
- package/dist/agent/base-agent.d.ts +4 -4
- package/dist/agent/base-agent.js +22 -9
- package/dist/agent/base-agent.js.map +1 -1
- package/dist/agent/cache-trace.d.ts +56 -0
- package/dist/agent/cache-trace.js +98 -0
- package/dist/agent/cache-trace.js.map +1 -0
- package/dist/agent/codebuddy-agent.js +3 -2
- package/dist/agent/codebuddy-agent.js.map +1 -1
- package/dist/agent/execution/agent-executor.d.ts +4 -4
- package/dist/agent/execution/agent-executor.js +41 -7
- package/dist/agent/execution/agent-executor.js.map +1 -1
- package/dist/agent/facades/agent-context-facade.js +1 -3
- package/dist/agent/facades/agent-context-facade.js.map +1 -1
- package/dist/agent/facades/message-history-manager.js +14 -12
- package/dist/agent/facades/message-history-manager.js.map +1 -1
- package/dist/agent/facades/session-facade.d.ts +3 -3
- package/dist/agent/facades/session-facade.js +6 -6
- package/dist/agent/facades/session-facade.js.map +1 -1
- package/dist/agent/history-repair.d.ts +37 -0
- package/dist/agent/history-repair.js +124 -0
- package/dist/agent/history-repair.js.map +1 -0
- package/dist/agent/specialized/archive-agent.d.ts +3 -0
- package/dist/agent/specialized/archive-agent.js +71 -31
- package/dist/agent/specialized/archive-agent.js.map +1 -1
- package/dist/agent/specialized/security-review/agent.js +19 -8
- package/dist/agent/specialized/security-review/agent.js.map +1 -1
- package/dist/agent/tool-executor.js +5 -0
- package/dist/agent/tool-executor.js.map +1 -1
- package/dist/agent/turn-diff-tracker.d.ts +79 -0
- package/dist/agent/turn-diff-tracker.js +195 -0
- package/dist/agent/turn-diff-tracker.js.map +1 -0
- package/dist/checkpoints/checkpoint-versioning.js +78 -20
- package/dist/checkpoints/checkpoint-versioning.js.map +1 -1
- package/dist/cli/config-loader.js +2 -4
- package/dist/cli/config-loader.js.map +1 -1
- package/dist/commands/handlers/fcs-handlers.js +1 -1
- package/dist/commands/handlers/fcs-handlers.js.map +1 -1
- package/dist/commands/handlers/memory-handlers.js +2 -1
- package/dist/commands/handlers/memory-handlers.js.map +1 -1
- package/dist/commands/handlers/worktree-handlers.js +11 -0
- package/dist/commands/handlers/worktree-handlers.js.map +1 -1
- package/dist/commands/mcp.d.ts +1 -0
- package/dist/commands/mcp.js +66 -7
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/pipeline.js +25 -13
- package/dist/commands/pipeline.js.map +1 -1
- package/dist/config/model-tools.d.ts +41 -0
- package/dist/config/model-tools.js +194 -0
- package/dist/config/model-tools.js.map +1 -0
- package/dist/context/context-manager-v2.d.ts +2 -1
- package/dist/context/context-manager-v2.js +34 -5
- package/dist/context/context-manager-v2.js.map +1 -1
- package/dist/daemon/daemon-manager.js +23 -19
- package/dist/daemon/daemon-manager.js.map +1 -1
- package/dist/database/database-manager.d.ts +4 -0
- package/dist/database/database-manager.js +16 -7
- package/dist/database/database-manager.js.map +1 -1
- package/dist/desktop-automation/nutjs-provider.js +89 -0
- package/dist/desktop-automation/nutjs-provider.js.map +1 -1
- package/dist/fcs/builtins.d.ts +2 -6
- package/dist/fcs/builtins.js +2 -568
- package/dist/fcs/builtins.js.map +1 -1
- package/dist/fcs/codebuddy-bindings.d.ts +3 -43
- package/dist/fcs/codebuddy-bindings.js +2 -606
- package/dist/fcs/codebuddy-bindings.js.map +1 -1
- package/dist/fcs/index.d.ts +2 -27
- package/dist/fcs/index.js +2 -53
- package/dist/fcs/index.js.map +1 -1
- package/dist/fcs/lexer.d.ts +2 -37
- package/dist/fcs/lexer.js +2 -459
- package/dist/fcs/lexer.js.map +1 -1
- package/dist/fcs/parser.d.ts +2 -68
- package/dist/fcs/parser.js +2 -893
- package/dist/fcs/parser.js.map +1 -1
- package/dist/fcs/runtime.d.ts +2 -59
- package/dist/fcs/runtime.js +2 -623
- package/dist/fcs/runtime.js.map +1 -1
- package/dist/fcs/script-registry.d.ts +3 -69
- package/dist/fcs/script-registry.js +2 -219
- package/dist/fcs/script-registry.js.map +1 -1
- package/dist/fcs/sync-bindings.d.ts +3 -101
- package/dist/fcs/sync-bindings.js +2 -410
- package/dist/fcs/sync-bindings.js.map +1 -1
- package/dist/fcs/types.d.ts +2 -285
- package/dist/fcs/types.js +2 -103
- package/dist/fcs/types.js.map +1 -1
- package/dist/hooks/use-input-handler.d.ts +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/input/voice-control.js +11 -5
- package/dist/input/voice-control.js.map +1 -1
- package/dist/integrations/json-rpc/server.js +5 -5
- package/dist/integrations/json-rpc/server.js.map +1 -1
- package/dist/integrations/mcp/mcp-server.js +1 -1
- package/dist/integrations/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/config.js +89 -5
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/mcp-client.js +65 -14
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/mcp/transports.d.ts +0 -1
- package/dist/mcp/transports.js +1 -5
- package/dist/mcp/transports.js.map +1 -1
- package/dist/mcp/types.d.ts +2 -0
- package/dist/persistence/session-lock.d.ts +42 -0
- package/dist/persistence/session-lock.js +165 -0
- package/dist/persistence/session-lock.js.map +1 -0
- package/dist/persistence/session-store.d.ts +18 -3
- package/dist/persistence/session-store.js +90 -21
- package/dist/persistence/session-store.js.map +1 -1
- package/dist/plugins/isolated-plugin-runner.d.ts +6 -0
- package/dist/plugins/isolated-plugin-runner.js +19 -1
- package/dist/plugins/isolated-plugin-runner.js.map +1 -1
- package/dist/providers/local-llm-provider.js +21 -4
- package/dist/providers/local-llm-provider.js.map +1 -1
- package/dist/sandbox/docker-sandbox.js +7 -4
- package/dist/sandbox/docker-sandbox.js.map +1 -1
- package/dist/scripting/builtins.d.ts +8 -3
- package/dist/scripting/builtins.js +506 -355
- package/dist/scripting/builtins.js.map +1 -1
- package/dist/scripting/codebuddy-bindings.d.ts +47 -0
- package/dist/scripting/codebuddy-bindings.js +487 -0
- package/dist/scripting/codebuddy-bindings.js.map +1 -0
- package/dist/scripting/index.d.ts +33 -30
- package/dist/scripting/index.js +41 -36
- package/dist/scripting/index.js.map +1 -1
- package/dist/scripting/lexer.d.ts +31 -13
- package/dist/scripting/lexer.js +379 -292
- package/dist/scripting/lexer.js.map +1 -1
- package/dist/scripting/parser.d.ts +63 -44
- package/dist/scripting/parser.js +700 -473
- package/dist/scripting/parser.js.map +1 -1
- package/dist/scripting/runtime.d.ts +55 -24
- package/dist/scripting/runtime.js +600 -288
- package/dist/scripting/runtime.js.map +1 -1
- package/dist/scripting/script-registry.d.ts +54 -0
- package/dist/scripting/script-registry.js +202 -0
- package/dist/scripting/script-registry.js.map +1 -0
- package/dist/scripting/sync-bindings.d.ts +105 -0
- package/dist/scripting/sync-bindings.js +353 -0
- package/dist/scripting/sync-bindings.js.map +1 -0
- package/dist/scripting/types.d.ts +297 -199
- package/dist/scripting/types.js +86 -60
- package/dist/scripting/types.js.map +1 -1
- package/dist/search/usearch-index.js +42 -7
- package/dist/search/usearch-index.js.map +1 -1
- package/dist/security/bash-parser.d.ts +51 -0
- package/dist/security/bash-parser.js +327 -0
- package/dist/security/bash-parser.js.map +1 -0
- package/dist/security/skill-scanner.d.ts +36 -0
- package/dist/security/skill-scanner.js +149 -0
- package/dist/security/skill-scanner.js.map +1 -0
- package/dist/security/trust-folders.d.ts +1 -0
- package/dist/security/trust-folders.js +19 -1
- package/dist/security/trust-folders.js.map +1 -1
- package/dist/server/websocket/handler.js +15 -5
- package/dist/server/websocket/handler.js.map +1 -1
- package/dist/skills/eligibility.js +26 -4
- package/dist/skills/eligibility.js.map +1 -1
- package/dist/tasks/background-tasks.js +5 -1
- package/dist/tasks/background-tasks.js.map +1 -1
- package/dist/tools/apply-patch.d.ts +55 -0
- package/dist/tools/apply-patch.js +273 -0
- package/dist/tools/apply-patch.js.map +1 -0
- package/dist/tools/registry/bash-tools.js +6 -3
- package/dist/tools/registry/bash-tools.js.map +1 -1
- package/dist/tools/registry/misc-tools.js +1 -2
- package/dist/tools/registry/misc-tools.js.map +1 -1
- package/dist/tools/registry/search-tools.js +1 -1
- package/dist/tools/registry/search-tools.js.map +1 -1
- package/dist/tools/registry/text-editor-tools.js +1 -1
- package/dist/tools/registry/text-editor-tools.js.map +1 -1
- package/dist/tools/registry/todo-tools.js +37 -5
- package/dist/tools/registry/todo-tools.js.map +1 -1
- package/dist/tools/registry/tool-registry.js +5 -4
- package/dist/tools/registry/tool-registry.js.map +1 -1
- package/dist/tools/registry/web-tools.d.ts +1 -1
- package/dist/tools/registry/web-tools.js +28 -8
- package/dist/tools/registry/web-tools.js.map +1 -1
- package/dist/tools/text-editor.d.ts +1 -1
- package/dist/tools/text-editor.js +23 -5
- package/dist/tools/text-editor.js.map +1 -1
- package/dist/tools/web-search.d.ts +52 -37
- package/dist/tools/web-search.js +368 -163
- package/dist/tools/web-search.js.map +1 -1
- package/dist/ui/components/ChatInterface.d.ts +1 -1
- package/dist/utils/head-tail-truncation.d.ts +34 -0
- package/dist/utils/head-tail-truncation.js +98 -0
- package/dist/utils/head-tail-truncation.js.map +1 -0
- package/dist/utils/sanitize.d.ts +5 -0
- package/dist/utils/sanitize.js +19 -0
- package/dist/utils/sanitize.js.map +1 -1
- package/dist/utils/settings-manager.js +4 -4
- package/dist/utils/settings-manager.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brave-search
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: Brave Search API for web search, local results, news, images, and videos
|
|
5
|
+
author: Code Buddy
|
|
6
|
+
tags: search, web, api, brave, news, images, local-search, real-time
|
|
7
|
+
env:
|
|
8
|
+
BRAVE_SEARCH_API_KEY: ""
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Brave Search
|
|
12
|
+
|
|
13
|
+
Brave Search API provides privacy-focused web search with support for general web results, local business searches, news, images, and videos. Unlike other search APIs, Brave Search maintains user privacy by not tracking searches or building user profiles.
|
|
14
|
+
|
|
15
|
+
## Direct Control (CLI / API / Scripting)
|
|
16
|
+
|
|
17
|
+
### API Authentication
|
|
18
|
+
|
|
19
|
+
All requests require an API key via the `X-Subscription-Token` header. Get your key at https://api.search.brave.com/
|
|
20
|
+
|
|
21
|
+
### Web Search
|
|
22
|
+
|
|
23
|
+
**cURL Example:**
|
|
24
|
+
```bash
|
|
25
|
+
curl -s "https://api.search.brave.com/res/v1/web/search?q=artificial+intelligence+trends+2026&count=10" \
|
|
26
|
+
-H "Accept: application/json" \
|
|
27
|
+
-H "X-Subscription-Token: ${BRAVE_SEARCH_API_KEY}"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Node.js Example:**
|
|
31
|
+
```javascript
|
|
32
|
+
import fetch from 'node-fetch';
|
|
33
|
+
|
|
34
|
+
async function braveWebSearch(query, options = {}) {
|
|
35
|
+
const params = new URLSearchParams({
|
|
36
|
+
q: query,
|
|
37
|
+
count: options.count || 10,
|
|
38
|
+
offset: options.offset || 0,
|
|
39
|
+
safesearch: options.safesearch || 'moderate',
|
|
40
|
+
freshness: options.freshness || '', // pd (past day), pw (past week), pm (past month), py (past year)
|
|
41
|
+
text_decorations: options.textDecorations !== false,
|
|
42
|
+
spellcheck: options.spellcheck !== false
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const response = await fetch(`https://api.search.brave.com/res/v1/web/search?${params}`, {
|
|
46
|
+
headers: {
|
|
47
|
+
'Accept': 'application/json',
|
|
48
|
+
'X-Subscription-Token': process.env.BRAVE_SEARCH_API_KEY
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
throw new Error(`Brave Search API error: ${response.status}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return await response.json();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Usage
|
|
60
|
+
const results = await braveWebSearch('TypeScript best practices', {
|
|
61
|
+
count: 20,
|
|
62
|
+
freshness: 'py'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
results.web.results.forEach(result => {
|
|
66
|
+
console.log(`${result.title}\n${result.url}\n${result.description}\n`);
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Python Example:**
|
|
71
|
+
```python
|
|
72
|
+
import requests
|
|
73
|
+
import os
|
|
74
|
+
|
|
75
|
+
def brave_web_search(query, count=10, freshness=None):
|
|
76
|
+
params = {
|
|
77
|
+
'q': query,
|
|
78
|
+
'count': count,
|
|
79
|
+
'safesearch': 'moderate',
|
|
80
|
+
'text_decorations': True,
|
|
81
|
+
'spellcheck': True
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if freshness:
|
|
85
|
+
params['freshness'] = freshness
|
|
86
|
+
|
|
87
|
+
response = requests.get(
|
|
88
|
+
'https://api.search.brave.com/res/v1/web/search',
|
|
89
|
+
params=params,
|
|
90
|
+
headers={
|
|
91
|
+
'Accept': 'application/json',
|
|
92
|
+
'X-Subscription-Token': os.environ['BRAVE_SEARCH_API_KEY']
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
response.raise_for_status()
|
|
97
|
+
return response.json()
|
|
98
|
+
|
|
99
|
+
# Usage
|
|
100
|
+
results = brave_web_search('machine learning tutorials', count=15, freshness='pm')
|
|
101
|
+
|
|
102
|
+
for result in results.get('web', {}).get('results', []):
|
|
103
|
+
print(f"{result['title']}")
|
|
104
|
+
print(f"{result['url']}")
|
|
105
|
+
print(f"{result['description']}\n")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Local Search (Places/Businesses)
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Search for restaurants near a location
|
|
112
|
+
curl -s "https://api.search.brave.com/res/v1/web/search?q=restaurants+in+San+Francisco&search_lang=en&result_filter=locations" \
|
|
113
|
+
-H "X-Subscription-Token: ${BRAVE_SEARCH_API_KEY}"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Node.js Local Search:**
|
|
117
|
+
```javascript
|
|
118
|
+
async function braveLocalSearch(query, location) {
|
|
119
|
+
const params = new URLSearchParams({
|
|
120
|
+
q: `${query} in ${location}`,
|
|
121
|
+
result_filter: 'locations',
|
|
122
|
+
count: 20
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const response = await fetch(`https://api.search.brave.com/res/v1/web/search?${params}`, {
|
|
126
|
+
headers: {
|
|
127
|
+
'X-Subscription-Token': process.env.BRAVE_SEARCH_API_KEY
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const data = await response.json();
|
|
132
|
+
return data.locations?.results || [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Usage
|
|
136
|
+
const places = await braveLocalSearch('coffee shops', 'Portland, OR');
|
|
137
|
+
places.forEach(place => {
|
|
138
|
+
console.log(`${place.title} - ${place.address}`);
|
|
139
|
+
console.log(`Rating: ${place.rating || 'N/A'} | ${place.phone || ''}`);
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### News Search
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Search recent news with freshness filter
|
|
147
|
+
curl -s "https://api.search.brave.com/res/v1/web/search?q=climate+change+policy&freshness=pd&result_filter=news" \
|
|
148
|
+
-H "X-Subscription-Token: ${BRAVE_SEARCH_API_KEY}"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Python News Search:**
|
|
152
|
+
```python
|
|
153
|
+
def brave_news_search(query, freshness='pw'):
|
|
154
|
+
"""Search news articles with freshness filter (pd/pw/pm/py)"""
|
|
155
|
+
params = {
|
|
156
|
+
'q': query,
|
|
157
|
+
'freshness': freshness,
|
|
158
|
+
'result_filter': 'news',
|
|
159
|
+
'count': 20
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
response = requests.get(
|
|
163
|
+
'https://api.search.brave.com/res/v1/web/search',
|
|
164
|
+
params=params,
|
|
165
|
+
headers={'X-Subscription-Token': os.environ['BRAVE_SEARCH_API_KEY']}
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return response.json().get('news', {}).get('results', [])
|
|
169
|
+
|
|
170
|
+
# Get today's news
|
|
171
|
+
articles = brave_news_search('artificial intelligence', freshness='pd')
|
|
172
|
+
for article in articles:
|
|
173
|
+
print(f"[{article.get('age', 'N/A')}] {article['title']}")
|
|
174
|
+
print(f"Source: {article.get('source', 'Unknown')}")
|
|
175
|
+
print(f"{article['url']}\n")
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Image Search
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
curl -s "https://api.search.brave.com/res/v1/images/search?q=northern+lights+photography&count=20&safesearch=strict" \
|
|
182
|
+
-H "X-Subscription-Token: ${BRAVE_SEARCH_API_KEY}"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Node.js Image Search:**
|
|
186
|
+
```javascript
|
|
187
|
+
async function braveImageSearch(query, options = {}) {
|
|
188
|
+
const params = new URLSearchParams({
|
|
189
|
+
q: query,
|
|
190
|
+
count: options.count || 20,
|
|
191
|
+
safesearch: options.safesearch || 'moderate',
|
|
192
|
+
spellcheck: true
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const response = await fetch(`https://api.search.brave.com/res/v1/images/search?${params}`, {
|
|
196
|
+
headers: {
|
|
197
|
+
'X-Subscription-Token': process.env.BRAVE_SEARCH_API_KEY
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
return await response.json();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Usage
|
|
205
|
+
const images = await braveImageSearch('sustainable architecture', { count: 50 });
|
|
206
|
+
images.results.forEach(img => {
|
|
207
|
+
console.log(`${img.title}`);
|
|
208
|
+
console.log(`${img.url} (${img.properties.width}x${img.properties.height})`);
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Video Search
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
async function braveVideoSearch(query, options = {}) {
|
|
216
|
+
const params = new URLSearchParams({
|
|
217
|
+
q: query,
|
|
218
|
+
count: options.count || 20,
|
|
219
|
+
safesearch: options.safesearch || 'moderate'
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const response = await fetch(`https://api.search.brave.com/res/v1/videos/search?${params}`, {
|
|
223
|
+
headers: {
|
|
224
|
+
'X-Subscription-Token': process.env.BRAVE_SEARCH_API_KEY
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
return await response.json();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Usage
|
|
232
|
+
const videos = await braveVideoSearch('TypeScript tutorials');
|
|
233
|
+
videos.results.forEach(video => {
|
|
234
|
+
console.log(`${video.title} - ${video.duration || 'N/A'}`);
|
|
235
|
+
console.log(`${video.url}\n`);
|
|
236
|
+
});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## MCP Server Integration
|
|
240
|
+
|
|
241
|
+
Add to `.codebuddy/mcp.json`:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"mcpServers": {
|
|
246
|
+
"brave-search": {
|
|
247
|
+
"command": "npx",
|
|
248
|
+
"args": [
|
|
249
|
+
"-y",
|
|
250
|
+
"@modelcontextprotocol/server-brave-search"
|
|
251
|
+
],
|
|
252
|
+
"env": {
|
|
253
|
+
"BRAVE_API_KEY": "${BRAVE_SEARCH_API_KEY}"
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Available MCP Tools
|
|
261
|
+
|
|
262
|
+
Once configured, the following tools become available:
|
|
263
|
+
|
|
264
|
+
1. **brave_web_search**
|
|
265
|
+
- Search the web with Brave Search
|
|
266
|
+
- Parameters: `query` (string), `count` (number, default 10)
|
|
267
|
+
- Returns web results with titles, URLs, descriptions
|
|
268
|
+
|
|
269
|
+
2. **brave_local_search**
|
|
270
|
+
- Search for local businesses and places
|
|
271
|
+
- Parameters: `query` (string), `count` (number)
|
|
272
|
+
- Returns location results with addresses, ratings, phone numbers
|
|
273
|
+
|
|
274
|
+
Example MCP usage:
|
|
275
|
+
```
|
|
276
|
+
Ask Code Buddy: "Use brave_web_search to find the latest React 19 documentation"
|
|
277
|
+
Ask Code Buddy: "Find coffee shops near downtown Seattle using brave_local_search"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Common Workflows
|
|
281
|
+
|
|
282
|
+
### 1. Research Topic with Recent Results
|
|
283
|
+
|
|
284
|
+
**Goal:** Research a technical topic and get only recent, relevant articles
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Step 1: Search with freshness filter for past month
|
|
288
|
+
curl -s "https://api.search.brave.com/res/v1/web/search?q=Rust+async+programming+best+practices&freshness=pm&count=20" \
|
|
289
|
+
-H "X-Subscription-Token: ${BRAVE_SEARCH_API_KEY}" | jq '.web.results[] | {title, url, description, age}'
|
|
290
|
+
|
|
291
|
+
# Step 2: Filter by domain if needed (in Node.js)
|
|
292
|
+
const results = await braveWebSearch('Rust async programming best practices', {
|
|
293
|
+
freshness: 'pm',
|
|
294
|
+
count: 20
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const officialDocs = results.web.results.filter(r =>
|
|
298
|
+
r.url.includes('doc.rust-lang.org') ||
|
|
299
|
+
r.url.includes('rust-lang.github.io')
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
# Step 3: Extract URLs for further processing
|
|
303
|
+
const urls = officialDocs.map(r => r.url);
|
|
304
|
+
|
|
305
|
+
# Step 4: Use Code Buddy to fetch and summarize
|
|
306
|
+
// Pass URLs to web_fetch or ask Code Buddy to analyze content
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### 2. Monitor News on Specific Topic
|
|
310
|
+
|
|
311
|
+
**Goal:** Track breaking news and recent developments
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
import time
|
|
315
|
+
from datetime import datetime
|
|
316
|
+
|
|
317
|
+
def monitor_news_topic(query, check_interval=3600):
|
|
318
|
+
"""Check for new articles every hour"""
|
|
319
|
+
seen_urls = set()
|
|
320
|
+
|
|
321
|
+
while True:
|
|
322
|
+
articles = brave_news_search(query, freshness='pd')
|
|
323
|
+
new_articles = [a for a in articles if a['url'] not in seen_urls]
|
|
324
|
+
|
|
325
|
+
if new_articles:
|
|
326
|
+
print(f"\n[{datetime.now()}] Found {len(new_articles)} new articles:")
|
|
327
|
+
for article in new_articles:
|
|
328
|
+
print(f" - {article['title']}")
|
|
329
|
+
print(f" {article['url']}")
|
|
330
|
+
seen_urls.add(article['url'])
|
|
331
|
+
|
|
332
|
+
time.sleep(check_interval)
|
|
333
|
+
|
|
334
|
+
# Monitor AI policy news
|
|
335
|
+
monitor_news_topic('AI regulation policy', check_interval=3600)
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### 3. Find Local Businesses with Filtering
|
|
339
|
+
|
|
340
|
+
**Goal:** Search for businesses matching specific criteria
|
|
341
|
+
|
|
342
|
+
```javascript
|
|
343
|
+
async function findTopRatedPlaces(type, location, minRating = 4.0) {
|
|
344
|
+
// Step 1: Search for places
|
|
345
|
+
const places = await braveLocalSearch(type, location);
|
|
346
|
+
|
|
347
|
+
// Step 2: Filter by rating
|
|
348
|
+
const topRated = places.filter(p =>
|
|
349
|
+
p.rating && parseFloat(p.rating) >= minRating
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
// Step 3: Sort by rating (descending)
|
|
353
|
+
topRated.sort((a, b) => parseFloat(b.rating || 0) - parseFloat(a.rating || 0));
|
|
354
|
+
|
|
355
|
+
// Step 4: Return formatted results
|
|
356
|
+
return topRated.map(place => ({
|
|
357
|
+
name: place.title,
|
|
358
|
+
address: place.address,
|
|
359
|
+
rating: place.rating,
|
|
360
|
+
phone: place.phone,
|
|
361
|
+
url: place.url
|
|
362
|
+
}));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Usage
|
|
366
|
+
const restaurants = await findTopRatedPlaces('Italian restaurants', 'Boston, MA', 4.5);
|
|
367
|
+
console.log(JSON.stringify(restaurants, null, 2));
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### 4. Comparative Search Analysis
|
|
371
|
+
|
|
372
|
+
**Goal:** Compare search results across different time periods
|
|
373
|
+
|
|
374
|
+
```javascript
|
|
375
|
+
async function compareSearchTrends(query) {
|
|
376
|
+
// Step 1: Get recent results (past day)
|
|
377
|
+
const recent = await braveWebSearch(query, { freshness: 'pd', count: 10 });
|
|
378
|
+
|
|
379
|
+
// Step 2: Get older results (past year)
|
|
380
|
+
const older = await braveWebSearch(query, { freshness: 'py', count: 10 });
|
|
381
|
+
|
|
382
|
+
// Step 3: Analyze domain distribution
|
|
383
|
+
const getDomains = (results) => {
|
|
384
|
+
return results.web.results.map(r => new URL(r.url).hostname);
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const recentDomains = getDomains(recent);
|
|
388
|
+
const olderDomains = getDomains(older);
|
|
389
|
+
|
|
390
|
+
// Step 4: Identify trending sources
|
|
391
|
+
const newSources = recentDomains.filter(d => !olderDomains.includes(d));
|
|
392
|
+
|
|
393
|
+
console.log('New sources in past day:', newSources);
|
|
394
|
+
|
|
395
|
+
// Step 5: Extract common themes from titles
|
|
396
|
+
const recentTitles = recent.web.results.map(r => r.title).join(' ');
|
|
397
|
+
console.log('\nRecent focus:', recentTitles);
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
recent: recent.web.results,
|
|
401
|
+
older: older.web.results,
|
|
402
|
+
newSources
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Track how coverage of a topic evolves
|
|
407
|
+
await compareSearchTrends('quantum computing breakthroughs');
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### 5. Multi-Modal Content Discovery
|
|
411
|
+
|
|
412
|
+
**Goal:** Find related content across web, images, videos, and news
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
async function comprehensiveSearch(topic) {
|
|
416
|
+
console.log(`Searching for: ${topic}\n`);
|
|
417
|
+
|
|
418
|
+
// Step 1: Web search for overview
|
|
419
|
+
const webResults = await braveWebSearch(topic, { count: 5 });
|
|
420
|
+
console.log('Top Web Results:');
|
|
421
|
+
webResults.web.results.slice(0, 3).forEach(r => {
|
|
422
|
+
console.log(` ${r.title} - ${r.url}`);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Step 2: Recent news articles
|
|
426
|
+
const news = await braveNewsSearch(topic, { freshness: 'pw' });
|
|
427
|
+
console.log('\nRecent News:');
|
|
428
|
+
news.slice(0, 3).forEach(article => {
|
|
429
|
+
console.log(` [${article.age}] ${article.title}`);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Step 3: Find relevant images
|
|
433
|
+
const images = await braveImageSearch(topic, { count: 10 });
|
|
434
|
+
console.log('\nTop Images:');
|
|
435
|
+
images.results.slice(0, 3).forEach(img => {
|
|
436
|
+
console.log(` ${img.title} - ${img.url}`);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// Step 4: Video content
|
|
440
|
+
const videos = await braveVideoSearch(topic, { count: 10 });
|
|
441
|
+
console.log('\nVideo Resources:');
|
|
442
|
+
videos.results.slice(0, 3).forEach(video => {
|
|
443
|
+
console.log(` ${video.title} - ${video.url}`);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// Step 5: Compile report
|
|
447
|
+
return {
|
|
448
|
+
overview: webResults.web.results[0]?.description,
|
|
449
|
+
topLinks: webResults.web.results.slice(0, 5).map(r => r.url),
|
|
450
|
+
newsCount: news.length,
|
|
451
|
+
imageCount: images.results.length,
|
|
452
|
+
videoCount: videos.results.length
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Comprehensive research on a topic
|
|
457
|
+
const report = await comprehensiveSearch('sustainable energy solutions 2026');
|
|
458
|
+
console.log('\nResearch Summary:', report);
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
## Best Practices
|
|
462
|
+
|
|
463
|
+
1. **Use Freshness Filters:** For time-sensitive queries, always specify `freshness` parameter (pd/pw/pm/py)
|
|
464
|
+
2. **Result Filtering:** Use `result_filter` to get specific content types (news, locations, videos)
|
|
465
|
+
3. **Rate Limiting:** Respect API rate limits (typically 1 req/sec for free tier, check your plan)
|
|
466
|
+
4. **Safe Search:** Set appropriate `safesearch` level (off/moderate/strict) based on use case
|
|
467
|
+
5. **Pagination:** Use `offset` parameter for paginated results (offset = page * count)
|
|
468
|
+
6. **Spellcheck:** Keep `spellcheck=true` to handle typos in queries
|
|
469
|
+
7. **Privacy:** Brave doesn't track searches, but still avoid including PII in queries
|
|
470
|
+
|
|
471
|
+
## Troubleshooting
|
|
472
|
+
|
|
473
|
+
**API Key Issues:**
|
|
474
|
+
```bash
|
|
475
|
+
# Test API key validity
|
|
476
|
+
curl -I "https://api.search.brave.com/res/v1/web/search?q=test" \
|
|
477
|
+
-H "X-Subscription-Token: ${BRAVE_SEARCH_API_KEY}"
|
|
478
|
+
|
|
479
|
+
# Should return 200 OK if valid, 401 if invalid
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**No Results:**
|
|
483
|
+
- Check query spelling and try with `spellcheck=true`
|
|
484
|
+
- Remove restrictive filters (freshness, result_filter)
|
|
485
|
+
- Try broader search terms
|
|
486
|
+
|
|
487
|
+
**Rate Limit Errors (429):**
|
|
488
|
+
- Add delays between requests (min 1 second)
|
|
489
|
+
- Upgrade to higher tier plan
|
|
490
|
+
- Implement exponential backoff retry logic
|