Skip to content

REST API 参考

Eidograph REST API 让本机脚本或自建 Agent 读取和修改 Windows 应用中当前打开的项目。它与 MCP 服务器使用同一组工具、编译校验、撤销历史、图形权限和使用额度。

API 由已安装的 Windows 应用提供。客户端工作期间必须保持 Eidograph 运行;Eidograph 不提供托管 REST 服务或面向用户的 Web 版。

快速开始

  1. 在 Eidograph 中打开设置 › MCP / REST 服务器
  2. 开启服务器,并只启用客户端需要的工具。
  3. 图形面板把目标图形的暴露圆点设为实心。
  4. 确认状态为运行中。默认 Base URL 是:
txt
http://127.0.0.1:14159/api/v1

先发现工具,再向当前图形追加一个构造:

bash
curl http://127.0.0.1:14159/api/v1/tools

curl -X POST http://127.0.0.1:14159/api/v1/tools/append_commands \
  -H "Content-Type: application/json" \
  -H "X-Eidograph-Client: geometry-script" \
  -d '{"commands":"point A -2 0\npoint B 2 0\nsegment s A B"}'

成功响应:

json
{
  "ok": true,
  "result": "ok — no diagnostics"
}

传输与安全

Base URL 与 JSON

下文路径均相对于 http://127.0.0.1:14159/api/v1。若在设置中更改端口,客户端也必须更新 URL —— 也可以从服务器运行期间应用写入的发现文件中读取当前地址,详见 MCP、REST 与应用内 Agent。工具调用使用 POST、JSON 对象以及 Content-Type: application/json

当前 REST 接口只有 /api/v1,没有额外的版本协商。

身份验证与网络范围

服务器没有 TLS;除非你自行设置,也没有密码。默认回环模式只允许同一台电脑上的客户端访问。开启允许同一网络客户端后,服务器监听 0.0.0.0;任何能访问该端口的设备都可以调用已启用工具,并操作已暴露图形。

在同一设置面板中开启需要访问令牌(开启 LAN 模式之前务必先开启),之后每个请求都必须携带生成的密钥:

http
Authorization: Bearer <token>

缺少该头的请求会返回 401{"ok":false,"error":"missing or invalid bearer token"}。这同样适用于 /status/activity。令牌会写入发现文件,因此本机客户端可以直接读取,而无需手动配置。

DANGER

LAN 模式只能用于可信网络。不要转发端口、通过隧道发布或暴露到互联网。

可选请求头:

http
X-Eidograph-Client: my-automation

它只是在外部活动记录中显示的调用方名称,不是身份验证。未提供时会记录调用方 IP。

Origin 检查

命令行工具、Node.js、Python、PowerShell 和原生 Agent 通常不发送 Origin,这类请求可以通过。如果请求带有 Origin,其主机必须是 localhost127.0.0.1::1,否则工具发现和工具调用返回 403

REST API 面向原生与命令行客户端,而不是任意网页。即使 Origin 主机在本机,浏览器的 CORS 和预检也可能阻止请求。

权限与副作用

每次执行工具时都会重新检查权限:

  • 设置 › MCP / REST 服务器 › 工具是工具允许列表;
  • 图形面板的实心暴露圆点决定外部客户端能否看到该图形;
  • “当前图形”工具总是操作 UI 中活动的项目和图形;
  • create_figure 会创建并激活图形,select_object 会改变画布选中项;
  • 脚本编辑在提交前编译。出现错误或“命令被跳过”警告时,整个编辑被拒绝,原脚本不变;
  • 成功编辑会立即重绘、保存到工作区并进入普通撤销历史。

不要并发发送依赖同一脚本版本的编辑。请串行调用,并在整体重写前重新执行 get_script

请求体与响应

推荐直接把参数对象作为请求体:

http
POST /api/v1/tools/get_figure_script
Content-Type: application/json
X-Eidograph-Client: docs-example

{"name":"图形 2"}

也支持 RPC 风格的 arguments 包装:

json
{
  "arguments": {
    "name": "图形 2"
  }
}

无参数工具可以传 {} 或空请求体。

工具成功:

json
{ "ok": true, "result": "工具特定的返回值" }

工具失败:

json
{ "ok": false, "error": "tool `set_script` is disabled" }

多数读取工具返回文本。list_figureslist_objectslist_commandsresult 是一个包含 JSON 的字符串;需要结构化数据时要再解析一次。export_figure 例外,它直接返回 JSON 对象。

HTTP 状态含义
200 OK状态/活动读取、成功发现或成功执行工具
400 Bad Request参数、工具、图形、编译或额度错误
403 Forbidden工具发现或调用带有不可信 Origin
503 Service Unavailable工具发现无法连接 Eidograph UI 桥
404 Not Found路径不存在
405 Method Not Allowed已知路径使用了错误 HTTP 方法

无效 JSON 或错误 Content-Type 可能产生框架错误,而不是标准 { "ok": false } 结构。客户端应同时检查 HTTP 状态以及存在时的 ok 字段。

端点

GET /status

直接返回原生服务器状态,不使用 ok 包装:

bash
curl http://127.0.0.1:14159/api/v1/status
json
{
  "running": true,
  "bridgeReady": true,
  "bindAddress": "127.0.0.1",
  "port": 14159,
  "lanAddresses": [],
  "lastError": null
}
字段类型说明
runningbooleanHTTP 监听器是否运行。
bridgeReadyboolean应用 UI 是否可以执行工具。
bindAddressstring 或 null通常为 127.0.0.10.0.0.0
portinteger 或 null实际监听端口。
lanAddresses字符串数组同一网络的客户端可访问的全部基础地址,按优先级排序(私有网段在前),最多 10 个。未开启 LAN 模式时为空。
lastErrorstring 或 null最近的监听器错误。

running: truebridgeReady: false 表示端口已打开,但工具暂时不能执行;应等待两者都为 true

GET /activity

返回最近最多 200 次 MCP/REST 工具调用,新记录在前。状态、活动读取和工具发现不会记录。

json
{
  "activity": [
    {
      "id": "342daa36-e4d3-4c96-aebe-d358d60a96dd",
      "at": 1788112800123,
      "transport": "rest",
      "caller": "geometry-script",
      "tool": "append_commands",
      "ok": true,
      "durationMs": 18
    }
  ]
}

at 是 Unix 毫秒时间戳,durationMs 是整个桥接与工具调用的耗时。客户端可以自行填写 caller,不能把它当作已验证身份。

GET /tools

只返回设置中当前启用的工具,不消耗工具调用额度:

bash
curl http://127.0.0.1:14159/api/v1/tools

缩略响应:

json
{
  "ok": true,
  "tools": [
    {
      "name": "append_commands",
      "description": "Append one or more command lines...",
      "inputSchema": {
        "type": "object",
        "properties": {
          "commands": { "type": "string" }
        },
        "required": ["commands"]
      }
    }
  ]
}

此端点是运行时权威来源:说明和 JSON Schema 直接来自应用与 MCP 服务器共用的工具定义。

POST /tools/{tool}

执行一个已启用工具。把 {tool} 换为发现到的工具名称,并把参数放入 JSON 请求体:

bash
curl -X POST http://127.0.0.1:14159/api/v1/tools/list_objects \
  -H "Content-Type: application/json" \
  -d '{}'

每次真正执行工具都会消耗一次外部 API 额度,包括进入工具后失败的调用;状态、活动和发现免费。导出成功生成字节后还会消耗导出额度。Pro 版不受这些限制;当前免费额度以应用的设置 › 账户为准。

工具参考

GET /tools 返回的 Schema 是权威定义。下表列出当前完整接口;禁用的工具不会出现在发现结果中,直接调用也会失败。

工具请求体result 与行为
get_script{}当前已暴露图形的完整 Eidolang 源码字符串。
list_figures{}JSON 字符串:已暴露图形的 { name, kind, active }[];未暴露图形被省略。
get_figure_script{ "name": string }按精确显示名称读取已暴露图形,不切换活动图形。
create_figure`{ "kind": "plane""solid", "name"?: string }`
append_commands{ "commands": string }追加换行分隔的命令;返回诊断摘要,只在候选脚本有效时提交。
set_script{ "source": string }替换全部源码;返回诊断摘要,只在候选脚本有效时提交。
list_objects{}JSON 字符串:编译对象的 { name, kind, tier, status, info }[]
list_diagnostics{}可读诊断文本;没有问题时为 ok — no diagnostics
list_commands{}JSON 字符串:当前 plane/solid 方言的 { kind, signature }[]
select_object{ "name": string }在当前画布选中并高亮对象;返回确认文本。
export_figure见下文直接返回包含文件内容的对象。

编辑工具的事务语义

append_commands 适合增量添加,set_script 只应在必须修改或删除已有行时使用。两者都会先编译候选脚本。如果存在错误或 skipped-command 警告,HTTP 与 ok 仍可能表示工具本身执行成功,但 result 会说明编辑没有应用:

json
{
  "ok": true,
  "result": "error line 2: unknown command `circel`\n  hint: ...\nedit not applied — the current script is unchanged. Fix the first reported issue; later errors may be consequences, then retry."
}

因此调用方必须检查诊断文本,不能只检查 ok。整体替换前应先调用 get_script,防止覆盖更新后的内容。

列表结果示例

list_figuresresult 再解析一次后:

json
[
  { "name": "构造", "kind": "plane", "active": true },
  { "name": "立体模型", "kind": "solid", "active": false }
]

list_objectsresult 再解析一次后:

json
[
  { "name": "A", "kind": "point", "tier": "free", "status": "ok", "info": "(-2, 0)" },
  { "name": "s", "kind": "segment", "tier": "derived", "status": "ok", "info": "len 4" }
]

info 是简短值摘要;无效对象的 info 是失败原因。tier 通常为 freeboundderivednull

list_commands 的每项包含命令 kind 与实时 signature。命令可能随应用演进,生成式客户端不应硬编码整个命令表。

export_figure

使用图形的实时渲染器导出已暴露图形。指定非活动图形时,Eidograph 会临时挂载该图形,完成后恢复原来的活动图形。

json
{
  "figure": "构造",
  "format": "png",
  "region": "content",
  "scale": 2,
  "transparent": true,
  "grid": false
}
参数类型必需说明
figurestring已暴露图形的精确名称;默认当前图形。
formatsvgpnggifmp4输出格式。
regionviewcontent当前视图或适应内容;默认 content
cropobject仅平面图形:屏幕坐标 { x, y, width, height };覆盖 region,宽高必须为正。
scale124pnggifmp4 的像素倍率;默认使用应用导出偏好。
transparentboolean仅平面静态图;默认使用应用导出偏好。
gridboolean是否包含坐标网格;默认使用应用导出偏好。
fps1–60 的整数gifmp4 的帧率;默认使用应用导出偏好。
seconds0.1–3600 的数字gifmp4 的时长;默认为时间轴的一个循环。
modetimelineorbitgifmp4 的运动来源;默认 timeline

立体图形不接受 transparent: true,自定义裁剪仅支持平面图形。

动画导出

gifmp4 会逐帧渲染图形的 animate / stage 时间轴。mode: "orbit" 改为让相机绕立体图形旋转,因此静态模型也能导出,但平面图形不接受该模式。两种格式都不支持透明背景。单次渲染上限为 1800 帧,时长与帧率过高的请求会被截断。

这类调用比静态导出慢得多,可能需要数秒到数分钟,因此 export_figure 的桥接预算是 600 秒,而其他工具都是 30 秒。MP4 还需要应用 WebView 支持 H.264 WebCodecs。

json
{
  "format": "mp4",
  "mode": "orbit",
  "seconds": 6,
  "fps": 30,
  "scale": 2
}

PNG 结果:

json
{
  "figure": "构造",
  "fileName": "构造.png",
  "format": "png",
  "mimeType": "image/png",
  "encoding": "base64",
  "data": "iVBORw0KGgoAAA..."
}

SVG 返回 mimeType: "image/svg+xml"encoding: "utf8"data 是 SVG 文本。PNG、GIF、MP4 的 data 是不带 data: 前缀的 Base64,mimeType 分别为 image/pngimage/gifvideo/mp4

动画结果额外包含 animation 对象,说明实际渲染的内容,便于判断是否触发了帧数上限:

json
{
  "animation": { "mode": "orbit", "seconds": 6, "frames": 180, "fps": 30, "capped": false }
}

在 MCP 上,PNG 与 GIF 以原生 image 内容返回,MP4 则以嵌入式二进制 resource 返回,因为 MCP 没有视频内容类型。

save_project

将当前活动项目保存为 .eido 包,直接写入指定路径 —— 不会弹出原生保存对话框,因为这类调用没有用户在场点击它。

json
{ "path": "C:\\Users\\me\\Documents\\构造.eido" }
参数类型必需说明
pathstring视情况而定保存目标的绝对路径。项目首次保存时必填;之后省略则覆盖项目已知的文件。缺少 .eido 后缀会自动补上。

结果: 项目实际保存到的绝对路径。

open_project

按绝对路径打开一个 .eido 包(或裸 .geo/.txt 脚本)为新的项目标签页 —— 相当于应用“打开”对话框的无界面版本。

json
{ "path": "C:\\Users\\me\\Documents\\构造.eido" }
参数类型必需说明
pathstring要打开文件的绝对路径。

结果: 项目打开并成为活动项目后的确认字符串。

完整客户端示例

JavaScript(Node.js 20+)

以下是服务端 Node.js 代码,不是浏览器代码:

js
const baseUrl = 'http://127.0.0.1:14159/api/v1'

async function callTool(name, arguments_ = {}) {
  const response = await fetch(`${baseUrl}/tools/${encodeURIComponent(name)}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Eidograph-Client': 'node-example',
    },
    body: JSON.stringify(arguments_),
  })
  const body = await response.json()
  if (!response.ok || !body.ok) {
    throw new Error(body.error || `HTTP ${response.status}`)
  }
  return body.result
}

const figures = JSON.parse(await callTool('list_figures'))
console.log(figures)

console.log(await callTool('append_commands', {
  commands: 'point A -2 0\npoint B 2 0\nsegment s A B',
}))

Python 3:导出 PNG

仅使用 Python 标准库:

python
import base64
import json
from pathlib import Path
from urllib.error import HTTPError
from urllib.request import Request, urlopen

BASE_URL = "http://127.0.0.1:14159/api/v1"

def call_tool(name, arguments=None):
    request = Request(
        f"{BASE_URL}/tools/{name}",
        data=json.dumps(arguments or {}).encode("utf-8"),
        method="POST",
        headers={
            "Content-Type": "application/json",
            "X-Eidograph-Client": "python-example",
        },
    )
    try:
        with urlopen(request) as response:
            body = json.load(response)
    except HTTPError as error:
        body = json.load(error)
        raise RuntimeError(body.get("error", f"HTTP {error.code}")) from error
    if not body.get("ok"):
        raise RuntimeError(body.get("error", "unknown Eidograph error"))
    return body["result"]

export = call_tool("export_figure", {
    "format": "png",
    "region": "content",
    "scale": 2,
    "grid": False,
})
Path(export["fileName"]).write_bytes(base64.b64decode(export["data"]))
print(f"saved {export['fileName']}")

SVG 应把 export["data"] 作为 UTF-8 文本写入,不要 Base64 解码。

PowerShell 7+

powershell
$baseUrl = 'http://127.0.0.1:14159/api/v1'
$headers = @{ 'X-Eidograph-Client' = 'powershell-example' }

$commands = @'
point O 0 0
circle c O radius 3
point P on c at 45deg
segment radius O P
'@

$body = @{ commands = $commands } | ConvertTo-Json
$response = Invoke-RestMethod `
  -Method Post `
  -Uri "$baseUrl/tools/append_commands" `
  -Headers $headers `
  -ContentType 'application/json' `
  -Body $body

if (-not $response.ok) { throw $response.error }
$response.result

创建图形并设置完整脚本

bash
export EIDO_API='http://127.0.0.1:14159/api/v1'

curl -sS -X POST "$EIDO_API/tools/create_figure" \
  -H 'Content-Type: application/json' \
  -H 'X-Eidograph-Client: curl-workflow' \
  -d '{"kind":"plane","name":"Circle API demo"}'

curl -sS -X POST "$EIDO_API/tools/set_script" \
  -H 'Content-Type: application/json' \
  -H 'X-Eidograph-Client: curl-workflow' \
  -d '{"source":"space plane\npoint O 0 0\ncircle c O radius 3\npoint P on c at 45deg\nsegment radius O P\n"}'

curl -sS -X POST "$EIDO_API/tools/list_diagnostics" \
  -H 'Content-Type: application/json' \
  -d '{}'

故障排查

现象检查内容
Connection refused开启服务器、确认端口、保持 Eidograph 运行并检查 /status
bridgeReady 为 false等待项目 UI 加载完成,或重启应用。
tool ... is disabled在服务器设置中启用该工具,然后重新发现。
no figure is open调用 create_figure,或在应用中打开并暴露图形。
the current figure is not exposed图形面板把目标圆点设为实心。
成功响应中出现 “edit not applied”修复第一条编译诊断后重试;原脚本没有改变。
403 untrusted Origin使用原生/命令行客户端或移除非本地 Origin;不要削弱 LAN 安全。
不能切换图形导出结束锁定图形切换的操作,手动激活目标,或导出当前图形。
每日额度错误查看设置 › 账户,等待每日重置或解锁 Pro。
请求在 30 秒后超时检查 /status、恢复应用状态、避免并行长调用后重试。

需要使用 Streamable HTTP 的 Agent 工具发现与资源读取时,请参阅 MCP、REST 与应用内 Agent