Skip to main content
Glama

Brave Search MCP Server

mcp.md12.9 kB
# Brave Search MCP Server Documentation ## Overview This guide walks you through setting up and running a Model Context Protocol (MCP) server that provides Brave Search functionality via Streamable HTTP transport. The server offers two search tools: web search and local business search. ## Prerequisites ### Required Software - **Bun** (JavaScript runtime) - Install from [bun.sh](https://bun.sh) - **Brave Search API Key** - Obtain from [Brave Search API](https://api.search.brave.com/) - **Basic terminal/command line knowledge** ### System Requirements - Node.js 18+ compatible environment - Internet connection for API calls - Available port (default: 8000) ## Installation & Setup ### 1. Project Setup ```bash # Clone or download the brave-search MCP server files # Ensure you have these files: # - index.ts (main server file) # - package.json (dependencies) # - tsconfig.json (TypeScript config) ``` ### 2. Install Dependencies ```bash # Navigate to the brave-search directory cd /path/to/brave-search # Install all required packages bun install ``` **What this does:** Downloads the MCP SDK and other dependencies needed to run the server. ### 3. API Key Configuration ```bash # Option 1: Environment variable (recommended for production) export BRAVE_API_KEY="your-brave-api-key-here" # Option 2: The server has a fallback hardcoded key for testing # (already configured in the current implementation) ``` **Security Note:** Never commit API keys to version control. Use environment variables in production. ## Running the Server ### Starting the Server ```bash # Start the server on port 8000 with Streamable HTTP transport bun run index.ts --port 8000 ``` **Expected Output:** ``` Listening on http://localhost:8000 Put this in your client config: { "mcpServers": { "brave-search": { "url": "http://localhost:8000/sse" } } } If your client supports streamable HTTP, you can use the /mcp endpoint instead. ``` ### Understanding the Endpoints The server provides two endpoints: 1. **`/sse`** - Server-Sent Events transport (for backward compatibility) 2. **`/mcp`** - Streamable HTTP transport (recommended for new implementations) ## Testing the Server ### 1. Initialize MCP Session ```bash curl -v -X POST http://localhost:8000/mcp \ -H "Accept: application/json, text/event-stream" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} }, "clientInfo": { "name": "TestClient", "version": "1.0.0" } } }' ``` **What to look for:** - Status: `200 OK` - Header: `mcp-session-id: [uuid]` (save this for next steps) - Response: JSON with server capabilities ### 2. Send Initialized Notification ```bash curl -X POST http://localhost:8000/mcp \ -H "Accept: application/json, text/event-stream" \ -H "Content-Type: application/json" \ -H "Mcp-Session-Id: YOUR_SESSION_ID_FROM_STEP_1" \ -d '{ "jsonrpc": "2.0", "method": "notifications/initialized" }' ``` **Critical:** Replace `YOUR_SESSION_ID_FROM_STEP_1` with the actual session ID from step 1. ### 3. List Available Tools ```bash curl -X POST http://localhost:8000/mcp \ -H "Accept: application/json, text/event-stream" \ -H "Content-Type: application/json" \ -H "Mcp-Session-Id: YOUR_SESSION_ID" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }' ``` **Expected Response:** List of two tools: - `brave_web_search` - General web search - `brave_local_search` - Local business search ### 4. Perform Web Search ```bash curl -X POST http://localhost:8000/mcp \ -H "Accept: application/json, text/event-stream" \ -H "Content-Type: application/json" \ -H "Mcp-Session-Id: YOUR_SESSION_ID" \ -d '{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "brave_web_search", "arguments": { "query": "latest AI news", "count": 3 } } }' ``` ### 5. Perform Local Search ```bash curl -X POST http://localhost:8000/mcp \ -H "Accept: application/json, text/event-stream" \ -H "Content-Type: application/json" \ -H "Mcp-Session-Id: YOUR_SESSION_ID" \ -d '{ "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "brave_local_search", "arguments": { "query": "pizza near Times Square NYC", "count": 2 } } }' ``` ## Implementation Details: From Stdio to Streamable HTTP ### What We Changed The original brave-search MCP server only supported stdio transport (standard input/output). We modified it to support Streamable HTTP transport for AWS Lambda compatibility and better web integration. ### Key Code Changes #### 1. Added HTTP Transport Imports ```typescript // Added these imports import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { createServer } from "http"; import { randomUUID } from "crypto"; ``` #### 2. Command Line Argument Parsing ```typescript // Added argument parsing for --port flag function parseArgs() { const args = process.argv.slice(2); const options: { port?: number; headless?: boolean } = {}; for (let i = 0; i < args.length; i++) { if (args[i] === '--port' && i + 1 < args.length) { options.port = parseInt(args[i + 1], 10); i++; } } return options; } ``` #### 3. HTTP Server Setup ```typescript // Added HTTP server with dual transport support function startHttpServer(port: number) { const httpServer = createServer(); httpServer.on('request', async (req, res) => { const url = new URL(req.url!, `http://${req.headers.host}`); if (url.pathname === '/sse') { await handleSSE(req, res); } else if (url.pathname === '/mcp') { await handleStreamable(req, res); } else { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not Found'); } }); } ``` #### 4. Session Management ```typescript // Added session storage for concurrent connections const streamableSessions = new Map<string, {transport: any, server: any}>(); // Each session gets its own server instance function createServerInstance() { const serverInstance = new Server({...}); // Set up tool handlers... return serverInstance; } ``` #### 5. Transport Handlers ```typescript // Streamable HTTP transport handler async function handleStreamable(req: any, res: any) { const sessionId = req.headers['mcp-session-id'] as string | undefined; if (sessionId) { // Use existing session const session = streamableSessions.get(sessionId); return await session.transport.handleRequest(req, res); } // Create new session for initialization const serverInstance = createServerInstance(); const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (sessionId) => { streamableSessions.set(sessionId, { transport, server: serverInstance }); } }); await serverInstance.connect(transport); await transport.handleRequest(req, res); } ``` ### Why These Changes Were Necessary 1. **Lambda Compatibility**: AWS Lambda doesn't support stdio, requiring HTTP-based communication 2. **Web Integration**: HTTP transport enables direct browser and web service integration 3. **Concurrent Sessions**: Multiple clients can connect simultaneously with session isolation 4. **Modern Protocol**: Streamable HTTP is the modern MCP transport standard ### Transport Comparison | Feature | Stdio Transport | Streamable HTTP Transport | |---------|----------------|---------------------------| | Use Case | CLI applications | Web services, Lambda | | Concurrency | Single client | Multiple concurrent clients | | State Management | Process-based | Session-based | | AWS Lambda | ❌ Not supported | ✅ Fully supported | | Web Browser | ❌ Not possible | ✅ Direct integration | | Debugging | Simple | Requires HTTP tools | ## Understanding MCP Concepts ### Session Management - Each client connection gets a unique session ID - Sessions maintain state between requests - Sessions are automatically cleaned up when connections close - **Important:** Always include the `Mcp-Session-Id` header after initialization ### Transport Types 1. **Streamable HTTP** (`/mcp`): Modern, efficient, supports streaming responses 2. **SSE** (`/sse`): Backward compatibility, uses Server-Sent Events ### Message Flow 1. **Initialize** - Establish capabilities and protocol version 2. **Initialized** - Confirm initialization complete 3. **Tools/List** - Discover available tools 4. **Tools/Call** - Execute tool functions ## Common Issues & Troubleshooting ### "Server not initialized" Error **Cause:** Missing or incorrect session ID **Solution:** Ensure you're using the session ID from the initialization response ### "Session not found" Error **Cause:** Session expired or invalid session ID **Solution:** Re-initialize with a new session ### Port Already in Use **Cause:** Another process is using port 8000 **Solution:** ```bash # Kill process on port 8000 lsof -ti:8000 | xargs kill -9 # Or use a different port bun run index.ts --port 8001 ``` ### API Rate Limiting **Cause:** Exceeded Brave Search API limits **Solution:** The server has built-in rate limiting (1 request/second, 15000/month) ### Connection Timeout **Cause:** Network issues or server overload **Solution:** Check network connectivity and server resources ## Concurrent Connection Management ### How It Works - Each client gets its own server instance and transport - Sessions are isolated - no shared state between clients - Automatic cleanup when clients disconnect - Memory-efficient session storage using Maps ### Scaling Considerations ```typescript // Current session storage (in-memory) const streamableSessions = new Map<string, {transport: any, server: any}>(); ``` **For production:** - Consider Redis for session storage across multiple instances - Implement session cleanup timeouts - Monitor memory usage for session maps - Use load balancers for horizontal scaling ### Connection Limits - Default: No explicit connection limit - Memory-bound by available system resources - Each session uses ~1-5MB of memory ## Production Deployment ### Environment Variables ```bash export BRAVE_API_KEY="your-production-api-key" export PORT="8000" export NODE_ENV="production" ``` ### Process Management ```bash # Using PM2 for process management npm install -g pm2 pm2 start "bun run index.ts --port 8000" --name brave-search-mcp ``` ### Docker Deployment ```dockerfile FROM oven/bun:latest WORKDIR /app COPY package.json bun.lockb ./ RUN bun install COPY . . EXPOSE 8000 CMD ["bun", "run", "index.ts", "--port", "8000"] ``` ### AWS Lambda Deployment The server supports Streamable HTTP, making it suitable for serverless deployment: - Configure API Gateway to proxy requests to `/mcp` - Set appropriate timeout values (30s+) - Handle cold starts gracefully ## Security Best Practices ### API Key Security - Use environment variables, never hardcode keys - Rotate API keys regularly - Monitor API usage and set alerts ### Network Security - Bind to localhost (`127.0.0.1`) for local development - Use HTTPS in production - Implement proper authentication for public deployments ### Input Validation - The server validates JSON-RPC message format - Search queries are limited to 400 characters - Count parameters are bounded (1-20 results) ## Monitoring & Logging ### Built-in Logging The server logs: - Session creation/destruction - API errors and rate limiting - Connection events ### Health Checks ```bash # Simple health check curl -f http://localhost:8000/mcp || echo "Server down" ``` ### Metrics to Monitor - Active session count - API call frequency - Response times - Error rates - Memory usage ## Advanced Configuration ### Custom Rate Limiting ```typescript const RATE_LIMIT = { perSecond: 1, // Requests per second perMonth: 15000 // Monthly request limit }; ``` ### Timeout Configuration ```typescript // Adjust in createServerInstance() if needed const serverInstance = new Server({ name: "brave-search", version: "1.0.0" }, { capabilities: { tools: {} }, // Add timeout configs here }); ``` ## Support & Further Reading - [MCP Specification](https://modelcontextprotocol.io/specification/draft/) - [Brave Search API Documentation](https://api.search.brave.com/app/documentation) - [Bun Documentation](https://bun.sh/docs) This server is now ready for production use and can handle multiple concurrent connections efficiently while providing reliable Brave Search functionality through the MCP protocol.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/windsornguyen/brave-search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server