关于 Bintu Web Reader
Bintu Web Reader 是一款 API,可从公开 HTML 网页提取适合 AI Agent 阅读的文本。它将页面结构整理为 Markdown,并同时提供 MCP 工具和 HTTP 接口。
主要功能
- 01从 HTML 提取可读文本
- 02以 Markdown 标记标题和表格
- 03可选 JavaScript 页面渲染
- 04文本长度限制及截断标记
- 05检查公开目标和响应大小
- 06短时提取缓存
适用场景
- 01为 Agent 提取公开网页文本
- 02在启用时读取 JavaScript 页面
- 03在文本预算内检查提取内容
MCP 相关
通过无状态 Streamable HTTP MCP 端点提供 bintu_scrape_text 工具。MCP 工具调用与抓取 API 共用身份验证和速率限制。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://bintu-web-reader.mcpize.run/mcpclaude mcp add --transport http l20941485-blip-bintu https://bintu-web-reader.mcpize.run/mcp{"mcpServers":{"l20941485-blip-bintu":{"type":"http","url":"https://bintu-web-reader.mcpize.run/mcp"}}}在 Cursor 中打开{"servers":{"l20941485-blip-bintu":{"type":"http","url":"https://bintu-web-reader.mcpize.run/mcp"}}}在 VS Code 中打开{"mcpServers":{"l20941485-blip-bintu":{"type":"http","url":"https://bintu-web-reader.mcpize.run/mcp"}}}{"mcpServers":{"l20941485-blip-bintu":{"serverUrl":"https://bintu-web-reader.mcpize.run/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://bintu-web-reader.mcpize.run/mcp需要授权工具
详细介绍
Bintu 数据提取 API
Bintu 是一个基于 FastAPI 的 API,用于从公开的 HTML 页面中提取可读文本。它将上游响应限制为 1 MiB,仅接受 HTML/XHTML,将出站连接固定到经过验证的公共 IP,并实施每分钟 60 个请求的进程级突发速率限制。
在线 API
该服务已在 Render 上线,可供测试:
- 基础 URL:https://bintu-api.onrender.com
- OpenAPI 文档:https://bintu-api.onrender.com/docs
- 健康检查:https://bintu-api.onrender.com/healthz
健康检查
curl https://bintu-api.onrender.com/healthz
响应示例:
{
"status": "ok"
}
抓取文本
如需直接访问已部署的服务,请在 PowerShell 中设置 API 密钥。安全提示不会在输入密钥时回显内容:
$env:BINTU_BASE_URL = "https://bintu-api.onrender.com"
$secure = Read-Host "Paste your Render API_KEY" -AsSecureString
$env:BINTU_API_KEY = [System.Net.NetworkCredential]::new("", $secure).Password
Remove-Variable secure
发送经过身份验证的抓取请求:
$target = "https://www.iana.org/domains/reserved"
$encodedUrl = [uri]::EscapeDataString($target)
$headers = @{ "X-API-Key" = $env:BINTU_API_KEY }
try {
$result = Invoke-RestMethod `
-Uri "$env:BINTU_BASE_URL/api/v1/scrape/text?url=$encodedUrl" `
-Headers $headers
$result | ConvertTo-Json -Depth 5
}
catch {
$response = $_.Exception.Response
if ($response) {
$statusCode = [int]$response.StatusCode
$retryAfter = $response.Headers["Retry-After"]
Write-Host "HTTP $statusCode; Retry-After: $retryAfter"
$reader = [System.IO.StreamReader]::new($response.GetResponseStream())
try { $reader.ReadToEnd() } finally { $reader.Dispose() }
}
else {
throw
}
}
成功响应:
{
"url": "https://www.iana.org/domains/reserved",
"text": "# IANA-managed Reserved Domains\n## Example domains\n...",
"truncated": false
}
如果提取的文本超过配置的字符数限制,truncated 就会是 true。API 会在 url 中返回请求的 URL。
在 PowerShell 中使用 curl.exe 时,也可以通过以下方式发送相同的请求:
curl.exe --get "$env:BINTU_BASE_URL/api/v1/scrape/text" `
--data-urlencode "url=https://www.iana.org/domains/reserved" `
--header "X-API-Key: $env:BINTU_API_KEY" `
--header "Accept: application/json"
Render 的 API_KEY 可在服务的 Environment 设置中找到。请妥善保密,不要提交,也不要放入 URL。上述示例会将其保留在当前 PowerShell 进程的环境中。如果未配置 API 密钥或代理密钥(例如默认的本地开发设置),则无需身份验证。可通过 /docs 访问交互式 API 文档——点击右上角的 Authorize,将密钥粘贴到 ApiKeyAuth 中;对于移动端接口,则将 Supabase 会话令牌粘贴到 BearerAuth 中,然后在任意受保护的路由上使用 Try it out。
常见错误
错误会使用包含 code、message 以及(如适用)hint 的 JSON detail 对象。例如,缺少密钥或密钥无效时会返回 HTTP 401:
{
"detail": {
"code": "invalid_api_key",
"message": "A valid API key is required."
}
}
URL 无效或不安全时会返回 HTTP 400:
{
"detail": {
"code": "invalid_or_unsafe_url",
"message": "URL must be an absolute HTTP or HTTPS URL",
"hint": "URL must start with http:// or https:// and be publicly accessible"
}
}
| HTTP 状态 | 错误代码 | 处理方法 |
|---|---|---|
| 400 | invalid_or_unsafe_url、render_js_disabled | 使用格式正确的公共 HTTP 或 HTTPS URL。禁止访问私有网络目标。除非服务启用了 render_js=true,否则该选项不可用——请改用 render_js=false 重试。 |
| 401 | invalid_api_key | 发送当前配置在 Render 中的 X-API-Key。 |
| 500 | auth_misconfiguration | 已设置 REQUIRE_AUTH=true(Render 生产环境默认值),但 API_KEY 和 RAPIDAPI_PROXY_SECRET 均为空。请在 Render 控制面板中恢复密钥,然后重新部署。 |
| 413 | payload_too_large | HTML 解压后的大小超过 1 MiB。 |
| 415 | unsupported_media_type | 目标必须返回 HTML 或 XHTML。 |
| 429 | burst_rate_limit_exceeded | 等待响应头 Retry-After 指定的秒数,然后重试。 |
| 502 | upstream_http_error、upstream_connection_error、upstream_render_error、unsupported_content_encoding 或 too_many_redirects | 目标返回了错误、无法访问或渲染、使用了不支持的压缩格式,或重定向次数过多。 |
| 504 | upstream_timeout | 目标未能及时响应。 |
429 响应也包含 Retry-After 标头。避免反复重试 4xx 响应;请修正请求,或按提示等待。
本地运行
使用 Python 3.12。安装应用和测试依赖,然后启动服务:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements-dev.txt
cd "Bintu API"
uvicorn main:app --reload
交互式 API 文档位于 /docs。未配置密钥时,本地开发环境不设访问限制。切勿部署未受保护的实例;Render 蓝图默认会生成 API_KEY。
Docker
docker build -t bintu-api .
docker run -p 8000:8000 -e API_KEY=your-key bintu-api
或者使用 Docker Compose:
docker-compose up
API
GET /healthz 是 Render 的轻量级健康检查,无需身份验证。
GET /version 返回服务配置(不会暴露机密)。
GET /metrics 提供 Prometheus 请求数、错误数、延迟直方图以及缓存命中/未命中计数器。指标使用路由模板,而非请求 URL,且不包含抓取的内容。应用程序请求日志包含请求 ID、方法、路由模板、状态码和耗时;不会记录目标 URL 或页面文本。Render 和 Docker 启动配置会禁用 Uvicorn 访问日志,因为访问日志中的请求行可能包含 url 查询参数。该端点使用与 API 相同的凭据保护,因此配置了密钥时,请发送 X-API-Key(或 RapidAPI 代理标头)。每个响应都会返回 X-Request-ID;如果调用方提供的 ID 有效,则予以保留,否则由 API 生成。
GET /api/v1/scrape/text?url=https%3A%2F%2Fexample.com 返回请求的 URL、提取的文本和一个 truncated 布尔值。只有在提取的内容超过配置的文本限制时,truncated 才为 true。如果存在可用内容,提取器会优先选择 <article> 或 <main> 内容,然后是 role="main" 或常见命名的主内容容器(例如 id="main"),否则退回到整个文档。它会省略隐藏元素以及常见控件或页面装饰,并将链接呈现为 链接文本(绝对 URL)。标题会以 Markdown # 前缀标记,段落和其他块级元素之间以换行分隔,每行中的表格单元格以 | 连接,表头行下方会添加分隔线。如果文档标题与首个标题重复,则会省略文档标题。字符编码根据上游 HTTP 字符集和 HTML 元数据检测。配置了 API_KEY 时,直接调用方必须发送 X-API-Key。该端点仅支持公开的 HTTP/HTTPS 目标,不会绕过访问控制。
添加 render_js=true,即可选择启用无头 Chromium 渲染 JavaScript 驱动的页面。渲染会等待 networkidle,验证浏览器请求的 HTTP 目标是否对应公开 DNS 地址,并省略图像、媒体和字体以减少内存使用。未渲染的请求仍使用现有的轻量级传输方式,将每个连接固定到经过验证的公开 IP。两种模式使用相同的提取器、文本限制、持久化缓存、身份验证和速率限制。
POST /mcp 是标准的 MCP Streamable HTTP 端点(无状态 JSON-RPC 2.0),供 Claude 自定义连接器和 Claude Code 使用:它会处理 initialize、ping、tools/list 和 tools/call,用于单个 bintu_scrape_text 工具,并且要求 Content-Type: application/json 以及与普通请求相同的 API 密钥。将 Claude 自定义连接器指向 https://<your-host>/mcp,并设置 X-API-Key 请求标头。通知会收到 202;由于服务端不保留会话或流,GET/DELETE 会返回 405。
GET /mcp/tools 会公布 bintu_scrape_text 工具,POST /mcp/tools/call 会通过 {"name":"bintu_scrape_text","arguments":{"url":"https://example.com","render_js":false}} 调用该工具。响应遵循 MCP 工具内容格式:{"content":[{"type":"text","text":"..."}]}。工具调用使用与普通抓取请求相同的 API 身份验证和速率限制。
查询参数
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
url | 字符串 | 必填 | 要抓取的 URL |
render_js | 布尔值 | false | 提取内容前,使用无头 Chromium 渲染 JavaScript |
include_nav | 布尔值 | false | 在输出中保留 <nav> 元素 |
include_header | 布尔值 | false | 在输出中保留 <header> 元素 |
include_footer | 布尔值 | false | 在输出中保留 <footer> 元素 |
服务限制
- 请求超时:每次连接尝试 10 秒。
- 重定向:最多 5 次,每个目标地址都会重新进行 URL 和 DNS 验证。
- HTML 正文:解压后最多 1 MiB,并以不超过 4 KiB 的块读取。支持 Gzip 编码的 HTML,解码后的大小限制相同。
- 文本响应:最多 6,000 个字符;内容超过限制时,
truncated为 true。截断后的文本会在最后一个可用的词边界处结束。 - JavaScript 渲染:默认禁用(
RENDER_JS_ENABLED=false);render_js=true会返回 400render_js_disabled。仅在 Chromium 启动成本已覆盖的付费基础设施上启用。 - 本地滥用防护:每个客户端身份每 60 秒最多 60 个请求,仅存储在进程内存中。在 Render 后方时,仅当客户端 IP 来自 Render 的代理范围(
100.64.0.0/10)才会被采纳,因此无法通过伪造X-Forwarded-For绕过防护。设置REDIS_URL可在多个实例间共享计数器;每个窗口的 TTL 仅设置一次,如果 Redis 无法访问,防护会回退到进程内存,而不会导致请求失败。 - 进程本地 HTML 缓存:TTL 为 5 分钟,每个实例最多缓存 64 个条目,并按最近最少使用策略淘汰。
CACHE_TTL_SECONDS=0会禁用此本地缓存。配置后,独立的 Supabase Markdown 缓存会将成功的提取结果保留 24 小时。 - 付费订阅配额和账单:由 RapidAPI 配置和强制执行,而非由此服务负责。
配置
| 环境变量 | 默认值 | 描述 |
|---|---|---|
API_KEY | (空) | 直接访问所用的 API 密钥 |
RAPIDAPI_PROXY_SECRET | (空) | 用于 RapidAPI 代理身份验证的密钥 |
SUPABASE_URL | (空) | 用于验证移动端用户会话的 Supabase 项目 URL |
SUPABASE_ANON_KEY | (空) | 用于验证移动端会话的 Supabase 可发布匿名密钥;切勿使用服务角色密钥或密钥 |
SUPABASE_SERVICE_ROLE_KEY | (空) | 用于持久化抓取缓存和 RapidAPI 使用量统计的私有服务器端密钥 |
CACHE_TTL_SECONDS | 300 | 进程本地 HTML 缓存 TTL(秒);0 会禁用该缓存(Supabase 的 24 小时缓存独立运行)。非数字或超出范围的值(允许范围为 0-86400)会回退到 300,并记录警告 |
REDIS_URL | (空) | 用于多实例速率限制的 Redis URL。为空或无法访问时,会使用进程级突发防护(故障时放行),每个实例各自执行其窗口限制 |
RENDER_JS_ENABLED | false | JavaScript 渲染熔断开关。仅精确值 true 会启用 Chromium;其他值在使用 render_js=true 时都会返回 400 render_js_disabled |
BINTU_UPGRADE_URL | https://mcpize.com | 嵌入 MCP 401 -32001 upgrade_url 的规范订阅 URL,以便 Agent 在聊天中输出可点击的链接 |
部署到 Render
- 将此项目推送到 GitHub 仓库。
- 在 Render 中创建一个新的 Blueprint 并选择该仓库。Render 会读取
render.yaml,安装requirements.txt和 Chromium 的系统依赖,然后在分配的端口上启动 Uvicorn。 - 等待
/healthz通过检查。从服务环境中复制生成的API_KEY,用于直接访问 API。不要提交这两个密钥。 - 测试已部署的
/docs页面,并在发布前发送经过身份验证的抓取请求。
免费实例在空闲时可能会休眠,因此首次请求可能较慢。免费服务最适合验证和早期用户,不适合对延迟敏感的生产环境,也不保证正常运行时间。本地突发防护会在重启时重置,且不会在多个实例间共享。它不是付费配额;请以 RapidAPI 计划限制作为计费依据。
商店渠道一致性(单一事实来源)
一个 API,三种入口。行为完全一致;只有各网关的身份验证和计费方式不同:
| Direct(Render) | RapidAPI | MCPize | |
|---|---|---|---|
| 列表名称 | 服务 bintu-data-extraction-api(MCP serverInfo.name: bintu) | Bintu Data Extraction API(子域名 bintu-data-extraction-api) | LLM Web Scraper & Clean Text Extractor(slug/主机名 bintu-web-reader.mcpize.run;用户将自己的 Claude 连接器命名为 Bintu-web-reader) |
| 端点 | https://bintu-api.onrender.com 上的 GET /api/v1/scrape/text?url=… | https://bintu-data-extraction-api.p.rapidapi.com 上的相同路径 | https://bintu-web-reader.mcpize.run 上的 bintu_scrape_text 工具(上游 POST https://bintu-api.onrender.com/mcp) |
| 身份验证 | X-API-Key: <Render API_KEY> | X-RapidAPI-Key + X-RapidAPI-Host(网关注入 X-RapidAPI-Proxy-Secret + X-RapidAPI-User) | 订阅者的 MCPize 密钥(sk_…);网关注入上游 X-API-Key。切勿引导用户从 MCPize 页面前往 RapidAPI |
| 计费 | 无(所有者密钥) | RapidAPI 套餐:BASIC $0/100 · PRO $9/10k · ULTRA $29/50k · MEGA $79/100k+ | MCPize 发布者等级(仪表板 → 变现):Free 约 1k · Pro $9–19 · Team $49+(通过 Stripe Connect 获取 80% 收益) |
| 配额 | 每个 IP 每 60 秒 60 个请求的突发限制 | 每个 X-RapidAPI-User 每 60 秒 60 个请求 + 套餐配额 | 所有 MCPize 订阅者共享每 60 秒 60 个请求的全局限制(单个上游令牌)+ 套餐配额 |
| 缓存 | 5 分钟内存缓存 + 24 小时 Supabase 持久缓存 | 相同 | 使用相同的上游缓存;冷抓取约 2–6 秒,缓存命中约 300 毫秒 |
Token Tax 定位(MCP): bintu_scrape_text 是 Token-Sanitized Context Gateway——剥离导航栏/广告/页脚,采用确定性的 max_tokens 分块(chunked→chunk、chunk_token_budget→max_tokens 别名);所有模式都会在 content[0].text 中返回统一的 JSON 封装 {mode, tokens, chunk_count, cache_hit, source_url, extracted_at, tokens_saved_estimate, truncated, chunks},以及 X-Token-Usage 标头和 401 -32001 upgrade_url(https://mcpize.com,可通过 BINTU_UPGRADE_URL 覆盖)。代码中不设等级上限——配额由仪表板管理。新增环境变量:BINTU_UPGRADE_URL(默认值 https://mcpize.com)。
所有渠道的限制:上游请求正文最大 1 MiB;仅支持 HTML/XHTML;文本上限为 6,000 个字符(带有 truncated 标记);最多重定向 5 次;render_js=true → 400 render_js_disabled(在付费基础设施上将 RENDER_JS_ENABLED=true 前,仅支持纯 HTML)。错误代码:参见常见错误。
RapidAPI 发布
RapidAPI 在其网关处理订阅者身份验证和计费。在 RapidAPI 提供商仪表板中,将 API 基础 URL 指向 Render 服务,并配置提供商代理密钥。将 Render 的 RAPIDAPI_PROXY_SECRET 设置为相同的值。接受通过 X-RapidAPI-Proxy-Secret 验证的请求;其 X-RapidAPI-User 身份会获得独立的每分钟 60 次请求配额桶。保留 API_KEY 用于所有者/直接访问,并且切勿在客户端示例中公开任何一个密钥。
在 RapidAPI 中配置订阅套餐、每月配额和价格。先提供小规模免费试用,再根据测得的 Render 延迟、故障率和上游成本设置付费等级。服务的每分钟 60 次限制是突发限制,不是月度配额或计费系统。无法保证获得市场推广位置或收益。
仅抓取你有权访问的内容。遵守目标网站的条款和 robots 政策。此 API 不会绕过登录、CAPTCHA、付费墙或反机器人控制。
连接 Claude
POST /mcp 实现了标准的 MCP Streamable HTTP 传输(协议 2025-11-25,同时接受 2025-06-18/2025-03-26),因此任何 MCP 客户端都可以调用此抓取工具。它是无状态的:不会发放 Mcp-Session-Id,GET 会返回空的 SSE 流(对于会探测专用 SSE 路径的网关,GET /sse 和 GET /mcp/sse 是兼容别名),DELETE/PUT/PATCH 会返回 405,每条 JSON-RPC 消息都会收到单个 application/json 响应。initialize 之后的请求必须携带协商得到的 MCP-Protocol-Version 标头(未知版本会返回 400),与 DNS 重绑定攻击防护相关的 Origin 标头不匹配时会被拒绝并返回 403。initialize、tools/list 和 ping 是公开的发现方法(协议协商、工具架构、存活状态检查——不执行内容提取),因此网关健康检查器、市场审核和 Claude Web(它们都无法在接入过程中发送标头)可以立即完成;tools/call 和所有其他方法都需要提供 X-API-Key 或 Authorization: Bearer,并使用限定范围的 MCP_API_KEY 或主密钥 API_KEY。执行调用缺少凭据或凭据无效时会返回 401 和 {"code": "invalid_api_key", "message": "A premium subscription or valid X-API-Key is required to execute scrapes."},所有计费工作都会受到身份验证保护。
- 直接连接 — Claude 网页版或桌面版:自定义连接器 URL
https://bintu-api.onrender.com/mcp,请求标头为X-API-Key: <MCP_API_KEY>。 - 直接连接 — Claude Code:
claude mcp add --transport http bintu https://bintu-api.onrender.com/mcp --header "X-API-Key: <MCP_API_KEY>"。 - MCPize(订阅用户):使用你的 MCPize
sk_…密钥连接到https://bintu-web-reader.mcpize.run——网关会注入上游令牌。无需 RapidAPI 订阅;费用由 MCPize 上的列表处理。
MCP_API_KEY 是在 Render 控制面板中设置的可选限定范围密钥。它仅适用于 MCP 端点(/mcp、/mcp/tools、/mcp/tools/call),不会用于 REST 路由或 /metrics,因此可以与连接器用户共享并单独轮换,无需更改主密钥 API_KEY。未设置 MCP_API_KEY 时,主密钥 API_KEY 仍可像以往一样用于 /mcp。
服务仅公开一个工具 bintu_scrape_text,其架构与 REST 抓取接口相同。工具执行失败(不安全的 URL、速率限制、上游错误、render_js_disabled)会以内联方式返回 isError: true 和可读文本,供模型自行修正。执行请求(tools/call)需要有效密钥(主密钥 API_KEY 或限定范围的 MCP_API_KEY,通过 X-API-Key 或 Authorization: Bearer 传递),并计入相同的速率限制;发现请求(initialize、tools/list、ping)无需凭据。此端点不会显示在 /docs 中;请参阅 README 的 MCP 部分。
原生移动应用 MVP
mobile-app/ 中的 Expo 项目为 iOS 和 Android 提供电子邮件注册/登录,以及将 URL 转换为易读文本的界面。用户会话保存在设备的安全存储中。应用会将 Supabase 访问令牌发送到 POST /api/v1/mobile/scrape/text;API 会通过 Supabase 验证用户,要求用户的电子邮件地址已验证,并应用现有的单用户突发请求限制。Bintu API_KEY 和 RapidAPI 提供商密钥绝不会发送到应用。
配置后端
- 创建 Supabase 项目并启用电子邮件/密码身份验证。保持电子邮件确认功能启用。
- 在 Supabase 项目设置中,复制项目 URL 和可发布密钥(或旧版 anon 密钥)。不要使用
service_role密钥或机密密钥。 - 在 Render 服务环境中设置
SUPABASE_URL和SUPABASE_ANON_KEY。妥善保管现有生成的API_KEY。 - 如需启用持久化抓取缓存和 RapidAPI 使用次数统计,请在 Render 中设置仅供服务器使用的
SUPABASE_SERVICE_ROLE_KEY。在 Supabase SQL 编辑器中运行supabase_schema.sql,以创建所需的表和原子使用次数递增函数。切勿将 service-role 密钥放入移动应用中。若未设置此密钥,抓取仍会使用现有的有界内存缓存,数据库功能则会停用。
持久化缓存会保留成功生成的 Markdown 24 小时。缓存键包含 URL、渲染模式和提取选项,过期条目会被忽略。只有携带有效已配置 RapidAPI 代理密钥和有效 X-RapidAPI-User 标头的请求才会递增 RapidAPI 使用次数;缓存命中的成功调用也会计数。数据库故障会记录日志,并回退到抓取,或返回已成功提取的内容。
只有配置好两项 Supabase 设置后,移动代理才会启用。API 必须能在请求时访问 Supabase,才能验证每个会话。
在 Supabase Authentication → URL Configuration → Redirect URLs 中,允许 Expo Go 回调 exp://**/--/auth/callback 和已安装应用回调 bintu://**。应用会为注册确认和密码恢复发送明确的回调 URL,因此这些链接会打开 Bintu,而不是默认的 localhost:3000。只有在开发服务器正在运行且手机所在网络可以访问时,Expo Go 重定向才会生效。
在 Android 手机上运行
安装当前的 Node.js LTS 版本,在 Android 手机上安装 Expo Go,然后在 mobile-app/ 目录中运行:
Copy-Item .env.example .env
# Edit .env and set the Supabase project URL and publishable/anon key.
npm install
node .\node_modules\expo\bin\cli start
扫描 Expo Go 显示的二维码。应用会处理确认和密码重置链接,并允许用户在点击恢复链接后设置新密码。EXPO_PUBLIC_ Supabase 密钥是客户端/公开密钥,并非服务机密;API 会验证会话并妥善保管 Bintu 服务密钥。本地 .env 文件已加入 git 忽略列表。构建 iOS 模拟器版本需要 macOS 和 Xcode;在应用商店公开发布则有单独的开发者注册要求和费用。
这是一个早期 MVP:API 的内存限流器会在重启时重置,也不提供账户滥用防护或每月用户配额。邀请更多用户前,请查看托管服务和 Supabase 套餐的限制。
测试
测试套件位于 tests/ 包中,且完全离线:它会拦截连接并使用模拟响应,因此不会发起任何实时网络请求。
python -m unittest discover -s tests -t . -p "test_*.py" -v
集成测试会在本地环回端口上运行真实 HTTP 服务器,以测试完整的获取、解析和提取流程;同时模拟 DNS 解析和连接目标,因此 SSRF 防护仍会生效:
python -m unittest tests.test_integration -v
tests/fixtures/extraction_quality/ 中的合成黄金样例覆盖文章、导航密集型和表格密集型 HTML,不依赖第三方网站。只有在确认提取变更是有意的之后,才更新样例及其预期 .txt 输出。
GitHub Actions 会在推送和拉取请求时运行离线测试套件。Render 配置为仅在 CI 检查通过后部署已关联的提交。部署后,请运行 python smoke_check.py 验证实际的上游获取功能(设置 BINTU_BASE_URL 和 BINTU_API_KEY);仅靠模拟测试无法发现上游 HTTP 回归问题。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。