@brave/brave-search-mcp-server 2.0.79 → 2.0.81
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 +60 -18
- package/dist/BraveAPI/index.js +37 -15
- package/dist/config.js +18 -44
- package/dist/server.js +1 -5
- package/dist/tools/index.js +4 -0
- package/dist/tools/llm_context/index.js +51 -0
- package/dist/tools/llm_context/schemas/input.js +228 -0
- package/dist/tools/llm_context/schemas/output.js +66 -0
- package/dist/tools/local/index.js +1 -1
- package/dist/tools/news/index.js +1 -1
- package/dist/tools/news/params.js +8 -4
- package/dist/tools/place_search/index.js +52 -0
- package/dist/tools/place_search/schemas/input.js +216 -0
- package/dist/tools/place_search/schemas/output.js +249 -0
- package/dist/tools/summarizer/index.js +1 -1
- package/dist/tools/videos/index.js +1 -1
- package/dist/tools/videos/params.js +6 -1
- package/dist/tools/web/index.js +1 -1
- package/dist/tools/web/params.js +8 -3
- package/package.json +2 -8
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Brave Search MCP Server
|
|
2
2
|
|
|
3
|
-
An MCP server implementation that integrates the Brave Search API, providing comprehensive search capabilities including web search, local business search, image search, video search, news search, and AI-powered summarization. This project supports both STDIO and HTTP transports, with STDIO as the default mode.
|
|
3
|
+
An MCP server implementation that integrates the Brave Search API, providing comprehensive search capabilities including web search, local business search, place search, image search, video search, news search, LLM context, and AI-powered summarization. This project supports both STDIO and HTTP transports, with STDIO as the default mode.
|
|
4
4
|
|
|
5
5
|
[](https://deepwiki.com/brave/brave-search-mcp-server)
|
|
6
6
|
|
|
@@ -98,6 +98,63 @@ Generates AI-powered summaries from web search results using Brave's summarizati
|
|
|
98
98
|
|
|
99
99
|
**Usage:** First perform a web search with `summary: true`, then use the returned summary key with this tool.
|
|
100
100
|
|
|
101
|
+
### Place Search (`brave_place_search`)
|
|
102
|
+
Searches for points of interest (POIs) in a specified geographic area using Brave's Place Search API. Returns rich, structured place data including name, address, opening hours, contact info, ratings, photos, categories, and timezone.
|
|
103
|
+
|
|
104
|
+
**Parameters:**
|
|
105
|
+
- `query` (string, optional): Query string used to refine the POI search (max 400 chars, 50 words). When omitted, returns general points of interest in the supplied area.
|
|
106
|
+
- `latitude` (number, optional): Latitude of the search center (-90 to 90). Typically paired with `longitude`.
|
|
107
|
+
- `longitude` (number, optional): Longitude of the search center (-180 to 180). Typically paired with `latitude`.
|
|
108
|
+
- `location` (string, optional): Location string used as an alternative to `latitude`/`longitude`. For US locations prefer the form `<city> <state> <country name>` (e.g., `san francisco ca united states`); for non-US locations use `<city> <country name>` (e.g., `tokyo japan`).
|
|
109
|
+
- `radius` (number, optional): Search radius around the supplied coordinates, in meters. If omitted, the search is performed globally.
|
|
110
|
+
- `count` (number, optional): Number of results to return (1-50, default 20).
|
|
111
|
+
- `country` (string, optional): Two-letter country code (default `US`).
|
|
112
|
+
- `search_lang` (string, optional): Search language (default `en`).
|
|
113
|
+
- `ui_lang` (string, optional): UI language (default `en-US`).
|
|
114
|
+
- `units` (string, optional): Distance units (`metric` or `imperial`, default `metric`).
|
|
115
|
+
- `safesearch` (string, optional): Safe search level (`off`, `moderate`, `strict`, default `strict`).
|
|
116
|
+
- `spellcheck` (boolean, optional): Whether to spellcheck the query (default `true`).
|
|
117
|
+
- `geoloc` (string, optional): Optional geolocation token used to refine results.
|
|
118
|
+
|
|
119
|
+
**Optional request headers:**
|
|
120
|
+
- `api-version` (string, optional): Brave API version (`YYYY-MM-DD`)
|
|
121
|
+
- `accept` (string, optional): Response media type (`application/json` or `*/*`)
|
|
122
|
+
- `cache-control` (string, optional): Use `no-cache` to request fresh content
|
|
123
|
+
- `user-agent` (string, optional): User agent originating the request
|
|
124
|
+
|
|
125
|
+
### LLM Context (`brave_llm_context`)
|
|
126
|
+
Retrieves pre-extracted web content optimized for AI agents, LLM grounding, and RAG pipelines.
|
|
127
|
+
|
|
128
|
+
**Parameters:**
|
|
129
|
+
- `query` (string, required): Search query (max 400 chars, 50 words)
|
|
130
|
+
- `country` (string, optional): Search country code
|
|
131
|
+
- `search_lang` (string, optional): Search language code
|
|
132
|
+
- `count` (number, optional): Maximum number of search results considered (1-50)
|
|
133
|
+
- `spellcheck` (boolean, optional): Enable spell checking
|
|
134
|
+
- `maximum_number_of_urls` (number, optional): Maximum number of URLs to include (1-50)
|
|
135
|
+
- `maximum_number_of_tokens` (number, optional): Approximate maximum number of context tokens (1024-32768)
|
|
136
|
+
- `maximum_number_of_snippets` (number, optional): Maximum number of snippets to include (1-256)
|
|
137
|
+
- `context_threshold_mode` (string, optional): Threshold mode ("disabled", "strict", "lenient", "balanced")
|
|
138
|
+
- `maximum_number_of_tokens_per_url` (number, optional): Maximum tokens per URL (512-8192)
|
|
139
|
+
- `maximum_number_of_snippets_per_url` (number, optional): Maximum snippets per URL (1-100)
|
|
140
|
+
- `goggles` (string or array, optional): Goggle URL or definition for custom re-ranking
|
|
141
|
+
- `freshness` (string, optional): Time filter ("pd", "pw", "pm", "py", or date range)
|
|
142
|
+
- `enable_local` (boolean, optional): Enable local recall
|
|
143
|
+
- `enable_source_metadata` (boolean, optional): Include source metadata enrichment
|
|
144
|
+
|
|
145
|
+
**Optional request headers:**
|
|
146
|
+
- `x-loc-lat` (number, optional): Client latitude (-90 to 90)
|
|
147
|
+
- `x-loc-long` (number, optional): Client longitude (-180 to 180)
|
|
148
|
+
- `x-loc-city` (string, optional): Client city name
|
|
149
|
+
- `x-loc-state` (string, optional): Client state or region code
|
|
150
|
+
- `x-loc-state-name` (string, optional): Client state or region name
|
|
151
|
+
- `x-loc-country` (string, optional): Client country code
|
|
152
|
+
- `x-loc-postal-code` (string, optional): Client postal code
|
|
153
|
+
- `api-version` (string, optional): Brave API version (`YYYY-MM-DD`)
|
|
154
|
+
- `accept` (string, optional): Response media type ("application/json" or "*/*")
|
|
155
|
+
- `cache-control` (string, optional): Use `no-cache` to request fresh content
|
|
156
|
+
- `user-agent` (string, optional): User agent originating the request
|
|
157
|
+
|
|
101
158
|
## Configuration
|
|
102
159
|
|
|
103
160
|
### Getting an API Key
|
|
@@ -117,8 +174,8 @@ The server supports the following environment variables:
|
|
|
117
174
|
- `BRAVE_MCP_PORT`: HTTP server port (default: 8000)
|
|
118
175
|
- `BRAVE_MCP_HOST`: HTTP server host (default: "0.0.0.0")
|
|
119
176
|
- `BRAVE_MCP_LOG_LEVEL`: Desired logging level("debug", "info", "notice", "warning", "error", "critical", "alert", or "emergency", default: "info")
|
|
120
|
-
- `BRAVE_MCP_ENABLED_TOOLS`: When used, specifies a whitelist for supported tools
|
|
121
|
-
- `BRAVE_MCP_DISABLED_TOOLS`: When used, specifies a blacklist for supported tools
|
|
177
|
+
- `BRAVE_MCP_ENABLED_TOOLS`: When used, specifies a space-separated whitelist for supported tools
|
|
178
|
+
- `BRAVE_MCP_DISABLED_TOOLS`: When used, specifies a space-separated blacklist for supported tools
|
|
122
179
|
- `BRAVE_MCP_STATELESS`: HTTP stateless mode (default: "true"). When running on Amazon Bedrock Agentcore, set to "true".
|
|
123
180
|
|
|
124
181
|
### Command Line Options
|
|
@@ -139,14 +196,6 @@ Options:
|
|
|
139
196
|
|
|
140
197
|
## Installation
|
|
141
198
|
|
|
142
|
-
### Installing via Smithery
|
|
143
|
-
|
|
144
|
-
To install Brave Search automatically via [Smithery](https://smithery.ai/server/brave):
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
npx -y @smithery/cli install brave
|
|
148
|
-
```
|
|
149
|
-
|
|
150
199
|
### Usage with Claude Desktop
|
|
151
200
|
|
|
152
201
|
Add this to your `claude_desktop_config.json`:
|
|
@@ -314,11 +363,6 @@ npx @modelcontextprotocol/inspector node dist/index.js
|
|
|
314
363
|
|
|
315
364
|
STDIO is the default mode. For HTTP mode testing, add `--transport http` to the arguments in the Inspector UI.
|
|
316
365
|
|
|
317
|
-
### Testing via Smithery.AI
|
|
318
|
-
|
|
319
|
-
1. Establish and acquire a smithery.ai account and API key
|
|
320
|
-
2. Run `npm run install`, `npm run smithery:build`, and lastly `npm run smithery:dev` to begin testing
|
|
321
|
-
|
|
322
366
|
### Available Scripts
|
|
323
367
|
|
|
324
368
|
- `npm run build`: Build the TypeScript project
|
|
@@ -329,8 +373,6 @@ STDIO is the default mode. For HTTP mode testing, add `--transport http` to the
|
|
|
329
373
|
|
|
330
374
|
- `npm run inspector`: Launch an instance of MCP Inspector
|
|
331
375
|
- `npm run inspector:stdio`: Launch a instance of MCP Inspector, configured for STDIO
|
|
332
|
-
- `npm run smithery:build`: Build the project for smithery.ai
|
|
333
|
-
- `npm run smithery:dev`: Launch the development environment for smithery.ai
|
|
334
376
|
|
|
335
377
|
### Docker Compose
|
|
336
378
|
|
package/dist/BraveAPI/index.js
CHANGED
|
@@ -8,6 +8,8 @@ const typeToPathMap = {
|
|
|
8
8
|
videos: '/res/v1/videos/search',
|
|
9
9
|
web: '/res/v1/web/search',
|
|
10
10
|
summarizer: '/res/v1/summarizer/search',
|
|
11
|
+
llmContext: '/res/v1/llm/context',
|
|
12
|
+
placeSearch: '/res/v1/local/place_search',
|
|
11
13
|
};
|
|
12
14
|
const getDefaultRequestHeaders = () => {
|
|
13
15
|
return {
|
|
@@ -25,9 +27,18 @@ const isValidGoggleURL = (url) => {
|
|
|
25
27
|
return false;
|
|
26
28
|
}
|
|
27
29
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const normalizeGoggle = (value) => {
|
|
31
|
+
if (typeof value !== 'string')
|
|
32
|
+
return null;
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
if (trimmed.length === 0)
|
|
35
|
+
return null;
|
|
36
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
37
|
+
return isValidGoggleURL(trimmed) ? trimmed : null;
|
|
38
|
+
}
|
|
39
|
+
return trimmed;
|
|
40
|
+
};
|
|
41
|
+
async function issueRequest(endpoint, parameters, requestHeaders = {}) {
|
|
31
42
|
// TODO (Sampson): Improve rate-limit logic to support self-throttling and n-keys
|
|
32
43
|
// checkRateLimit();
|
|
33
44
|
// Determine URL, and setup parameters
|
|
@@ -49,11 +60,18 @@ requestHeaders = {}) {
|
|
|
49
60
|
}
|
|
50
61
|
// Handle `result_filter` parameter
|
|
51
62
|
if (key === 'result_filter') {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Handle special behavior of 'summary' parameter:
|
|
65
|
+
* When 'summary' is true, we need to either set result_filter to
|
|
66
|
+
* 'summarizer', or leave it excluded entirely. This is due to a known
|
|
67
|
+
* bug in the now-deprecated Summarizer endpoint. Setting it to
|
|
68
|
+
* 'summarizer' will result in no web results being returned, which is
|
|
69
|
+
* not ideal. As such, we skip the parameter entirely.
|
|
70
|
+
* See https://github.com/brave/brave-search-mcp-server/issues/272 and
|
|
71
|
+
* https://bravesoftware.slack.com/archives/C01NNFM9XMM/p1751654841090929
|
|
72
|
+
*/
|
|
55
73
|
if ('summary' in parameters && parameters.summary === true) {
|
|
56
|
-
|
|
74
|
+
continue;
|
|
57
75
|
}
|
|
58
76
|
else if (Array.isArray(value) && value.length > 0) {
|
|
59
77
|
queryParams.set(key, value.join(','));
|
|
@@ -62,23 +80,27 @@ requestHeaders = {}) {
|
|
|
62
80
|
}
|
|
63
81
|
// Handle `goggles` parameter(s)
|
|
64
82
|
if (key === 'goggles') {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
queryParams.append(key, url);
|
|
83
|
+
const candidates = Array.isArray(value) ? value : [value];
|
|
84
|
+
for (const candidate of candidates) {
|
|
85
|
+
const normalized = normalizeGoggle(candidate);
|
|
86
|
+
if (normalized !== null) {
|
|
87
|
+
queryParams.append(key, normalized);
|
|
71
88
|
}
|
|
72
89
|
}
|
|
73
90
|
continue;
|
|
74
91
|
}
|
|
75
|
-
if (value !== undefined) {
|
|
92
|
+
if (value !== undefined && value !== null) {
|
|
76
93
|
queryParams.set(key === 'query' ? 'q' : key, value.toString());
|
|
77
94
|
}
|
|
78
95
|
}
|
|
79
96
|
// Issue Request
|
|
80
97
|
const urlWithParams = url.toString() + '?' + queryParams.toString();
|
|
81
|
-
const headers =
|
|
98
|
+
const headers = new Headers(getDefaultRequestHeaders());
|
|
99
|
+
for (const [key, value] of Object.entries(requestHeaders)) {
|
|
100
|
+
if (value === undefined || value === null)
|
|
101
|
+
continue;
|
|
102
|
+
headers.set(key, String(value));
|
|
103
|
+
}
|
|
82
104
|
const response = await fetch(urlWithParams, { headers });
|
|
83
105
|
// Handle Error
|
|
84
106
|
if (!response.ok) {
|
package/dist/config.js
CHANGED
|
@@ -1,43 +1,18 @@
|
|
|
1
1
|
import { LoggingLevelSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import dotenv from 'dotenv';
|
|
4
|
-
import { z } from 'zod';
|
|
5
4
|
import tools from './tools/index.js';
|
|
6
5
|
dotenv.config({ debug: false, quiet: true });
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
disabledTools: z
|
|
18
|
-
.array(z.string())
|
|
19
|
-
.describe('Enforces a tool blacklist (cannot be used with enabledTools)')
|
|
20
|
-
.optional(),
|
|
21
|
-
loggingLevel: z
|
|
22
|
-
.enum([
|
|
23
|
-
'debug',
|
|
24
|
-
'error',
|
|
25
|
-
'info',
|
|
26
|
-
'notice',
|
|
27
|
-
'warning',
|
|
28
|
-
'critical',
|
|
29
|
-
'alert',
|
|
30
|
-
'emergency',
|
|
31
|
-
])
|
|
32
|
-
.default('info')
|
|
33
|
-
.describe('Desired logging level')
|
|
34
|
-
.optional(),
|
|
35
|
-
stateless: z
|
|
36
|
-
.boolean()
|
|
37
|
-
.default(false)
|
|
38
|
-
.describe('Whether the server should be stateless')
|
|
39
|
-
.optional(),
|
|
40
|
-
});
|
|
6
|
+
function parseToolNameList(value) {
|
|
7
|
+
if (value == null)
|
|
8
|
+
return [];
|
|
9
|
+
if (Array.isArray(value))
|
|
10
|
+
return value.map((t) => t.trim()).filter((t) => t.length > 0);
|
|
11
|
+
return value
|
|
12
|
+
.trim()
|
|
13
|
+
.split(/\s+/)
|
|
14
|
+
.filter((t) => t.length > 0);
|
|
15
|
+
}
|
|
41
16
|
const state = {
|
|
42
17
|
transport: 'stdio',
|
|
43
18
|
port: 8080,
|
|
@@ -69,14 +44,16 @@ export function getOptions() {
|
|
|
69
44
|
const options = program.opts();
|
|
70
45
|
const toolNames = Object.values(tools).map((tool) => tool.name);
|
|
71
46
|
// Validate tool inclusion configuration
|
|
72
|
-
const enabledTools = options.enabledTools
|
|
73
|
-
const disabledTools = options.disabledTools
|
|
47
|
+
const enabledTools = parseToolNameList(options.enabledTools);
|
|
48
|
+
const disabledTools = parseToolNameList(options.disabledTools);
|
|
74
49
|
if (enabledTools.length > 0 && disabledTools.length > 0) {
|
|
75
50
|
console.error('Error: --enabled-tools and --disabled-tools cannot be used together');
|
|
76
51
|
return false;
|
|
77
52
|
}
|
|
78
|
-
|
|
79
|
-
|
|
53
|
+
const invalidToolNames = [...enabledTools, ...disabledTools].filter((t) => !toolNames.includes(t));
|
|
54
|
+
if (invalidToolNames.length > 0) {
|
|
55
|
+
console.error(`Invalid tool name(s) used: ${invalidToolNames.join(', ')}`);
|
|
56
|
+
console.error(`Valid tool names are: ${toolNames.join(', ')}`);
|
|
80
57
|
return false;
|
|
81
58
|
}
|
|
82
59
|
// Validate all other options
|
|
@@ -110,13 +87,10 @@ export function getOptions() {
|
|
|
110
87
|
state.port = options.port;
|
|
111
88
|
state.host = options.host;
|
|
112
89
|
state.loggingLevel = options.loggingLevel;
|
|
113
|
-
state.enabledTools =
|
|
114
|
-
state.disabledTools =
|
|
90
|
+
state.enabledTools = enabledTools;
|
|
91
|
+
state.disabledTools = disabledTools;
|
|
115
92
|
state.stateless = options.stateless;
|
|
116
93
|
state.ready = true;
|
|
117
94
|
return options;
|
|
118
95
|
}
|
|
119
|
-
export function setOptions(options) {
|
|
120
|
-
return Object.assign(state, options);
|
|
121
|
-
}
|
|
122
96
|
export default state;
|
package/dist/server.js
CHANGED
|
@@ -2,11 +2,7 @@ import tools from './tools/index.js';
|
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import pkg from '../package.json' with { type: 'json' };
|
|
4
4
|
import { isToolPermittedByUser } from './config.js';
|
|
5
|
-
|
|
6
|
-
export { configSchema } from './config.js';
|
|
7
|
-
export default function createMcpServer(options) {
|
|
8
|
-
if (options?.config)
|
|
9
|
-
setOptions(options.config);
|
|
5
|
+
export default function createMcpServer() {
|
|
10
6
|
const mcpServer = new McpServer({
|
|
11
7
|
version: pkg.version,
|
|
12
8
|
name: 'brave-search-mcp-server',
|
package/dist/tools/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import VideoSearchTool from './videos/index.js';
|
|
|
4
4
|
import ImageSearchTool from './images/index.js';
|
|
5
5
|
import NewsSearchTool from './news/index.js';
|
|
6
6
|
import SummarizerTool from './summarizer/index.js';
|
|
7
|
+
import LlmContextTool from './llm_context/index.js';
|
|
8
|
+
import PlaceSearchTool from './place_search/index.js';
|
|
7
9
|
export default {
|
|
8
10
|
WebSearchTool,
|
|
9
11
|
LocalSearchTool,
|
|
@@ -11,4 +13,6 @@ export default {
|
|
|
11
13
|
ImageSearchTool,
|
|
12
14
|
NewsSearchTool,
|
|
13
15
|
SummarizerTool,
|
|
16
|
+
LlmContextTool,
|
|
17
|
+
PlaceSearchTool,
|
|
14
18
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import API from '../../BraveAPI/index.js';
|
|
3
|
+
import { RequestParamsSchema, RequestHeadersSchema, LlmContextInputSchema, } from './schemas/input.js';
|
|
4
|
+
import { LlmContextSearchApiResponseSchema } from './schemas/output.js';
|
|
5
|
+
export const name = 'brave_llm_context';
|
|
6
|
+
export const annotations = {
|
|
7
|
+
title: 'Brave LLM Context',
|
|
8
|
+
openWorldHint: true,
|
|
9
|
+
};
|
|
10
|
+
export const description = `
|
|
11
|
+
Retrieves pre-extracted, relevance-ranked web content using Brave's LLM Context API, optimized for AI agents, LLM grounding, and RAG pipelines. Unlike a traditional web search that returns links and short descriptions, this tool returns the actual substance of matching pages — text chunks, tables, code blocks, and structured data — so the model can reason over it directly.
|
|
12
|
+
|
|
13
|
+
When to use:
|
|
14
|
+
- Grounding answers in fresh, relevant web content (RAG)
|
|
15
|
+
- Giving an AI agent ready-to-use page content from a single search call
|
|
16
|
+
- Question answering and fact-checking against current sources
|
|
17
|
+
- Gathering source material for research without manually fetching pages
|
|
18
|
+
- When you need the contents of pages, not just titles, descriptions, and URLs
|
|
19
|
+
|
|
20
|
+
When relaying results in markdown-supporting environments, cite the source URLs from the "sources" map.
|
|
21
|
+
`.trim();
|
|
22
|
+
export const execute = async (params) => {
|
|
23
|
+
const parsedParams = RequestParamsSchema.parse(params);
|
|
24
|
+
const parsedHeaders = RequestHeadersSchema.parse(params);
|
|
25
|
+
const response = await API.issueRequest('llmContext', parsedParams, parsedHeaders);
|
|
26
|
+
const { success, data, error } = LlmContextSearchApiResponseSchema.safeParse(response);
|
|
27
|
+
const payload = success ? data : z.treeifyError(error);
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
30
|
+
isError: !success,
|
|
31
|
+
structuredContent: payload,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export const register = (mcpServer) => {
|
|
35
|
+
mcpServer.registerTool(name, {
|
|
36
|
+
title: name,
|
|
37
|
+
description: description,
|
|
38
|
+
inputSchema: LlmContextInputSchema.shape,
|
|
39
|
+
outputSchema: LlmContextSearchApiResponseSchema.shape,
|
|
40
|
+
annotations: annotations,
|
|
41
|
+
}, execute);
|
|
42
|
+
};
|
|
43
|
+
export default {
|
|
44
|
+
name,
|
|
45
|
+
description,
|
|
46
|
+
annotations,
|
|
47
|
+
inputSchema: LlmContextInputSchema.shape,
|
|
48
|
+
outputSchema: LlmContextSearchApiResponseSchema.shape,
|
|
49
|
+
execute,
|
|
50
|
+
register,
|
|
51
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Keep up-to-date with documentation:
|
|
4
|
+
* https://api-dashboard.search.brave.com/api-reference/summarizer/llm_context/get
|
|
5
|
+
*/
|
|
6
|
+
const CountryCodesSchema = z.enum([
|
|
7
|
+
'AR',
|
|
8
|
+
'AU',
|
|
9
|
+
'AT',
|
|
10
|
+
'BE',
|
|
11
|
+
'BR',
|
|
12
|
+
'CA',
|
|
13
|
+
'CL',
|
|
14
|
+
'DK',
|
|
15
|
+
'FI',
|
|
16
|
+
'FR',
|
|
17
|
+
'DE',
|
|
18
|
+
'GR',
|
|
19
|
+
'HK',
|
|
20
|
+
'IN',
|
|
21
|
+
'ID',
|
|
22
|
+
'IT',
|
|
23
|
+
'JP',
|
|
24
|
+
'KR',
|
|
25
|
+
'MY',
|
|
26
|
+
'MX',
|
|
27
|
+
'NL',
|
|
28
|
+
'NZ',
|
|
29
|
+
'NO',
|
|
30
|
+
'CN',
|
|
31
|
+
'PL',
|
|
32
|
+
'PT',
|
|
33
|
+
'PH',
|
|
34
|
+
'RU',
|
|
35
|
+
'SA',
|
|
36
|
+
'ZA',
|
|
37
|
+
'ES',
|
|
38
|
+
'SE',
|
|
39
|
+
'CH',
|
|
40
|
+
'TW',
|
|
41
|
+
'TR',
|
|
42
|
+
'GB',
|
|
43
|
+
'US',
|
|
44
|
+
'ALL',
|
|
45
|
+
]);
|
|
46
|
+
const SearchLangCodesSchema = z.enum([
|
|
47
|
+
'ar',
|
|
48
|
+
'eu',
|
|
49
|
+
'bn',
|
|
50
|
+
'bg',
|
|
51
|
+
'ca',
|
|
52
|
+
'zh-hans',
|
|
53
|
+
'zh-hant',
|
|
54
|
+
'hr',
|
|
55
|
+
'cs',
|
|
56
|
+
'da',
|
|
57
|
+
'nl',
|
|
58
|
+
'en',
|
|
59
|
+
'en-gb',
|
|
60
|
+
'et',
|
|
61
|
+
'fi',
|
|
62
|
+
'fr',
|
|
63
|
+
'gl',
|
|
64
|
+
'de',
|
|
65
|
+
'el',
|
|
66
|
+
'gu',
|
|
67
|
+
'he',
|
|
68
|
+
'hi',
|
|
69
|
+
'hu',
|
|
70
|
+
'is',
|
|
71
|
+
'it',
|
|
72
|
+
'jp',
|
|
73
|
+
'kn',
|
|
74
|
+
'ko',
|
|
75
|
+
'lv',
|
|
76
|
+
'lt',
|
|
77
|
+
'ms',
|
|
78
|
+
'ml',
|
|
79
|
+
'mr',
|
|
80
|
+
'nb',
|
|
81
|
+
'pl',
|
|
82
|
+
'pt-br',
|
|
83
|
+
'pt-pt',
|
|
84
|
+
'pa',
|
|
85
|
+
'ro',
|
|
86
|
+
'ru',
|
|
87
|
+
'sr',
|
|
88
|
+
'sk',
|
|
89
|
+
'sl',
|
|
90
|
+
'es',
|
|
91
|
+
'sv',
|
|
92
|
+
'ta',
|
|
93
|
+
'te',
|
|
94
|
+
'th',
|
|
95
|
+
'tr',
|
|
96
|
+
'uk',
|
|
97
|
+
'vi',
|
|
98
|
+
]);
|
|
99
|
+
const FreshnessSchema = z
|
|
100
|
+
.union([
|
|
101
|
+
z.enum(['pd', 'pw', 'pm', 'py']),
|
|
102
|
+
z
|
|
103
|
+
.string()
|
|
104
|
+
.regex(/^\d{4}-\d{2}-\d{2}to\d{4}-\d{2}-\d{2}$/, "Use 'pd', 'pw', 'pm', 'py', or a custom range as YYYY-MM-DDtoYYYY-MM-DD."),
|
|
105
|
+
])
|
|
106
|
+
.describe("Filters search results by when they were discovered. The following values are supported: 'pd' - Discovered within the last 24 hours. 'pw' - Discovered within the last 7 days. 'pm' - Discovered within the last 31 days. 'py' - Discovered within the last 365 days. 'YYYY-MM-DDtoYYYY-MM-DD' - Timeframe is also supported by specifying the date range e.g. 2022-04-01to2022-07-30.");
|
|
107
|
+
export const RequestParamsSchema = z.object({
|
|
108
|
+
query: z
|
|
109
|
+
.string()
|
|
110
|
+
.trim()
|
|
111
|
+
.min(1)
|
|
112
|
+
.max(400)
|
|
113
|
+
.refine((str) => str.split(/\s+/).length <= 50, 'Query cannot exceed 50 words')
|
|
114
|
+
.describe("The user's search query term. Query can not be empty. Maximum of 400 characters and 50 words in the query."),
|
|
115
|
+
country: CountryCodesSchema.describe('The search query country, where the results come from. The country string is limited to 2 character country codes of supported countries.').optional(),
|
|
116
|
+
search_lang: SearchLangCodesSchema.describe('The search language preference. The 2 or more character language code for which the search results are provided.').optional(),
|
|
117
|
+
count: z
|
|
118
|
+
.number()
|
|
119
|
+
.int()
|
|
120
|
+
.min(1)
|
|
121
|
+
.max(50)
|
|
122
|
+
.describe('The maximum number of search results considered to select the LLM context data. The default is 20 and the maximum is 50.')
|
|
123
|
+
.optional(),
|
|
124
|
+
spellcheck: z.boolean().describe('Whether to enable spellcheck on the query.').optional(),
|
|
125
|
+
maximum_number_of_urls: z
|
|
126
|
+
.number()
|
|
127
|
+
.int()
|
|
128
|
+
.min(1)
|
|
129
|
+
.max(50)
|
|
130
|
+
.describe('Maximum number of different URLs to include in LLM context.')
|
|
131
|
+
.optional(),
|
|
132
|
+
maximum_number_of_tokens: z
|
|
133
|
+
.number()
|
|
134
|
+
.int()
|
|
135
|
+
.min(1024)
|
|
136
|
+
.max(32768)
|
|
137
|
+
.describe('Approximate maximum number of tokens to include in context. The default is 8192 and maximum is 32768.')
|
|
138
|
+
.optional(),
|
|
139
|
+
maximum_number_of_snippets: z
|
|
140
|
+
.number()
|
|
141
|
+
.int()
|
|
142
|
+
.min(1)
|
|
143
|
+
.max(256)
|
|
144
|
+
.describe('Maximum number of different snippets (or chunks of text) to include in LLM context. The default is 50 and maximum is 256.')
|
|
145
|
+
.optional(),
|
|
146
|
+
context_threshold_mode: z
|
|
147
|
+
.enum(['disabled', 'strict', 'lenient', 'balanced'])
|
|
148
|
+
.describe('The mode to use to determine the threshold for including content in context. Default is balanced.')
|
|
149
|
+
.optional(),
|
|
150
|
+
maximum_number_of_tokens_per_url: z
|
|
151
|
+
.number()
|
|
152
|
+
.int()
|
|
153
|
+
.min(512)
|
|
154
|
+
.max(8192)
|
|
155
|
+
.describe('Maximum number of tokens to include per URL. The default is 4096 and maximum is 8192.')
|
|
156
|
+
.optional(),
|
|
157
|
+
maximum_number_of_snippets_per_url: z
|
|
158
|
+
.number()
|
|
159
|
+
.int()
|
|
160
|
+
.min(1)
|
|
161
|
+
.max(100)
|
|
162
|
+
.describe('Maximum number of snippets to include per URL. The default is 50 and maximum is 100.')
|
|
163
|
+
.optional(),
|
|
164
|
+
goggles: z
|
|
165
|
+
.union([z.string(), z.array(z.string())])
|
|
166
|
+
.describe("Goggles act as a custom re-ranking on top of Brave's search index. The parameter supports both a url where the Goggle is hosted or the definition of the Goggle. Multiple goggle URLs and/or definitions can be provided in an array. For more details, refer to the Goggles repository (i.e., https://github.com/brave/goggles-quickstart).")
|
|
167
|
+
.optional(),
|
|
168
|
+
freshness: FreshnessSchema.optional(),
|
|
169
|
+
enable_local: z
|
|
170
|
+
.boolean()
|
|
171
|
+
.describe('Whether to enable local recall. Not setting this value means auto-detect and uses local recall if any of the localization headers are provided.')
|
|
172
|
+
.optional(),
|
|
173
|
+
enable_source_metadata: z
|
|
174
|
+
.boolean()
|
|
175
|
+
.describe('Enable source metadata enrichment (site_name, favicon) in the sources attribute of the response.')
|
|
176
|
+
.optional(),
|
|
177
|
+
});
|
|
178
|
+
export const RequestHeadersSchema = z.object({
|
|
179
|
+
'x-loc-lat': z
|
|
180
|
+
.number()
|
|
181
|
+
.min(-90)
|
|
182
|
+
.max(90)
|
|
183
|
+
.describe("The latitude of the client's geographical location in degrees, to provide relevant local results. The latitude must be greater than or equal to -90.0 degrees and less than or equal to +90.0 degrees.")
|
|
184
|
+
.optional(),
|
|
185
|
+
'x-loc-long': z
|
|
186
|
+
.number()
|
|
187
|
+
.min(-180)
|
|
188
|
+
.max(180)
|
|
189
|
+
.describe("The longitude of the client's geographical location in degrees, to provide relevant local results. The longitude must be greater than or equal to -180.0 and less than or equal to +180.0 degrees.")
|
|
190
|
+
.optional(),
|
|
191
|
+
'x-loc-city': z.string().describe('The generic name of the client city').optional(),
|
|
192
|
+
'x-loc-state': z
|
|
193
|
+
.string()
|
|
194
|
+
.max(3)
|
|
195
|
+
.describe("A code which could be up to three characters, that represent the client's state/region. The region is the first-level subdivision (the broadest or least specific) of the ISO 3166-2 code.")
|
|
196
|
+
.optional(),
|
|
197
|
+
'x-loc-state-name': z
|
|
198
|
+
.string()
|
|
199
|
+
.describe('The name of the client’s state/region. The region is the first-level subdivision (the broadest or least specific) of the ISO 3166-2 code.')
|
|
200
|
+
.optional(),
|
|
201
|
+
'x-loc-country': z
|
|
202
|
+
.string()
|
|
203
|
+
.length(2)
|
|
204
|
+
.describe('The two letter country code for the client’s country. For a list of country codes, see ISO 3166-1 alpha-2')
|
|
205
|
+
.optional(),
|
|
206
|
+
'x-loc-postal-code': z.string().describe('The client’s postal code').optional(),
|
|
207
|
+
'api-version': z
|
|
208
|
+
.string()
|
|
209
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
210
|
+
.describe('The API version to use. This is denoted by the format YYYY-MM-DD. Default is the latest that is available. Read more about API versioning at https://api-dashboard.search.brave.com/documentation/guides/versioning.')
|
|
211
|
+
.optional(),
|
|
212
|
+
accept: z
|
|
213
|
+
.enum(['application/json', '*/*'])
|
|
214
|
+
.describe('The default supported media type is application/json.')
|
|
215
|
+
.optional(),
|
|
216
|
+
'cache-control': z
|
|
217
|
+
.literal('no-cache')
|
|
218
|
+
.describe('Brave Search will return cached content by default. To prevent caching set the Cache-Control header to no-cache. This is currently done as best effort.')
|
|
219
|
+
.optional(),
|
|
220
|
+
'user-agent': z
|
|
221
|
+
.string()
|
|
222
|
+
.describe('The user agent originating the request. Brave search can utilize the user agent to provide a different experience depending on the device as described by the string. The user agent should follow the commonly used browser agent strings on each platform. For more information on curating user agents, see RFC 9110.')
|
|
223
|
+
.optional(),
|
|
224
|
+
});
|
|
225
|
+
export const LlmContextInputSchema = z.object({
|
|
226
|
+
...RequestParamsSchema.shape,
|
|
227
|
+
...RequestHeadersSchema.shape,
|
|
228
|
+
});
|