内容
# Inkscape-MCP
> 一个 **MCP** 服务器,使得 Inkscape / SVG 文档 **支持代理操作** —
> 从任何 MCP 客户端检查、编辑、验证、渲染和导出矢量图形。
[](https://www.python.org/)
[](https://github.com/jlowin/fastmcp)
[](#%E8%BF%9E%E6%9E%90%E4%B8%80%E4%B8%80MCP%E5%AE%A2%E6%88%B7)
[](#%E7%9B%96%E6%89%96%E6%9D%83)
`inkscape-mcp` 在您的 SVG 文档上提供了一个小型、强类型工具表面。LLM 代理
可以打开绘图、读取其结构、重新着色和重新标记对象、转换几何体、渲染
预览和导出生产资产 — 所有操作都 **优先考虑无头模式** 且 **可逆**。
每个变异操作都在工作副本上运行、拍摄快照并记录操作记录,
因此代理执行的操作不会触及或破坏您的原件。
---
## 目录
- [为什么](#%E4%B8%BA%E4%BB%80%E4%B9%88)
- [亮点](#%E4%BA%8C%E6%9C%9F%E7%82%B9)
- [工作原理](#%E5%B7%A5%E4%BD%9C%E5%8E%84%E5%8A%8B)
- [需求](#%E9%99%86%E6%B1%82)
- [安装和快速入门](#%E5%AE%89%E8%A3%85%E5%8F%98%E5%BF%AB%E9%80%9F%E5%90%AF%E5%8A%A8)
- [连接 MCP 客户端](#%E8%BF%9E%E6%9E%90%E4%B8%80%E4%B8%80MCP%E5%AE%A2%E6%88%B7)
- [配置](#%E9%85%8D%E7%BD%AE)
- [工具参考](#%E5%B7%A5%E5%85%B7%E5%8F%82%E9%A1%B5)
- [资源参考](#%E8%B5%B7%E6%BA%90%E5%8F%82%E9%A1%B5)
- [提示参考](#%E6%8F%90%E7%A4%BA%E5%8F%82%E9%A1%B5)
- [尝试让您的代理...](#%E5%90%93%E8%AF%81%E8%AE%A9%E6%88%B7%E7%9A%84%E4%BB%A4%E4%BA%BA%E5%8A%8C)
- [安全模型](#%E5%AE%89%E5%85%A8%E6%A8%A1%E5%BC%8F)
- [项目布局](#%E9%A1%B1%E7%9B%96%E5%B8%83%E5%B1%80)
- [开发](#%E5%BC%80%E5%8F%91)
- [许可证](#%E6%89%96%E6%9D%83)
---
## 为什么
LLM 代理擅长推理 *应该* 在绘图中更改 *什么*(“使标志为蓝色,
将标题调整为 24 像素,导出 512 像素图标”),但不擅长安全地操作原始 XML 或驱动 GUI。
一个天真的“运行此 Inkscape 命令”工具是危险的:它可以覆盖原件,以不安全的方式执行,
或在没有回溯能力的情况下静默破坏文件。
`inkscape-mcp` 通过 **有界、类型化的 API** 解决了这个问题;每个功能都是一个具有显式参数和声明风险类别的小型工具。
简单的结构编辑通过直接的 `lxml` DOM 层进行;渲染、导出和复杂的几何运算通过 Inkscape CLI 进行。
原件永远不会被修改,每个更改都有快照支持且可逆,子进程调用使用参数列表 — 而不是 shell 字符串。
## 亮点
- **88 种类型工具**,涵盖读取、验证、渲染、导出、优化、安全编辑、元素创建、
定义/分组、路径几何、快照、保存和实时组。
- **优先考虑无头模式.** 不需要 GUI;Inkscape 二进制文件仅用于渲染 / 导出 /
几何运算,服务器探测运行时而不是假设版本。
- **可逆.** 每个变异操作 = 预变异快照 + 变前/变后预览
+ 操作记录。`restore_snapshot` 回滚。
- **原件是神圣的.** 文档打开后进入受跟踪的工作副本。没有任何内容会覆盖源文件;
保存到 *新* 路径,覆盖需要明确批准。
- **风险分类.** 每个工具声明 `低` / `中` / `高` / `受限`;策略层强制执行(高风险需要每个操作批准令牌;
受限功能在 MVP 中永远不会发布)。
- **沙盒化.** 工作区根目录监狱、路径规范化 + 符号链接保护、输入/输出/导出大小
限制、每个进程超时、安全 XML 解析(无实体扩展)、无网络、无任意
扩展执行。
- **MCP 资源** 公开文档结构(摘要 / 树 / 层 / 对象 / 样式 / 字体 /
资产)和运行时能力矩阵作为可寻址 URI。
## 工作原理
```
MCP 客户端(Claude 等)
│ STDIO / JSON-RPC
▼
FastMCP 应用程序 ──► 类型化的 @mcp.tool 函数 (风险分类,参数验证)
│
├─ 直接 DOM 引擎(lxml) → 结构读取 + 安全编辑
├─ Inkscape CLI 适配器(参数列表) → 渲染 / 导出 / 几何运算
├─ 快照引擎 → 变异前副本 + 可逆恢复
├─ 操作记录 → 每次变异的审计跟踪
└─ 工作区沙盒 → 路径/大小/超时/XML 安全
```
1. **`open_document`** 将您的 SVG 复制到受跟踪的工作区文档中,并返回一个不透明的
`doc_id`。原始文件永远不会被写入。
2. **读取工具/资源** 检查工作副本 — 树、层、样式、字体、资产。
3. **编辑工具** 通过管道修改工作副本:拍摄快照 → 应用更改
→ 渲染前后预览 → 编写操作记录。所有中风险且可逆。
4. **渲染/导出工具** 调用 Inkscape CLI(仅限参数列表)并将工件
放入工作区工件/导出目录中,路径相对工作区。
5. **`save_document_as`** 将工作副本写入 *新* 文件(验证前后)。
覆盖现有文件是一个单独的、需要批准的高风险路径。
## 需求
- **Python ≥ 3.12** 和 [`uv`](https://docs.astral.sh/uv/)。
- 运行时依赖(由 `uv sync` 安装):**FastMCP 3.x**、**lxml** 和 **Pillow** (聚焦
实时前后视觉差异,`live_diff_view` 使用 Pillow 进行像素差异计算和注释叠加)。
- **`PATH` 上的 Inkscape** 用于渲染 / 导出 / 几何运算工具(开发和测试针对
Inkscape **1.4.x**)。读取/编辑/验证工具无需 Inkscape。
- 使用 `inkscape --version` / `inkscape --action-list` 检测您的安装,或运行
`diagnose_runtime` 工具。
- 至少配置一个 **工作区根目录** (参见 [配置](#%E9%85%8D%E7%BD%AE))— 沙盒
拒绝触及工作区根目录以外的任何内容。
## 安装和快速入门
该软件包公开了一个控制台脚本,`inkscape-mcp` → `inkscape_mcp.server:main`,它在
STDIO 上启动 FastMCP 应用程序。可以通过 `uvx` (一次性)、`pipx` (持久)或从源代码安装。
> **尚未发布到 PyPI** — 从源代码/ git 安装(相同的软件包,相同的脚本)。裸名称
> `uvx inkscape-mcp` / `pipx install inkscape-mcp` 将在发布后生效。
```bash
# uvx — 无需安装(从本地检出;存储库根目录包含 pyproject.toml):
uvx --from /abs/path/to/inkscape-mcp inkscape-mcp
# uvx — 直接从 git:
uvx --from "git+https://github.com/johnnyjagatpal/inkscape-mcp.git" inkscape-mcp
# pipx — 持久安装控制台脚本:
pipx install /abs/path/to/inkscape-mcp
# 从源代码(开发/测试):
cd inkscape-mcp # 存储库根目录
uv sync # 安装运行时 + 开发依赖
uv run pytest # 运行测试套件
uv run inkscape-mcp # 启动 STDIO MCP 服务器
```
启动的服务器等待来自 STDIN 的 MCP JSON-RPC(MCP 主机驱动它)。使用
`inkscape-mcp </dev/null` 或 `uv run python -c "from inkscape_mcp.server import main"` 确认它启动。
完整的安装矩阵(包括 `claude mcp add` 表单):[`docs/install/install.md`](docs/install/install.md)。
质量门控:
```bash
uv run ruff check --fix .
uv run ruff format .
uv run mypy src
```
> 需要实际 Inkscape 二进制文件的测试用例标记为 `@pytest.mark.inkscape`。它们在
> 没有 `inkscape` 的主机上 **自动跳过** (中央 `pytest_collection_modifyitems` 钩子在
> `tests/conftest.py` 中),因此在没有 Inkscape 的主机上测试套件为绿色;当存在
> 二进制文件时,测试正常运行。可以使用 `uv run pytest -m "not inkscape"` 显式跳过。
**CI.** [`.github/workflows/ci.yml`](.github/workflows/ci.yml) 在 Linux/macOS/Windows 上运行 ruff + ruff-format
+ mypy + pytest,在 Linux 上进行无头 + 跨平台实时传输套件测试,在 Linux 上进行完整的测试套件,
包括真实 Inkscape 测试,以及在所有三个操作系统上进行打包的 `pipx` 安装 STDIO 启动烟雾测试,
此外还进行完整的表面 MCP 烟雾测试(`ci_surface_smoke.py`),该测试断言已注册的
原始计数(**99 种工具 / 7 种提示 / 16 种资源**)并通过内存客户端读取每个资源。
CI 帮助脚本位于 [`scripts/`](scripts/)(`ci_diagnostics.py`、`ci_boot_smoke.py`、
`ci_surface_smoke.py`)。
**评估.** [`evals/`](evals/) 包含一个确定性的、可在 CI 中运行的工具可用性测试框架,
它在没有实时 LLM 的情况下衡量“代理友好性”:`tool_selection_scenarios.json` 是一个标记的
自然语言请求集(镜像下面的意图目录),而 `run_eval.py` 驱动服务器自己的发现层
(`how_do_i` / [`intents.py`](src/inkscape_mcp/intents.py))以报告每个组和整体的
工具选择准确性和超出范围的标记(`uv run python evals/run_eval.py`,`--json` 用于报告字典)。
`tests/test_eval_harness.py` 防止回归;场景模式与运行器无关。一个可选的、仅限报告的实时
代理运行器(`run_live_eval.py`)重用 **相同的** 数据集 + 评分器,以捕获实际的工具调用轨迹
+ 通过可插入的 `AgentDriver`(默认为确定性的 `ReplayDriver`;除非 `--driver real` /
`INKSCAPE_MCP_EVAL_DRIVER=real`,否则实时 MCP+LLM 路径关闭)并计算回合数。
## 连接 MCP 客户端
服务器通过 **STDIO 上的 MCP** 进行通信。将任何支持 MCP 的客户端指向 `inkscape-mcp`
控制台脚本。现成的宿主配置位于 [`examples/`](examples/)
([`claude_desktop_config.json`](examples/claude_desktop_config.json)、
[`mcp.json`](examples/mcp.json));完整的宿主特定说明(Claude Desktop、Claude Code +
`claude mcp add`、通用 STDIO)在
[`docs/install/host-configs.md`](docs/install/host-configs.md) 中。示例客户端配置:
```jsonc
{
"mcpServers": {
"inkscape": {
"command": "uvx",
"args": ["--from", "/绝对路径/to/inkscape-mcp", "inkscape-mcp"],
"env": {
"INKSCAPE_MCP_WORKSPACE_ROOTS": "/绝对路径/to/your/svgs"
}
}
}
}
```
(使用 `pipx install` 时,使用 `"command": "inkscape-mcp"`、`"args": []`。)从源代码检出直接测试,
在 `uv sync` 运行后,将宿主指向 `uv run --directory /abs/path/to/inkscape-mcp inkscape-mcp`。
使用
[兼容性矩阵](docs/install/compatibility.md) 和
[故障排除](docs/install/troubleshooting.md) 文档映射任何平台/功能差距。
## 配置
所有配置都通过环境变量驱动(不需要配置文件)。沙盒是唯一 **必需的**
设置 — 没有工作区根目录,服务器就没有它可以触及的内容。相同的表格(和
`claude mcp add` / 通用主机表单)在
[`docs/install/host-configs.md`](docs/install/host-configs.md) 中。
| 环境变量 | 默认值 | 目的 |
|---|---|---|
| `INKSCAPE_MCP_WORKSPACE_ROOTS` | *无* | **必需.** 服务器可以读写的操作系统路径分隔的目录列表。除此之外的一切都被拒绝。 |
| `INKSCAPE_MCP_MAX_INPUT_BYTES` | `52428800` (50 MiB) | 输入 SVG 的最大大小。 |
| `INKSCAPE_MCP_MAX_EXPORT_PX` | `8192` | 渲染/导出的最大栅格尺寸。 |
| `INKSCAPE_MCP_MAX_OUTPUT_BYTES` | `104857600` (100 MiB) | 生成的工件的最大大小。 |
| `INKSCAPE_MCP_PROCESS_TIMEOUT_S` | `60` | 每个 Inkscape 进程的超时时间(秒)。 |
| `INKSCAPE_MCP_MAX_PROCS` | `2` | 并发 Inkscape 子进程的最大数量。 |
| `INKSCAPE_MCP_SNAPSHOT_KEEP_N` | `50` | 每个文档保留的快照数量。 |
| `INKSCAPE_MCP_SNAPSHOT_KEEP_DAYS` | `30` | 快照的年龄保留时间。 |
| `INKSCAPE_MCP_SNAPSHOT_HARD_MAX_N` | `500` | 每个文档的快照数量的硬上限。 |
| `INKSCAPE_MCP_SNAPSHOT_HARD_MAX_BYTES` | `5368709120` (5 GiB) | 快照字节的硬上限。 |
| `INKSCAPE_MCP_ARTIFACT_KEEP_DAYS` | `14` | 工件的年龄保留时间。 |
| `INKSCAPE_MCP_ARTIFACT_MAX_BYTES` | `2147483648` (2 GiB) | 工件的总字节预算。 |
| `INKSCAPE_MCP_ARTIFACT_MAX_BYTES_PER_DOC` | `536870912` (512 MiB) | 每个文档的工件字节预算。 |
| `INKSCAPE_MCP_LIVE_CACHE_MAX_ENTRIES` | `64` | 每个会话的实时渲染缓存中的最大帧数(LRU)。向下舍入。 |
| `INKSCAPE_MCP_LIVE_CACHE_MAX_BYTES` | `268435456` (256 MiB) | 实时渲染缓存的总字节预算(LRU 驱逐)。向下舍入。 |
| `INKSCAPE_MCP_LIVE_COALESCE_BUDGET_MS` | `200` | 帧合并延迟预算:重复的相同键渲染在该窗口内返回刚刚缓存的帧而不是重新渲染。`0` 禁用。 |
| `INKSCAPE_MCP_LIVE_FRAME_KEEP_DAYS` | `7` | 循环/实时渲染帧的年龄保留时间,由 **显式** 保留扫描(启动 + `prune_snapshots`)修剪,从不由变异工具隐式修剪。 |
| `INKSCAPE_MCP_LIVE_FRAME_MAX_BYTES` | `536870912` (512 MiB) | 循环/实时渲染帧的总字节预算(保留最新者),由显式扫描修剪。 |
| `INKSCAPE_MCP_LIVE_ENABLED` | `true` | 实时模式的主开关。**默认开启** (操作员选择);设置一个假值(`0`/`false`/`no`/`off`)以选择退出,此时 `live_connect` 干净地拒绝。 |
| `INKSCAPE_MCP_LIVE_RENDEZVOUS` | *无* | 实时帮助程序的 rendezvous 文件的路径(否则在 Inkscape 用户数据目录/临时目录下发现)。 |
| `INKSCAPE_MCP_ACTION_ALLOWLIST` | *内置默认值* | 添加到内置允许列表的 Inkscape Action ID 的操作系统路径分隔列表。服务器端,从不客户端提供;不能删除默认项或打开任意直通端口。每个 Action 还必须存在于版本键控的能力映射中才能运行。 |
| `INKSCAPE_MCP_EXTENSION_ALLOWLIST` | *空* | 添加到(空)执行允许列表的 Inkscape 扩展 ID 的操作系统路径分隔列表。发现是只读的,不受影响。 |
| `INKSCAPE_MCP_RAW_ACTION_ENABLED` | `false` | `run_raw_action` 转义门的调试模式门控(ADR-003)。**默认关闭**;设置真值(`1`/`true`/`yes`/`on`)以选择加入。启用它并不扩大允许列表 — 每个 Action 仍然必须被允许列出,存在于能力映射中,字符集安全,并且(对于真正的运行)高 + 批准令牌门控。 |
| `INKSCAPE_MCP_ENGINE_MODE` | `per_call` | 渲染/导出/路径/布尔/操作链的引擎传输(ADR-007)。`per_call` 为每个调用生成一个新的 Inkscape(默认,始终正确);`shell` 通过一个温暖、长期运行的 `inkscape --shell` 工作器路由这些操作,对于任何故障都有 **自动每个调用的回退**。比多操作批次更快;任何值除了 `shell` 都降级为 `per_call`。一个私有的无头工作器,**不是** 您的实时 GUI 通道。 |
| `INKSCAPE_MCP_ENGINE_MAX_PROCESSES` | `2` | 当 `engine_mode=shell` 时,最大并发温暖 shell 工作器(LRU 驱逐)。向下舍入为 1。 |
| `INKSCAPE_MCP_ENGINE_IDLE_TIMEOUT_S` | `300` | 空闲温暖 shell 工作器被回收之前的秒数。向下舍入为 1。 |
| `INKSCAPE_MCP_TOOL_PROFILE` | `full` | 工具披露配置文件。`full` 保留标志允许的表面不变;`core` 将 `tools/list` 限制为精选的基本作者集(`document`/`find`/`create`/`style`/`transform`/`export`/`snapshots` 模块),以削减每回合的模型上下文成本(~60% 较少的 `tools/list` 标记)。仅在标志允许的表面内 **缩小** (第 12 节 / ADR-003);错误值降级为 `full`。 |
| `INKSCAPE_MCP_TOOL_DESC` | `full` | 工具描述模式,与 `INKSCAPE_MCP_TOOL_PROFILE` 正交(后者修剪工具数量 — 本模式修剪描述长度)。`full` 提供每个工具的完整文档字符串;`short` 提供派生的简短形式(“它做什么”的第一行 + `Risk class:` 行),将 ~86% 的描述字节(~23k 个标记)从每个 `tools/list` 中剪切掉。简短形式始终从规范文档字符串(无第二个副本)和 JSON `inputSchema`(参数名称/类型)导出,因此调用者保留完整的参数详细信息;`llms.txt`/`llms-full.txt` 始终携带完整目录。错误值降级为 `full`。 |
## 工具参考
89 个工具。风险类别:**低**(读取/渲染/导出/质量/操作发现)· **中等**(写入-新建/元素创建/定义分组/样式/文本/变换/网页优化/类型批次;可逆)
· **高**(覆盖/删除/路径几何/操作链/原始操作;审批门控)·
**受限**(实时助手安装)。
变异工具返回一个 `EditResult`,携带 `operation_id`、快照 ID 和前后预览。
**约定(参数 + 路径命名)。** 单对象工具使用 `object_id`;多对象工具使用 `object_ids`。调用者选择的写入目标是 `dest_path`(文件)或 `out_dir` + `name_prefix`(目录);相对 `dest_path`/`out_dir`锚定到**工作区根目录**,而非进程 CWD,并且经过沙箱 + 符号链接检查(否则 `path rejected: outside workspace`)。每个生成工件的工具返回一个 `workspace_relative_path`(根相对路径,直接打开,无需 `find`/`stat`)以及托管的 `artifact_path`;绝不会在结果中出现绝对主机路径(第 12 节)。变异结果的 `changed` 在**一个地方**决定 — 编辑管道将文档序列化后再进行突变。前后对比,若有实际变更,报告 `changed: true`,附带链接的快照 + 操作记录;若无实际变更(例如 `replace_color` 匹配不到任何内容,`normalize_viewbox` 在有效 viewBox 上操作,`set_fill` 设置为已存在的颜色,第二次 `fit_to_content`),报告 `changed: false`,`operation_id`/`snapshot_id` 为空,**不生成快照和操作记录** — 无变更发生,因此不会污染快照列表或审计轨迹。
**MCP `ToolAnnotations`。** 每个工具还携带机器可读的 MCP 注解 — `readOnlyHint`、`destructiveHint`、`idempotentHint`、`openWorldHint` 和人类可读的 `title` — 来自**一个中心映射表**(`src/inkscape_mcp/tool_annotations.py`),按键工具的风险类别进行索引,启动时作为一个后注册过程应用。`readOnlyHint` 直接遵循风险类别(低 ⇒ 只读);破坏性(覆盖/删除/轮廓)、幂等性(纯重置)和开放世界(主机探测 + `live_*`)集合在该模块中显式定义。客户端无需解析文档字符串即可读取读写、破坏性和幂等性;标题仅为静态标签(无主机路径,第 12 节)。添加带有风险类别文档字符串的工具会自动注解。
**标签 + 分级披露。** 每个工具还携带**一个领域**标签 — `create` / `edit` / `transform` / `paths` / `export` / `live` / `actions` / `system` / `quality` — 和**一个风险**标签(`low` / `medium` / `high` / `restricted`),由相同的启动过程从**一个中心映射表**(`src/inkscape_mcp/tool_tags.py`)中 штам印。两个现有的操作员标志驱动**基于标签的排除**,因此默认客户端会看到一个较小的核心界面,并选择进入高级/实时组(FastMCP `disable(tags=…)` 可见性转换 — 它们只会**缩小 `tools/list`,绝不会扩大**):
| 标志 | 默认值 | 关闭 → 隐藏 |
|------|---------|-------------|
| `INKSCAPE_MCP_LIVE_ENABLED` | `true` | 每个带有 `live` 标签的工具 |
| `INKSCAPE_MCP_RAW_ACTION_ENABLED` (高级模式) | `false` | ADR-003 草案组:`run_raw_action` + 每个带有 `paths` 和 `actions` 标签的工具 |
因此,**默认**界面(实时开启,高级关闭)会暴露核心的 86 个工具;开启高级模式会添加 `paths`/`actions` 几何图形 + 操作界面(完整 98),或关闭实时功能会删除实时组(66 个,两者关闭)。自我描述的 `list_capabilities.tool_count` / `tools[]` 会报告**活动**的过滤后界面,因为它们会读取与转换器相同的 `mcp.list_tools()`。生成的 `llms.txt` 清单仍然记录**完整**的目录(在强制启用两个标志时生成)。
**最小 `core` 配置文件。** 为了进一步减小默认模型上下文占用,引入了可选的 `INKSCAPE_MCP_TOOL_PROFILE` 环境变量(默认为 `full`,`core` 为最小配置文件),进一步缩小 `tools/list` 到一个精选的基本创作集 — `document` / `find` / `create` / `style` / `transform` / `export` / `snapshots` 模块(开放/检查/查找/创建-*/样式/变换/导出/快照)。探索发现:默认 85 工具界面约 76k 个 token 的 `tools/list` 调用;40 工具核心集约 31k — 约 60% 的每次调用节省。配置文件仅在**标志允许的界面**内缩小(它通过名称禁用非核心工具;绝不会暴露实时/高级标志隐藏的工具 — 第 12 节 / ADR-003),重用相同的 `disable(...)` 机制,并且是幂等的 + 可重新评估的。流氓值会恢复为 `full`。`tool_count` / `tools[]` 报告活动界面;`llms.txt` 仍然记录**完整**目录(配置文件为 `full`)。
### 系统和诊断 — *低*
| 工具 | 签名 | 描述 |
|---|---|---|
| `diagnose_runtime` | `()` | 探测本地 Inkscape + Python 运行时**新鲜**并返回能力矩阵(版本、操作、导出格式、DBus/实时、inkex、字体)— 以及精选的 `intents` 目标→工具映射和权威的 MCP 工具界面(`tool_count` + `tools:[{name, purpose, risk}]`,来自实时注册表)。 |
| `list_capabilities` | `()` | 返回**缓存**的能力矩阵(一次性探测,然后重用)。包括附加的 `intents` 部分:精选的自然语言目标 → 工具(s)映射(`[{goal_pattern, tools, how_to, group}]`)— 与 `how_do_i` 匹配的同一个映射。同时携带权威的 MCP 工具界面:`tool_count`(注册的 `@mcp.tool` 的真实计数)+ `tools:[{name, purpose, risk}]`,来自实时注册表 — 一个数字代替四个。 |
| `how_do_i` | `(goal)` | 将自然语言目标映射到实现该目标的具体工具名称(s)(最佳匹配优先:`[{goal_pattern, tools, how_to, group}]`)。**仅指导 — 不执行**(ADR-002/003:无混合端口 / 原始操作入口)。标记超出范围的目标(栅格/像素编辑、任意操作/扩展/脚本、网络获取、代码执行)为 `out_of_scope=True` + 原因;建议 `list_capabilities`/`inspect_document` 匹配失败。*低(无快照/操作记录)。* |
| `stat_artifact` | `(path)` | 只读磁盘大小 + 沙箱工件的 sha256 → `{path, bytes, sha256}`。路径是工作区相对路径或绝对路径,经过沙箱 + 符号链接验证(逃逸 → `path rejected: outside workspace`);大小上限(`max_input_bytes`),sha256 流式读取区块;回声路径是工作区相对路径(无主机路径泄漏)。替换 `wc -c`/`sha256sum` 回落。 |
| `stat_artifacts` | `(paths)` | `stat_artifact` 的集合版本 → `{artifacts:[{path, bytes, sha256}], total_bytes, count}`。每个文件统计 + 聚合字节预算,用于图标集 / `dist/` 树,一次调用完成;相同的每个路径沙箱 + 大小规则。 |
### 文档 — *低(创建是中等)*
| 工具 | 签名 | 描述 |
|---|---|---|
| `open_document` | `(path)` | 打开 SVG 到跟踪的工作区工作副本;返回不透明的 `doc_id` + 摘要。`path` 可以是工作区**相对路径**(锚定到工作区根目录,而非进程 CWD)或绝对路径;两者都经过沙箱 + 符号链接检查(否则 `path rejected: outside workspace`)。原始文件从不突变。文档字符串记录工作副本模型。 |
| `create_document` | `(width, height, viewBox?, background?)` | 从头创建空白的跟踪工作副本文档 — 无需源文件。`validate_document`-clean;返回与 `open_document` 相同的 `{doc_id, summary}` 形状。可选验证的 `background` 颜色作为整个页面矩形绘制。*中等,可逆。* |
| `reload_document` | `(doc_id)` | 从其源文件刷新工作副本,**相同** `doc_id`:获取预加载快照(可逆),重新验证源文件仍在沙箱中,重新复制到工作副本。`create_document` 文档从其空白种子恢复。返回刷新后的摘要 + `pre_reload_snapshot_id`。 |
| `inspect_document` | `(doc_id)` | 聚合检查:树、图层、样式、字体、外部资产和可寻址的 `objects` 列表(`ObjectRef`:`object_id`/`tag`/`bbox`/`fill`/`stroke`/`text`)。每个元素携带 `paint` 摘要(`fill`/`stroke`/`stroke-width`)+ `is_leaf`/`is_layer`;对象携带 `bbox`;字体/资产标记 `available` 和 `used_by`。 |
| `find_objects` | `(doc_id, tag?, fill?, stroke?, text?, id_prefix?, bbox?, accurate_bbox?)` | 文档的可寻址对象的只读筛选(与操作语义)→ `[{object_id, tag, bbox?, fill?, stroke?, text?}]`。绘制匹配不区分大小写 - 半色调不敏感(`dom.color_key`)并通过 CSS 层叠解析 — `<style>` 规则 / `.class` / `#id` / 继承的绘制匹配 `fill`/`stroke` 过滤器(报告的令牌保留每个元素)。`bbox` = 属性派生的框交集(路径/文本/组/变换排除在 bbox 过滤器下)**除非** `accurate_bbox=true`,它选择一个单独的批处理 `inkscape --query-all` 以获取真正的轮廓/变换感知框(如果引擎不存在,则降级为属性框)。`text` = 不区分大小写的子字符串。使 ID 接受的编辑工具可用于文档代理未创建的文档。*低(只读;`accurate_bbox` 运行引擎)。* |
### 组合/采用 SVG — *高(审批门控),可逆*
| 工具 | 签名 | 描述 |
|---|---|---|
| `set_document_svg` | `(doc_id, svg, approval_token?)` | 用代理组合的 SVG 字符串替换整个工作副本(根必须为 `<svg>`)。强化安全解析 + 严格元素/属性允许列表(拒绝 `<script>`、`on*` 处理程序、`javascript:`/外部/`data:` hrefs — 仅允许同文档 `#id` 引用)。自动运行 `validate_document` 并将发现结果合并到结果(`validation`)。通过突变前的快照可逆。 |
| `insert_svg_fragment` | `(doc_id, svg, parent_id?, unwrap?, approval_token?)` | 在 `parent_id` 下插入代理组合的 SVG 片段(单个元素子树)或文档根目录。默认情况下,包装器 `<svg>` 被解包(`unwrap=true`);传递 `unwrap=false` 以保留显式嵌套 `<svg>` 容器原样。 与 `set_document_svg` 相同的强化 + 内联 `validation`。可逆。关闭 `Write`→ 重新 `open_document` 循环。 |
| `compose_grid` *(中等)* | `(rows, cols, cell, doc_ids? \| object_ids?+source_doc_id?, target_doc_id?, gap?, padding?, scale_to_fit?)` | 在**不同**资产的 `rows`×`cols` 网格中布局(联系/规格表)**一次可逆调用**。 **EXACTLY ONE** 源模式:`doc_ids`(每个单元格一个完整文档)或 `object_ids`+`source_doc_id`(来自一个文档的对象)。每个资产被深度复制 + 重新 ID 并包装在 `<g>` 单元格组中,翻译到其行主导原点 + 可选**缩小**以适应 `cell − 2·padding`。组合到 `target_doc_id` 或创建空白表格大小的表格。整个表格的**一个**快照 + 操作记录(ADR-004);从不突变源。重用 `tile` 的放置基元。 |
| `place_document` *(中等)* | `(target_doc_id, x, y, source_doc_id?, object_id?, scale=1.0)` | 将现有文档或命名对象**放入**另一个文档中,位于 `(x, y)` 并具有 `scale` — 单个资产伴侣的 `compose_grid`。源子树被深度复制 + 重新 ID(从不突变源)并包装在 `<g>` 中,翻译到 `(x, y)` 并均匀缩放,在**一个**快照 + 操作记录下。让现有几何图形可以跨文档重新组合而无需重新创作。 |
### 验证 — *低*
| 工具 | 签名 | 描述 |
|---|---|---|
| `validate_document` | `(doc_id)` | 验证加载的文档;返回结构化、可机器读取的发现结果。包括每个文本元素的 glyph-coverage 检查(`missing_glyphs`):当声明的字体 **OWN** cmap(通过 fontconfig 读取,不自动替换)无法渲染文本时,它会命名未覆盖的字符和一个覆盖家族尝试。 |
| `quality_report` | `(doc_id)` | 机器可读的质量报告:包装 `validate_document` 的发现结果并添加指标(对象/节点/层计数、嵌入式栅格权重、字体覆盖率、viewBox 健康状况)+ 优化机会,与 `svg_web_optimize` 剥离的内容一致。只读。 |
| `quality_report_set` | `(doc_ids)` | 质量报告**一组**在一个只读调用:每个文档 `QualityReport` + 聚合(`all_ok`、`worst_score`/`mean_score`、`total_opportunities`)+ 结构化的跨文档 `consistency` 判决(每个属性 viewBox/ stroke-width/ id-naming: `agree` + `majority` + `{value:[doc_ids]}` + unknowns)。组合文档引擎;无快照。 |
### 渲染和导出 — *低*
每个渲染/导出结果携带 `stale: bool` 陈旧信号:`False` 在新鲜生成的工件上(它反映当前工作副本);保留标记 **以前返回的工件** 工作副本自此之后已经超过(完整的 mtime 跟踪是一个后续 - 见)。
渲染/导出结果还自我认证内容真实性,在进程中计算(无 `pdffonts`/`pdfimages`/`mutool` shell-out,无 Pillow 子进程):**栅格**(PNG)结果携带 `opaque_px`(绘制非透明像素计数)+ `all_blank` 以便“渲染实际绘制了什么”是可从结果检查的;**PDF** 结果携带 `is_vector`(无嵌入式栅格图像)+ `fonts_outlined`(无嵌入式字体 - 文本路径化路径),当两者都成立时为 true 矢量。每个字段都是增量且 `None` 输出不适用(或验证被跳过)。
| 工具 | 签名 | 描述 |
|---|---|---|
| `render_preview` | `(doc_id, width_px?, name?)` | 渲染整个文档的 PNG 预览到工件目录。连续调用相同的宽度永远不会覆盖(每个调用的唯一帧;可选 `name`/标签)。报告真正的磁盘栅格大小 + 内容真实性 `opaque_px`/`all_blank`(证明渲染绘制了像素)。 |
| `export_document` | `(doc_id, format, width_px?, out_dir?, name_prefix?)` | 将整个文档导出到 **PNG / PDF / SVG** 到导出目录(或沙箱检查的 `out_dir`)。报告 PNG 的真实写入栅格大小 + 内容真实性:PNG → `opaque_px`/`all_blank`,PDF → `is_vector`/`fonts_outlined`(两者成立时为 true 矢量)。 |
| `export_object` | `(doc_id, object_id, format="png", width_px?, out_dir?, name_prefix?)` | 导出单个对象(按 ID)到其边界框;报告实际裁剪的栅格大小 + 相同的内容真实性字段。 ID 是字符验证的,从不直接传递给 Inkscape。 |
| `capture_frame` | `(doc_id, series?, width_px?, label?)` | 捕获运行脚本的 PNG 快照系列(`frame-001.png`、`frame-002.png`...)到 `artifacts/frames/<series>/`,以记录文档编辑运行。仅限画布(无 UI 铬)。索引是文件系统派生的(单调,重启证明,不会覆盖);`series`/`label` 被清理到一个单独的托管子目录。返回路径 + `series`/`frame_index`。 |
| `list_frames` | `(doc_id, series?)` | 列出 `capture_frame` 系列的帧,按索引排序(可解析的工作区相对路径)。当系列未使用时为空。只读。 |
### 导出配置文件和批量导出 — *低*
| 工具 | 签名 | 描述 |
|---|---|---|
| `export_web_profile` | `(doc_id, width_px=1024, widths?, scales?, out_dir?, name_prefix?)` | Web 资产集:一个 PNG 栅格 + 一个纯 SVG。传递 `widths`/`scales` 以获取 1×/2×/3× 响应式 PNG 集(每个输出不同且可解析)。`out_dir`/`name_prefix` 直接写入调用者命名的树(例如 `dist/web/`);相对锚定到工作区根目录,进行沙箱检查。PNG 条目报告 `opaque_px`/`all_blank`。 |
| `create_icon_set` | `(doc_id, sizes?, out_dir?, name_prefix?)` | 来自源文档的多尺寸方形 PNG 图标集。过度或 ≤0 大小给出不同的错误消息。`out_dir`/`name_prefix` 目标是一个调用者选择的目录(沙箱检查)。条目报告 `opaque_px`/`all_blank`。 |
| `export_print_profile` | `(doc_id, out_dir?, name_prefix?)` | 文档的打印导向矢量 PDF;应用并 **报告** 打印特定导出设置(因此输出与纯 PDF 不同且可审计)。`out_dir`/`name_prefix` 将验证后的 PDF 直接写入 `dist/` 树(沙箱检查)。报告内容真实性 `is_vector`/`fonts_outlined`(两者成立时为 true 矢量)。 |
| `export_batch` | `(doc_id, specs, dry_run=True, byte_budget?, out_dir?, name_prefix?)` | 在一个有界调用中运行一个 **类型化** 的导出规范列表(`format` png/pdf/svg,可选 `width_px`/`object_id`)。每个调用项限制 + 总输出字节预算(限制为每个文档的工件上限);`dry_run` 默认 True(报告计划 + 投影大小,不写入任何内容)。组合导出引擎;无新权限。 |
| `export_set` | `(doc_ids, specs, dry_run=True, byte_budget?, out_dir?, name_prefix?)` | 批量导出一个**集合**:在一个调用中运行 `export_batch` 的规范到每个文档 → 每个文档 `BatchResult` + 聚合(`total_items`,`total_bytes`)+ 一个结构化的跨文档 `consistency` 判决。组合每个文档的引擎(未重新实现);仅限工件。 |
### 优化 — 中等,可逆
| 工具 | 签名 | 描述 |
|---|---|---|
| `svg_web_optimize` | `(doc_id, precision=2, keep_ids?)` | 对工作副本进行网页优化:去除编辑器元数据/命名空间属性/注释,删除未引用的 `defs`/id/空组(保留引用的id — 无悬空引用;`keep_ids` 中的id始终保留,例如刻意的 a11y/human id),并将坐标精度降低到 `precision` 小数(0–8;根 `viewBox` 不动)。返回结构化差异 `{bytes_before, bytes_after, removed:{code:count}}`(代码与 `quality_report.opportunities` 交叉连接)。直接 DOM(ADR-005);通过变异管道 → 快照 + 操作记录 + 前后预览(可逆)。 |
| `optimize_set` | `(doc_ids, precision=2, keep_ids?)` | 一次调用优化一个 **集合**:对每个文档运行 `svg_web_optimize` → 每个文档的 `WebOptimizeResult` + 聚合(`total_bytes_before`/`_after`/`_saved`,`changed_count`)+ 结构化的跨文档 `consistency` 验证(在优化前状态下计算)。组合每个文档的引擎;**每个更改的文档一个快照 + 操作记录**(ADR-004)。 |
### 快照 — 低
| 工具 | 签名 | 描述 |
|---|---|---|
| `create_snapshot` | `(doc_id, label?)` | 快照当前工作副本并索引它。 |
| `list_snapshots` | `(doc_id)` | 按顺序列出文档的快照,并附带元数据。 |
| `restore_snapshot` | `(doc_id, snapshot_id)` | 将工作副本恢复到选定的快照;返回 `restored_sha256` + 大小,以便在无文件系统访问的情况下进行恢复校验。 |
| `prune_snapshots` | `(doc_id)` | 应用保留策略(保留 N / 保留天数 + 硬上限),删除过时的快照和孤立的操作记录,**以及** 按年龄 + 字节预算删除文档根的循环/实时渲染帧(从不引用实时操作记录的帧)。永远不会触及工作副本或原始文件。显式维护扫描 — 也会在启动时运行一次;从不通过变异工具隐式触发。 |
### 样式编辑 — 中等,可逆
| 工具 | 签名 | 描述 |
|---|---|---|
| `set_fill` | `(doc_id, object_ids, color, opacity?)` | 设置填充颜色(和可选的填充不透明度)。颜色会被验证;拒绝 CSS 注入标点符号。 |
| `set_stroke` | `(doc_id, object_ids, color?, width?, opacity?)` | 设置描边颜色,宽度和/或不透明度。 |
| `set_opacity` | `(doc_id, object_ids, opacity)` | 设置元素级不透明度(`[0, 1]`)。 |
| `replace_color` | `(doc_id, from_color, to_color, scope_ids?)` | 在文档中(或在 `scope_ids` 子树中)将一种颜色替换为另一种;匹配内联样式和表示属性。 |
| `apply_palette` | `(doc_id, mapping, scope_ids?)` | 在单个可逆操作中应用多个 `from → to` 颜色替换。 |
### 文本和对象编辑 — 中等,可逆
| 工具 | 签名 | 描述 |
|---|---|---|
| `replace_text` | `(doc_id, object_id, text)` | 替换 `<text>` / `<tspan>` / flow-text 元素的文本内容。 |
| `set_font` | `(doc_id, object_ids, family?, size?, weight?)` | 在文本对象上设置字体系列/字体大小/字体粗细(至少需要一个)。返回 `coverage_ok` + 每个对象的 `font_coverage`(`uncovered_chars`,`suggested_family`),以便在应用时捕获非覆盖字体(从字体的 cmap 读取,而非 fontconfig 替代)。 |
| `duplicate_object` | `(doc_id, object_id, new_id?)` | 原地复制一个对象/组,在原始对象后立即插入克隆。 |
| `tile` | `(doc_id, object_id, rows, cols, dx, dy)` | 将一个对象复制到 N×M 网格中(克隆 `(r,c)` 偏移 `(c·dx, r·dy)`);一次性调用,限定数量。 |
| `rename_object` | `(doc_id, object_id, new_id?, label?)` | 更改对象的 `id` 和/或 `inkscape:label`。 |
| `delete_object` | `(doc_id, object_ids, approval_token?)` | **高风险,可逆**:从 DOM 中删除指定 id 的对象 → `DeleteResult`(`EditResult` + `affected_ids`)。需要批准令牌(真正的删除需要非空 `approval_token`;否则拒绝)。已经不存在的 id 被跳过;无匹配 → `changed=false`,无快照。操作前快照 + 操作记录,每个操作;通过 `restore_snapshot` 可逆。 |
### 类型化批量编辑 — 中等(成员最大),可逆
| 工具 | 签名 | 描述 |
|---|---|---|
| `apply_edits` | `(doc_id, edits, approval_token?)` | **批量**:应用有序列表(≤ 64)的 **类型化** 编辑 — 现有 DOM 操作的辨别联合(`set_*` / `replace_*` / `apply_palette` / `replace_text` / `set_font` / `duplicate`/`rename`/`delete` / `move`/`scale`/`rotate`/`resize_canvas`/`normalize_viewbox`/`tile` / `create_*` / `group_objects`/`reparent`/`create_use` / `add_*_gradient`)— 通过与 **单个** 原子操作相同的编辑内核。所有操作首先验证(一个错误的编辑 → 文档字节不变);全部或不全部回滚,**一个快照 + 一个操作记录**(单个 `restore_snapshot` 可逆转整个批次)。有效风险 = 成员中的最大值;`delete_object` 成员将批次提升为高风险,需要 `approval_token`。关闭往返税费与免费文本 `execute_code`,而无需放弃类型/验证/可逆性(Penpot 调查)。 |
| `transform_objects` | `(doc_id, selector, operation, dry_run=True, max_matches=64, approval_token?)` | **选择器 → 操作**:无需代码入口的声明式批量编辑 — 通过现有的 `find_objects` 谓词引擎解析目标集(`tag`/`fill`/`stroke`/`text`/`id_prefix`/`bbox`,完整的 CSS 层叠)并对每个匹配项应用 **类型化** 操作(`set_fill`/`set_stroke`/`set_opacity`/`set_font`/`move_object`/`scale_object`/`rotate_object`/`delete_object`),通过与 `apply_edits` 相同的原子批量内核(一个快照 + 一个操作记录;全部或不全部)。文档范围/创建/身份冲突的操作被拒绝。`dry_run=True`(默认)返回匹配的 id + 投影计划,不写入任何内容;`max_matches`(默认 64)拒绝过宽的选择器,然后进行任何变异。有效风险 = 操作的类;`delete_object` 操作是高风险的,需要 `approval_token`(ADR-002/003/004)。 |
### 元素创建 — 中等,可逆
直接 DOM(ADR-005)形状基元 — 每个形状有一个小型类型化工具(无通用的 `add_element(tag, attrs)`,根据 ADR-002/003)。每个工具都插入到可选的 `parent_id`(必须存在)或文档默认父级(第一个 `inkscape:groupmode="layer"`,否则根节点),并返回 `CreateResult`(扩展的 `EditResult`,包含 `object_id` + 分析 `bbox`;`bbox` 为 `None`,表示路径/文本的几何形状无法廉价计算)。每个值都经过严格验证(有限数字、字符集安全 id、控制字符清理文本、命令/字符集允许列表路径 `d`)。
| 工具 | 签名 | 描述 |
|---|---|---|
| `create_rect` | `(doc_id, x, y, width, height, parent_id?, object_id?, rx?, ry?, fill?, stroke?, stroke_width?)` | 插入 `<rect>`(大小 > 0;可选圆角)。可选内联 `fill`/`stroke`/`stroke_width` 在一次调用中绘制,验证如同 `set_fill`/`set_stroke`。 |
| `create_circle` | `(doc_id, cx, cy, r, parent_id?, object_id?, fill?, stroke?, stroke_width?)` | 插入 `<circle>`(半径 > 0);可选内联 `fill`/`stroke`/`stroke_width`。 |
| `create_ellipse` | `(doc_id, cx, cy, rx, ry, parent_id?, object_id?, fill?, stroke?, stroke_width?)` | 插入 `<ellipse>`(半径 > 0);可选内联 `fill`/`stroke`/`stroke_width`。 |
| `create_line` | `(doc_id, x1, y1, x2, y2, parent_id?, object_id?, stroke?, stroke_width?)` | 插入 `<line>`;可选内联 `stroke`/`stroke_width`(直线无填充 — 无 `fill`)。 |
| `create_polygon` | `(doc_id, points, parent_id?, object_id?, fill?, stroke?, stroke_width?)` | 从 `(x, y)` 对插入封闭的 `<polygon>`;可选内联 `fill`/`stroke`/`stroke_width`。 |
| `create_polyline` | `(doc_id, points, parent_id?, object_id?, fill?, stroke?, stroke_width?)` | 从 `(x, y)` 对插入开放的 `<polyline>`;可选内联 `fill`/`stroke`/`stroke_width`。 |
| `create_path` | `(doc_id, d, parent_id?, object_id?, fill?, stroke?, stroke_width?)` | 插入具有严格字符验证、长度限制的 `d` 的 `<path>`;几何形状不解析(`bbox=None`)。可选内联 `fill`/`stroke`/`stroke_width`。 |
| `create_text` | `(doc_id, x, y, text, parent_id?, object_id?, fill?, stroke?, stroke_width?)` | 插入包含 `text` 的 `<text>`(存储为文本节点;拒绝控制字符;`bbox=None`)。可选内联 `fill`/`stroke`/`stroke_width`(通过 `set_font` 使用字体)。 |
### 定义,渐变和分组 — 中等,可逆
渐变定义位于文档的 `<defs>` 中(如果不存在,则自动创建为第一个子节点);返回的 id 可用作 `url(#id)` 涂料。分组/结构工具重新组织现有的对象。
| 工具 | 签名 | 描述 |
|---|---|---|
| `add_linear_gradient` | `(doc_id, stops, x1="0%", y1="0%", x2="100%", y2="0%", object_id?)` | 将 `<linearGradient>` 添加到 `<defs>`。`stops` = `{offset, color, opacity?}` 列表(偏移 0..1 或 %,验证颜色)。返回渐变 id;`bbox=None`。 |
| `add_radial_gradient` | `(doc_id, stops, cx="50%", cy="50%", r="50%", fx?, fy?, object_id?)` | 将 `<radialGradient>` 添加到 `<defs>`(可选焦点)。返回渐变 id;`bbox=None`。 |
| `create_group` | `(doc_id, parent_id?, object_id?)` | 插入一个空 `<g>` 以备后用。 |
| `group_objects` | `(doc_id, object_ids, object_id?)` | 在 **现有** 对象(≥ 1,必须存在)周围包装一个新的 `<g>`,位于第一个目标的位置。 |
| `reparent_object` | `(doc_id, object_id, new_parent_id)` | 将对象移动到新的父级下(拒绝后代/自身父级;坐标空间可能会移动)。 |
| `create_use` | `(doc_id, href_id, parent_id?, object_id?, x?, y?, transform?)` | 插入 `<use href="#href_id">` 到现有同文档对象(拒绝外部/`javascript:`/`url(...)` href)。文档字符串注意 `<use x/y>` + `transform="scale"` 翻译缩放陷阱。 |
### 变换 — 中等,可逆
| 工具 | 签名 | 描述 |
|---|---|---|
| `move_object` | `(doc_id, object_id, dx, dy)` | 在父坐标空间中平移 `(dx, dy)`。 |
| `scale_object` | `(doc_id, object_id, sx, sy?)` | 缩放 `sx`(和 `sy`,默认为 `sx` 表示均匀缩放)。 |
| `rotate_object` | `(doc_id, object_id, degrees, cx?, cy?)` | 绕 `(cx, cy)` 或原点旋转 `degrees`。 |
| `resize_canvas` | `(doc_id, width, height, adjust_viewbox=False, bleed?, bleed_color="#ffffff")` | 将画布 `width` / `height` 设置为验证的 CSS 长度;`adjust_viewbox=True` 将 `viewBox` 重新定位以跟踪新的画布。`bleed`> 0 还会向外扩展 `viewBox`,每个边距增加 `bleed`,并用 `bleed_color` 通过一个背景 `<rect>` 绘制新的条带 — 一个调用中的打印出血大小调整;与 `adjust_viewbox` 互斥;默认关闭。 |
| `normalize_viewbox` | `(doc_id)` | 标准化或修复根 `viewBox`(在有效的 `viewBox` 上幂等)。 |
| `fit_to_content` | `(doc_id)` | 将根 `viewBox` 设置为文档的内容边界框(在文档的固有用户坐标空间中通过 Inkscape 引擎计算)。**幂等** — 在已经拟合的文档上进行第二次调用是一个无操作(`changed: false`,无快照)。可逆操作 + 对实际更改的快照。 |
### 路径几何 — 高风险(需要批准),默认干运行,可逆
通过 Inkscape **引擎** (`select-by-id;<action>` 参数列表,从不作为 shell 字符串)运行破坏性路径操作,而不是直接 DOM(ADR-005)。每个工具都是高风险的:真正的更改需要非空 `approval_token`;`dry_run`(类型参数,**默认 `True`**)验证目标并报告哪些对象 id + 哪些 Inkscape 操作将运行,写入任何内容。每个应用的操作都会快照 + 记录 + 预览前后(可逆)。对象 id 在到达引擎之前经过验证(argv 安全字符集 + 必须存在)。
| 工具 | 签名 | 描述 |
|---|---|---|
| `simplify_path` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 简化路径(`path-simplify`),删除冗余节点。 |
| `boolean_union` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 将 ≥2 个路径合并为一个(`path-union`)。返回 `result_id` = 幸存的(最底层)id,可在无需重新检查的情况下链接。 |
| `boolean_difference` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 从最低层路径中减去上层路径(`path-difference`);需要 ≥2 个 id。返回 `result_id`。 |
| `combine_paths` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 将 ≥2 个路径合并为一个多子路径路径(`path-combine`)。标准化以保留最底层 id(作为 `result_id` 返回),匹配布尔运算。 |
| `break_apart` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 将复合路径分解为其子路径(`path-break-apart`)。 |
| `stroke_to_path` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 将每个描边轮廓为填充路径(`object-stroke-to-path`)。 |
| `cleanup_paths` | `(doc_id, object_ids, dry_run=True, approval_token?)` | 删除冗余/退化路径数据(`path-simplify`)。 |
### 操作和扩展 — 发现风险低;执行风险高(需要批准)
一种控制 Inkscape **操作** 的受控方式,无需开放字符串直通(ADR-003)。发现是基于探测的(重用 `inkscape --action-list`);执行表面由 **类型化**、有序的 `ActionStep` 链构建 — 从不作为原始字符串。每个步骤都针对 **服务器端允许列表**(`INKSCAPE_MCP_ACTION_ALLOWLIST`,可累加到内置默认值 — 绝不客户提供)和 **版本化的操作能力映射**(保存在 `<root>/.inkscape-mcp/action-maps/<version>.json` 中,按检测到的 Inkscape 版本键控)进行验证,以便干净地拒绝主机上不存在的操作。链执行通过 Inkscape 引擎(参数列表,`shell=False`)在工作副本上运行,并快照 + 记录 + 预览前后(可逆)。单个操作的 **原始逃生口**(`run_raw_action`,ADR-003)重用相同的防护措施后,开启按需、高级模式的开关(`INKSCAPE_MCP_RAW_ACTION_ENABLED`)。
| 工具 | 签名 | 描述 |
|---|---|---|
| `list_actions` | `()` | 发现主机实际的操作表面 + 允许/可用子集;持久化版本键控能力映射。 |
| `discover_extensions` | `()` | 列出服务器端允许的扩展集 + 探测笔记(诊断;无执行;默认情况下为空)。 |
| `validate_action_chain` | `(steps)` | **干运行**:验证类型化的 `ActionStep` 链是否符合允许列表 + 能力映射 + 字符集;返回解析的 `--actions` 参数 + argv 预览,无调用/写入。无效的链被拒绝,并带有机器可读的错误代码。 |
| `run_action_chain` | `(doc_id, steps, approval_token?)` | **高风险**:在变异管道(快照 + 操作记录 + 前后预览,可逆)上,通过工作副本运行验证的链。需要非空的 `approval_token`。 |
| `run_raw_action` | `(doc_id, action, args?, dry_run=True, approval_token?)` | **高风险,高级模式(默认关闭)**。ADR-003 的逃生口:运行一个允许的操作(类型化的 `action` + `args`,绝不原始字符串)。在未设置 `INKSCAPE_MCP_RAW_ACTION_ENABLED` 的情况下被 `raw_action_disabled` 拒绝。重用相同的允许列表 + 能力映射 + 字符集验证;默认为 `dry_run=True`(解析的 argv,无变异);实际运行需要非空的 `approval_token`,并通过变异管道(快照 + 操作记录 + 前后预览,可逆)。 |
### 保存 — 中等/高风险(需要批准)
| 工具 | 签名 | 描述 |
|---|---|---|
| `save_document_as` | `(doc_id, dest_path, overwrite=False, approval_token?)` | 将工作副本保存到 **新** 文件(先验证)。新文件 = 中等风险。覆盖现有文件需要 `overwrite=True` **和** 非空 `approval_token`,记录为高风险。绝不触及原始文件或托管源。 |
### 实时模式(读写/视图循环)— 默认启用(操作员选择)
控制正在运行的 Inkscape,通过传输抽象实现跨平台(任何操作系统上的扩展套接字桥;Linux 上的 DBus `org.gtk.Actions` 作为可选的快速路径)。通过 `INKSCAPE_MCP_LIVE_ENABLED` 控制(默认启用;设置为假值以退出);缺失/不支持的传输会被干净地报告,而不是作为错误。**无冻结:** 套接字桥是一个模态的 `inkex` 效果扩展(冻结整个会话的 GUI);Linux DBus 路径在 Inkscape 自己的主循环中运行,**不会** 冻结 GUI — `live_connect(prefer="no_freeze")` 在 Linux 上为视口、样式/变换写入和结构化导出到文件读取(实时 SVG/PNG/活动文档)选择它。选择 ID 读取保持在(模态)套接字路径上;Windows/macOS 实时保持模态(尽力而为)。命令模式是一个固定的枚举(线路 **协议 v5**)— 没有任意代码或原始操作直通(ADR-003)。添加 **语义写入:** 三个变异工具是高风险的,需要明确的 `approval_token`,每个工具都会产生一个带有前后画布渲染的实时操作记录;实时模式从不修改未经批准的内容。添加 **视图循环:** 仅查看视口/区域工具和 **结构感知** — `live_get_scene` 将每个渲染帧与机器可读的 `LiveScene` 配对(活动文档引用、选择 ID + 边框、视口、画布大小、可见对象摘要,重用无头 `ObjectInfo` 形状),以便代理根据结构而不是像素进行推理(ADR-006)— 加上 **变化检测:** `live_wait_for_change` 轮询一个廉价的服务器哈希状态令牌(修订版 + 选择 + 视口 — 永远不是完整文档或 PNG),在有界、可取消的等待时间内,以便循环仅在更改时渲染(包括用户自己的 GUI 编辑),而不会一直渲染。并且 **聚焦视觉差异:** `live_diff_view` 重用突变的捕获的前后帧,对它们进行像素差异,得到一个更改区域的边界框,并发出一个注释叠加层(更改的边界框 + 选择轮廓)链接回实时操作记录 — 一个有针对性的差异,而不是两个原始的整个窗口截图。视图/感知/变化/差异工具是低风险的 — 没有文档突变,没有操作记录,没有批准。
| 工具 | 签名 | 风险 | 描述 |
| --- | --- | --- | --- |
| `check_live_support` | `()` | 低 | 报告此主机上探测到的每个实时传输、最佳读取能力传输以及助手是否安装。 |
| `live_connect` | `(prefer="read")` | 中 | 通过最佳排名的传输连接;记录选择的传输 + 活动文档。`prefer="read"`(默认)= 完整读取套接字(模态);`prefer="no_freeze"` = Linux DBus 无冻结操作路径(无选择 ID 读取)。需要主门控。 |
| `live_status` | `()` | 低 | 当前会话状态:启用、连接、活动传输、可用传输。永不引发。 |
| `live_disconnect` | `()` | 低 | 关闭实时会话(X1 禁用开关)。幂等。 |
| `live_install_helper` | `()` | 受限 | 将随附的扩展套接字助手安装到 Inkscape 用户扩展目录中。由主开关控制。 |
| `live_arm_socket` | `()` | 受限 | 自动启用套接字助手:安装它(幂等)然后启动一个带有助手效果的无头 Inkscape,通过 `--actions`(固定参数列表,无 shell)自动调用,以便环回套接字绑定而无需扩展菜单点击 — 然后 `live_connect` 获取完整的感知/合成表面,而不仅仅是 DBus 的减少集。套接字桥保持跨平台的主要桥。GUI 仅限: 在无头主机(无 `DISPLAY`/`WAYLAND_DISPLAY`)上,它会带有明确的消息失败,而不是生成一个注定失败的进程。由主开关控制。 |
| `live_get_active_document` | `()` | 低 | 实时实例中打开的文档的身份。 |
| `live_get_selection` | `()` | 低 | 当前选择为对象 ID。 |
| `live_inspect_selection` | `()` | 低 | 选择的每个对象的详细信息(重用无头 `ObjectInfo` 形状)。 |
| `live_render_view` | `(region_x?, region_y?, region_width?, region_height?, scale?, fast?)` | 低 | 将实时画布渲染为 PNG,位于实时工件目录下。可选区域/边界框(所有四个一起)+ `scale` 渲染一个有针对性的、可缩放的帧;`fast=True` 应用文档的半分辨率循环预览(显式 `scale` 优先)。从会话渲染缓存中提供,按 `(doc_revision, viewport, scale)` 键入,因此命中跳过重新渲染,并且在文档更改后,永不会出现过时帧。数值在服务器端有界;传输渲染,永不是操作系统的截图(ADR-006)。仅查看,无记录。 |
| `live_set_viewport` | `(mode, zoom?, center_x?, center_y?, dx?, dy?)` | 低 | 控制实时画布视口:`mode` ∈ `zoom`/`pan`/`fit_selection`/`fit_page`(固定语义动词)。数值在服务器端有界。仅查看 — 无文档突变,无操作记录,无批准。 |
| `live_get_scene` | `(region_x?, region_y?, region_width?, region_height?, scale?, fast?)` | 低 | 捕获一个实时帧:渲染的 PNG **加上** 结构化的 `LiveScene`(活动文档引用、选择 ID + 边框、视口、画布大小、可见对象摘要,重用 `ObjectInfo`)。区域/比例/快速与 `live_render_view` 一起工作(缓存帧)。场景通过固定的 `get_scene` 命令拉取(协议 v4)。只读感知 — 无突变,无操作记录。 |
| `live_wait_for_change` | `(timeout_s=5.0, poll_interval_s=0.5)` | 低 | 阻塞直到实时状态更改或有界超时到期。轮询一个廉价的服务器哈希状态令牌(修订版 + 选择 + 视口 — 永远不是完整文档或 PNG;`get_state_token`,协议 v5)并将增量分类为 `selection_changed` / `document_changed` / `viewport_changed`。有界 + 可取消(`timeout_s` 限制在 60s,睡眠之间 — 无忙碌循环);检测用户自己的 GUI 编辑。只读 — 无突变,无操作记录。 |
| `live_sync_to_workspace` | `(dest_path)` | 中 | 将实时文档保存为 **新** 跟踪的工作区文档(原子写入,永不覆盖;操作记录 + 快照)。 |
| `live_apply_to_selection` | `(approval_token, fill?, stroke?, stroke_width?, opacity?, dx?, dy?, scale?, rotate?)` | **高** | 将验证的样式和/或简单变换应用于实时选择(重用语义)。批准门控;实时操作记录 + 前后渲染。 |
| `live_insert_svg` | `(svg_fragment, approval_token)` | **高** | 将安全解析的 SVG 片段插入正在运行的文档中。批准门控;记录 + 渲染。 |
| `live_set_selected_text` | `(text, approval_token)` | **高** | 替换选定的文本对象的内容(长度/控制字符保护)。批准门控;记录 + 渲染。 |
| `live_export_selection` | `()` | 低 | 仅将当前实时选择导出到实时工件目录下的 PNG(只读反馈,无记录)。 |
| `live_diff_view` | `(operation_id)` | 低 | 产生一个聚焦的、注释的实时操作的前后视觉差异 — 而不是两个原始的整个窗口截图。重用操作的 `preview_before`/`preview_after` 帧(通过操作 ID 解析,沙箱验证),将它们进行像素差异,得到一个更改区域的边界框,并发出一个叠加层(更改的边界框 + 选择轮廓来自 `LiveScene`)。服务器生成的 PNG,位于实时工件目录下;返回工作区相对路径 + 像素更改边界框;链接回实时操作记录(`diff_artifacts`)。仅限工件 — 无突变,无记录,无批准。 |
| `live_session_step` | `(action?, approval_token?, fill?, stroke?, stroke_width?, opacity?, dx?, dy?, scale?, rotate?, svg_fragment?, text?)` | 感知时为低 / **高** 时为动作 | 运行一个感知 → 决策 → 动作 → 观察循环迭代。感知 = `LiveScene` + 帧(始终,只读)。如果没有 `action`,则仅感知(无记录)。如果 `action` ∈ 固定集 `apply`/`insert_svg`/`set_text`(每个都是与写入引擎 1:1 匹配的 — 无原始操作/代码),则动作通过 `run_live_mutation`(高 + `approval_token` + 实时操作记录 + 前后帧 — 相同的写入路径,零新权限)运行,然后观察捕获一个后场景 + 一个链接到记录的 `live_diff_view`。有界 + 可取消的构造(单步基本操作;代理驱动循环)。 |
助手扩展也可以通过 [`scripts/`](scripts/) 中的动态安装程序安装,而无需通过服务器:`install-live-helper.sh`(Linux / macOS / Windows 下的 Git Bash 或 WSL)和 `install-live-helper.ps1`(本地 Windows PowerShell)。两者都在运行时解析 Inkscape 用户扩展目录(`inkscape --user-data-directory`,带有 `INKSCAPE_PROFILE_DIR` 和 OS 感知的备用方案),并且不需要主门控。
## 资源参考
可以通过 URI 访问的只读 MCP 资源。文档资源在 `doc_id` 上模板化。
| URI | 描述 |
| --- | --- |
| `inkscape://runtime/capabilities` | 缓存的运行时能力矩阵,包括权威的 MCP 工具表面(`tool_count` + `tools:[{name, purpose, risk}]`,来自实时注册表)。 |
| `inkscape://runtime/intents` | 精选的目标 → 工具意图映射(`[{goal_pattern, tools, how_to, group}]`)— 与 `how_do_i` / `list_capabilities` 使用的相同映射,不包含完整的能力有效载荷。 |
| `inkscape://documents` | 打开的文档索引及其具体的每个文档资源 URI(可通过 `ListMcpResourcesTool` 发现)。 |
| `inkscape://prompts` | 已注册的 MCP 提示索引(名称 + 一行目的 + 参数,可通过 `ListMcpResourcesTool` 发现,以便提示库可发现); 通过 MCP 提示 API 获取提示的文本。 |
| `inkscape://document/{doc_id}/summary` | 顶级文档摘要。 |
| `inkscape://document/{doc_id}/tree` | 元素树。 |
| `inkscape://document/{doc_id}/layers` | 层列表。 |
| `inkscape://document/{doc_id}/objects` | 对象库存。 |
| `inkscape://document/{doc_id}/styles` | 样式用法。 |
| `inkscape://document/{doc_id}/fonts` | 引用的字体。 |
| `inkscape://document/{doc_id}/assets` | 外部资产/引用。 |
| `inkscape://live/session` | 实时会话状态(启用/连接/传输)。当没有会话时清除。 |
| `inkscape://live/selection` | 当前实时选择(对象 ID)。当没有会话时为空。 |
| `inkscape://live/view` | 当前实时帧的结构化元数据:`LiveScene`(选择 ID + 边框、视口、画布大小、可见对象摘要),无 PNG 字节。当没有会话时为空。 |
| `inkscape://live/events` | 最新实时更改状态:当前廉价状态令牌 + 分类增量(`selection_changed` / `document_changed` / `viewport_changed`)。只读;当没有会话时,`LiveChange` 为空。 |
| `inkscape://live/operations` | 最近的实时操作记录:每个突变更改了什么、批准、前后渲染。路径是工作区相对或不透明的(`<external>`)— 永远不是主机路径 — 并且在每个会话边界清除。当没有时为空。 |
## 提示参考
MCP 提示引导代理了解如何安全地使用工具表面;它们不授予任何能力(架构 §4.1)。
| 提示 | 参数 | 描述 |
| --- | --- | --- |
| `live_canvas_assist` | `(goal)` | 实时视图协同循环的入口点。引导代理通过 `live_session_step` 将正在运行的 Inkscape 引导向 `goal`,一次一个有界的感知 → 决策 → 动作 → 观察迭代:感知 `LiveScene`,从固定集 (`apply`/`insert_svg`/`set_text`) 中选择一个语义动作,通过批准门控的 `run_live_mutation` 路径执行动作,观察聚焦的差异,并通过 `live_wait_for_change` 对用户编辑做出反应。强调动作仅限于语义且批准门控,循环有界/可取消 — 循环添加零新权限。 |
| `prepare_web_export` | `()` | 引导代理生成网络就绪资产(可选地优化和质量检查,然后 `export_web_profile` / `export_batch`)。仅指导。 |
| `prepare_icon_set` | `()` | 引导代理通过 `create_icon_set` 生成多大小的方形 PNG 图标集。仅指导。 |
| `prepare_print_export` | `()` | 引导代理通过 `export_print_profile` 生成印刷就绪的矢量 PDF(先验证字体/资产)。仅指导。 |
| `theme_recoloring` | `()` | 引导代理将颜色重构为品牌/主题调色板,通过 `replace_color` / `apply_palette`(验证,可逆)。仅指导。 |
| `compose_artwork` | `(goal)` | 为 `goal` 引导生成循环:`create_document` → `create_*` 形状 / `add_*_gradient` + `set_fill`(包括 `url(#id)` 绘制)/ `create_group`(+ `find_objects` 以寻址 ID)→ `render_preview`(内联栅格)→ `validate_document` → `export_document`,具有 `restore_snapshot` 可逆性。仅指导。 |
| `restyle_artwork` | `(goal)` | 为 `goal` 引导对象目标样式循环:`find_objects` 以寻址 ID → 每个对象的 `set_fill` / `set_stroke` / `set_opacity`(或 `set_font` / `replace_text`)→ `render_preview` → `export_document`; 伴侣到文档范围的 `theme_recoloring`。仅指导。 |
## 尝试让你的代理...
自然语言请求和每个工具练习。 此目录 **与相同的精选目标→工具映射** 对齐,该映射支持 `how_do_i` 工具和 `list_capabilities` 的 `intents` 部分 ([`src/inkscape_mcp/intents.py`](src/inkscape_mcp/intents.py)) — 因此文档、发现工具和运行时矩阵永远不会分歧。 不知道哪个工具合适? 只需询问 `how_do_i("…")` 并带有目标文字,它会返回相同的映射。 对于完整的创建→渲染→导出工作流、快照/可逆性和风险/批准模型,请参阅 [代理使用指南](docs/agent-usage-guide.md)。
**生成/绘制**
- “在新画布上绘制一个矩形/圆形/线条。” → `create_document`、`create_rect`、`create_circle`、`create_line`
- “添加文本标签。” → `create_text`
- “添加渐变填充(线性或径向)。” → `add_linear_gradient`、`add_radial_gradient`、`set_fill`
- “将这些对象组合在一起。” → `group_objects`、`create_group`
**编辑**
- “使这个形状变为蓝色/更改其填充颜色。” → `set_fill`
- “更改描边/轮廓和不透明度。” → `set_stroke`、`set_opacity`
- “在整个文档中用另一种颜色替换一种颜色。” → `replace_color`、`apply_palette`
- “移动/缩放/旋转一个对象。” → `move_object`、`scale_object`、`rotate_object`
- “删除这些 ID 的对象。”(高风险,批准门控,可逆)→ `delete_object`
- “调整画布大小或将其适应内容。” → `resize_canvas`、`fit_to_content`、`normalize_viewbox`
- “简化/清理这些路径。”(高风险,先进行试运行)→ `simplify_path`、`cleanup_paths`
- “联合/减去这些形状。”(高风险)→ `boolean_union`、`boolean_difference`、`combine_paths`
**检查**
- “打开这个 SVG 并告诉我里面有什么。” → `open_document`、`inspect_document`
- “查找红色形状/所有文本/ ID 对象。” → `find_objects`
- “这个文档是否有效?给我一个质量报告。” → `validate_document`、`quality_report`
- “审计整个图标系统的完整性(查看Box/ID命名)。” → `quality_report_set`
- “这个文件/集合的大小/ SHA256 是多少?” → `stat_artifact`、`stat_artifacts`
- “这个服务器能做什么?” → `list_capabilities`、`how_do_i`
**导出**
- “导出一个 512 像素的 PNG(或预览图)。” → `export_document`、`render_preview`
- “仅导出这个对象。” → `export_object`
- “导出整个图标集/一次多个尺寸。” → `create_icon_set`、`export_batch`
- “以联系/规格表格的形式布局一个 12 个图标的系统。” → `compose_grid`
- “导出/优化整个文档集一次。” → `export_set`、`optimize_set`
- “让 SVG 更小,以便在网络上使用。” → `svg_web_optimize`
- “导出网络就绪/印刷就绪的资产。” → `export_web_profile`、`export_print_profile`
- “保存到一个新文件。” → `save_document_as`
**实时**
- “快照/撤销/恢复文档状态。” → `create_snapshot`、`list_snapshots`、`restore_snapshot`
- “连接到正在运行的 Inkscape 并处理打开的画布。” → `live_connect`、`live_get_scene`、`live_apply_to_selection`
## 安全模型
服务器的设计使其能够安全地与自主代理交互:
- **工作空间沙箱。** 每个路径都被规范化和解析;符号链接受到保护;在进行任何I/O操作之前,拒绝访问配置的工作空间根目录之外。
- **原始文件不受影响。** 文档以工作副本的形式打开。没有任何工具会覆盖源文件;`save_document_as` 会写入其他位置,而覆盖现有文件需要明确的批准。
- **可逆性。** 变异工具会先快照,然后发出操作记录;`restore_snapshot` 可以将工作副本回滚到任何索引快照。明确的保留扫描(启动时 + `prune_snapshots`)限制了快照的增长,而不会修剪基准线或实时头部。
- **风险策略。** 允许 `low`/`medium` 风险;`high` 风险需要每个操作的 `approval_token`(在带外铸造,绑定到一个操作 — 绝不是环境标志,模型可以设置);`restricted`(代码/网络/文件系统逃逸)永远不会在MVP中发货。
- **子进程卫生。** Inkscape CLI始终使用**参数列表,而不是shell字符串**调用。对象ID和格式在到达二进制之前经过字符集验证。
- **资源限制。** 输入/输出/导出大小上限、每个进程超时和并发上限。
- **安全XML。** 解析禁用实体扩展和外部实体解析(无XXE /亿笑)。无网络访问。无任意扩展执行。
- **稳定的错误。** 工具引发带有主机路径免费公共消息的`ToolError`;完整详细信息仅记录到stderr日志(stdout是MCP通道)。
## 项目布局
```bash
src/inkscape_mcp/
server.py # FastMCP应用 + STDIO入口点(register_tools连接每个模块)
config.py # 进程设置 + 操作员可调限制(环境驱动)
registry.py # doc_id <-> 路径注册;打开工作副本,绝不会修改原件
operations.py # 操作记录模型 + 持久性(ADR-004)
snapshots.py # 快照引擎 + 可逆恢复
retention.py # 快照 + 实时帧保留/清理(keep-N/keep-days/hard上限 + 实时帧年龄/字节上限;显式启动扫描 + prune工具 — 绝不隐式)
validate.py # 只读验证引擎
quality.py # 只读质量报告(包装验证 + 检查 + 优化器计数)
logging_setup.py # stderr-only结构化日志(stdout保留给MCP STDIO)
document/ # 直接DOM检查引擎(摘要/树/层/样式/字体/资产)
edit/ # 安全编辑引擎:dom.py(lxml基元 + 共享SAFE_ID_RE),pipeline.py
# (快照 + 前后预览 + 操作记录包装;风险分类),
# style.py,text_object.py,transform.py,create.py(元素创建
# + defs/渐变 + 分组引擎),optimize.py(网页优化:剥离编辑器
# cruft + 删除死结构 + 减少坐标精度;可逆),paths.py
# (高风险路径几何图形,通过Inkscape引擎 — 参数列表操作 →
# 安全解析 → DOM替换)
actions/ # 受控操作界面:capability_map.py(版本键控操作映射 +
# 发现,持久化在操作映射下),chains.py(类型操作步骤链 →
# 允许列表 + 映射验证 → 参数列表 --actions argv → 引擎;无原始直通;
# 由run_raw_action逃生舱重用)
render/ # Inkscape CLI渲染/导出引擎(cli.py)+ 导出配置文件(profiles.py)+
# 有限类型批量导出(batch.py:项目上限 + 字节预算 + 干燥运行)+
# 进程内内容真实性验证器(verify.py:PDF是_vector/fonts_outlined,
# 光栅不透明_px/all_blank — 无pdffonts/Pillow子进程)
engine/ # ADR-007选择加入温暖`inkscape --shell`引擎:process.py(一个受监管的
# 工作人员 — 读取直到提示帧,每个命令超时+杀死,崩溃/空闲回收),
# manager.py(每个工作副本的工作人员池,序列化,LRU,新鲜度重新打开),
# ops.py(shell导出/操作组合)。通过INKSCAPE_MCP_ENGINE_MODE=shell门控
# 具有自动每个调用CLI回退;render/paths/chains通过它路由。
live/ # 实时读取 + 实时写入 + 实时查看:传输ABC + 功能感知
# 后端选择,扩展套接字 + DBus后端,protocol.py线缆模式
# (v3:读取 + 语义写入 + 仅查看命令,区域/比例渲染),
# 会话管理器,render/sync,edit.py(写入 + 查看引擎重用语义
# + 有限查看验证器),records.py(实时操作记录 + 批准门),
# scene.py(LiveScene),diff.py(聚焦视觉差异),loop.py(感知→决策→行动→观察编织器 — 组合上述,零新权限),
# cache.py(有限LRU渲染缓存键控(doc_revision,viewport,scale)+
# 凝聚预算;通过修订键的鲜度),helper_extension/(在
# Inkscape内部运行)。默认情况下关闭。
prompts/ # MCP提示(架构§4.1):live.py(live_canvas_assist — 实时查看循环入口
# 点),library.py(导出/重新着色方向提示),authoring.py
# (compose_artwork / restyle_artwork — 生成式斜坡提示)
resources/ # MCP资源模板(运行时上限,文档/{id}/...,实时/{会话,选择,操作})
runtime/ # Inkscape功能探针
tools/ # 类型@mcp.tool模块:系统,文档,验证,质量,导出,
# 配置文件,导出批次,优化,快照,样式,
# 文本对象,创建(元素创建 + 定义/渐变 + 分组),
# 变换,路径(路径几何),操作(发现 +
# 操作链 + run_raw_action),保存,实时(读取 + 写入)
workspace/ # 沙箱/路径安全,限制,风险策略,安全XML解析,子进程包装器
scripts/ # install-live-helper.sh(Linux/macOS/Git-Bash)+ .ps1(Windows):复制实时
# 助手扩展到Inkscape的用户扩展目录,动态解析;
# gen_llms_txt.py:从实时注册表重新生成llms.txt / llms-full.txt
llms.txt # GENERATED LLM索引(一行 + 每个工具的风险类别);不要手动编辑
llms-full.txt # GENERATED完整清单(完整描述 + 关键参数 + 提示 + 资源)
evals/ # 确定性工具可用性测试:tool_selection_scenarios.json +
# run_eval.py(驱动how_do_i/intents;报告工具选择准确性)。ruff-checked。
# run_live_eval.py:可选报告仅实时代理运行器(相同数据集/评估器)。
examples/ # 准备好复制的MCP主机配置(claude_desktop_config.json,mcp.json)
tests/ # pytest;Inkscape依赖测试用例标记为@ pytest.mark.inkscape
```
安装/配置/兼容性/故障排除文档:[`docs/install/`](docs/install/)。
从代理驱动服务器(创建→渲染→导出循环,快照,风险/批准门,工具选择):[`docs/agent-usage-guide.md`](docs/agent-usage-guide.md).
## 开发
- **堆栈:** Python ≥ 3.12 · `uv` · FastMCP 3.x · `lxml` · Pillow(实时视觉差异)· Inkscape CLI(每个调用,加上一个选择加入的温暖`inkscape --shell`引擎 — ADR-007)· STDIO传输。
- **约定:** 小型类型工具(无混合术语 / `run_action(string)`),风险分类,
变异操作发出操作记录,绝不会覆盖原件,通过参数列表进行子进程调用。
有关完整的贡献者工作流程 + 约定,请参见[`CONTRIBUTING.md`](CONTRIBUTING.md)。
- **Lint / 格式:** `ruff`(选择`E,F,I,B,UP,S,RUF`; `S603`/`S607`被故意忽略
因为Inkscape CLI适配器需要子进程 — 通过参数列表 + 审查强制执行安全)。
- **类型:** `mypy --strict`超过`src`。
- **测试:** `pytest`; 将Inkscape二进制测试用例标记为`@pytest.mark.inkscape`.
```bash
uv run pytest # 完整套件
uv run pytest -m "not inkscape" # 跳过需要Inkscape二进制文件的测试
uv run ruff check --fix . && uv run ruff format .
uv run mypy src
```
## 许可证
MIT © Johannes Sood
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器