🚀 LLM Researcher
LLM Researcher 是一款轻量级的 MCP(模型上下文协议)服务器,专为大语言模型编排设计,具备高效的网页内容搜索与提取能力。借助这款 CLI 工具,大语言模型可在 DuckDuckGo 上进行搜索,并从网页中提取简洁、适配大语言模型的内容。
项目采用 TypeScript、tsup 和 vitest 构建,带来现代化的开发体验。
✨ 主要特性
- 支持 MCP 服务器:提供模型上下文协议服务器,便于与大语言模型集成。
- 免费使用:使用 DuckDuckGo 的 HTML 端点,无需支付 API 费用。
- GitHub 代码搜索:可在 GitHub 仓库中搜索代码示例和实现模式。
- 智能内容提取:结合 Playwright 和 @mozilla/readability,提取简洁内容。
- 适配大语言模型的输出:输出经过净化处理的 Markdown 格式(仅包含 h1 - h3、粗体、斜体和链接)。
- 速率限制:遵循 DuckDuckGo 的速率限制,每秒仅发起 1 次请求。
- 跨平台支持:可在 macOS、Linux 和 WSL 上运行。
- 多种模式:提供 CLI、MCP 服务器、搜索、直接 URL 和交互模式。
- 类型安全:完全采用 TypeScript 实现,具备严格的类型检查。
- 现代化工具:使用 tsup 打包工具和 vitest 测试框架。
📦 安装指南
前提条件
- Node.js 20.0.0 或更高版本。
- 无需本地安装 Chrome,使用 Playwright 自带的 Chromium 浏览器。
安装步骤
cd light-research-mcp
pnpm install
pnpm build
pnpm install-browsers
pnpm link --global
💻 使用示例
MCP 服务器模式
作为模型上下文协议服务器,为大语言模型提供搜索和内容提取工具:
llmresearcher --mcp
与 Claude Code 集成
claude mcp add light-research-mcp /path/to/light-research-mcp/dist/bin/llmresearcher.js --mcp
claude mcp add light-research-mcp -s project /path/to/light-research-mcp/dist/bin/llmresearcher.js --mcp
claude mcp list
claude mcp get light-research-mcp
MCP 工具使用示例
配置完成后,可在 Claude 中使用这些工具:
> 在 GitHub 上搜索 React 钩子示例
Tool: github_code_search
Query: "useState useEffect hooks language:javascript"
> 搜索 TypeScript 最佳实践
Tool: duckduckgo_web_search
Query: "TypeScript best practices 2024"
Locale: us-en (或 wt-wt 表示无区域限制)
> 从搜索结果中提取内容
Tool: extract_content
URL: https://example.com/article-from-search-results
命令行界面
llmresearcher "machine learning transformers"
llmresearcher -g "useState hooks language:typescript"
llmresearcher -u https://example.com/article
llmresearcher
llmresearcher -v "search query"
llmresearcher --mcp
📚 详细文档
开发脚本
pnpm build
pnpm dev
pnpm test
pnpm test:run
pnpm test -- --coverage
pnpm type-check
pnpm clean
pnpm install-browsers
交互式命令
在搜索结果视图中:
- 1 - 10:通过编号选择结果。
- b 或 back:返回搜索结果。
- open <n>:在外部浏览器中打开第 n 个结果。
- q 或 quit:退出程序。
在查看内容时:
- b 或 back:返回搜索结果。
- /<term>:在提取的内容中搜索指定术语。
- open:在外部浏览器中打开当前页面。
- q 或 quit:退出程序。
配置
环境变量
在项目根目录下创建 .env
文件:
USER_AGENT=Mozilla/5.0 (compatible; LLMResearcher/1.0)
TIMEOUT=30000
MAX_RETRIES=3
RATE_LIMIT_DELAY=1000
CACHE_ENABLED=true
MAX_RESULTS=10
配置文件
在主目录下创建 ~/.llmresearcherrc
文件:
{
"userAgent": "Mozilla/5.0 (compatible; LLMResearcher/1.0)",
"timeout": 30000,
"maxRetries": 3,
"rateLimitDelay": 1000,
"cacheEnabled": true,
"maxResults": 10
}
配置选项
选项 |
默认值 |
描述 |
userAgent |
Mozilla/5.0 (compatible; LLMResearcher/1.0) |
HTTP 请求的用户代理 |
timeout |
30000 |
请求超时时间(毫秒) |
maxRetries |
3 |
失败请求的最大重试次数 |
rateLimitDelay |
1000 |
请求间隔时间(毫秒) |
cacheEnabled |
true |
启用/禁用本地缓存 |
maxResults |
10 |
显示的最大搜索结果数 |
架构
核心组件
- MCPResearchServer (
src/mcp-server.ts
)
- 模型上下文协议服务器的实现。
- 提供三个主要工具:github_code_search、duckduckgo_web_search、extract_content。
- 以 JSON 格式响应,便于大语言模型使用。
- DuckDuckGoSearcher (
src/search.ts
)
- 支持按地区对 DuckDuckGo 搜索结果进行 HTML 抓取。
- 对
/l/?uddg=
格式的链接进行 URL 解码。
- 实现速率限制和重试逻辑。
- GitHubCodeSearcher (
src/github-code-search.ts
)
- 通过 gh CLI 集成 GitHub 代码搜索 API。
- 支持使用语言、仓库和文件过滤器进行高级查询。
- 实现身份验证和速率限制。
- ContentExtractor (
src/extractor.ts
)
- 使用 Playwright 渲染页面并阻止资源加载。
- 使用 @mozilla/readability 提取主要内容。
- 使用 DOMPurify 进行内容净化和 Markdown 转换。
- CLIInterface (
src/cli.ts
)
- 提供交互式命令行界面。
- 支持搜索结果导航。
- 支持内容查看和文本搜索。
- Configuration (
src/config.ts
)
- 加载环境变量和 RC 文件配置。
- 支持详细日志记录。
内容处理流程
MCP 服务器模式
- 搜索:
- DuckDuckGo:通过 HTML 端点获取结果 → 解析结果 → 以 JSON 格式响应并支持分页。
- GitHub:使用代码搜索 API → 格式化结果 → 以 JSON 格式响应并包含代码片段。
- 提取:从搜索结果中获取 URL → 使用 Playwright 导航到页面 → 提取内容。
- 处理:使用 @mozilla/readability 提取内容 → 使用 DOMPurify 净化内容 → 输出干净的 JSON。
- 输出:以结构化 JSON 格式输出,供大语言模型使用。
CLI 模式
- 搜索:通过 DuckDuckGo HTML 端点获取结果 → 解析结果 → 显示编号列表。
- 提取:使用 Playwright 导航到页面 → 阻止资源加载 → 进行 JS 渲染。
- 处理:使用 @mozilla/readability 提取内容 → 使用 DOMPurify 净化内容 → 转换为 Turndown Markdown。
- 输出:输出干净的 Markdown 格式,仅包含 h1 - h3、粗体、斜体 和 链接。
安全特性
- 资源阻止:为提高速度和安全性,阻止加载图像、CSS 和字体。
- 内容净化:使用 DOMPurify 移除脚本、iframe 和危险元素。
- 受限 Markdown:仅允许安全的格式化元素(h1 - h3、strong、em、a)。
- 速率限制:遵循 DuckDuckGo 的速率限制,采用指数退避策略进行重试。
示例
MCP 服务器与 Claude Code 结合使用
1. GitHub 代码搜索
你: "查找用于状态管理的 React 钩子示例"
Claude 使用 github_code_search 工具:
{
"query": "useState useReducer state management language:javascript",
"results": [
{
"title": "facebook/react/packages/react/src/ReactHooks.js",
"url": "https://raw.githubusercontent.com/facebook/react/main/packages/react/src/ReactHooks.js",
"snippet": "function useState(initialState) {\n return dispatcher.useState(initialState);\n}"
}
],
"pagination": {
"currentPage": 1,
"hasNextPage": true,
"nextPageToken": "2"
}
}
2. 带地区设置的网页搜索
你: "搜索日语的 Vue.js 教程"
Claude 使用 duckduckgo_web_search 工具:
{
"query": "Vue.js チュートリアル 入門",
"locale": "jp-jp",
"results": [
{
"title": "Vue.js入門ガイド",
"url": "https://example.com/vue-tutorial",
"snippet": "Vue.jsの基本的な使い方を学ぶチュートリアル..."
}
]
}
3. 内容提取
你: "从那个 Vue.js 教程中提取完整内容"
Claude 使用 extract_content 工具:
{
"url": "https://example.com/vue-tutorial",
"title": "Vue.js入門ガイド",
"extractedAt": "2024-01-15T10:30:00.000Z",
"content": "# Vue.js入門ガイド\n\nVue.jsは...\n\n## インストール\n\n..."
}
CLI 示例
基本搜索
$ llmresearcher "python web scraping"
🔍 搜索结果:
══════════════════════════════════════════════════
1. Python Web Scraping Tutorial
URL: https://realpython.com/python-web-scraping-practical-introduction/
完整的使用 Python 和 requests、Beautiful Soup 进行网页抓取的教程...
2. Web Scraping with Python - BeautifulSoup and requests
URL: https://www.dataquest.io/blog/web-scraping-python-tutorial/
学习如何使用 Python、Beautiful Soup 和 requests 进行网页抓取...
══════════════════════════════════════════════════
命令: [1-10] 选择结果 | b) 返回 | q) 退出 | open <n>) 在浏览器中打开
> 1
📥 正在从 "Python Web Scraping Tutorial" 提取内容
📄 内容:
══════════════════════════════════════════════════
**Python Web Scraping Tutorial**
来源: https://realpython.com/python-web-scraping-practical-introduction/
提取时间: 2024-01-15T10:30:00.000Z
──────────────────────────────────────────────────
网页抓取是从网页收集和解析原始数据的过程...
网页抓取是一种自动访问和提取大量网页数据的技术...
══════════════════════════════════════════════════
命令: b) 返回结果 | /<term>) 在文本中搜索 | q) 退出 | open) 在浏览器中打开
> /beautiful soup
🔍 找到 3 个与 "beautiful soup" 匹配的结果:
──────────────────────────────────────────────────
第 15 行: Beautiful Soup is a Python library for parsing HTML and XML documents.
第 42 行: from bs4 import BeautifulSoup
第 67 行: soup = BeautifulSoup(html_content, 'html.parser')
直接 URL 模式
$ llmresearcher -u https://docs.python.org/3/tutorial/
📄 内容:
══════════════════════════════════════════════════
**The Python Tutorial**
来源: https://docs.python.org/3/tutorial/
提取时间: 2024-01-15T10:35:00.000Z
──────────────────────────────────────────────────
Python 是一种易于学习、功能强大的编程语言...
在以下示例中,输入和输出是有区别的...
详细日志模式
$ llmresearcher -v "nodejs tutorial"
[详细信息] 正在搜索: https://duckduckgo.com/html/?q=nodejs%20tutorial&kl=us-en
[详细信息] 响应状态码: 200,耗时 847ms
[详细信息] 解析了 10 个结果
[详细信息] 正在启动浏览器...
[详细信息] 阻止资源: https://example.com/style.css
[详细信息] 阻止资源: https://example.com/image.png
[详细信息] 正在导航到页面...
[详细信息] 页面加载完成,耗时 1243ms
[详细信息] 正在使用 Readability 处理内容...
[详细信息] Readability 提取成功
[详细信息] 正在关闭浏览器...
测试
运行测试
pnpm test
pnpm test:run
pnpm test -- --coverage
测试覆盖率
测试套件包括:
- 单元测试:对单个组件进行测试。
search.test.ts
:测试 DuckDuckGo 搜索功能、URL 解码和速率限制。
extractor.test.ts
:测试内容提取、Markdown 转换和资源管理。
config.test.ts
:测试配置验证和环境处理。
- 集成测试:进行端到端的工作流测试。
integration.test.ts
:测试完整的搜索到提取工作流、错误处理和清理操作。
测试特性
- 快速:由 vitest 提供支持,可快速获得反馈。
- 类型安全:测试代码完全支持 TypeScript。
- 隔离性:每个测试会清理其使用的资源。
- 全面性:覆盖搜索、提取、配置和集成等场景。
故障排除
常见问题
“未找到浏览器” 错误
pnpm install-browsers
速率限制问题
- 工具会自动处理速率限制,每次请求间隔 1 秒。
- 若遇到 429 错误,工具会自动使用指数退避策略进行重试。
内容提取失败
- 部分网站可能会阻止自动化访问。
- 工具包含备用提取方法(优先提取主内容,若失败则提取 body 内容)。
- 使用详细日志模式 (
-v
) 查看详细错误信息。
权限拒绝(Unix/Linux)
chmod +x bin/llmresearcher.js
性能优化
该工具针对速度进行了优化:
- 资源阻止:自动阻止加载图像、CSS 和字体。
- 网络空闲检测:等待 JavaScript 渲染完成。
- 内容缓存:支持本地缓存,避免重复请求。
- 依赖精简:使用轻量级、专注的库。
开发
项目结构
light-research-mcp/
├── dist/ # 构建生成的 JavaScript 文件
│ ├── bin/
│ │ └── llmresearcher.js # CLI 入口点(可执行文件)
│ └── *.js # 编译后的 TypeScript 模块
├── src/ # TypeScript 源代码文件
│ ├── bin.ts # CLI 入口点
│ ├── index.ts # 主要的 LLMResearcher 类
│ ├── mcp-server.ts # MCP 服务器实现
│ ├── search.ts # DuckDuckGo 搜索实现
│ ├── github-code-search.ts # GitHub 代码搜索实现
│ ├── extractor.ts # 使用 Playwright 进行内容提取
│ ├── cli.ts # 交互式 CLI 界面
│ ├── config.ts # 配置管理
│ └── types.ts # TypeScript 类型定义
├── test/ # 测试文件(使用 vitest)
│ ├── search.test.ts # 搜索功能测试
│ ├── extractor.test.ts # 内容提取测试
│ ├── config.test.ts # 配置测试
│ ├── mcp-locale.test.ts # MCP 地区功能测试
│ ├── mcp-content-extractor.test.ts # MCP 内容提取器测试
│ └── integration.test.ts # 端到端集成测试
├── tsconfig.json # TypeScript 配置文件
├── tsup.config.ts # 构建配置文件
├── vitest.config.ts # 测试配置文件
├── package.json
└── README.md
依赖项
运行时依赖
- @modelcontextprotocol/sdk:模型上下文协议服务器实现。
- @mozilla/readability:从 HTML 中提取内容。
- cheerio:用于解析搜索结果的 HTML。
- commander:CLI 参数解析。
- dompurify:HTML 净化。
- dotenv:加载环境变量。
- jsdom:用于服务器端处理的 DOM 操作。
- playwright:用于浏览器自动化和 JS 渲染。
- turndown:将 HTML 转换为 Markdown。
开发依赖
- typescript:TypeScript 编译器。
- tsup:快速的 TypeScript 打包工具。
- vitest:快速的单元测试框架。
- @types/*:TypeScript 类型定义。
📄 许可证
本项目采用 MIT 许可证,详情请查看 LICENSE 文件。
贡献指南
- Fork 仓库。
- 创建功能分支。
- 进行修改。
- 如有必要,添加测试。
- 提交拉取请求。
路线图
计划功能
- 增强 MCP 工具:添加用于文档、API 等的专业搜索工具。
- 缓存层:基于 SQLite 实现 URL 到 Markdown 的缓存,缓存有效期为 24 小时。
- 搜索引擎抽象:支持 Brave Search、Bing 等其他搜索引擎。
- 内容摘要:提供可选的 AI 驱动的内容摘要功能。
- 导出格式:支持 JSON、纯文本等输出格式。
- 批量处理:支持从文件输入处理多个 URL。
- SSE 传输:支持服务器发送事件(Server-Sent Events)的 MCP 传输。
性能改进
- 并行处理:对多个结果进行并发内容提取。
- 智能缓存:根据内容新鲜度智能使缓存失效。
- 内存优化:对大文档采用流式内容处理。