@brave/brave-search-mcp-server 1.3.7 → 2.0.3
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 +32 -5
- package/dist/BraveAPI/index.js +7 -5
- package/dist/config.js +47 -2
- package/dist/index.js +4 -5
- package/dist/server.js +10 -13
- package/dist/tools/images/index.js +42 -29
- package/dist/tools/images/schemas/output.js +20 -0
- package/dist/tools/images/schemas/response.js +58 -0
- package/dist/tools/local/index.js +9 -0
- package/dist/tools/news/index.js +9 -0
- package/dist/tools/summarizer/index.js +9 -0
- package/dist/tools/videos/index.js +9 -0
- package/dist/tools/web/index.js +9 -0
- package/package.json +13 -6
- /package/dist/tools/images/{params.js → schemas/input.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
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
|
|
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.
|
|
4
|
+
|
|
5
|
+
## Migration
|
|
6
|
+
|
|
7
|
+
### 1.x to 2.x
|
|
8
|
+
|
|
9
|
+
#### Default transport now STDIO
|
|
10
|
+
|
|
11
|
+
To follow established MCP conventions, the server now defaults to STDIO. If you would like to continue using HTTP, you will need to set the `BRAVE_MCP_TRANSPORT` environment variable to `http`, or provide the runtime argument `--transport http` when launching the server.
|
|
12
|
+
|
|
13
|
+
#### Response structure of `brave_image_search`
|
|
14
|
+
|
|
15
|
+
Version 1.x of the MCP server would return base64-encoded image data along with image URLs. This dramatically slowed down the response, as well as consumed unnecessarily context in the session. Version 2.x removes the base64-encoded data, and returns a response object that more closely reflects the original Brave Search API response. The updated output schema is defined in [`src/tools/images/schemas/output.ts`](https://github.com/brave/brave-search-mcp-server/blob/main/src/tools/images/schemas/output.ts).
|
|
4
16
|
|
|
5
17
|
## Tools
|
|
6
18
|
|
|
@@ -99,10 +111,12 @@ Generates AI-powered summaries from web search results using Brave's summarizati
|
|
|
99
111
|
The server supports the following environment variables:
|
|
100
112
|
|
|
101
113
|
- `BRAVE_API_KEY`: Your Brave Search API key (required)
|
|
102
|
-
- `BRAVE_MCP_TRANSPORT`: Transport mode ("http" or "stdio", default: "
|
|
114
|
+
- `BRAVE_MCP_TRANSPORT`: Transport mode ("http" or "stdio", default: "stdio")
|
|
103
115
|
- `BRAVE_MCP_PORT`: HTTP server port (default: 8080)
|
|
104
116
|
- `BRAVE_MCP_HOST`: HTTP server host (default: "0.0.0.0")
|
|
105
117
|
- `BRAVE_MCP_LOG_LEVEL`: Desired logging level("debug", "info", "notice", "warning", "error", "critical", "alert", or "emergency", default: "info")
|
|
118
|
+
- `BRAVE_MCP_ENABLED_TOOLS`: When used, specifies a whitelist for supported tools
|
|
119
|
+
- `BRAVE_MCP_DISABLED_TOOLS`: When used, specifies a blacklist for supported tools
|
|
106
120
|
|
|
107
121
|
### Command Line Options
|
|
108
122
|
|
|
@@ -111,9 +125,12 @@ node dist/index.js [options]
|
|
|
111
125
|
|
|
112
126
|
Options:
|
|
113
127
|
--brave-api-key <string> Brave API key
|
|
114
|
-
--transport <stdio|http> Transport type (default:
|
|
128
|
+
--transport <stdio|http> Transport type (default: stdio)
|
|
115
129
|
--port <number> HTTP server port (default: 8080)
|
|
116
130
|
--host <string> HTTP server host (default: 0.0.0.0)
|
|
131
|
+
--logging-level <string> Desired logging level (one of _debug_, _info_, _notice_, _warning_, _error_, _critical_, _alert_, or _emergency_)
|
|
132
|
+
--enabled-tools Tools whitelist (only the specified tools will be enabled)
|
|
133
|
+
--disabled-tools Tools blacklist (included tools will be disabled)
|
|
117
134
|
```
|
|
118
135
|
|
|
119
136
|
## Installation
|
|
@@ -145,7 +162,7 @@ Add this to your `claude_desktop_config.json`:
|
|
|
145
162
|
"mcpServers": {
|
|
146
163
|
"brave-search": {
|
|
147
164
|
"command": "npx",
|
|
148
|
-
"args": ["-y", "@brave/brave-search-mcp-server", "--transport", "
|
|
165
|
+
"args": ["-y", "@brave/brave-search-mcp-server", "--transport", "http"],
|
|
149
166
|
"env": {
|
|
150
167
|
"BRAVE_API_KEY": "YOUR_API_KEY_HERE"
|
|
151
168
|
}
|
|
@@ -283,7 +300,12 @@ node dist/index.js
|
|
|
283
300
|
npx @modelcontextprotocol/inspector node dist/index.js
|
|
284
301
|
```
|
|
285
302
|
|
|
286
|
-
For
|
|
303
|
+
STDIO is the default mode. For HTTP mode testing, add `--transport http` to the arguments in the Inspector UI.
|
|
304
|
+
|
|
305
|
+
### Testing via Smithery.AI
|
|
306
|
+
|
|
307
|
+
1. Establish and acquire a smithery.ai account and API key
|
|
308
|
+
2. Run `npm run install`, `npm run smithery:build`, and lastly `npm run smithery:dev` to begin testing
|
|
287
309
|
|
|
288
310
|
### Available Scripts
|
|
289
311
|
|
|
@@ -293,6 +315,11 @@ For STDIO mode testing, add `--transport stdio` to the arguments in the Inspecto
|
|
|
293
315
|
- `npm run format:check`: Check code formatting
|
|
294
316
|
- `npm run prepare`: Format and build (runs automatically on npm install)
|
|
295
317
|
|
|
318
|
+
- `npm run inspector`: Launch an instance of MCP Inspector
|
|
319
|
+
- `npm run inspector:stdio`: Launch a instance of MCP Inspector, configured for STDIO
|
|
320
|
+
- `npm run smithery:build`: Build the project for smithery.ai
|
|
321
|
+
- `npm run smithery:dev`: Launch the development environment for smithery.ai
|
|
322
|
+
|
|
296
323
|
### Docker Compose
|
|
297
324
|
|
|
298
325
|
For local development with Docker:
|
package/dist/BraveAPI/index.js
CHANGED
|
@@ -9,10 +9,12 @@ const typeToPathMap = {
|
|
|
9
9
|
web: '/res/v1/web/search',
|
|
10
10
|
summarizer: '/res/v1/summarizer/search',
|
|
11
11
|
};
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const getDefaultRequestHeaders = () => {
|
|
13
|
+
return {
|
|
14
|
+
Accept: 'application/json',
|
|
15
|
+
'Accept-Encoding': 'gzip',
|
|
16
|
+
'X-Subscription-Token': config.braveApiKey,
|
|
17
|
+
};
|
|
16
18
|
};
|
|
17
19
|
const isValidGoggleURL = (url) => {
|
|
18
20
|
try {
|
|
@@ -76,7 +78,7 @@ requestHeaders = {}) {
|
|
|
76
78
|
}
|
|
77
79
|
// Issue Request
|
|
78
80
|
const urlWithParams = url.toString() + '?' + queryParams.toString();
|
|
79
|
-
const headers = { ...
|
|
81
|
+
const headers = { ...getDefaultRequestHeaders(), ...requestHeaders };
|
|
80
82
|
const response = await fetch(urlWithParams, { headers });
|
|
81
83
|
// Handle Error
|
|
82
84
|
if (!response.ok) {
|
package/dist/config.js
CHANGED
|
@@ -1,25 +1,65 @@
|
|
|
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
|
+
import tools from './tools/index.js';
|
|
4
6
|
dotenv.config({ debug: false, quiet: true });
|
|
7
|
+
// Config schema for Smithery.ai
|
|
8
|
+
export const configSchema = z.object({
|
|
9
|
+
braveApiKey: z.string().describe('Your API key'),
|
|
10
|
+
enabledTools: z
|
|
11
|
+
.array(z.string())
|
|
12
|
+
.describe('Enforces a tool whitelist (cannot be used with disabledTools)')
|
|
13
|
+
.optional(),
|
|
14
|
+
disabledTools: z
|
|
15
|
+
.array(z.string())
|
|
16
|
+
.describe('Enforces a tool blacklist (cannot be used with enabledTools)')
|
|
17
|
+
.optional(),
|
|
18
|
+
loggingLevel: z
|
|
19
|
+
.enum(LoggingLevelSchema.options)
|
|
20
|
+
.default('info')
|
|
21
|
+
.describe('Desired logging level')
|
|
22
|
+
.optional(),
|
|
23
|
+
});
|
|
5
24
|
const state = {
|
|
6
|
-
transport: '
|
|
25
|
+
transport: 'stdio',
|
|
7
26
|
port: 8080,
|
|
8
27
|
host: '0.0.0.0',
|
|
9
28
|
braveApiKey: process.env.BRAVE_API_KEY ?? '',
|
|
10
29
|
loggingLevel: 'info',
|
|
11
30
|
ready: false,
|
|
31
|
+
enabledTools: [],
|
|
32
|
+
disabledTools: [],
|
|
12
33
|
};
|
|
34
|
+
export function isToolPermittedByUser(toolName) {
|
|
35
|
+
return state.enabledTools.length > 0
|
|
36
|
+
? state.enabledTools.includes(toolName)
|
|
37
|
+
: state.disabledTools.includes(toolName) === false;
|
|
38
|
+
}
|
|
13
39
|
export function getOptions() {
|
|
14
40
|
const program = new Command()
|
|
15
41
|
.option('--brave-api-key <string>', 'Brave API key', process.env.BRAVE_API_KEY ?? '')
|
|
16
42
|
.option('--logging-level <string>', 'Logging level', process.env.BRAVE_MCP_LOG_LEVEL ?? 'info')
|
|
17
|
-
.option('--transport <stdio|http>', 'transport type', process.env.BRAVE_MCP_TRANSPORT ?? '
|
|
43
|
+
.option('--transport <stdio|http>', 'transport type', process.env.BRAVE_MCP_TRANSPORT ?? 'stdio')
|
|
44
|
+
.option('--enabled-tools <names...>', 'tools to enable', process.env.BRAVE_MCP_ENABLED_TOOLS?.split(' ') ?? [])
|
|
45
|
+
.option('--disabled-tools <names...>', 'tools to disable', process.env.BRAVE_MCP_DISABLED_TOOLS?.split(' ') ?? [])
|
|
18
46
|
.option('--port <number>', 'desired port for HTTP transport', process.env.BRAVE_MCP_PORT ?? '8080')
|
|
19
47
|
.option('--host <string>', 'desired host for HTTP transport', process.env.BRAVE_MCP_HOST ?? '0.0.0.0')
|
|
20
48
|
.allowUnknownOption()
|
|
21
49
|
.parse(process.argv);
|
|
22
50
|
const options = program.opts();
|
|
51
|
+
const toolNames = Object.values(tools).map((tool) => tool.name);
|
|
52
|
+
// Validate tool inclusion configuration
|
|
53
|
+
const { enabledTools, disabledTools } = options;
|
|
54
|
+
if (enabledTools.length > 0 && disabledTools.length > 0) {
|
|
55
|
+
console.error('Error: --enabled-tools and --disabled-tools cannot be used together');
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
if ([...enabledTools, ...disabledTools].some((t) => !toolNames.includes(t))) {
|
|
59
|
+
console.error(`Invalid tool name used. Must be one of: ${toolNames.join(', ')}`);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
// Validate all other options
|
|
23
63
|
if (!['stdio', 'http'].includes(options.transport)) {
|
|
24
64
|
console.error(`Invalid --transport value: '${options.transport}'. Must be one of: stdio, http.`);
|
|
25
65
|
return false;
|
|
@@ -48,7 +88,12 @@ export function getOptions() {
|
|
|
48
88
|
state.port = options.port;
|
|
49
89
|
state.host = options.host;
|
|
50
90
|
state.loggingLevel = options.loggingLevel;
|
|
91
|
+
state.enabledTools = options.enabledTools;
|
|
92
|
+
state.disabledTools = options.disabledTools;
|
|
51
93
|
state.ready = true;
|
|
52
94
|
return options;
|
|
53
95
|
}
|
|
96
|
+
export function setOptions(options) {
|
|
97
|
+
return Object.assign(state, options);
|
|
98
|
+
}
|
|
54
99
|
export default state;
|
package/dist/index.js
CHANGED
|
@@ -7,13 +7,12 @@ async function main() {
|
|
|
7
7
|
console.error('Invalid configuration');
|
|
8
8
|
process.exit(1);
|
|
9
9
|
}
|
|
10
|
-
// stdio
|
|
11
|
-
if (options.transport === '
|
|
12
|
-
|
|
10
|
+
// default to stdio server unless http is explicitly requested
|
|
11
|
+
if (options.transport === 'http') {
|
|
12
|
+
httpServer.start();
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
httpServer.start();
|
|
15
|
+
await stdioServer.start();
|
|
17
16
|
}
|
|
18
17
|
main().catch((error) => {
|
|
19
18
|
console.error(error);
|
package/dist/server.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import tools from './tools/index.js';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import { SetLevelRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
3
|
import pkg from '../package.json' with { type: 'json' };
|
|
5
|
-
|
|
4
|
+
import { isToolPermittedByUser } from './config.js';
|
|
5
|
+
import { setOptions } from './config.js';
|
|
6
|
+
export { configSchema } from './config.js';
|
|
7
|
+
export default function createMcpServer(options) {
|
|
8
|
+
if (options?.config)
|
|
9
|
+
setOptions(options.config);
|
|
6
10
|
const mcpServer = new McpServer({
|
|
7
11
|
version: pkg.version,
|
|
8
12
|
name: 'brave-search-mcp-server',
|
|
@@ -14,18 +18,11 @@ export default function createMcpServer() {
|
|
|
14
18
|
},
|
|
15
19
|
instructions: `Use this server to search the Web for various types of data via the Brave Search API.`,
|
|
16
20
|
});
|
|
17
|
-
try {
|
|
18
|
-
mcpServer.server.assertCanSetRequestHandler(SetLevelRequestSchema.shape.method.value);
|
|
19
|
-
mcpServer.server.setRequestHandler(SetLevelRequestSchema, () => ({}));
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
/**
|
|
23
|
-
* An error here signifies native-handling of the SetLevel request.
|
|
24
|
-
* See https://github.com/modelcontextprotocol/typescript-sdk/issues/871.
|
|
25
|
-
*/
|
|
26
|
-
}
|
|
27
21
|
for (const tool of Object.values(tools)) {
|
|
28
|
-
|
|
22
|
+
// The user may have enabled/disabled this tool at runtime
|
|
23
|
+
if (!isToolPermittedByUser(tool.name))
|
|
24
|
+
continue;
|
|
25
|
+
tool.register(mcpServer);
|
|
29
26
|
}
|
|
30
27
|
return mcpServer;
|
|
31
28
|
}
|
|
@@ -1,48 +1,61 @@
|
|
|
1
|
-
import params from './
|
|
1
|
+
import params from './schemas/input.js';
|
|
2
2
|
import API from '../../BraveAPI/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import OutputSchema, { SimplifiedImageResultSchema } from './schemas/output.js';
|
|
4
4
|
export const name = 'brave_image_search';
|
|
5
5
|
export const annotations = {
|
|
6
6
|
title: 'Brave Image Search',
|
|
7
7
|
openWorldHint: true,
|
|
8
8
|
};
|
|
9
9
|
export const description = `
|
|
10
|
-
Performs an image search using the Brave Search API. Helpful for when you need pictures of people, places,
|
|
10
|
+
Performs an image search using the Brave Search API. Helpful for when you need pictures of people, places, things, graphic design ideas, art inspiration, and more. When relaying results in a markdown environment, it may be helpful to include images in the results (e.g., ).
|
|
11
11
|
`;
|
|
12
12
|
export const execute = async (params) => {
|
|
13
|
-
const content = [];
|
|
14
13
|
const response = await API.issueRequest('images', params);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
const items = response.results.map(simplifySchemaForLLM).filter((o) => o !== null);
|
|
15
|
+
const structuredContent = OutputSchema.safeParse({
|
|
16
|
+
type: 'object',
|
|
17
|
+
items,
|
|
18
|
+
count: items.length,
|
|
19
|
+
might_be_offensive: response.extra.might_be_offensive,
|
|
20
|
+
});
|
|
21
|
+
const payload = structuredContent.success
|
|
22
|
+
? structuredContent.data
|
|
23
|
+
: structuredContent.error.flatten();
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
26
|
+
isError: !structuredContent.success,
|
|
27
|
+
structuredContent: payload,
|
|
28
|
+
};
|
|
28
29
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
export const register = (mcpServer) => {
|
|
31
|
+
mcpServer.registerTool(name, {
|
|
32
|
+
title: name,
|
|
33
|
+
description: description,
|
|
34
|
+
inputSchema: params.shape,
|
|
35
|
+
outputSchema: OutputSchema.shape,
|
|
36
|
+
annotations: annotations,
|
|
37
|
+
}, execute);
|
|
38
|
+
};
|
|
39
|
+
function simplifySchemaForLLM(result) {
|
|
40
|
+
const parsed = SimplifiedImageResultSchema.safeParse({
|
|
41
|
+
title: result.title,
|
|
42
|
+
url: result.url,
|
|
43
|
+
page_fetched: result.page_fetched,
|
|
44
|
+
confidence: result.confidence,
|
|
45
|
+
properties: {
|
|
46
|
+
url: result.properties?.url,
|
|
47
|
+
width: result.properties?.width,
|
|
48
|
+
height: result.properties?.height,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
return parsed.success ? parsed.data : null;
|
|
41
52
|
}
|
|
42
53
|
export default {
|
|
43
54
|
name,
|
|
44
55
|
description,
|
|
45
56
|
annotations,
|
|
46
57
|
inputSchema: params.shape,
|
|
58
|
+
outputSchema: OutputSchema.shape,
|
|
47
59
|
execute,
|
|
60
|
+
register,
|
|
48
61
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ConfidenceSchema, ExtraSchema } from './response.js';
|
|
3
|
+
export const SimplifiedImageResultSchema = z.object({
|
|
4
|
+
title: z.string(),
|
|
5
|
+
url: z.string().url(),
|
|
6
|
+
page_fetched: z.string().datetime(),
|
|
7
|
+
confidence: ConfidenceSchema,
|
|
8
|
+
properties: z.object({
|
|
9
|
+
url: z.string().url(),
|
|
10
|
+
width: z.number().int().positive(),
|
|
11
|
+
height: z.number().int().positive(),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
const OutputSchema = z.object({
|
|
15
|
+
type: z.literal('object'),
|
|
16
|
+
items: z.array(SimplifiedImageResultSchema),
|
|
17
|
+
count: z.number().int().nonnegative(),
|
|
18
|
+
might_be_offensive: ExtraSchema.shape.might_be_offensive,
|
|
19
|
+
});
|
|
20
|
+
export default OutputSchema;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* https://api-dashboard.search.brave.com/app/documentation/image-search/responses
|
|
4
|
+
*/
|
|
5
|
+
const QuerySchema = z.object({
|
|
6
|
+
original: z.string().describe('The original query string.'),
|
|
7
|
+
altered: z.string().optional().describe('The altered query string.'),
|
|
8
|
+
spellcheck_off: z.boolean().optional().describe('Whether spellcheck was disabled.'),
|
|
9
|
+
show_strict_warning: z
|
|
10
|
+
.boolean()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe('When true, some results were blocked by safesearch.'),
|
|
13
|
+
});
|
|
14
|
+
const ThumbnailSchema = z.object({
|
|
15
|
+
src: z.string().url().optional().describe('The URL of the thumbnail.'),
|
|
16
|
+
width: z.number().int().positive().optional().describe('The width of the thumbnail.'),
|
|
17
|
+
height: z.number().int().positive().optional().describe('The height of the thumbnail.'),
|
|
18
|
+
});
|
|
19
|
+
const PropertiesSchema = z.object({
|
|
20
|
+
url: z.string().url().optional().describe('The URL of the image.'),
|
|
21
|
+
placeholder: z.string().url().optional().describe('The lower resolution placeholder image.'),
|
|
22
|
+
width: z.number().int().positive().optional().describe('The width of the image.'),
|
|
23
|
+
height: z.number().int().positive().optional().describe('The height of the image.'),
|
|
24
|
+
});
|
|
25
|
+
const MetaUrlSchema = z.object({
|
|
26
|
+
scheme: z.enum(['https', 'http']).optional().describe('The scheme of the URL.'),
|
|
27
|
+
netloc: z.string().optional().describe('The network location of the URL.'),
|
|
28
|
+
hostname: z.string().optional().describe('The lowercased hostname of the URL.'),
|
|
29
|
+
favicon: z.string().url().optional().describe('The URL of the favicon of the URL.'),
|
|
30
|
+
path: z.string().optional().describe('The path of the URL (useful as a display string).'),
|
|
31
|
+
});
|
|
32
|
+
export const ConfidenceSchema = z
|
|
33
|
+
.enum(['low', 'medium', 'high'])
|
|
34
|
+
.describe('The confidence level of the result.');
|
|
35
|
+
const ImageResultSchema = z.object({
|
|
36
|
+
type: z.literal('image_result').describe('The type of result.'),
|
|
37
|
+
title: z.string().optional().describe('The title of the image.'),
|
|
38
|
+
url: z.string().url().optional().describe('The URL of the image.'),
|
|
39
|
+
source: z.string().url().optional().describe('The source URL of the image.'),
|
|
40
|
+
page_fetched: z
|
|
41
|
+
.string()
|
|
42
|
+
.datetime()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe('The date and time the page was fetched.'),
|
|
45
|
+
thumbnail: ThumbnailSchema.optional().describe('The thumbnail of the image.'),
|
|
46
|
+
properties: PropertiesSchema.optional().describe('The metadata for the image.'),
|
|
47
|
+
meta_url: MetaUrlSchema.optional().describe('Information about the URL associated with the image.'),
|
|
48
|
+
confidence: ConfidenceSchema.optional(),
|
|
49
|
+
});
|
|
50
|
+
export const ExtraSchema = z.object({
|
|
51
|
+
might_be_offensive: z.boolean().describe('Whether the image might be offensive.'),
|
|
52
|
+
});
|
|
53
|
+
export const ImageSearchApiResponseSchema = z.object({
|
|
54
|
+
type: z.literal('images').describe('The type of API response.'),
|
|
55
|
+
query: QuerySchema.describe('The query used to generate the results.'),
|
|
56
|
+
results: z.array(ImageResultSchema).describe('The results of the image search.'),
|
|
57
|
+
extra: ExtraSchema.describe('Extra information about the search.'),
|
|
58
|
+
});
|
|
@@ -53,6 +53,14 @@ export const execute = async (params) => {
|
|
|
53
53
|
})),
|
|
54
54
|
};
|
|
55
55
|
};
|
|
56
|
+
export const register = (mcpServer) => {
|
|
57
|
+
mcpServer.registerTool(name, {
|
|
58
|
+
title: name,
|
|
59
|
+
description: description,
|
|
60
|
+
inputSchema: webParams.shape,
|
|
61
|
+
annotations: annotations,
|
|
62
|
+
}, execute);
|
|
63
|
+
};
|
|
56
64
|
const buildFallbackWebResponse = (web_fallback) => {
|
|
57
65
|
if (!web_fallback || web_fallback.results.length === 0)
|
|
58
66
|
throw new Error('No web results found');
|
|
@@ -133,4 +141,5 @@ export default {
|
|
|
133
141
|
annotations,
|
|
134
142
|
inputSchema: webParams.shape,
|
|
135
143
|
execute,
|
|
144
|
+
register,
|
|
136
145
|
};
|
package/dist/tools/news/index.js
CHANGED
|
@@ -44,10 +44,19 @@ export const execute = async (params) => {
|
|
|
44
44
|
}),
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
+
export const register = (mcpServer) => {
|
|
48
|
+
mcpServer.registerTool(name, {
|
|
49
|
+
title: name,
|
|
50
|
+
description: description,
|
|
51
|
+
inputSchema: params.shape,
|
|
52
|
+
annotations: annotations,
|
|
53
|
+
}, execute);
|
|
54
|
+
};
|
|
47
55
|
export default {
|
|
48
56
|
name,
|
|
49
57
|
description,
|
|
50
58
|
annotations,
|
|
51
59
|
inputSchema: params.shape,
|
|
52
60
|
execute,
|
|
61
|
+
register,
|
|
53
62
|
};
|
|
@@ -59,6 +59,14 @@ export const execute = async (params) => {
|
|
|
59
59
|
}
|
|
60
60
|
return response;
|
|
61
61
|
};
|
|
62
|
+
export const register = (mcpServer) => {
|
|
63
|
+
mcpServer.registerTool(name, {
|
|
64
|
+
title: name,
|
|
65
|
+
description: description,
|
|
66
|
+
inputSchema: summarizerQueryParams.shape,
|
|
67
|
+
annotations: annotations,
|
|
68
|
+
}, execute);
|
|
69
|
+
};
|
|
62
70
|
const pollForSummary = async (params, pollInterval = 50, attempts = 20) => {
|
|
63
71
|
let result = null;
|
|
64
72
|
while (!result && attempts > 0) {
|
|
@@ -84,4 +92,5 @@ export default {
|
|
|
84
92
|
annotations,
|
|
85
93
|
inputSchema: summarizerQueryParams.shape,
|
|
86
94
|
execute,
|
|
95
|
+
register,
|
|
87
96
|
};
|
|
@@ -28,10 +28,19 @@ export const execute = async (params) => {
|
|
|
28
28
|
}),
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
|
+
export const register = (mcpServer) => {
|
|
32
|
+
mcpServer.registerTool(name, {
|
|
33
|
+
title: name,
|
|
34
|
+
description: description,
|
|
35
|
+
inputSchema: params.shape,
|
|
36
|
+
annotations: annotations,
|
|
37
|
+
}, execute);
|
|
38
|
+
};
|
|
31
39
|
export default {
|
|
32
40
|
name,
|
|
33
41
|
description,
|
|
34
42
|
annotations,
|
|
35
43
|
inputSchema: params.shape,
|
|
36
44
|
execute,
|
|
45
|
+
register,
|
|
37
46
|
};
|
package/dist/tools/web/index.js
CHANGED
|
@@ -88,6 +88,14 @@ export const formatWebResults = (web) => {
|
|
|
88
88
|
extra_snippets,
|
|
89
89
|
}));
|
|
90
90
|
};
|
|
91
|
+
export const register = (mcpServer) => {
|
|
92
|
+
mcpServer.registerTool(name, {
|
|
93
|
+
title: name,
|
|
94
|
+
description: description,
|
|
95
|
+
inputSchema: params.shape,
|
|
96
|
+
annotations: annotations,
|
|
97
|
+
}, execute);
|
|
98
|
+
};
|
|
91
99
|
const formatFAQResults = (faq) => {
|
|
92
100
|
return (faq.results || []).map(({ question, answer, title, url }) => ({
|
|
93
101
|
question,
|
|
@@ -137,4 +145,5 @@ export default {
|
|
|
137
145
|
annotations,
|
|
138
146
|
inputSchema: params.shape,
|
|
139
147
|
execute,
|
|
148
|
+
register,
|
|
140
149
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brave/brave-search-mcp-server",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "Brave Search MCP Server: web results, images, videos, rich results, AI summaries, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
7
7
|
"brave",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"url": "https://github.com/brave/brave-search-mcp-server.git"
|
|
18
18
|
},
|
|
19
19
|
"type": "module",
|
|
20
|
+
"module": "dist/server.js",
|
|
20
21
|
"bin": {
|
|
21
22
|
"brave-search-mcp-server": "dist/index.js"
|
|
22
23
|
},
|
|
@@ -25,25 +26,31 @@
|
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
28
|
"build": "tsc && shx chmod +x dist/*.js",
|
|
29
|
+
"smithery:build": "npx @smithery/cli build",
|
|
30
|
+
"smithery:dev": "npx @smithery/cli dev",
|
|
28
31
|
"prepare": "npm run format && npm run build",
|
|
29
32
|
"watch": "tsc --watch",
|
|
30
33
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
31
34
|
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
32
35
|
"inspector": "npx @modelcontextprotocol/inspector",
|
|
33
|
-
"inspector:
|
|
36
|
+
"inspector:http": "npx @modelcontextprotocol/inspector --transport http"
|
|
34
37
|
},
|
|
35
38
|
"dependencies": {
|
|
36
|
-
"@modelcontextprotocol/sdk": "1.
|
|
39
|
+
"@modelcontextprotocol/sdk": "1.18.0",
|
|
37
40
|
"commander": "14.0.0",
|
|
38
|
-
"dotenv": "
|
|
41
|
+
"dotenv": "17.2.2",
|
|
39
42
|
"express": "5.1.0",
|
|
40
43
|
"zod": "3.25.76"
|
|
41
44
|
},
|
|
42
45
|
"devDependencies": {
|
|
43
46
|
"@types/express": "5.0.3",
|
|
44
|
-
"@types/node": "24.3.
|
|
47
|
+
"@types/node": "24.3.1",
|
|
45
48
|
"prettier": "3.6.2",
|
|
46
49
|
"shx": "0.4.0",
|
|
50
|
+
"tsx": "4.20.5",
|
|
47
51
|
"typescript": "5.9.2"
|
|
52
|
+
},
|
|
53
|
+
"overrides": {
|
|
54
|
+
"formdata-node": "6.0.3"
|
|
48
55
|
}
|
|
49
56
|
}
|
|
File without changes
|