mcpField
L
Lens

Lens

远程服务
api.bysages.com媒体与设计42 周前更新

关于 Lens

Lens 是基于 TypeScript 的 Web 服务工具集,提供图像处理、网页截图、内容提取、字体等功能。其 HTTP API 也以 MCP 工具形式开放,供客户端调用。

主要功能

  1. 01调整尺寸、转换和优化图像
  2. 02截取网站页面
  3. 03将网页内容提取为 Markdown 或 HTML
  4. 04提供字体服务并生成 Open Graph 图像
  5. 05提取网站图标并代理 Gravatar 头像
  6. 06Redis 缓存与 URL 安全检查

适用场景

  1. 01按需生成指定格式的缩放图像
  2. 02截取桌面或移动设备网页画面
  3. 03提取文章内容供后续处理
  4. 04为网页生成 Open Graph 图像

MCP 相关

Lens 在 `/mcp` 提供 HTTP MCP 接口,将各项服务作为工具开放,包括内容提取、截图、网站图标、OG 图像、Gravatar 和图像转换。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://api.bysages.com/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

6
参数类型必填说明
urlstring是要提取内容的网站 URL
formatenum否输出格式(默认:markdown)html | markdown

详细介绍

Lens

GitHub Contributor Covenant

使用现代 TypeScript 构建的高性能图像代理和 Web 服务工具包。Lens 提供全面的 Web 实用工具套件,包括图像处理、截图、字体服务等。

🚀 功能

核心服务
  • 🖼️ 图像代理:由 UnImage 驱动的图像处理,支持调整大小、格式转换和优化
  • 📸 截图:快速的网站截图服务,并进行资源优化
  • 📄 阅读器:使用 Readability 提取文章内容(Markdown/HTML)
  • 🅰️ 字体服务:兼容 Google Fonts 的 API,支持多个提供商
  • 🎨 Open Graph 图像:动态生成 OG 图像
  • 🎯 网站图标提取:从网站智能提取网站图标
  • 👤 Gravatar 代理:带缓存的 Gravatar 头像代理,支持输入邮箱或哈希值
  • 🤖 MCP 服务:通过 JSON-RPC 2.0 将所有服务作为工具提供的 Model Context Protocol 服务
性能与可扩展性
  • ⚡ Redis 缓存:由 Redis 驱动的缓存,支持 24 小时智能缓存
  • 🧭 按需浏览器:通过 CDP 驱动 Moli 无头浏览器(Rust)——内存占用约为 Chromium 的 1/10
  • 🛡️ 速率限制:限制高开销操作的速率
  • 🔒 SSRF 防护:通过 DNS 解析检查验证 URL,并在浏览器层阻止访问专用网络
  • 🔄 优雅降级:服务不可用时自动回退

📦 快速开始

前提条件
  • Node.js 24+
  • pnpm 10+(推荐)或 npm
  • Moli 无头浏览器(截图/阅读器通过 CDP 连接到它)
安装
# Clone the repository
git clone https://github.com/bysages/lens.git
cd lens

# Install dependencies
pnpm install

# Copy environment configuration
cp .env.example .env
开发
# Start the Moli browser server (default CDP endpoint: http://127.0.0.1:9222)
moli serve --layout --resource

# In another terminal, start development server
pnpm dev

# Build for production
pnpm build

# Preview production build
pnpm preview

服务器默认在 http://localhost:3000 上启动。

🛠️ 配置

配置

所有配置项均为可选项;未配置时会进行优雅降级:

# Image proxy security
ALLOWED_DOMAINS=example.com,cdn.example.com

# Set only when requests arrive through a trusted reverse proxy
TRUST_PROXY=1

# Requests per IP within RATE_WINDOW seconds; Redis makes these cluster-wide
BROWSER_RATE_LIMIT=20
FAVICON_RATE_LIMIT=30
IMAGE_RATE_LIMIT=120
GRAVATAR_RATE_LIMIT=120
RATE_WINDOW=60

# Caching (significantly improves performance)
REDIS_URL=redis://localhost:6379

# Browser: Moli CDP endpoint (defaults to http://127.0.0.1:9222)
BROWSER_CDP_ENDPOINT=http://127.0.0.1:9222

# Browser: optional user-agent overrides (default: the engine's own UA)
#BROWSER_USER_AGENT=...
#BROWSER_USER_AGENT_MOBILE=...

# Browser: cluster-wide maximum with Redis (process-local fallback otherwise)
BROWSER_MAX_CONCURRENCY=4

# Maximum wait for a global browser slot (ms)
BROWSER_QUEUE_TIMEOUT=15000

# Reject full-page captures above this CSS pixel count
SCREENSHOT_MAX_PIXELS=24000000

# Cluster: worker count (Docker defaults to 2; raw Nitro defaults to CPU count)
NITRO_CLUSTER_WORKERS=2

所有可用选项请参阅 .env.example。

📡 API 参考

由缓存支持的路由会返回 X-Cache 和强 ETag;对于匹配的 If-None-Match 请求,会返回 304。

图像
图像代理

使用 UnImage 转换和优化图像,采用兼容 IPX 的 URL:

GET /img/{modifiers}/{image_url}

示例:

# Resize to 300px width, negotiate the best supported format
https://api.bysages.com/img/w_300,f_auto/https://example.com/image.jpg

# Explicit WebP output
https://api.bysages.com/img/w_300,f_webp/https://example.com/image.jpg

# Create a 200x200 cover thumbnail
https://api.bysages.com/img/s_200x200,q_80/https://example.com/image.png

# Rotate and desaturate
https://api.bysages.com/img/rotate_90,grayscale/https://example.com/photo.jpg

常用修饰符:

  • w_XXX / h_XXX - 宽度 / 高度
  • s_XXXxYYY - 尺寸简写
  • fit_contain|cover|fill|outside - 适配模式
  • f_FORMAT - 输出格式(webp、jpg、png、avif、svg、gif 等;f_auto 会根据 Accept 协商格式)
  • q_XXX - 质量
  • rotate_90、grayscale、blur_2、sharpen_1、animated - 常见变换
  • _/path - 不带修饰符的透传

服务器处理栈使用 SVGO 处理 SVG,使用 Canvas 执行支持的操作,并使用 Sharp 作为光栅图像的回退方案。远程图像受到域名允许列表、DNS/专用地址检查和重定向验证的保护。本地路径限定在 public 目录内。响应使用 Redis 缓存、强 ETag、304 状态码,以及针对协商格式的 Vary: Accept。

截图捕获

使用浏览器样式选项捕获网站截图:

GET /screenshot?url={website_url}&options

示例:

# Basic screenshot
https://api.bysages.com/screenshot?url=https://example.com

# JPEG with custom quality
https://api.bysages.com/screenshot?url=https://example.com&type=jpeg&quality=80

# Mobile screenshot with custom viewport
https://api.bysages.com/screenshot?url=https://example.com&width=375&height=667&mobile=true

# Full page capture
https://api.bysages.com/screenshot?url=https://example.com&fullPage=true

# Clip region (x,y,width,height)
https://api.bysages.com/screenshot?url=https://example.com&clip=0,0,400,300

# Disable animations for clean capture
https://api.bysages.com/screenshot?url=https://example.com&animations=disabled

# Custom CSS scale
https://api.bysages.com/screenshot?url=https://example.com&scale=css

# Inject custom stylesheet
https://api.bysages.com/screenshot?url=https://example.com&style=body{background:red}

参数:

参数描述默认值
url网站 URL(必填)-
width视口宽度(100-2560)1280
height视口高度(100-1440)720
type输出格式(png、jpeg)png
quality图像质量,1-100(仅适用于 jpeg)-
fullPage捕获完整可滚动页面(true/false)false
clip裁剪区域,格式为 x,y,width,height-
scale截图比例(css 表示 CSS 像素,device 表示设备像素)device
animations动画处理方式(disabled 或 allow)disabled
caret文本插入光标(hide 或 initial)hide
style要应用的自定义 CSS 样式表-
timeout导航超时时间,单位为 ms(1000-30000)10000
mobile移动设备用户代理和触摸输入(true/false)false
darkMode深色模式(true/false)false
waitUntil导航等待条件(load、domcontentloaded、networkidle)load
delay页面加载后的额外延迟,单位为 ms(0-10000)-

性能说明:

  • 截图会缓存 1 天,并进行速率限制
  • 相同的请求会返回缓存结果,响应时间不到 1 秒
  • 截图会短暂等待字体和图像加载,默认会冻结动画
  • Moli 会将整页截图渲染为一张位图;SCREENSHOT_MAX_PIXELS 会拒绝尺寸过大的截图
  • BROWSER_MAX_CONCURRENCY 是集群范围内的并发限制,使用 Redis,并包含有界队列
Open Graph 图像

生成动态 OG 图像:

GET /og?title={title}&description={description}

示例:

# Basic OG image
https://api.bysages.com/og?title=Welcome&description=Get%20started%20with%20Lens

# Custom styling
https://api.bysages.com/og?title=Hello%20World&theme=dark&fontSize=72&width=1200&height=630

缓存:

  • 生成的 OG 图像会缓存 24 小时
  • 参数相同的重复请求会立即返回缓存结果
Web 服务
Reader(内容提取)

从任意 URL 提取渲染后的 Markdown 或 HTML 内容:

GET /reader?url={website_url}&options

示例:

# Extract rendered Markdown (default)
https://api.bysages.com/reader?url=https://github.com/bysages/lens

# Get HTML instead
https://api.bysages.com/reader?url=https://github.com/bysages/lens&format=html

# Wait for full page load
https://api.bysages.com/reader?url=https://github.com/bysages/lens&waitUntil=load

参数:

参数描述默认值
url网站 URL(必填)-
format输出格式(html、markdown)markdown
waitUntil导航等待条件(load、domcontentloaded、networkidle)domcontentloaded
delay页面加载后的额外延迟,单位为 ms(0-10000)-
timeout导航超时时间,单位为 ms(1000-30000)10000
Favicon 提取

提取高质量的 favicon:

GET /favicon?url={website_url}&size={size}

示例:

# Extract favicon
https://api.bysages.com/favicon?url=github.com

# Custom size
https://api.bysages.com/favicon?url=github.com&size=64

功能:

  • 从多个来源智能提取 favicon(PWA 清单、Apple 触控图标、HTML 标签)
  • 支持 ETag/304 的服务端缓存,缓存时间为 30 天
  • 如果未找到 favicon,则自动回退到生成的 favicon
Gravatar 代理

通过电子邮件地址、MD5 哈希或路径获取 Gravatar 头像。除 email/hash 外,所有查询参数都会直接转发给 Gravatar。只需替换 URL 前缀,即可切换 Gravatar。

GET /gravatar/{md5}?{gravatar_params}
GET /gravatar?email={email}
GET /gravatar?hash={md5}&{gravatar_params}

示例:

# By path (drop-in replacement for Gravatar URLs)
https://api.bysages.com/gravatar/{md5}?size=200

# By email
https://api.bysages.com/[email protected]

# By MD5 hash
https://api.bysages.com/gravatar?hash={md5}

# With Gravatar parameters
https://api.bysages.com/[email protected]&size=200&default=identicon&rating=pg

参数:

  • {md5} - URL 路径中的 MD5 哈希(直接替换模式)
  • email - 电子邮件地址(会自动计算 MD5 哈希)
  • hash - 预先计算的 MD5 哈希(可替代电子邮件地址)
  • 其他所有参数都会转发至 Gravatar API
MCP 服务

通过 HTTP 上的 JSON-RPC 2.0 将所有 Lens 服务作为工具公开的 Model Context Protocol 服务。

POST /mcp

在 Claude Desktop 中设置(claude_desktop_config.json):

{
  "mcpServers": {
    "lens": {
      "url": "https://api.bysages.com/mcp"
    }
  }
}

可用工具:

工具描述返回值
reader从 URL 提取文章内容(Markdown/HTML)文本
screenshot截取网站屏幕截图图像
favicon提取网站的 favicon图像
og生成动态 Open Graph 图像图像
gravatar通过电子邮件地址或哈希获取 Gravatar 头像图像
img转换并优化图像(调整大小、裁剪、转换格式)图像
字体
字体服务

兼容 Google Fonts 的 API,同时支持 v1 和 v2 端点:

GET /css?family={font_family}&display=swap
GET /css2?family={font_family}&display=swap

API 差异:

功能/css(v1)/css2(v2)
多种字体family=A|B(竖线分隔)family=A&family=B(重复参数)
样式语法FontName:400,700(旧)FontName:wght@400;700(新,严格)
可变字体❌ 不支持✅ 完全支持范围值([email protected])
基础 URLfonts.googleapis.com/cssfonts.googleapis.com/css2

参数:

  • family - 字体系列名称(必填)
  • display - 字体显示策略(默认:swap)
  • subset - 字体子集(默认:latin)
  • provider - 字体提供方(google、bunny、fontshare、fontsource,默认:google)
  • proxy - 是否为字体文件使用代理(true/false,默认:false)

示例:

# Basic font (v1 API - pipe separator)
https://api.bysages.com/css?family=Roboto:wght@400;700|Open+Sans:wght@300;400;600&display=swap

# Multiple fonts (v2 API - repeated family parameter)
https://api.bysages.com/css2?family=Inter:wght@400;700&family=Roboto:wght@300;400&display=swap

# Variable fonts with weight range (v2 only)
https://api.bysages.com/css2?family=Inter:[email protected]&display=swap

# Font metadata
https://api.bysages.com/webfonts?sort=popularity&category=sans-serif

建议:

  • 使用 /css,以便与旧版 Google Fonts 语法保持兼容
  • 使用 /css2,适用于采用可变字体并追求更佳优化的现代应用
  • 两种端点都支持所有字体提供方(Google、Bunny、Fontshare、Fontsource)

🏗️ 架构

Lens 采用现代 Web 标准构建,并遵循整洁架构原则:

核心技术
  • 运行时:Node.js 24+ 和 Nitro
  • 语言:TypeScript,具备严格的类型安全性
  • 图像代理:UnImage,搭配 SVGO、Canvas 和 Sharp
  • 浏览器自动化:Moli 无头浏览器,由 Playwright 通过 CDP 驱动
  • 缓存:Redis 和 unstorage
设计原则
  • KISS(保持简单):优先采用简单、专注的解决方案,而非复杂的抽象
  • DRY(不要重复自己):共享工具和配置
  • 优雅降级:为缺失的依赖项提供回退方案
  • 类型安全:全面覆盖 TypeScript
  • 性能优先:针对速度和效率进行优化

🚀 部署

先决条件
  • Node.js 24+ 运行时
  • pnpm 10+ 包管理器
  • Redis(已包含在 Docker Compose 中;其他部署方式可选)
生产环境部署
# Build the application
pnpm run build

# Start production server
pnpm run preview
Docker 部署(推荐)
选项 1:使用 Docker Compose
# Copy environment variables
cp .env.example .env

# Edit .env file to configure your settings
# nano .env

# Start the application
docker-compose up -d

# View logs
docker-compose logs -f app

# Stop the application
docker-compose down

应用将在 http://localhost:3000 上提供服务。

GET /healthz 会报告存活状态,包括浏览器(CDP)的可用性 —— Compose 健康检查和编排器探针应指向此端点。

该堆栈包括:

  • Lens 应用,运行在端口 3000,Moli 浏览器在容器内运行
  • Redis,用于分布式缓存,并采用 LRU 淘汰策略限制容量(512 MB)
选项 2:使用 Docker Run
# Pull the official image
docker pull bysages/lens:latest

# Run container with host network (recommended for accurate IP logging);
# --init is needed because the image runs Moli alongside Node
docker run -d \
  --name lens \
  --network host \
  --init \
  --env-file .env \
  --restart unless-stopped \
  bysages/lens:latest

# View logs
docker logs -f lens

# Stop the container
docker stop lens
docker rm lens
选项 3:从源代码构建
# Build Docker image
docker build -t lens .

# Run container
docker run -d \
  --name lens \
  --network host \
  --init \
  --env-file .env \
  --restart unless-stopped \
  lens
环境变量

所有配置均为可选项:

# Image Proxy Security
ALLOWED_DOMAINS=example.com,cdn.example.com

# Set only when requests arrive through a trusted reverse proxy
TRUST_PROXY=1

# Caching (significantly improves performance)
REDIS_URL=redis://localhost:6379

# Browser: Moli CDP endpoint (defaults to http://127.0.0.1:9222)
BROWSER_CDP_ENDPOINT=http://127.0.0.1:9222

# Browser: cluster-wide maximum with Redis (process-local fallback otherwise)
BROWSER_MAX_CONCURRENCY=4

# Maximum wait for a global browser slot (ms)
BROWSER_QUEUE_TIMEOUT=15000

# Reject full-page captures above this CSS pixel count
SCREENSHOT_MAX_PIXELS=24000000

# Cluster: worker count (Docker defaults to 2; raw Nitro defaults to CPU count)
NITRO_CLUSTER_WORKERS=2

# Moli server flags used by the Docker entrypoint
# (--block-private-networks is always enforced by the entrypoint)
MOLI_FLAGS=--layout --resource --http-cache-dir=/tmp/lens-cache/moli-http --http-max-concurrent=32 --http-max-total-connections=64

请参阅 .env.example,了解所有可用选项。

📄 许可证

MIT 许可证 — 详情请参阅 LICENSE 文件。


由 By Sages 倾心打造 ❤️

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。