REST API 参考
Eidograph REST API 让本机脚本或自建 Agent 读取和修改 Windows 应用中当前打开的项目。它与 MCP 服务器使用同一组工具、编译校验、撤销历史、图形权限和使用额度。
API 由已安装的 Windows 应用提供。客户端工作期间必须保持 Eidograph 运行;Eidograph 不提供托管 REST 服务或面向用户的 Web 版。
快速开始
- 在 Eidograph 中打开设置 › MCP / REST 服务器。
- 开启服务器,并只启用客户端需要的工具。
- 在图形面板把目标图形的暴露圆点设为实心。
- 确认状态为运行中。默认 Base URL 是:
http://127.0.0.1:14159/api/v1先发现工具,再向当前图形追加一个构造:
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"}'成功响应:
{
"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 模式之前务必先开启),之后每个请求都必须携带生成的密钥:
Authorization: Bearer <token>缺少该头的请求会返回 401 和 {"ok":false,"error":"missing or invalid bearer token"}。这同样适用于 /status 与 /activity。令牌会写入发现文件,因此本机客户端可以直接读取,而无需手动配置。
DANGER
LAN 模式只能用于可信网络。不要转发端口、通过隧道发布或暴露到互联网。
可选请求头:
X-Eidograph-Client: my-automation它只是在外部活动记录中显示的调用方名称,不是身份验证。未提供时会记录调用方 IP。
Origin 检查
命令行工具、Node.js、Python、PowerShell 和原生 Agent 通常不发送 Origin,这类请求可以通过。如果请求带有 Origin,其主机必须是 localhost、127.0.0.1 或 ::1,否则工具发现和工具调用返回 403。
REST API 面向原生与命令行客户端,而不是任意网页。即使 Origin 主机在本机,浏览器的 CORS 和预检也可能阻止请求。
权限与副作用
每次执行工具时都会重新检查权限:
- 设置 › MCP / REST 服务器 › 工具是工具允许列表;
- 图形面板的实心暴露圆点决定外部客户端能否看到该图形;
- “当前图形”工具总是操作 UI 中活动的项目和图形;
create_figure会创建并激活图形,select_object会改变画布选中项;- 脚本编辑在提交前编译。出现错误或“命令被跳过”警告时,整个编辑被拒绝,原脚本不变;
- 成功编辑会立即重绘、保存到工作区并进入普通撤销历史。
不要并发发送依赖同一脚本版本的编辑。请串行调用,并在整体重写前重新执行 get_script。
请求体与响应
推荐直接把参数对象作为请求体:
POST /api/v1/tools/get_figure_script
Content-Type: application/json
X-Eidograph-Client: docs-example
{"name":"图形 2"}也支持 RPC 风格的 arguments 包装:
{
"arguments": {
"name": "图形 2"
}
}无参数工具可以传 {} 或空请求体。
工具成功:
{ "ok": true, "result": "工具特定的返回值" }工具失败:
{ "ok": false, "error": "tool `set_script` is disabled" }多数读取工具返回文本。list_figures、list_objects 与 list_commands 的 result 是一个包含 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 包装:
curl http://127.0.0.1:14159/api/v1/status{
"running": true,
"bridgeReady": true,
"bindAddress": "127.0.0.1",
"port": 14159,
"lanAddresses": [],
"lastError": null
}| 字段 | 类型 | 说明 |
|---|---|---|
running | boolean | HTTP 监听器是否运行。 |
bridgeReady | boolean | 应用 UI 是否可以执行工具。 |
bindAddress | string 或 null | 通常为 127.0.0.1 或 0.0.0.0。 |
port | integer 或 null | 实际监听端口。 |
lanAddresses | 字符串数组 | 同一网络的客户端可访问的全部基础地址,按优先级排序(私有网段在前),最多 10 个。未开启 LAN 模式时为空。 |
lastError | string 或 null | 最近的监听器错误。 |
running: true、bridgeReady: false 表示端口已打开,但工具暂时不能执行;应等待两者都为 true。
GET /activity
返回最近最多 200 次 MCP/REST 工具调用,新记录在前。状态、活动读取和工具发现不会记录。
{
"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
只返回设置中当前启用的工具,不消耗工具调用额度:
curl http://127.0.0.1:14159/api/v1/tools缩略响应:
{
"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 请求体:
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 会说明编辑没有应用:
{
"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_figures 的 result 再解析一次后:
[
{ "name": "构造", "kind": "plane", "active": true },
{ "name": "立体模型", "kind": "solid", "active": false }
]把 list_objects 的 result 再解析一次后:
[
{ "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 通常为 free、bound、derived 或 null。
list_commands 的每项包含命令 kind 与实时 signature。命令可能随应用演进,生成式客户端不应硬编码整个命令表。
export_figure
使用图形的实时渲染器导出已暴露图形。指定非活动图形时,Eidograph 会临时挂载该图形,完成后恢复原来的活动图形。
{
"figure": "构造",
"format": "png",
"region": "content",
"scale": 2,
"transparent": true,
"grid": false
}| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
figure | string | 否 | 已暴露图形的精确名称;默认当前图形。 |
format | svg、png、gif 或 mp4 | 是 | 输出格式。 |
region | view 或 content | 否 | 当前视图或适应内容;默认 content。 |
crop | object | 否 | 仅平面图形:屏幕坐标 { x, y, width, height };覆盖 region,宽高必须为正。 |
scale | 1、2 或 4 | 否 | png、gif、mp4 的像素倍率;默认使用应用导出偏好。 |
transparent | boolean | 否 | 仅平面静态图;默认使用应用导出偏好。 |
grid | boolean | 否 | 是否包含坐标网格;默认使用应用导出偏好。 |
fps | 1–60 的整数 | 否 | gif、mp4 的帧率;默认使用应用导出偏好。 |
seconds | 0.1–3600 的数字 | 否 | gif、mp4 的时长;默认为时间轴的一个循环。 |
mode | timeline 或 orbit | 否 | gif、mp4 的运动来源;默认 timeline。 |
立体图形不接受 transparent: true,自定义裁剪仅支持平面图形。
动画导出
gif 与 mp4 会逐帧渲染图形的 animate / stage 时间轴。mode: "orbit" 改为让相机绕立体图形旋转,因此静态模型也能导出,但平面图形不接受该模式。两种格式都不支持透明背景。单次渲染上限为 1800 帧,时长与帧率过高的请求会被截断。
这类调用比静态导出慢得多,可能需要数秒到数分钟,因此 export_figure 的桥接预算是 600 秒,而其他工具都是 30 秒。MP4 还需要应用 WebView 支持 H.264 WebCodecs。
{
"format": "mp4",
"mode": "orbit",
"seconds": 6,
"fps": 30,
"scale": 2
}PNG 结果:
{
"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/png、image/gif、video/mp4。
动画结果额外包含 animation 对象,说明实际渲染的内容,便于判断是否触发了帧数上限:
{
"animation": { "mode": "orbit", "seconds": 6, "frames": 180, "fps": 30, "capped": false }
}在 MCP 上,PNG 与 GIF 以原生 image 内容返回,MP4 则以嵌入式二进制 resource 返回,因为 MCP 没有视频内容类型。
save_project
将当前活动项目保存为 .eido 包,直接写入指定路径 —— 不会弹出原生保存对话框,因为这类调用没有用户在场点击它。
{ "path": "C:\\Users\\me\\Documents\\构造.eido" }| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
path | string | 视情况而定 | 保存目标的绝对路径。项目首次保存时必填;之后省略则覆盖项目已知的文件。缺少 .eido 后缀会自动补上。 |
结果: 项目实际保存到的绝对路径。
open_project
按绝对路径打开一个 .eido 包(或裸 .geo/.txt 脚本)为新的项目标签页 —— 相当于应用“打开”对话框的无界面版本。
{ "path": "C:\\Users\\me\\Documents\\构造.eido" }| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
path | string | 是 | 要打开文件的绝对路径。 |
结果: 项目打开并成为活动项目后的确认字符串。
完整客户端示例
JavaScript(Node.js 20+)
以下是服务端 Node.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 标准库:
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+
$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创建图形并设置完整脚本
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。
