pulp
Click on "Install 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., "@pulpCreate a landing page with hero, features, and footer."
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.
pulp
The local-first, agent-driven design canvas. pulp is an infinite canvas where drawings are real HTML and CSS, humans and coding agents edit the same document, and the browser remains the source of truth. Ask Claude or Codex to design a page and watch it appear live, refine it by hand, save the editable drawing as a file, or export it as PNG, SVG, HTML, a portable deck, or PDF.
Real DOM, not pictures. Every frame is real flexbox layout rendered by the browser. Canvas rendering and export share the same code generator, so HTML export is lossless.
Local first. Named workspaces autosave independently in browser storage. Editable
.pulp.jsonfiles provide explicit backups and handoff; no cloud account or database is required.Agents first. Eighteen MCP tools let Claude, Codex, and other clients read and mutate the document. Multiple agents can share one live workspace or use isolated named sessions without fighting over the bridge port.
Review is a loop, not a screenshot. Pin human feedback to a layer or canvas position; agents read the workspace inbox over MCP, make the change, and resolve it with a visible response. The MCP console keeps a searchable, workspace-persistent audit of every received request and response.
Rust core, WASM delivery. The scene graph, command API, undo/redo, validation, and HTML codegen are a Rust crate compiled to WebAssembly. The app itself is static and deploys to GitHub Pages.
Browser demo

The 45-second browser-only walkthrough shows the live canvas, presentation mode, the MCP request/response history, and the multi-format export menu.
Quick start
Prerequisites: Node 20+, Rust via rustup with the WASM target, and wasm-pack:
rustup target add wasm32-unknown-unknown
cargo install wasm-pack --lockedThen:
npm install
npm run build:engine # rerun after Rust changes
npm run build:mcp # rerun after MCP changes
npm run dev # http://localhost:5173Open http://localhost:5173 for the default workspace, or name one in the
URL:
http://localhost:5173/?workspace=design-notesThe workspace chip can switch among drawings already saved by that browser.
Names are normalized to lowercase letters, numbers, _, and -; use the name
shown in the chip when configuring an agent.
Connect agents
The repo's .mcp.json automatically registers Pulp for Claude Code launched
inside this directory. For a global registration:
claude mcp add pulp -- node /absolute/path/to/pulp/mcp/dist/index.js
codex mcp add pulp -- node /absolute/path/to/pulp/mcp/dist/index.jsWith the default editor open, both clients join the default session and can
work on the same canvas. The first local MCP process becomes the lightweight
broker; later processes join it automatically, so EADDRINUSE is not a user
workflow or an error to work around.
For a named browser workspace, set the MCP session to the same normalized name:
claude mcp add pulp-design-notes -- \
env PULP_SESSION=design-notes PULP_CLIENT_NAME=claude \
node /absolute/path/to/pulp/mcp/dist/index.js
codex mcp add pulp-design-notes -- \
env PULP_SESSION=design-notes PULP_CLIENT_NAME=codex \
node /absolute/path/to/pulp/mcp/dist/index.jsPULP_SESSION controls routing; PULP_CLIENT_NAME is the label shown in logs
and the editor's live agent-activity cards. Agents using the same session share
the corresponding editor. Give agents different sessions, with one browser tab
per named workspace, to isolate their documents. All normal sessions share
port 7857 through the broker.
Advanced local experiments can pair PULP_PORT=7867 with ?port=7867, or use
an explicit browser bridge such as ?bridge=ws://127.0.0.1:7867. A hosted HTTPS
page requires an explicitly supplied wss:// bridge; this repository does not
deploy one.
Once the toolbar says agent live, ask an agent something like:
Design a SaaS landing page in pulp: dark hero, three feature cards, footer.
The agent reads a compact document outline, applies JSON commands, and every change renders immediately. Human edits use the same engine and undo history, so the next agent read sees them. The canvas shows the four most recent agent operations with pending, success, or error state; click a completed targeted operation to reveal its layer. Open MCP for the full searchable request and response history, including source agent, session, target, timing, filters, and copyable JSON.
Press C or open Review to attach feedback to the selected layer or place
a pin on the canvas. Open items are stored per workspace. Agents consume them
with pulp_list_feedback and close the loop with pulp_resolve_feedback; their
name and response appear on the feedback card. Because MCP stdio is
client-initiated, a pin is a durable inbox item for the agent's next read—it
does not wake an idle Claude/Codex process by itself.
Agent onboarding is in AGENTS.md. Claude and Codex also receive
the matching pulp-design skill from .claude/skills/ and .agents/skills/.
Local-first files and workspaces
Each ?workspace=<name> has its own autosave key,
pulp.doc.<normalized-name>, on the current browser origin. Autosave is
debounced after document mutations and its state appears in the toolbar.
Save downloads the complete editable document as
<title>.pulp.json.Open validates a
.pulp.jsonfile, replaces the current drawing, and autosaves it into the current workspace.PNG / SVG / HTML export the selected frame as a 2x raster image, scalable wrapper, or lossless standalone DOM page.
Presentation HTML turns every root frame into a portable keyboard-driven deck. Print / PDF opens the same frames one per print page.
Browser storage is convenient working state, not a durable backup. Save a
.pulp.json file before clearing site data, changing browsers, or handing a
drawing to another machine. Invalid or structurally broken document files are
rejected without replacing the current canvas.
How it fits together
browser workspace (?workspace=design-notes)
editor UI -> Rust/WASM document engine -> local autosave / .pulp.json / HTML
^
| session "design-notes" over ws://127.0.0.1:7857
|
shared MCP broker
^ ^
| stdio | stdio
Claude Code Codex (and other MCP clients)Every mutation goes through the same engine command API. The document is plain JSON; a patch looks like:
{ "cmd": "set_props", "id": "n4",
"props": { "style": { "fill": "#0b0b10", "shadow": null } } }Patches deep-merge: only fields present in the command change, and null
clears a field.
Editor controls
Action | Input |
Pan | Space+drag, middle-drag, or scroll |
Zoom | Pinch or ⌘/Ctrl+scroll |
Actual size |
|
Fit selection / fit all |
|
Create frame |
|
Create rectangle / ellipse |
|
Create sticky note / text |
|
Select | Click; Shift+click for multi-select |
Move / resize | Drag a frame or absolute child; drag selection handles |
Undo / redo | ⌘/Ctrl+Z / Shift+⌘/Ctrl+Z |
Duplicate / delete | ⌘/Ctrl+D / Delete |
Clear selection | Escape |
Toggle Layers / Inspector |
|
Focus mode |
|
Pin review feedback |
|
Present frames as slides |
|
Rename | Double-click in the Layers panel |
Reveal on canvas | Alt+double-click in the Layers panel |
On initial load, Pulp fits all frames into view. Creation shortcuts place new objects in the active frame, creating a frame first when necessary.
Verification
npm run test:engine # native Rust engine tests
npm run test:mcp-multi # shared broker, isolation, failover, timeout tests
npm run test:mcp-tools # MCP tool registration, including feedback tools
npm run test:feedback # workspace feedback persistence and isolation
npm test # both suites
npm run build # WASM engine + app + MCP builds
npm run check # tests, then the full production buildWith a local editor open on the matching session, the destructive end-to-end smoke test exercises the MCP tools and creates a sample frame:
node mcp/smoke.mjsDeploy
Pushing to main runs the test suites, builds the engine and app, and deploys
app/dist to GitHub Pages. The hosted editor, named workspaces, local autosave,
file Open/Save, all export formats, and presentation mode work without a backend. Agent control defaults
to local development because a hosted HTTPS page cannot open an insecure local
WebSocket; an explicit wss:// bridge is an opt-in advanced configuration. On
HTTPS, the app also registers its manifest and offline shell; after the assets
have been cached by an online visit, it can reopen without the network.
Layout
engine/ Rust/WASM document model, commands, validation, history, codegen
app/ Vite/TypeScript editor, canvas UI, workspaces, local files, bridge client
mcp/ MCP tools, shared multi-session WebSocket broker, smoke testsThis server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nipunbatra/pulp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server