Back to MCP Servers

Edict

Agent-first programming language: agents produce JSON AST, the compiler validates, type-checks, effect-checks, verifies contracts via Z3/SMT, and compiles to WASM. 19 MCP tools for the full compile-and-execute loop.

code-executionagent
By Sowiedu
72Updated 1 week agoJavaScriptMIT

Installation

npx -y Edict

Configuration

{
  "mcpServers": {
    "Edict": {
      "command": "npx",
      "args": ["-y", "Edict"]
    }
  }
}

How to use

  1. Run the installation command above (if needed)
  2. Open your Claude Code settings file (~/.claude/settings.json)
  3. Add the configuration to the mcpServers section
  4. Restart Claude Code to apply changes

Edict

CI License: MIT Node.js MCP

<a href="https://glama.ai/mcp/servers/Sowiedu/Edict"><img width="380" height="200" src="https://glama.ai/mcp/servers/Sowiedu/Edict/badge" /></a>

A programming language designed for AI agents. No parser. No syntax. Agents produce AST directly as JSON.

Edict is a statically-typed, effect-tracked programming language where the canonical program format is a JSON AST. It's purpose-built so AI agents can write, verify, and execute programs through a structured pipeline — no text parsing, no human-readable syntax, no ambiguity.

Agent (LLM)
  │  produces JSON AST via MCP tool call
  ↓
Schema Validator ─── invalid? → StructuredError → Agent retries
  ↓
Name Resolver ────── undefined? → StructuredError + candidates → Agent retries
  ↓
Type Checker ─────── mismatch? → StructuredError + expected type → Agent retries
  ↓
Effect Checker ───── violation? → StructuredError + propagation chain → Agent retries
  ↓
Contract Verifier ── unproven? → StructuredError + counterexample → Agent retries
  (Z3/SMT)            ↓
                  Code Generator (pure-JS WASM encoder) → WASM → Execute

Features

  • JSON AST — Programs are JSON objects, not text files. No lexer, no parser.
  • Structured errors — Every error is a typed JSON object with enough context for an agent to self-repair.
  • Type systemInt, Float, String, Bool, Array<T>, Option<T>, Result<T,E>, records, enums, refinement types.
  • Effect tracking — Functions declare pure, reads, writes, io, fails. The compiler verifies consistency.
  • Contract verification — Pre/post conditions verified at compile time by Z3 (via SMT). Failing contracts return concrete counterexamples.
  • WASM compilation — Verified programs compile to WebAssembly via a pure-JS encoder and run in Node.js.
  • MCP interface — All tools exposed via Model Context Protocol for direct agent integration.
  • Schema migration — ASTs from older schema versions are auto-migrated. No breakage when the language evolves.

Execution Model

Edict compiles to WebAssembly and runs in a sandboxed VM. This is a deliberate security decision — not a limitation:

  • No ambient authority — compiled WASM cannot access the filesystem, network, or OS unless the host explicitly provides those capabilities via the pluggable EdictHostAdapter interface
  • Compile-time capability declaration — the effect system (io, reads, writes, fails) lets the host inspect what a program requires before running it
  • Runtime enforcementRunLimits controls execution timeout, memory ceiling, and filesystem sandboxing
  • Defense-in-depth — agent-generated code that runs immediately needs stronger isolation than human-reviewed code. The effect system + WASM sandbox + host adapter pattern provides exactly that

Host capabilities available through adapters: filesystem (sandboxed), HTTP, crypto (SHA-256, MD5, HMAC), environment variables, CLI arguments. New capabilities are added by extending EdictHostAdapter.

Quick Start

For AI Agents (MCP)

The fastest way to use Edict is through the MCP server — it exposes the entire compiler pipeline as tool calls:

npx edict-lang          # start MCP server (stdio transport, no install needed)

Or install locally:

npm install edict-lang
npx edict-lang          # start MCP server

Two calls to get started: edict_schema (learn the AST format) → edict_check (submit a program). See MCP Tools for the full tool list.

For Development

npm install
npm test          # 2675 tests across 136 files
npm run mcp       # start MCP server (stdio transport)

Docker

Run the Edict MCP server in a container — no local Node.js required:

# stdio transport (default — for local MCP clients)
docker run -i ghcr.io/sowiedu/edict

# HTTP transport (for remote/networked MCP clients)
docker run -p 3000:3000 -e EDICT_TRANSPORT=http ghcr.io/sowiedu/edict

Supported platforms: linux/amd64, linux/arm64.

Browser

Run the Edict compiler entirely in the browser — no server required:

BundleSizePhasesUse case
edict-lang/browser318 KB1–3 (validate, resolve, typecheck, effects, lint, patch)Lightweight checking
edict-lang/browser-full~14 MB1–5 (+ WASM codegen, Z3 contracts, WASM execution)Full compile & run
import { compileBrowser, runBrowserDirect } from 'edict-lang/browser-full';

const result = compileBrowser(astJson);
if (result.ok) {
    const run = await runBrowserDirect(result.wasm);
    console.log(run.output);  // "Hello, World!"
}

Note: ESM modules require HTTP serving. Use npx serve . or any static server — file:// won't work.

See examples/browser/index.html for a working example.

QuickJS (Sandboxed Environments)

The Edict compiler also runs inside QuickJS WASM — useful for sandboxed runtimes, edge workers, or embedding in other WASM applications:

BundleSizePhasesSlowdown vs Node.js
dist/edict-quickjs-check.js373 KB1–3 (validate, resolve, typecheck, effects)~3.7x
dist/edict-quickjs-full.js932 KB1–5 (check + WASM compile)~3.7x
import { EdictQuickJS } from "edict-lang/quickjs";

const edict = await EdictQuickJS.createFull();  // phases 1-5
const result = edict.compile(ast);
if (result.ok) {
    console.log(result.wasm);  // Uint8Array of valid WASM
}
edict.dispose();

Note: quickjs-emscripten is an optional peer dependency — install it alongside edict-lang to use EdictQuickJS. For fs-free environments, pass bundleSource directly instead of loading from disk.

See docs/quickjs-feasibility-report.md for full benchmarks and recommendations.

MCP Tools

ToolDescription
edict_schemaReturns the full AST JSON Schema — the spec for how to write programs
edict_versionReturns compiler version and capability info
edict_examplesReturns 41 example programs as JSON ASTs (includes schema snippet)
edict_validateValidates AST structure (field names, types, node kinds)
edict_checkFull pipeline: validate → resolve names → type check → effect check → verify contracts
edict_compileCompiles a checked AST to WASM (returns base64-encoded binary)
edict_runExecutes a compiled WASM binary, returns output and exit code
edict_patchApplies targeted AST patches by nodeId and re-checks
edict_errorsReturns machine-readable catalog of all error types
edict_lintRuns non-blocking quality analysis and returns warnings
edict_debugExecution tracing and crash diagnostics
edict_composeCombines composable program fragments into a module
edict_explainExplains AST nodes, errors, or compiler behavior
edict_exportPackages a program as a UASF portable skill
edict_import_skillImports and executes a UASF skill package
edict_generate_testsGenerates tests from Z3-verified contracts
edict_replayRecords and replays deterministic execution traces
edict_deployCompiles and deploys an Edict program to edge runtimes (Cloudflare Workers)
edict_invokeInvokes a deployed Edict WASM service via HTTP
edict_invoke_skillInvokes a UASF skill package directly
edict_packagePackages a compiled program as a deployable skill bundle
edict_supportReturns diagnostics and environment info for troubleshooting

MCP Resources

URIDescription
edict://schemaThe full AST JSON Schema
edict://schema/minimalMinimal schema variant for token-efficient bootstrap
edict://examplesAll example programs
edict://errorsMachine-readable error catalog
edict://schema/patchJSON Schema for the AST patch protocol
edict://guideAgent bootstrap guide for MCP-first onboarding
edict://supportDiagnostics and environment info

Example Program

A "Hello, World!" in Edict's JSON AST:

{
  "kind": "module",
  "id": "mod-hello-001",
  "name": "hello",
  "imports": [],
  "definitions": [
    {
      "kind": "fn",
      "id": "fn-main-001",
      "name": "main",
      "params": [],
      "effects": ["io"],
      "returnType": { "kind": "basic", "name": "Int" },
      "contracts": [],
      "body": [
        {
          "kind": "call",
          "id": "call-print-001",
          "fn": { "kind": "ident", "id": "ident-print-001", "name": "print" },
          "args": [
            { "kind": "literal", "id": "lit-msg-001", "value": "Hello, World!" }
          ]
        },
        { "kind": "literal", "id": "lit-ret-001", "value": 0 }
      ]
    }
  ]
}

The Agent Loop

The core design: an agent submits an AST → the compiler validates it → if wrong, returns a StructuredError with enough context for the agent to self-repair → the agent fixes it → resubmits.

// 1. Agent reads the schema to learn the AST format
const schema = edict_schema();

// 2. Agent writes a program (may contain errors)
const program = agentWritesProgram(schema);

// 3. Compile — returns structured errors or WASM
const result = edict_compile(program);

if (!result.ok) {
  // 4. Agent reads errors and fixes the program
  //    Errors include: nodeId, expected type, candidates, counterexamples
  const fixed = agentFixesProgram(program, result.errors);
  // 5. Resubmit
  return edict_compile(fixed);
}

// 6. Run the WASM
const output = edict_run(result.wasm);

Architecture

src/
├── ast/           # TypeScript interfaces for every AST node
├── validator/     # Schema validation (structural correctness)
├── resolver/      # Name resolution (scope-aware, with Levenshtein suggestions)
├── checker/       # Type checking (bidirectional, with unit types)
├── effects/       # Effect checking (call-graph propagation)
├── contracts/     # Contract verification (Z3/SMT integration)
├── codegen/       # WASM code generation (pure-JS encoder)
│   ├── codegen.ts       # IR → WASM module orchestration
│   ├── compile-ir-expr.ts  # IR expression compilation
│   ├── compile-ir-*.ts  # Specialized IR compilers (calls, data, match, scalars)
│   ├── runner.ts        # WASM execution (Node.js WebAssembly API)
│   ├── host-adapter.ts  # EdictHostAdapter interface + platform adapters
│   ├── closures.ts      # Closure capture and compilation
│   ├── hof-generators.ts # Higher-order function WASM generators
│   ├── wasm-encoder.ts  # Pure-JS WASM binary encoder (replaced binaryen)
│   ├── wasm-interpreter.ts # Pure-JS WASM interpreter (no WebAssembly API needed)
│   ├── recording-adapter.ts # Execution recording for replay
│   ├── replay-adapter.ts  # Deterministic replay from recorded traces
│   └── string-table.ts  # String interning for WASM memory
├── ir/            # Mid-level IR (lowering, optimization)
├── builtins/      # Builtin registry and domain-specific builtins
├── compact/       # Compact AST format (token-efficient for agents)
├── compose/       # Composable program fragments
├── deploy/        # Edge deployment scaffolding (Cloudflare Workers)
├── incremental/   # Incremental checking (dependency graph + diff)
├── lint/          # Non-blocking quality warnings
├── patch/         # Surgical AST patching by nodeId
├── migration/     # Schema version migration (auto-upgrade older AS

…
View source on GitHub