A Model Context Protocol (MCP) server that provides web search and content extraction tools for AI assistants. Built with Bun, Hono, and the MCP SDK.
- MCP Server with stdio and HTTP transports
- Web Search via Brave Search and DuckDuckGo with aggregated, ranked results
- Content Extraction — fetch any URL and extract clean Markdown via readability parsing
- Content Resolution — built-in resolvers for GitHub issues, Stack Exchange, and Wikipedia
- Security — URL validation, anti-bot detection, proxy agent support
- Structured Logging via
pino - Schema Validation via
zod
| Package | Description |
|---|---|
apps/web-search-mcp |
CLI application — starts the MCP server (stdio or HTTP) |
packages/web-search-mcp |
MCP server and tool definitions (web_search, web_fetch, get_content) |
packages/web-search-core |
Search aggregation, content extraction, security, and configuration |
packages/common |
Shared utilities |
just setup
just lint
just test
just bdd
just test-all
# Start MCP server over stdio (for use with Claude Desktop, Cursor, etc.)
bun run apps/web-search-mcp/src/cli.ts stdio
# Start HTTP server (default port 3000)
bun run apps/web-search-mcp/src/cli.ts http --port 3000Search the web and return aggregated, ranked results from multiple providers.
Fetch a URL and return its content as Markdown.
Resolve structured content from known sources (GitHub issues, Stack Exchange, Wikipedia).
- BDD acceptance tests via
features/*.featureandjust bdd. - Unit tests via Vitest in
apps/*/src/*.test.tsandpackages/*/src/*.test.ts. - Property tests with
fast-checkinside the standard Vitest run for invariants. - Optional fuzzing with
jazzer.jsfor parser-like or security-sensitive packages. - Optional benchmarks with Vitest Bench for code with explicit performance targets.
- Write a failing Gherkin scenario in
features/*.feature. - Drive implementation with failing Vitest tests.
- Add
fast-checkproperties for invariants across many generated inputs. - Run
just testso deterministic examples and generated property checks execute together. - Implement the smallest change that makes the inner loop pass, then re-run
just bdd.
- Application packages under
apps/* - Reusable library packages under
packages/* - Shared devDependencies in root
package.json workspace:*for internal package references
just format
just lint
just test
just bdd
just test-all
just build
just typecheckApache-2.0