Guide

Worked WebMCP requests

Start with the before-and-after programs for organization and access. They include complete requests with the source filled in. The calls below cover verification, frontend generation, and reports. The editable safety lessons demonstrate owner keys and role authority; analysis input recipes provide complete protocol cases and implementation views.

Read each linked file as UTF-8, then replace the uppercase variable with its full text. Pass sources as an array of file objects and numeric parameters as numbers. Most calls work through the browser connection or local Node server; the Lean proof call below needs a configured native or Node host, or the isolated browser Lean Wasm page.

If a result differs, call api_compile with the same sources. Check the source files and topology, then follow the reported finding.

api_law_check over an explicit Bosatsu domain

Use the complete finite-law Bosatsu source. It declares a FiniteObligation over the distinct values [1, 0], a predicate that accepts only zero, and a witness that reaches zero. Run:

api_law_check({
  "sources": [{
    "fileName": "finite-law.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }],
  "mode": "exhaustive",
  "maximum": 2
})

The result is violated with replayable input 1; its listed scope records two values entries with replayable input values 1 and 0, not just their count. Reducing maximum to 1 is inconclusive, never a sampled pass. api_obligations currently accepts sampled Obligation declarations only, so this finite verdict does not select a commit strategy.

api_lean_check on a direct Bool law

Use the complete Bool-law Bosatsu source. It declares a law over both Bool values and a witness that True exists. With a local proof host configured, or on the browser Lean page, call:

api_lean_check({
  "sources": [{
    "fileName": "lean-bool.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }]
})

The default compact result keys rows by obligation and names each proved predicate, its quantified domain, and fullReceiptSha256. An inconclusive not-admitted row means this translation or method could not check the law; seek another proof route rather than treating the law as false. Pass that digest back as receipt_sha256 to the same live host to fetch the exact full lean-law-run native receipt or lean-wasm-law-run Node or browser receipt; a missing cache entry requires another check of the current source. The main browser workbench needs a proof host; its separate Lean page runs the pinned Wasm checker. A false mutation, unsupported translation, or incomplete checker run does not produce a verified receipt. The command-line equivalent is yichus lean --toolchain PATH --source lean-bool.bosatsu --json --view compact --result FULL.json; the result file holds the full native receipt named by the view’s digest. The Node CLI uses yichus lean lean-bool.bosatsu --lean-wasm-root DIRECTORY and records that independent kernel replay was not run.

api_lean_check on a recursive list law

Use the complete List[Bool] Bosatsu source. Its check recurses on the bound tail of a Nil/Cons match. The generated Lean theorem uses induction to check the law for every finite Boolean list, and a separate theorem proves the named witness using the empty list. With the local proof host configured, call:

api_lean_check({
  "sources": [{
    "fileName": "lean-list.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }]
})

The CLI equivalent is yichus lean --toolchain PATH --source lean-list.bosatsu --json, or on Node, yichus lean lean-list.bosatsu --lean-wasm-root DIRECTORY. This translator accepts only its checked structural List[Bool] shape: one direct law check, one direct filled witness, a tail-only self-call, and expressions in its supported grammar. Other recursive shapes, host externals, and finite obligations remain inconclusive. The isolated browser Lean page supports this list shape.

Use an existing theorem to verify an implementation

The complete modular-inverse example defines modular exponentiation, a primality check, and an inverse law in Bosatsu. Its proof connects those generated functions to Mathlib's arithmetic definitions, then applies ZMod.pow_card_sub_one_eq_one, an existing form of Fermat's little theorem. A separate proof establishes the named witness.

Install the optional theorem library beside the pinned native Lean toolchain from a Yichus checkout, then check the source:

node scripts/install_lean_mathlib.mjs /path/to/lean-4.34.0-platform
  yichus lean --toolchain /path/to/lean-4.34.0-platform \
    --source lean-inverse.bosatsu --emit-lean Proof.lean \
    --json --view compact --result FULL.json

--emit-lean saves the generated definitions and theorem goals before verification, including when an author proof is unfinished. Edit the exported lean_proof and lean_witness strings and rerun the command. The author term can use definitions from its package by their names; imported helpers receive distinct generated package namespaces. A saved Lean module is not a verified receipt.

The integer grammar accepts Int or a declared, non-generic product with at least two fields, all Int. Predicates and helpers must be monomorphic, capture-free named functions. Supported operations are integer addition, subtraction, multiplication, modulus, comparison, equality, and Boolean not, and, and or, plus local bindings, conditionals, and input-field projections. Other compiled builtin helpers, including Bosatsu/Char helpers, are outside this translated closure. Destructure products into names, then compare their fields: literal patterns such as case Query(0, 1) require mutable pattern slots and are not admitted. Division, arbitrary higher-order calls, other data types, and mutual recursion are not admitted. Self-recursion requires a top-level zero test of an integer parameter; Lean must prove each recursive call decreases that parameter's toNat. Negative branches retain their Bosatsu behavior. The modulus adapter preserves Bosatsu's divisor-sign convention, including the defined zero-divisor case.

Local MCP uses api_lean_check with the same source file and a configured proof host. A verified result requires elaboration, an approved-axiom audit, source replay, and independent kernel checking of the generated law and witness. It covers every value of the declared input type. Unsupported syntax, failed termination, missing or changed libraries, and timeouts are inconclusive. This optional Mathlib bundle runs on native Lean; browser WebMCP does not yet provide it. The portable Lean runtime and native Mathlib have different pins.

api_access_check on the full four-route Notes API

Source: demos/service/notes-api.bosatsu. Load that file as the source string and call:

api_access_check({
  "sources": [{
    "fileName": "notes-api.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }]
})

The access check holds: the read, write, add, and clear handlers key the owner-scoped table from Principal.user_id, so the owner-key findings hold. This tool does not establish the composite API verdict. Its tool page defines the three access statuses and parameters.

api_verify on full Notes with single-instance topology

Use the same linked source and declare the deployment topology:

api_verify({
  "sources": [{
    "fileName": "notes-api.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }],
  "instances": 1
})

Verification is proven under instances: 1. The add route reads and then writes the same row. With no topology argument, api_verify uses the multi-instance default and reports the read-modify-write and bounded integrity properties as violations. The api_verify page contains an engine-generated request and response for this specimen.

Fixing a read-modify-write with Yichus/Transaction

When api_verify reports rmw-transactions violated and the service really does run on several instances, the fix is a transaction plan, not a topology declaration. The plan reads and writes the table through one named accessor, and the handler maps every outcome:

def stock_rows[s](scope: Scope[s]) -> TxTable[s, Stock]:
  tx_table(scope, "stock")

def reserve_plan[s](scope: Scope[s], sku: String, qty: Int) -> Txn[s, String, Response]:
  found <- tx_bind(tx_read(stock_rows(scope), sku))
  match found:
    case None: tx_pure(Response(404, sku))
    case Some(Stock(on_hand)):
      match cmp_Int(on_hand, qty):
        case LT: tx_pure(Response(409, sku))
        case _:
          _ <- tx_bind(tx_write(stock_rows(scope), sku, Stock(sub(on_hand, qty))))
          tx_pure(ok(sku))

def reserve_txn(db: Db, sku: String, qty: Int) -> IO[Outcome[String, Response]]:
  scope <- transaction(db)
  reserve_plan(scope, sku, qty)

def reserve(db: Db, _: Principal, req: ReserveRequest) -> IO[Response]:
  ReserveRequest(sku, qty) = req
  outcome <- flat_map(reserve_txn(db, sku, qty))
  match outcome:
    case Committed(response): pure(response)
    case Aborted(reason): pure(Response(500, reason))
    case RetryExhausted: pure(Response(503, "retry"))
    case CommitUnknown: pure(Response(503, "unknown"))

The imports are Scope, Txn, TxTable, Outcome, Committed, Aborted, RetryExhausted, CommitUnknown, transaction, tx_table, tx_bind, tx_pure, tx_read, tx_write from Yichus/Transaction. tx_read returns an Option; the route keeps its declared permissions. After the edit the same api_verify call reads rmw-transactions: proven. The guide's section "Atomic commands with Yichus/Transaction" (api_guide with section: "transaction") carries the full contract.

api_access_check on the literal-key Notes variant

Source: demos/service/notes-api-leaky.bosatsu. Load the linked file and call:

api_access_check({
  "sources": [{
    "fileName": "notes-api-leaky.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }]
})

The list_notes handler uses a literal read key, so interpret the expected access:notes result as violated. Calling api_verify with instances: 1 cannot repair that access failure; its composite result remains unproven. See the failed read and the repair in the access diagram.

api_frontend from Notes routes and FrontendSpec

Load the API source above and demos/service/notes-app.bosatsu, which selects list, form, and action views. Then call:

api_frontend({
  "sources": [
    { "fileName": "notes-api.bosatsu", "source": LINKED_API_FILE_CONTENTS },
    { "fileName": "notes-app.bosatsu", "source": LINKED_FRONTEND_FILE_CONTENTS }
  ],
  "instances": 1,
  "transport": "in-process",
  "auth": "dev"
})

Generation should succeed because the composite API verdict is proven at the declared topology and each view matches a typed route. The returned HTML is the same kind of artifact as the deployed Notes App, where the four API routes appear as generated views. The api_frontend reference defines transport, authentication, and route-shape checks.

api_report on ProjectHub

Load the projecthub.bosatsu multi-entity service and frontend specification, then call:

api_report({
  "sources": [{
    "fileName": "projecthub.bosatsu",
    "source": LINKED_FILE_CONTENTS
  }],
  "format": "html",
  "detail": "summary"
})

Interpret the result by checking overview.surfaces for the service, data, and frontend structures, then follow each guarantee's evidence pointer. The ProjectHub App shows the generated frontend artifact for those typed routes. The api_report page defines the JSON and HTML formats and topology parameter.

Follow the inspect–edit–recheck workflow. The connection guide configures browser and Node MCP clients. The full catalog provides every parameter and generated per-tool page.

Where this fits

What this is about: How the pieces fit