npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@miadi/stateloom-mcp

v0.2.0

Published

MCP server for miadi-stateloom (formerly smcraft-mcp) — lets LLM agents design state machines through conversation

Readme

@miadi/stateloom-mcp

npm

MCP server for stateloom — an LLM agent designs a hierarchical state machine through conversation, and the diagram on your screen changes while it talks.

Install

npm install -g @miadi/stateloom-mcp
# or let your MCP client fetch it:
npx -y @miadi/stateloom-mcp

What it is

A Model Context Protocol server over stdio that gives an agent fifteen tools for building a state machine: create it, add states and events and transitions, validate it, generate code or a RISE rispec from it, and draw it. Every mutation persists to a .smdf.json file on disk and — when a bridge URL is configured — emits to the live hub, so a human watching the web canvas or a terminal running smcx watch sees each edit as the agent makes it.

It is not the state machine engine (@miadi/stateloom-engine runs the machines) and not the hub (@miadi/stateloom sequences the live document). This is the agent-facing surface, sitting beside the human-facing ones on the same file.

Configure your MCP client

{
  "mcpServers": {
    "stateloom": {
      "command": "npx",
      "args": ["-y", "@miadi/stateloom-mcp"],
      "env": {
        "STATELOOM_PROJECT_FILE": "/abs/path/to/statemachine.smdf.json",
        "STATELOOM_BRIDGE_URL": "http://127.0.0.1:4599"
      }
    }
  }
}

| Environment variable | Default | Meaning | |---|---|---| | STATELOOM_PROJECT_FILE | ./statemachine.smdf.json | The document read and written; also the live room key | | STATELOOM_BRIDGE_URL | — | Hub URL; without it the server persists to disk only | | STATELOOM_AGENT_NAME | — | Presence label shown to other people in the room | | STATELOOM_BRIDGE_TOKEN | — | Handshake token, when the hub requires one |

The legacy SMCRAFT_* twin of each name is still honored. The package ships two bins — stateloom-mcp and, for existing registrations, smcraft-mcp.

Remote access (optional, 0.2.0+)

By default this server speaks stdio and runs as a child process beside one agent, with that agent's trust. Setting a port switches it to Streamable HTTP so agents on other machines can reach the same loom. Nothing changes unless you set the port.

STATELOOM_MCP_HTTP_PORT=4790 \
STATELOOM_MCP_TOKEN="$(openssl rand -hex 32)" \
STATELOOM_MCP_ROOT=/srv/machines \
  npx -y @miadi/stateloom-mcp
# → stateloom-mcp on http://127.0.0.1:4790/mcp

| Environment variable | Default | Meaning | |---|---|---| | STATELOOM_MCP_HTTP_PORT | — | Bind this port and speak HTTP. Unset means stdio, unchanged. | | STATELOOM_MCP_HTTP_HOST | 127.0.0.1 | Interface. Loopback by default — put a TLS terminator in front before widening it. | | STATELOOM_MCP_TOKEN | — | Required in HTTP mode. Authorization: Bearer <token>, compared in constant time. | | STATELOOM_MCP_ROOT | — | Confine the active document to this directory; set_project_file refuses to leave it. | | STATELOOM_MCP_LOCK_PROJECT | — | 1/true refuses set_project_file outright. |

Endpoints: POST /mcp (the MCP endpoint) and GET /health.

The server refuses to start in HTTP mode without a token. A reachable port here is a way to read and write files on the host, and a default-open one would be a mistake someone else pays for.

What remote mode is not

It is not multi-tenant. The active document is process state, so every HTTP client shares one board. That is the loom's whole premise when a human and an agent work together, and a hazard between strangers — one caller's set_project_file moves the document for everyone. STATELOOM_MCP_ROOT bounds where it can move; STATELOOM_MCP_LOCK_PROJECT stops it moving at all. Run one server per document, or per team, rather than one for everybody.

Each request gets its own server instance and transport (stateless Streamable HTTP), so clients may connect, disconnect and reconnect freely.

It does not serve concurrent clients fairly. generate_code shells out to smcg and render_diagram shells out to a rasterizer, both synchronously — they block the event loop for as long as the subprocess runs. On stdio that is invisible, because there is one caller and it is waiting anyway. Over HTTP, one agent's slow codegen stalls every other request, and a subprocess outlasting Node's 5-second keep-alive timeout makes those requests fail outright rather than merely arrive late. Until those calls are made asynchronous, treat a remote server as serving one working agent at a time, not a pool.

What is confined and what is not. With STATELOOM_MCP_ROOT set, both caller-supplied paths — set_project_file's path and render_diagram's path — are resolved through realpath and refused if they land outside the root, so a symlink inside the root cannot walk out of it. The server also refuses to start if STATELOOM_PROJECT_FILE is itself outside the root. generate_code writes only to a temporary directory. Note that STATELOOM_MCP_ROOT is read the same way every other setting is, so it constrains set_project_file on stdio too if you set it there.

Tools

| Tool | What it does | |---|---| | create_state_machine | Start a definition with a namespace and name | | add_state | Add a state; parent defaults to Root | | add_event | Add an event to an event source | | add_transition | Add a transition from a state, triggered by an event | | remove_state | Remove a state | | get_definition | Return the whole definition as JSON | | load_definition | Replace the definition from JSON | | list_states | Every state with its kind and transitions | | list_events | Every event | | validate_definition | Run the rule-coded validator | | generate_code | Emit Python or TypeScript from the definition | | generate_rispec | Emit a RISE rispec in markdown, folding in the source PDE's intent when the SMDF carries one | | render_diagram | Draw the machine as png, svg, mermaid or ascii, write it beside the document, and hand a png back inside the tool result so the agent sees what it designed | | set_project_file | Re-point the loom at another .smdf.json mid-session — disk target and live room both move | | get_project_file | The active document path, whether it exists, and bridge status |

Also exposed: the resource smcraft://definition (the current definition), and the prompt design-state-machine — a guided conversation for building one from a domain description.

What a session looks like

You: design an order fulfillment workflow

The agent calls create_state_machine, then add_event and add_state and add_transition a few times, then validate_definition to check its work, then render_diagram to look at it. Every one of those writes /abs/path/to/statemachine.smdf.json and pushes the change to the hub. Your canvas redraws as it goes.

Because rooms are keyed by the document's absolute path, set_project_file is how one agent moves between machines in a session — point it at another episode's diagram and the next edit lands there instead.

Part of the stateloom stack

| Package | Role | |---|---| | @miadi/stateloom-engine | State machine engine: parser, validator, interpreter, code generators | | @miadi/stateloom-protocol | Patch ops, diff/apply, layout, renderers — zero runtime deps | | @miadi/stateloom | socket.io hub holding the live document | | @miadi/stateloom-client | Framework-agnostic client for the hub | | @miadi/stateloom-react | React binding over the client | | @miadi/stateloom-cli | smcx — terminal design surface and renderers | | @miadi/stateloom-mcp | MCP server so LLM agents can design machines — this package |

License

MIT © Guillaume Isabelle