内容
<p align="center">
<img src="./logo.png" alt="svg-mcp" width="460">
</p>
# svg-mcp
一款 [FastMCP](https://github.com/jlowin/fastmcp) 服务器,提供 **结构化、分层 SVG 编辑** 功能,适用于大型语言模型(LLM)—— 所有基本图形、渐变/图案、路径、文本路径、嵌入式光栅图像、可重用样式 —— 构建于 **inkex 支持的文档模型** 之上,AI 可以导航、查询和操作这些元素,支持 **快速构建 → 渲染 → 查看 → 迭代** 循环。
> 上方的标志图完全通过这些工具创建 - 请参阅 [用法](#用法).
查看 [`DESIGN.md`](./DESIGN.md) 以获取完整的架构信息,以及 [`INKEX_PRIMITIVES.md`](./INKEX_PRIMITIVES.md) 目录以获取 inkex 工具映射信息。
## 快速开始(Claude)
1. **前提条件** - 只需 **Python ≥ 3.12**。渲染发生在 **进程内**([resvg](https://github.com/linebender/resvg) 引擎作为 `resvg-py` 依赖项提供),因此无需安装单独的渲染器。*可选*,安装 resvg **CLI** 以实现小幅度的渲染加速 - 当 `PATH` 中存在时自动使用:
```bash
brew install resvg # 可选(macOS;或:cargo install resvg)
```
**Linux 构建头文件。** 在 macOS 上,安装是纯粹的轮子。在 Linux 上,两个依赖项 - **lxml** 和 **PyGObject**(后者由 `inkex` 拉取)- 有时没有与最新解释器的匹配轮子,因此由 pip 从源代码编译,需要 C 头文件。提前安装它们(参见 [Linux 系统软件包](#linux-系统软件包) 以获取完整的库映射和其他发行版)。在 **Debian 13(trixie)/ Ubuntu** 上:
```bash
sudo apt-get install build-essential python3-dev pkg-config \
libxml2-dev libxslt1-dev \
libgirepository-2.0-dev gir1.2-girepository-2.0
```
2. **从此仓库的克隆中**安装服务器(拉取 fastmcp、inkex、fontTools 等)。以下命令使用 [uv](https://docs.astral.sh/uv/) - 如果您还没有安装,请先安装它([完整安装文档](https://docs.astral.sh/uv/getting-started/installation/)):
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
# 替代方案:brew install uv · pipx install uv · winget install astral-sh.uv(Windows)
```
然后选择 **以下两种安装布局之一** - 此选择决定了您在步骤 3 中指向 Claude 的路径:
**a) 项目本地虚拟环境(推荐,自包含)。** 在仓库内创建 `./.venv` 并将 svg-mcp 可编辑地安装到其中 - 您的其他环境均不受影响:
```bash
uv sync # → ./.venv with svg-mcp + deps(from pyproject/uv.lock)
# 等效地,无 uv.lock: uv venv && uv pip install -e .
# 无 uv: python -m venv .venv && .venv/bin/pip install -e .
```
→ 入口点:**`./.venv/bin/svg-mcp`**(绝对路径:`$(pwd)/.venv/bin/svg-mcp`)。
**b) 进入您现有的虚拟环境。** 激活您想要的虚拟环境,然后可编辑地安装:
```bash
source /path/to/your/venv/bin/activate # 或以其他方式设置 VIRTUAL_ENV
uv pip install -e . # 或:pip install -e .
```
→ 入口点:**`/path/to/your/venv/bin/svg-mcp`**.
> ⚠️ **`uv sync` 始终针对项目的 `./.venv`**,但 **`uv pip install` / `pip install` 针对当前激活的虚拟环境**。如果您已经激活了一个环境,svg-mcp **及其依赖项**(fastmcp、inkex、fontTools、numpy、Pillow 等)将被安装到其中。使用选项(a)- 或显式的新虚拟环境 - 除非您故意将其放在现有环境中。
3. **连接 Claude** - 将其指向 **步骤 2 中的入口点路径** (`./.venv/bin/svg-mcp` 适用于选项 a,或 `/path/to/your/venv/bin/svg-mcp` 适用于选项 b;始终使用 **绝对路径** 在配置文件中):
- **Claude 代码** - 从仓库目录(显示选项 a):
```bash
claude mcp add svg-mcp -- "$(pwd)/.venv/bin/svg-mcp"
```
(或仅打开项目 - 它附带一个您可以批准的 [.mcp.json](./.mcp.json))。
- **Claude 桌面版** - 添加到 `claude_desktop_config.json` 并重启应用程序:
```json
{ "mcpServers": { "svg-mcp": { "command": "/ABSOLUTE/PATH/TO/<venv>/bin/svg-mcp" } } }
```
4. **试用** - 问 Claude:
> 使用 svg-mcp 创建一个 320×120 的徽章,上面用蓝色渐变写着“hello”,然后给我看渲染结果。
Claude 创建一个文档,添加形状和文本,并调用 `render_document` 显示图像内联 - 然后您可以迭代用纯语言进行操作(“更大的文本”,“添加阴影”,“将文本轮廓为路径”)。有关约定和示例,请参阅 [用法](#用法)。
## 状态
完整的 inkex 目录映射到 **107 个 MCP 工具**(参见 [`INKEX_PRIMITIVES.md`](./INKEX_PRIMITIVES.md)),ruff/mypy 清洁,测试套件绿色。
- **文档模型**(inkex 支持,多文档,默认活动文档):形状,路径(+ 弧形/星形工厂和路径数据操作),文本 + tspan 运行 + 文本路径 + 流式文本,图像(base64/文件嵌入),组(+ 解组,z 顺序,复制,世界保留重新父级),**图层**(+ 可见/锁定/不透明度),符号/使用,超链接。
- **文本 → 路径**(`text_to_path`):纯 Python 字形轮廓(fontTools)- 展平 tspan,尊重粗体/斜体/每运行填充,并沿 **曲线** (`<textPath>`)行走文本。`list_fonts` 枚举安装的系列;`measure_text` 从字体指标返回运行的宽度/高度,以便您可以拟合和居中文本 **而无需渲染往返**。
- **可变宽度笔画**(`add_variable_width_path`):SVG 没有原生可变笔画宽度,因此膨胀/锥形线条 - 刻字,雕刻,刷子,锥形箭头 - 被扩展为填充的色带,具有 butt/round 帽和可选 **三次**(Catmull-Rom)路径和宽度的平滑。
- **批量构造函数**(`add_rects`/`add_circles`/`add_lines`/`add_paths`/ `add_variable_width_paths`):一次添加许多形状(一次往返)- 用于程序艺术,阴影/雕刻字段和数据可视化。
- **导入** 现有 SVG(`import_svg`,内联或从文件)到会话文档中以渲染,检查或编辑。
- **可重用资源**:命名样式(CSS 类 + `@name` 填充引用),线性/辐射/网格渐变,图案,标记,**剪辑 + 遮罩**,以及 **过滤器**(模糊,投影,颜色矩阵/叠加,混合,形态学,湍流,位移,加上原始过滤器图构建器)。
- **变换** 作为基元:翻译,旋转中心,缩放锚点,倾斜,原始。
- **查询/上下文**:`current_context`,`describe_node`,`list_resources`,`outline`,边界框,计算样式,变换/CTM,单位转换,选择器(`find`/`get_subtree`),图像提取;元数据(标题/描述/RDF);指南和页面。
- **渲染-查看循环**:通过 **resvg** CLI 进行序列化然后栅格化;图像直接作为 base64 图像内容返回。文档也作为可读的 MCP **资源** (`svg://documents`,`svg://{id}/svg`,`svg://{id}/render`) 公开,并附带更改通知。
- **文件导出**(`export_render`):忠实的栅格(png/jpeg/webp via resvg)和 **真实矢量**(pdf/ps/eps via librsvg)。cairo 被故意避免 - 它会默默地丢弃 SVG 过滤器(阴影渲染为空),因此它不忠实于文档。
## 架构
<p align="center">
<img src="./docs/architecture.png" alt="svg-mcp architecture" width="900">
</p>
> 完全通过 svg-mcp 工具创作并通过服务器的 resvg 后端渲染([`docs/architecture.svg`](./docs/architecture.svg) 是实时序列化源)。
三个层次:**接口和契约** 层(FastMCP 服务器,pydantic 输入模式和每个会话的文档存储),**文档操作** 层(inkex 面向构造/编辑,只读检查和文档模型),以及 **渲染和输出** 层(纯 Python 排版,渲染/导出后端和 SVG 序列化)。有关完整的分层原理,请参阅 [`DESIGN.md`](./DESIGN.md)。
## 安装
```bash
pip install -e ".[dev]"
```
### Linux 系统软件包
macOS 完全从轮子安装 - 无需额外操作。 在 Linux 上,pip 默认为 **从源代码** 构建某些依赖项,只要没有与您的解释器匹配的轮子可用(在 **Debian 13 “trixie”** 和其他最近/边缘发行版上常见),这些构建需要 C 头文件和构建工具。每个库需要什么:
| Python 依赖项 | 原因 | Debian/Ubuntu 软件包 |
|---|---|---|
| (所有 C 扩展构建) | 编译器,头文件,`pkg-config` | `build-essential` · `python3-dev` · `pkg-config` |
| **lxml** | 它绑定的 XML/XSLT C 库 | `libxml2-dev` · `libxslt1-dev` |
| **PyGObject**(通过 `inkex` 在 Linux 上拉取) | GObject-Introspection 绑定(`girepository`) | `libgirepository-2.0-dev` · `gir1.2-girepository-2.0`(拖入 `libglib2.0-dev`) |
| **cairocffi / pangocffi / pangocairocffi**(仅 `cairo` 额外) | cairo + pango C 库 | `libcairo2-dev` · `libpango1.0-dev` · `libffi-dev` |
Core 安装(除了可选的 `cairo` 额外项)基于 **Debian/Ubuntu** - 在 Debian 13(trixie)上验证:
```bash
sudo apt-get install build-essential python3-dev pkg-config \
libxml2-dev libxslt1-dev \
libgirepository-2.0-dev gir1.2-girepository-2.0
```
> 在 trixie 上,**GObject-Introspection** 开发包是新的 **`libgirepository-2.0-dev`**(它拉入 `libglib2.0-dev`);在较旧的版本中,它是 `libgirepository1.0-dev`。同样,XSLT 头文件是 `libxslt1-dev`(bare `libxslt-dev` 名称仅是一个虚拟别名)。
如果您还安装了 **`cairo` 额外项**(`pip install -e ".[cairo]"`),请添加:
```bash
sudo apt-get install libcairo2-dev libpango1.0-dev libffi-dev
```
其他发行版的等效项(相同的库,发行版特定的名称):
```bash
# Fedora / RHEL
sudo dnf install gcc python3-devel pkgconf-pkg-config \
libxml2-devel libxselt-devel \
gobject-introspection-devel glib2-devel \
cairo-devel pango-devel libffi-devel # 最后一行 = cairo 额外
# Arch
sudo pacman -S base-devel libxml2 libxslt gobject-introspection \
cairo pango libffi # cairo/pango/libffi = cairo 额外
```
如果 pip 找到您平台/解释器上的所有依赖项轮子,则不需要上述任何操作 - 从源代码的后备项是唯一拉取这些项的内容。
### inkex(SVG DOM)
依赖发布的 **PyPI `inkex>=1.4.1`**。请注意其 API 形状(验证):`inkex.colors` 是平面模块,并且 **没有 `Image.embed_image()`** - 栅格嵌入是通过 base64 数据 URI 手动完成的。所有元素类加上 `bounding_box`,`composed_transform`,`specified_style` 和 `Transform @` 组合均存在。
### resvg(默认渲染器)
resvg 是一个确定性,跨平台的渲染器,具有原生的文本路径支持和广泛的过滤器支持,并且没有系统库。它通过捆绑的 **`resvg-py`** 绑定(与引擎相同 - 与 CLI 像素相同验证),因此安装是自包含的,无需额外二进制。
### 可选后端
- `cairo` 额外项 - 通过 cairocffi + pango 进行次要矢量/栅格后端(PDF/PS/SVG 输出)- 需要 cairo + pango 系统库(macOS:Homebrew `cairo` + `pango`; Linux: 参见 [Linux 系统软件包](#linux-系统软件包)。今天是一个存根。
- Headless Inkscape - 参考渲染器 + 重型操作,通过 `--shell` 驱动(macOS 上没有 D-Bus)。今天是一个存根。
## 配置
所有设置均为 `SVG_MCP_` 前缀的环境变量(或 `.env` 文件):
| 变量 | 默认值 | 含义 |
|---|---|---|
| `SVG_MCP_RENDERER` | `resvg` | 渲染后端:`resvg`(CLI 如果存在,否则进程内)· `resvg-py` · `resvg-cli` · `cairo` · `inkscape` |
| `SVG_MCP_RESVG_BINARY` | 自动 | resvg CLI 的路径 |
| `SVG_MCP_INKSCAPE_BINARY` | 自动 | Inkscape CLI 的路径 |
| `SVG_MCP_FEEDBACK_MAX_EDGE` | 未设置 | 可选的长边上限(像素);设置为原始图像直接返回 base64,无需限制 |
| `SVG_MCP_DEFAULT_BACKGROUND` | 透明 | 默认渲染背景(CSS 颜色) |
| `SVG_MCP_RENDER_TIMEOUT_S` | `30` | 每个渲染子进程超时 |
| `SVG_MCP_TRANSPORT` | `stdio` | 服务器传输:`stdio` · `http` · `streamable-http` · `sse` |
| `SVG_MCP_HOST` / `SVG_MCP_PORT` | `127.0.0.1` / `8000` | HTTP 传输的绑定地址 |
传输、主机和端口也可以使用 CLI 标志设置(这些标志优先于环境变量):`svg-mcp --transport streamable-http --host 127.0.0.1 --port 7731`.
## 开发
```bash
pytest # 测试(如果缺少 resvg 烟雾测试,则自动跳过)
ruff check . # 校验
mypy src # 类型(无 Any / object - 仅精确类型)
```
## 运行
```bash
svg-mcp # FastMCP 服务器通过 stdio(默认)
svg-mcp --transport streamable-http --port 7731 # 或 streamable-http 在 127.0.0.1:7731/mcp
# 环境变量也适用:SVG_MCP_TRANSPORT=http SVG_MCP_PORT=7731 svg-mcp
```
长时间运行的 HTTP 服务器对于共享/持久性端点很有用(服务器作为单个进程运行;每个客户端连接都有自己的隔离文档)。
## 使用 LLM 实验
快速健全检查(无 LLM):渲染样本海报到 PNG。
```bash
.venv/bin/python scripts/demo.py # 写入 demo_output.png
```
**Claude 代码** - 此仓库附带一个项目 [.mcp.json](./.mcp.json);打开项目并批准 `svg-mcp` 服务器,或显式添加:
```bash
claude mcp add svg-mcp -- /Users/geohar/Development/svg-mcp/.venv/bin/svg-mcp
```
**Claude 桌面版** - 将以下内容添加到 `claude_desktop_config.json`:
```json
{
"mcpServers": {
"svg-mcp": { "command": "/Users/geohar/Development/svg-mcp/.venv/bin/svg-mcp" }
}
}
```
**MCP 检查器** - 交互式调用工具和在浏览器中查看渲染图像:
```bash
uv run fastmcp dev src/svg_mcp/server.py:mcp
```
模型的循环是:`create_document` → 添加节点/资源 → `render_document` 在内联查看结果 → 迭代 → `export_svg`。服务器的 `instructions` 描述了完整的工作流程和约定;每个工具都带有自己的描述。
## 用法
工具由 LLM 通过 MCP 调用。核心循环是 **create → build → render-and-see → iterate → export**。最小会话(显示为 JSON,每个工具接收的参数):
```text
create_document(width=320, height=120) # → {document_id:"doc1", active:true}
# 定义可重用渐变,然后用其名称(@name)或 url(#id) 着色
define_linear_gradient(x1=0, y1=0, x2=1, y2=0,
stops=[{offset:0, color:"#7dd3fc"}, {offset:1, color:"#1e3a8a"}], name="brand")
add_rect(x=0, y=0, width=320, height=120, rx=16, style={fill:"@brand"})
add_text(x=160, y=72, content="svg-mcp", name="title",
style={font_family:"Helvetica", font_size:"40px", font_weight:"bold",
text_anchor:"middle", fill:"#ffffff"})
apply_drop_shadow(target="title", dx=0, dy=2, blur=3, color="#000", opacity=0.4)
render_document(scale=2) # 返回内联渲染的 PNG - 看看然后调整
export_svg() # 最终 SVG 源字符串
```
### 约定
- **活动文档**。`create_document` 返回一个 `document_id` 并使其生效;您可以 **省略 `document_id`** 在后续调用中以目标文档。显式传递它以切换,或使用 `set_active_document`。调用 `current_context()` 以重新锚定(活动 ID,打开文档,轮廓)。
- **按 ID 或名称定位目标**。每个 `target`/`parent`/`content` 参数采用节点的返回 ID **或** 您为其指定的友好 `name`。命名那些您将重访的内容;通过 `find(name=…)` 和 `outline` 进行推理。**名称应唯一** - 匹配多个节点的名称被拒绝(无静默猜测);使用层次路径 `ancestor/name` 或 ID 消除歧义。每个聊天/连接都有自己的隔离文档集(`current_context` 报告 `session_id`)。
- **堆叠**。较晚的兄弟节点在上面绘制。相对于兄弟节点重新堆叠,使用 `reparent(target, above=<node>)`/`below=<node>` 代替计算子索引。
- **坐标**。用户单位,原点在左上角,y 向下增加。
- **样式**。结构化对象 - `fill`,`stroke`,`stroke_width`,`opacity`,加上排版(`font_family`,`font_size`,`font_weight`,`font_style`,`text_anchor`)。颜色接受十六进制 / `rgb()` / CSS 名称 / `none`,**或** 定义的填充 `url(#id)`/`@name` 的引用。渐变或图案。
- **资源** 遵循 *create → define → reference/apply*:`define_*` 返回一个 ID,您将其用作填充(`url(#id)`)/`@name`)或通过 `apply_*` 附加(剪辑/遮罩/标记/筛选器)。剪辑/遮罩/符号/图案定义 **移动** 列出的内容节点,因此先构建这些形状。`list_resources()` 显示已定义的内容。
- **变换** 复合:`translate_node`,`rotate_node` (可选中心),`scale_node` (可选锚点),`skew_node`,或 `apply_transform("rotate(45 100 100)")`。
- **文本**。`add_text` + `add_text_run` 用于多行/样式化跨度;`add_text_on_path` 沿路径流动。 `text_to_path` 轮廓文本为字形路径 - **独立于字体**,展平 tspan,并沿 `<textPath>` 曲线行走;`list_fonts` 列出可安装的系列。
### 资源
打开的文档也作为可读的 MCP 资源公开,因此主机可以显示实时状态:`svg://documents`(索引 + 活动项),`svg://{id}/svg`(源),`svg://{id}/render`(PNG)。突变会发出 `resources/updated` 通知。
### 示例:徽标
标头徽标(`logo.svg`)是用这些工具创建的 - `<mcp>svg</mcp>` 作为蓝色渐变文字标志,橙色→白色星云剪辑到字形中,内部 `svg` 单词在半透明白色面纱下(因此 `<mcp>` 标签读取为星空且 `svg` 为磨砂白色),所有这些都在一个投影下 - 然后 `text_to_path` 轮廓了字形,以便最终文件是独立于字体的。`scripts/demo.py` 显示了一个较小的端到端构建,您可以直接运行。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器