@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 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 HTTP and STDIO transports, with HTTP 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, 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: "http")
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: http)
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", "stdio"],
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 STDIO mode testing, add `--transport stdio` to the arguments in the Inspector UI.
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:
@@ -9,10 +9,12 @@ const typeToPathMap = {
9
9
  web: '/res/v1/web/search',
10
10
  summarizer: '/res/v1/summarizer/search',
11
11
  };
12
- const defaultRequestHeaders = {
13
- Accept: 'application/json',
14
- 'Accept-Encoding': 'gzip',
15
- 'X-Subscription-Token': config.braveApiKey,
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 = { ...defaultRequestHeaders, ...requestHeaders };
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: 'http',
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 ?? 'http')
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 requires explicit request
11
- if (options.transport === 'stdio') {
12
- await stdioServer.start();
10
+ // default to stdio server unless http is explicitly requested
11
+ if (options.transport === 'http') {
12
+ httpServer.start();
13
13
  return;
14
14
  }
15
- // default to http server
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
- export default function createMcpServer() {
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
- mcpServer.tool(tool.name, tool.description, tool.inputSchema, tool.annotations, tool.execute);
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 './params.js';
1
+ import params from './schemas/input.js';
2
2
  import API from '../../BraveAPI/index.js';
3
- import { stringify } from '../../utils.js';
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, or things, ideas for graphic design, inspiration for art, or anything else where images are useful. When relaying the results in a markdown-supporting environment, it is helpful to include some/all of the images in the results. Example: ![Image Description](image_url).
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., ![image.title](image.properties.url)).
11
11
  `;
12
12
  export const execute = async (params) => {
13
- const content = [];
14
13
  const response = await API.issueRequest('images', params);
15
- for (const { url: page_url, title, thumbnail, properties } of response.results) {
16
- // Skip results without an image
17
- if (!thumbnail?.src)
18
- continue;
19
- // Prefer property URL as it is the shortest-possible URL
20
- const image_url = properties?.url ?? thumbnail.src;
21
- const fetched_image = await fetchImage(image_url);
22
- if (fetched_image) {
23
- const { mimeType, data } = fetched_image;
24
- content.push({ type: 'text', text: stringify({ title, page_url, image_url }) }, { type: 'image', mimeType, data });
25
- }
26
- }
27
- return { content, isError: false };
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
- async function fetchImage(url) {
30
- try {
31
- const response = await fetch(url);
32
- const buffer = await response.arrayBuffer();
33
- return {
34
- data: Buffer.from(buffer).toString('base64'),
35
- mimeType: response.headers.get('content-type') ?? 'image/jpeg',
36
- };
37
- }
38
- catch (error) {
39
- return null;
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
  };
@@ -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
  };
@@ -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": "1.3.7",
4
- "description": "MCP server for Brave Search. Uses the Brave Search API to return results from the web, including ranked links, images, and videos, as well as AI summaries of pages, rich results, and more.",
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:stdio": "npx @modelcontextprotocol/inspector --transport stdio"
36
+ "inspector:http": "npx @modelcontextprotocol/inspector --transport http"
34
37
  },
35
38
  "dependencies": {
36
- "@modelcontextprotocol/sdk": "1.17.3",
39
+ "@modelcontextprotocol/sdk": "1.18.0",
37
40
  "commander": "14.0.0",
38
- "dotenv": "^17.2.1",
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.0",
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
  }