Procedures as data for TypeScript: one typed call model for in-process, HTTP, WebSocket, CLI and MCP (Claude) — with streaming, middleware and a visual composer.
Overview
You define a procedure one time: a path, a Zod input, a Zod output and a handler. Then you use it in the same process, over HTTP or WebSocket, from the mark CLI, or from Claude as an MCP tool. A program is plain JSON: calls, references to earlier results, and control flow. The client gives streams, middleware, retries and a cache. has the Composer (build a program from blocks, then start it in your browser), the middleware lab, the procedure catalog and the status board. The packages need Node.js 22 or later. They are ES modules. Replace LocalTransport with HttpTransport or WebSocketTransport to use the same procedures on a server. PROGRAM-FORMAT.md tells the rules of programs. tRPC is the better choice for type inference from server to client in one application. This repository is for procedures that many hosts use: a program, a CLI, a server and Claude. All packages are in packages/. The public packages are in the npm scope @procedures, with one version together.
README
client
Procedures as data for TypeScript. You define a procedure one time: a path, a Zod input, a Zod output and a handler. Then you use it in the same process, over HTTP or WebSocket, from the mark CLI, or from Claude as an MCP tool. A program is plain JSON: calls, references to earlier results, and control flow. The client gives streams, middleware, retries and a cache.
The site has the Composer (build a program from blocks, then start it in your browser), the middleware lab, the procedure catalog and the status board.
Install
npm install @procedures/client zod
The packages need Node.js 22 or later. They are ES modules.
Example
import { z } from "zod";
import { Client, LocalTransport, PROCEDURE_REGISTRY, allCoreProcedures, createProcedure, zodAdapter } from "@procedures/client";
import "@procedures/client/register"; // the control flow: client.chain and the others
// A procedure: a path, a typed input and output, and a handler
PROCEDURE_REGISTRY.register(
createProcedure()
.path(["greet"])
.input(zodAdapter(z.object({ name: z.string() })))
.output(zodAdapter(z.string()))
.handler(async ({ name }) => `Hello, ${name}!`)
.build(),
);
for (const p of allCoreProcedures) if (!PROCEDURE_REGISTRY.has(p.path)) PROCEDURE_REGISTRY.register(p);
const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
console.log(await client.exec({ $proc: ["greet"], input: { name: "Ada" } }));
// Hello, Ada!
// A program is JSON: the second step reads the result of the first step
const result = await client.exec({
$proc: ["client", "chain"],
input: {
steps: [
{ $proc: ["client", "add"], input: { a: 2, b: 3 } },
{ $proc: ["client", "multiply"], input: { a: { $ref: "$last" }, b: 4 } },
],
},
});
console.log(result.final);
// 20
Replace LocalTransport with HttpTransport or WebSocketTransport to use the same procedures on a server. PROGRAM-FORMAT.md tells the rules of programs.
Compared with other tools
| client | tRPC | JSON-RPC 2.0 | MCP TypeScript SDK | |
|---|---|---|---|---|
| Unit of work | A procedure: path, Zod input and output, handler | A router of queries, mutations and subscriptions | A method name and its parameters | Tools, resources and prompts |
| Transports | In the process, HTTP (JSON or NDJSON streams), WebSocket, MCP over stdio, a CLI | HTTP and WebSocket links | Not part of the specification | stdio and Streamable HTTP |
| Programs as data | JSON programs with references and control flow | No | A batch of calls | No |
| Streams | Async generators, with flow control | Subscriptions | Notifications only | Progress notifications |
| Types on the client | A typed call for each path | End-to-end inference from the router type | No | JSON Schema of the tools |
| Maturity | Version 0.x, one author | Version 11, wide use | A stable specification | The official SDK |
tRPC is the better choice for type inference from server to client in one application. This repository is for procedures that many hosts use: a program, a CLI, a server and Claude.
Packages
All packages are in packages/. The public packages are in the npm scope @procedures, with one version together. The table gives the npm name, and the link goes to the folder.
| Group | Packages |
|---|---|
| Core | @procedures/client (procedures, client, transports, middleware), @procedures/compiler (the check and the compiler of programs), @procedures/systems (the timer law of systems for the client), @procedures/collections (data structures), @procedures/store (the program store), @procedures/dag (dependency graphs, and dag.traverse) |
| Commands | @procedures/shell, @procedures/git, @procedures/pnpm, @procedures/npm (the npm registry), @procedures/docker, @procedures/node, @procedures/vite, @procedures/vitest, @procedures/cue, @procedures/cli-run, @procedures/gh |
| Data and services | @procedures/fs, @procedures/http (HTTP with a host allowlist), @procedures/json (JSON and YAML transforms), @procedures/archive (tar.gz and zip with a check of each path), @procedures/llm (a language model: completions and structured answers), @procedures/s3, @procedures/mongo, @procedures/sqlite, @procedures/snapshot, @procedures/splay |
| Everyday data | @procedures/ics (calendars and recurrences), @procedures/mail (MIME and IMAP), @procedures/geo (geocoding and routes), @procedures/weather (forecasts), @procedures/exif (photo time and place), @procedures/notify (push notifications) |
| Tool commands | @procedures/restic (backups), @procedures/tailscale (the tailnet), @procedures/pdf (HTML to PDF with an installed browser), @procedures/claude-cli (a turn of the Claude Code CLI as a process) |
| Private data | @procedures/ios-backup (iPhone backups and messages), @procedures/privacy-scan (private data in text before a release) |
| Servers and MCP | @procedures/peer, @procedures/server, @procedures/mcp, @procedures/mcp-server, @procedures/mcp-dev-tools (an MCP server for Claude Code) |
| Tools | @procedures/mark (the mark CLI), @procedures/lib, @procedures/procedure, @procedures/playground, @procedures/schedule (a cron for stored programs), @procedures/env (environment variables, with the secrets masked) |
| Bundles | @procedures/bundle-dev, @procedures/bundle-mcp, @procedures/bundle-assistant (the opt-in tools of the assistant) |
| Private | site (the website), documentation |
Until October 2026, these packages had the scope @mark1russell7 (for example @mark1russell7/client-shell). The general packages @mark1russell7/cue, @mark1russell7/splay and @mark1russell7/docker-sqlite keep their scope.
Use with Claude
@procedures/mcp-dev-tools is an MCP server with 91 developer tools: Docker, MongoDB, SQLite, CUE, Vitest and the workspace. Each tool call has a time limit, and a tool can use only the procedures that it declares. Add it to the MCP configuration of Claude Code:
{
"mcpServers": {
"dev-tools": { "command": "npx", "args": ["-y", "@procedures/mcp-dev-tools"] }
}
}
Build and test
- Install the dependencies:
pnpm install - Build all packages:
pnpm build - Start the tests:
pnpm test - Examine the types:
pnpm typecheck
pnpm build builds the packages in the sequence of their dependencies. Each package writes its output to its dist/ folder. Git ignores dist/. ONBOARDING.md tells more.
Release
RELEASE.md tells how the packages go to npm. node scripts/check-packages.mjs examines each package as npm gives it.
Other repositories
Some packages use general packages from other repositories: cue, splay and docker-sqlite. A general package does not use a package of this repository.
License
MIT. Refer to LICENSE.
Install
npx -y @procedures/mcp-dev-toolsConfiguration
{
"mcpServers": {
"dev-tools": { "command": "npx", "args": ["-y", "@procedures/mcp-dev-tools"] }
}
}