OCS WebMCP
Provides agentic editing of DWG/DXF drawings, enabling AI agents to inspect, query, and modify AutoCAD drawing files through an in-browser CAD editor (Open CAD Studio).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OCS WebMCPdraw a 100 × 50 rectangle on layer WALLS"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OCS WebMCP: agentic DWG/DXF editing in the browser
Open CAD Studio's drawing editor, with its editing verbs registered as WebMCP tools, so an AI agent in the browser can inspect and edit DWG/DXF drawings. Every change waits for a human.
Ask for "draw a 100 × 50 rectangle on layer WALLS" and the agent calls the editor's own command
engine (PLINE 0,0 100,0 100,50 0,50 C). It is the same engine Open CAD Studio's desktop MCP
server drives, running in the browser tab.
What is ours, and what is not
This repository (MIT) | The WebMCP layer ( |
Not ours (GPL-3.0-only) | The CAD application itself: Open CAD Studio by Hakan Seven and contributors, including its DWG/DXF engine. Built unmodified from a pinned upstream commit; no upstream file is edited. |
The combined deployment is a GPL-3.0 work. See NOTICE.md for its Corresponding Source.
Related MCP server: autocad-mcp
How it works
browser tab (document.modelContext: 24 tools)
┌──────────────────────────────────────────────┬──────────────────┐
│ / shell (MIT) │ agent activity │
│ registers tools → gate → confirm dialog │ (every call) │
│ ┌──────────────────────────────────────┐ │ │
│ │ /ocs/ Open CAD Studio (GPL-3, │ │ │
│ │ unmodified, same-origin iframe)│ │ │
│ │ window.wasmBindings │ │ │
│ │ .ocs_control_submit / _take ◄────┼── src/control.js │
│ └──────────────────────────────────────┘ │ │
└──────────────────────────────────────────────┴──────────────────┘Open CAD Studio's web build compiles the same semantic control core as its native MCP server,
and exports it to JavaScript as ocs_control_submit / ocs_control_take. The shell reaches
those exports in a same-origin iframe, so nothing upstream needs a plugin hook or a patch.
Tools
Read (no confirm): ocs_get_state · ocs_get_capabilities · ocs_count_entities ·
ocs_query_records (filters, JSON-Pointer projections, paging) · ocs_get_record_schema ·
ocs_list_commands (vocabulary, or one command's exact prompts) · ocs_get_history ·
ocs_measure (bounds, curve length and area, solid/mesh mass properties) · ocs_spatial_query
(nearest to a point, containing a point, inside a box, by type/layer; or two entities'
intersections: how an agent finds the handles to pick)
See (no confirm): ocs_capture_view (screenshot: JPEG/PNG, max_width, if_changed +
threshold to skip unchanged views and save tokens) · ocs_set_view (zoom_extents / home,
preset views top, iso_se/iso_sw/iso_ne/iso_nw, front/back/right/left, and a
visual style such as shaded_with_edges; never the drawing's geometry)
Preset views: the web build has no command or control action for them, so ocs_set_view clicks
Open CAD Studio's ViewCube the way a user would (src/viewcube.js): it finds the cube in a
captured frame, clicks the position upstream's own hit test maps to that view, and checks the
camera actually reached the expected pitch before reporting success. Visual styles go through
start with the whole line (VSCURRENT <style>): through run, upstream's keyword picker
announces the style but drops the message that applies it.
Record (starting it waits for a human): ocs_start_recording → ocs_stop_recording. The
human gets the video (MP4, or WebM where MP4 can't be recorded) as a download in the activity
panel. The agent gets a contact sheet: one image of the frames that changed, with timestamps
and the changed region outlined. An agent can't watch a video, but it can read a contact sheet.
Write (each waits for a human): ocs_new_drawing · ocs_open_drawing (by url for real
drawings; tool arguments are size-limited, e.g. agent-browser caps them at 1 MB; or base64/DXF text
for small files) · ocs_add_text (single-line note; TEXT's in-canvas editor can't be filled by a
command line) · ocs_run_command · ocs_cancel_command · ocs_set_properties ·
ocs_undo · ocs_redo ·
ocs_command_steps (a command answered prompt by prompt, with entity picks by handle: FILLET,
TRIM, OFFSET, MOVE on a selection, and geometric constraints on builds that have them; reports the
handles added, removed and modified, since such edits replace entities) · ocs_set_layer
(visible / frozen / locked / current, set rather than toggled) · ocs_batch (several of the edits
above under ONE approval; the dialog lists every step; stops at the first failure)
The editor reports what each prompt accepts; ocs_command_steps refuses a step of another kind
before sending it. One exception: on builds after v2026.37 a point step that also takes keyword
letters (MOVE/COPY's base point with [Displacement]) is reported as accepting only token, so a
point is let through wherever a token is.
Not possible through automation yet: creating a layer (no command, action or record op for it upstream).
Screenshots and recording: how
Frames come from
canvas.captureStream(), nevertoDataURL(). The editor renders through WebGL without a preserved drawing buffer, sotoDataURL()from outside the render loop is all black (measured: mean 0, spread 0). Stream frames are the composited output. The web build's owncaptureop answersgui_required.Change detection counts changed pixels per tile at 480 px, not mean change. CAD is thin lines on a flat background, and averaging dilutes a 1-px line to nothing (a new circle measured 0% that way).
MP4 by default: Chrome's MP4 has a real duration (2.03 s measured on a 2 s take) and plays in QuickTime/Keynote. Its WebM has no duration header (
ffprobe: N/A).The contact-sheet and
if_changeddesign follows vercel-labs/agent-browser's recording and screenshot options (Apache-2.0), reimplemented in-page. No code copied.
Safety model
One gate (
src/gate.js): every tool is registered through it, and there is no path around it. Writes stop at a confirm dialog before anything reaches the editor. A declined call returnsREFUSEDand never runs.Confirms are serialised, so approving one dialog is never consent to a second one.
Optimistic concurrency: writes quote the drawing's revision, and Open CAD Studio itself refuses a stale one. Agents may pass the
revisionthey last read;ocs_set_propertiessupports per-fieldexpectedvalues, compared by value.Output is capped, and truncation is announced, never silent. All tools carry
untrustedContentHint, because drawing content (text, layer names) reaches the agent verbatim.Recording needs consent. It changes nothing in the drawing, but it continuously captures the user's screen content, so starting it is confirmed like a write, and a red REC indicator stays visible until it stops. A
max_secondslimit (default 120) always ends it.Only Open CAD Studio's donation prompt is dismissed automatically, and only on a path the human has already approved. Any other dialog is reported to the agent, not closed.
Build and run
Requirements: Node ≥ 22, git, rustup with
rustup target add wasm32-unknown-unknown, trunk, and wasm-bindgen-cli
at exactly the version in upstream's Cargo.lock (0.2.108 at the pinned commit:
cargo install wasm-bindgen-cli --version 0.2.108 --locked).
npm run build # clone upstream at the pinned commit, build it unmodified, assemble dist/
OCS_COMMIT=<sha> npm run build # same, at another upstream commit (dist/ocs-source.json: pinned=false)
npm run serve # http://127.0.0.1:8787/ with the COOP/COEP headers upstream expects
npm run test:e2e # 56 checks through real WebMCP in headless Chrome (57 where constraints exist)
node scripts/open-file.mjs plan.dwg # open a real DWG/DXF through the tools; report + zoomed screenshot
node scripts/demo.mjs plan.dwg # record a demo video, driven through agent-browser (needs ffmpeg)Real-file check, 2026-09-18: a 2.6 MB AutoCAD 2007 DWG (AC1021, a canteen from
dwgmodels.com) opened through ocs_open_drawing in 4.7 s. It had 29,212 entities (24,947
lines, 750 block references, 279 hatches, 216 MTexts, 141 3D solids, …), 14 layers and 110
blocks, and rendered correctly after ocs_set_view. The web build does not draw hatches
(an upstream WebGL2 limitation), but they are in the data and can be queried.
Driving it from an agent: agent-browser
agent-browser enables WebMCP in the Chrome it manages, so it works as the agent-side client with no flags. Verified 2026-09-18 with agent-browser 0.37.1:
npm run serve &
agent-browser open http://127.0.0.1:8787/
agent-browser webmcp list # all 24 tools
agent-browser webmcp invoke ocs_get_state
agent-browser webmcp invoke ocs_capture_view --params '{"max_width":900}' # returns image/jpeg
# a write blocks on the human's dialog, so detach it and collect the result after approval:
agent-browser webmcp invoke ocs_run_command --params '{"cmd":"PLINE 0,0 100,0 100,50 0,50 C"}' --detach
agent-browser webmcp result <invocation-id> # "pending" until approvedWebMCP is behind a flag in Chrome: enable chrome://flags/#enable-webmcp-testing (headless:
--enable-features=WebMCPTesting).
Running a whole task with any agent: scripts/agent-run.mjs
scripts/agent-run.mjs gives any agent that can run shell commands a task and the tools. It
serves the editor and opens it in an agent-browser session. With --pdf, it also opens a drawing in
Chrome's PDF viewer in a second session, so the agent needs nothing but agent-browser to read it.
It then writes the agent a prompt explaining how to reach both sessions, runs the agent command
you give it, and records the run.
A stand-in human answers every confirm dialog and logs exactly what each one showed
(approvals.json). It approves everything unless the request matches --decline <regex>. It is
for demos and tests. It does not replace a person reviewing edits.
With --record, the videos are:
run.mp4: the drawing on the left, as the agent views it, and the editor on the right. Idle stretches are compressed.run-editor.mp4: the editor alone, starting at the first edit.
--start-blank dismisses Open CAD Studio's donation prompt and opens a blank drawing before the
agent starts.
Both of these were verified on 2026-09-19. The task was to rebuild a 7th-floor plan from a PDF of one sheet as a 3D model (grid, columns and walls, extruded to 3600 mm):
npm run build # once
# Claude Code (headless)
node scripts/agent-run.mjs task.md --pdf sheet.pdf --start-blank --record -- \
sh -c 'cd "$(dirname "$OCS_PROMPT_FILE")" && claude -p "$(cat "$OCS_PROMPT_FILE")" \
--allowedTools "Bash(agent-browser:*)" Read'
# Codex CLI
node scripts/agent-run.mjs task.md --pdf sheet.pdf --start-blank --record -- \
sh -c 'cd "$(dirname "$OCS_PROMPT_FILE")" && codex exec --skip-git-repo-check \
--sandbox workspace-write -c sandbox_workspace_write.network_access=true \
-c "sandbox_workspace_write.writable_roots=[\"$HOME/.agent-browser\"]" \
"$(cat "$OCS_PROMPT_FILE")" < /dev/null'Notes on the two runs:
Both got the grid exactly right. Codex also matched the sheet's overall 29,600 × 15,400 mm footprint and column sizes, in 5 approvals and 9.5 minutes. Claude Code (Sonnet) took 8 approvals and 17 minutes.
What each agent is allowed to do: Claude Code may run
agent-browserand read files (it looks at its own screenshots). Codex runs in itsworkspace-writesandbox with network access, plus agent-browser's socket folder~/.agent-browsermade writable.Codex's sandbox cannot launch Chrome. That is why the harness starts both browser sessions and the agent only connects to them.
Other agents: any other agent that can run shell commands plugs in the same way. Pass its command after
--; it reads the prompt from$OCS_PROMPT_FILE.Writes wait for the human. agent-browser's CLI gives up on a call after 25 s, so the prompt tells the agent to use
--detachfor writes and collect the result withwebmcp result.
macOS + Homebrew rustup: the rustup proxies live in
/opt/homebrew/opt/rustup/bin, which is not on PATH by default. Calling a toolchain'scargodirectly makesrust-lldfail to loadlibLLVM.dylib.scripts/vendor.mjsfinds the proxies itself.
Why this upstream commit
95bad2a3 is exactly what the official web app at opencadstudio.com/app was built from
(/site-version.txt): release v2026.37 plus one web hotfix. As of 2026-09-18, the bare release
tag and upstream main both failed to compile for wasm32 (desktop-only calls in shared code).
Upstream fixed main on 2026-09-18 (#1347). The pin moves to the first release after that.
Upstream internals this depends on
src/control.js is the only file that touches them:
window.wasmBindings, which is the Trunk loader's default, not a documented API;polling
ocs_control_takefor replies;opening a file, on builds before upstream #1351: writing it into the app's OPFS "recent files" cache, then
openby name. Builds with #1351 (merged 2026-09-18) take the file itself ({"op":"open","name":…,"data_base64":…}).openBytes()tries that first and falls back when the app answers "Missing path";ocs_open_drawingreports which route it used (open_method), and the e2e checks it matches the build.
A documented promise-based entry point and no donation prompt while automation drives are
proposed upstream (#1349). When they land, only src/control.js changes.
Licence
MIT for this repository (LICENSE). The deployed combination with Open CAD Studio is GPL-3.0-only (NOTICE.md).
This server cannot be deployed
Maintenance
Related MCP Connectors
DXF and PDF/X-4 for AI agents: structured facts, PNG renders, an interactive in-chat viewer.
Preventive human-approval write-gate for AI agents: writes commit only after a human approves.
Create and edit architecture diagrams from your AI agent; get an SVG and a live editable canvas.
Agent-first CAD: editable .kcad.ts source, deterministic review, OpenCASCADE kernel.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to generate and edit draw.io diagrams with real-time browser preview.525 npmApache 2.0
- AlicenseBqualityBmaintenanceEnables AI agents to automate AutoCAD LT and create DXF files headless, with tools for drawing, entity, layer, block, annotation, PID, and system operations.16MIT
- AlicenseNot gradedqualityBmaintenanceEnables agent-driven CAD automation by inspecting, editing, and validating DWG drawings through a handle-first workflow, with support for visual grounding, CADPlan execution, and local SQLite workspace management.18MIT
- AlicenseAqualityCmaintenanceEnables reading, analyzing, and editing CAD files (DXF and DWG) via natural language, including entity queries, layer management, and safe copy-based edits.171MIT