xyz.pflow.sim/whatif
REMOTE · SIM.PFLOW.XYZ · SCANNED OCT 7
Conversational what-if simulation: build, diagnose and compare Petri-net models; CC0 catalog.
Available components
Recent critical change
Authorization (17 Sept 2026). See the changelog before you install this server.
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security57
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation check failed: no authorisation is required to call this server, and it exposes a tool marked destructive (sim_accept_migration). See how to fix → View diagnostics → Fail
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability76
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 19535 tokens (~348/item across 56 items; 55 tools + 1 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management67
- Stability observed for 20 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety50
- Injection-marker check failed: the description of parameter "system" on tool "sim_reroll" contains an instruction override, the text "override the original prompt", at byte 0 of that field, plus 1 further marker(s) of the same kind. See how to fix → Fail
- All 4 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 56 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities60
- Spec-recency check failed: implements MCP spec 2025-06-18; the latest is 2026-07-28. See how to fix → Fail
How do I install the xyz.pflow.sim/whatif MCP server?
xyz.pflow.sim/whatif is a hosted endpoint at https://sim.pflow.xyz/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · sim.pflow.xyz
claude mcp add --transport http xyz-pflow-sim-whatif 'https://sim.pflow.xyz/mcp'
{
"mcpServers": {
"xyz-pflow-sim-whatif": {
"url": "https://sim.pflow.xyz/mcp"
}
}
} {
"servers": {
"xyz-pflow-sim-whatif": {
"type": "http",
"url": "https://sim.pflow.xyz/mcp"
}
}
} [mcp_servers.xyz-pflow-sim-whatif] url = "https://sim.pflow.xyz/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"xyz-pflow-sim-whatif": {
"type": "remote",
"url": "https://sim.pflow.xyz/mcp",
"enabled": true
}
}
} openclaw mcp add xyz-pflow-sim-whatif --url 'https://sim.pflow.xyz/mcp' --transport streamable-http
mcp_servers:
xyz-pflow-sim-whatif:
url: "https://sim.pflow.xyz/mcp" {
"McpServers": {
"xyz-pflow-sim-whatif": {
"Transport": "http",
"Url": "https://sim.pflow.xyz/mcp"
}
}
} assistant mcp add xyz-pflow-sim-whatif -t streamable-http -u 'https://sim.pflow.xyz/mcp'
{
"mcpServers": {
"xyz-pflow-sim-whatif": {
"type": "http",
"url": "https://sim.pflow.xyz/mcp"
}
}
} The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 7 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 57 to 67. That category is still filling its 30-day observation window: 17 days of observed history at the previous scan, 20 at this one. The score rises as the window fills, whether or not the server changes.
- 4 Oct 26 +1
- Tool “sim_run_pipeline” rewrote its description, which is the text the model reads security
- 3 Oct 26 0
- New tool “sim_accept_migration”, which the server declares destructive security
- New tool “sim_create_system”, which the server declares destructive security
- New tool “sim_migration_offers”, which the server declares destructive security
- New tool “sim_system”, which the server declares destructive security
- Tool “sim_bind” rewrote its description, which is the text the model reads security
- Tool “sim_check_witness” rewrote its description, which is the text the model reads security
- Tool “sim_create_collection” rewrote its description, which is the text the model reads security
- Tool “sim_edges” rewrote its description, which is the text the model reads security
- Tool “sim_get_binding” rewrote its description, which is the text the model reads security
- Tool “sim_link” rewrote its description, which is the text the model reads security
- Tool “sim_neighbors” rewrote its description, which is the text the model reads security
- Tool “sim_prove” rewrote its description, which is the text the model reads security
- Tool “sim_query” rewrote its description, which is the text the model reads security
- Tool “sim_reach” rewrote its description, which is the text the model reads security
- Tool “sim_run_pipeline” rewrote its description, which is the text the model reads security
- Tool “sim_supersede_model” rewrote its description, which is the text the model reads security
- Schema quality: 239 → 346 ▼ functional
- “sim_bind” added an optional parameter “convertFactor” cosmetic
- “sim_bind” added an optional parameter “convertFrom” cosmetic
- “sim_bind” added an optional parameter “convertTo” cosmetic
- “sim_bind” added an optional parameter “delay” cosmetic
- “sim_check_witness” added an optional parameter “reachResult” cosmetic
- “sim_check_witness” added an optional parameter “refutation” cosmetic
- “sim_prove” added an optional parameter “via” cosmetic
- “sim_bind” reworded the description of “fromPort” cosmetic
- “sim_bind” reworded the description of “toPort” cosmetic
- “sim_bind” reworded the description of “transform” cosmetic
- “sim_check_witness” reworded the description of “derivation” cosmetic
- “sim_check_witness” reworded the description of “reach” cosmetic
- “sim_prove” reworded the description of “predicate” cosmetic
- “sim_reach” reworded the description of “from” cosmetic
- “sim_reach” reworded the description of “system” cosmetic
- “sim_reach” reworded the description of “to” cosmetic
- 2 Oct 26 0
- New tool “sim_check_witness”, which the server declares destructive security
- New tool “sim_prove”, which the server declares destructive security
- New tool “sim_query”, which the server declares destructive security
- New tool “sim_reach”, which the server declares destructive security
- Tool “sim_bind” rewrote its description, which is the text the model reads security
- Tool “sim_canonical” rewrote its description, which is the text the model reads security
- Tool “sim_classify” rewrote its description, which is the text the model reads security
- Tool “sim_create_collection” rewrote its description, which is the text the model reads security
- Tool “sim_edges” rewrote its description, which is the text the model reads security
- Tool “sim_link” rewrote its description, which is the text the model reads security
- Tool “sim_neighbors” rewrote its description, which is the text the model reads security
- Tool “sim_supersede_model” rewrote its description, which is the text the model reads security
- Schema quality: 196 → 239 ▼ functional
- “sim_link” reworded the description of “object” cosmetic
- “sim_link” reworded the description of “predicate” cosmetic
- “sim_link” reworded the description of “subject” cosmetic
- 30 Sept 26 +1
- Tool “sim_calibrate” rewrote its description, which is the text the model reads security
- Tool “sim_code_to_flow” rewrote its description, which is the text the model reads security
- Tool “sim_compare” rewrote its description, which is the text the model reads security
- Tool “sim_conformance” rewrote its description, which is the text the model reads security
- Tool “sim_create_model” rewrote its description, which is the text the model reads security
- Tool “sim_diagnose” rewrote its description, which is the text the model reads security
- Tool “sim_distill” rewrote its description, which is the text the model reads security
- Tool “sim_evaluate” rewrote its description, which is the text the model reads security
- Tool “sim_link” rewrote its description, which is the text the model reads security
- Tool “sim_optimize” rewrote its description, which is the text the model reads security
- Tool “sim_param_heatmap” rewrote its description, which is the text the model reads security
- Tool “sim_propose_types” rewrote its description, which is the text the model reads security
- Tool “sim_publish” rewrote its description, which is the text the model reads security
- Tool “sim_publish_app” rewrote its description, which is the text the model reads security
- Tool “sim_publish_compare” rewrote its description, which is the text the model reads security
- Tool “sim_receipt” rewrote its description, which is the text the model reads security
- Tool “sim_refine” rewrote its description, which is the text the model reads security
- Tool “sim_run_pipeline” rewrote its description, which is the text the model reads security
- Schema quality: 178 → 196 ▼ functional
- “sim_bind” reworded the description of “transform” cosmetic
- “sim_compare” reworded the description of “scenarios” cosmetic
- “sim_crosscheck” reworded the description of “hours” cosmetic
- “sim_diagnose” reworded the description of “hours” cosmetic
- “sim_distill” reworded the description of “options” cosmetic
- “sim_evaluate” reworded the description of “horizon” cosmetic
- “sim_evaluate” reworded the description of “realizations” cosmetic
- “sim_optimize” reworded the description of “hours” cosmetic
- “sim_optimize” reworded the description of “samples” cosmetic
- “sim_optimize” reworded the description of “seed” cosmetic
- “sim_param_heatmap” reworded the description of “hours” cosmetic
- “sim_param_heatmap” reworded the description of “range_x” cosmetic
- “sim_param_heatmap” reworded the description of “range_y” cosmetic
- “sim_propose_types” reworded the description of “limit” cosmetic
- “sim_propose_types” reworded the description of “realizations” cosmetic
- “sim_publish” reworded the description of “scenario” cosmetic
- “sim_publish_compare” reworded the description of “scenarios” cosmetic
- “sim_receipt” reworded the description of “scenario” cosmetic
- “sim_run_pipeline” reworded the description of “realizations” cosmetic
- “sim_scenario” reworded the description of “scenario” cosmetic
- 28 Sept 26 +1
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 25 Sept 26 +1
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 23 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 17 to 20. That category is still filling its 30-day observation window: 5 days of observed history at the previous scan, 6 at this one. The score rises as the window fills, whether or not the server changes.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 9 Oct 2026 · Probed https://sim.pflow.xyz/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=sim.pflow.xyz | CN=WR3,O=Google Trust Services,C=US | 1 Oct 2026 | 30 Dec 2026 | RSA 2048 | SHA256-RSA | feaa8ca4234680401049f2e85024e248 |
| SANs: sim.pflow.xyz | ||||||
| CN=WR3,O=Google Trust Services,C=US (CA) | CN=GTS Root R1,O=Google Trust Services LLC,C=US | 13 Dec 2023 | 20 Feb 2029 | RSA 2048 | SHA256-RSA | 7ff005a91568d63abc22861684aa4b5a |
| CN=GTS Root R1,O=Google Trust Services LLC,C=US (CA) | CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE | 19 Jun 2020 | 28 Jan 2028 | RSA 4096 | SHA256-RSA | 77bd0d6cdb36f91aea210fc4f058d30d |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of sim.pflow.xyz. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| xyz. | present | 3599, 18130 | 8, 8 | Verified |
| pflow.xyz. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://sim.pflow.xyz/mcp | Verified | 200 | |
| http (plaintext) | http://sim.pflow.xyz/mcp | HTTPS enforced | 302 | https://sim.pflow.xyz/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
sim_accept_migration ~331
Carry offered taxonomic edges of a superseded model forward to its current successor. edges lists 1 to 25 edge ids that sim_migration_offers(model) offered; pass successor (the current it returned) so a different current successor — a re-point or a chain that grew since — is refused rather than followed. Every edge is checked before anything is written (it must touch model, be offered, pass sim_link's check, you must own model or have authored the edge, and the edge it becomes must pass its predicate's write rule for you — hasMember only for the collection's owner); one failure refuses the call and writes nothing. Each accepted edge is written on the successor attributed to you, with no timestamp, plus a migratedFrom edge from it to the old edge (provenance; sim_edges(<new edge>) shows it, and sim_query closure over migratedFrom traces it back across several supersessions). The old edge stays. Re-running converges on the same ids; an edge you already linked the same way is reused (existing: true, keeping its own timestamp). A call stopped after some edges were written says which were and which were not. Needs sign-in with write scope (opens OAuth the first time); MCP only. Costs 1 compute token per call.
| Name | Type | Req | Description |
|---|---|---|---|
| edges | array | yes | 1 to 25 edge ids sim_migration_offers(model) offered |
| model | string | yes | content id of the superseded model |
| successor | string | – | the current successor sim_migration_offers returned; a different current successor now is refused |
No output schema declared.
No examples provided.
sim_bind ~929
Record a checked connection between two stored models' declared ports, fromModel's fromPort (a place tagged port.output) feeding toModel's toPort (a transition tagged port.input), as a content-addressed Binding (ROADMAP.md Phase 9/11f). Checked now, by the same binds-port-v1 rule sim_run_pipeline applies: both ports exist with the right direction and element kind, the output is a token place, the input is not a delayed transition, the declared kinds are equal, port.unit agrees exactly where both ends declare one (a unit missing on either end is reported unchecked, never agreed), and a numeric transform is at most 1000000. Differing units bind only with a declared conversion, never inferred from the unit names ("order" and "orders" are two units): pass convertFrom, convertTo and convertFactor together (1 convertFrom = convertFactor convertTo), checked by binds-port-v2 — both ports declare port.unit, the two differ, convertFrom and convertTo are exactly those units, the factor is between 1e-06 and 1000000, and the transform times the factor is at most 1000000; sim_run_pipeline multiplies the resampled rate by the transform and then by the factor. A binding without a conversion is checked by binds-port-v1 exactly as before and keeps its id. A delay (hours, in (0, 10000]) is checked by binds-port-v3 (v2 plus check 12: a finite number in range; 0 is no delay and keeps the binding's id): the target receives the source's flow that many hours later and runs on its own declared rate before then, and a loop between models runs only through a binding that declares one. A self-binding is refused, with or without a delay: a model driving its own input is a loop inside one net, built with sim_extend. Set-level checks (a loop with no delayed binding, two bindings into one input, the schedule-segment cap, a loop over 4 models) belong to sim_run_pipeline and sim_create_system; a binding that closes a loop with bindings already stored is not refused here, since a loop exists only in…
| Name | Type | Req | Description |
|---|---|---|---|
| convertFactor | number | – | how many convertTo one convertFrom is (1 convertFrom = convertFactor convertTo), between 1e-06 and 1000000; sim_run_pipeline multiplies the resampled rate by it, after any numeric transform |
| convertFrom | string | – | a declared unit conversion's source unit: exactly fromPort's port.unit. Pass convertFrom, convertTo and convertFactor together or none of them |
| convertTo | string | – | a declared unit conversion's target unit: exactly toPort's port.unit, which must differ from fromPort's |
| delay | number | – | hours after the source's flow that toPort receives it, in (0, 10000]; default unset, no delay. Before the delay ends toPort runs on its own declared rate. A loop between models runs only through a bi… |
| fromModel | string | yes | id of the model supplying the connection's output |
| fromPort | string | yes | element id of the declared output port on fromModel: a token place tagged port.output (see GET /api/models/{id}/ports) |
| toModel | string | yes | id of the model receiving the connection |
| toPort | string | yes | element id of the declared input port on toModel: a rated transition tagged port.input |
| transform | string | – | how fromPort's value becomes toPort's. A plain non-negative number is applied by sim_run_pipeline as a scale factor on the resampled rate; it scales, never converts a unit. Any other text (a unit not… |
No output schema declared.
No examples provided.
sim_calibrate ~457
Calibrate a model against YOUR event log — the reading that meets reality. Upload CSV (case_id, activity, timestamp; the shape sim_dataset emits, activities = transition ids), and rates are learned from the observed timings: sources from inter-arrival times, services from the gap before their completions, all per hour. Instant-pickup transitions (declared rate >= 100) keep their declared rate — their observed gap is the queue wait, and learning it would destroy the calibration discipline. A transition declaring a delay (a fixed-duration timer, not a rate) is fit differently and returned in learnedDelays instead of learnedRates: the MEDIAN observed gap, in hours, written onto the transition itself since a delay has no solver-map slot — a gapCV in rateEvidence far from 0 means the log looks exponential, not fixed, and the calibration says so in a caveat rather than trusting the median anyway. Returns a NEW content-addressed model (learned rates in the solver map, learned delays on the transitions, declared values otherwise untouched, lineage recorded) plus a conformance report: fittingPercent (full replays) is the headline, worst traces named with the activities that could not fire. tokenFitness is a second, harsher reading of the same replay (raw tokens present vs. required at every step, not full-trace success) that under-reads any net with a resource pool — read fittingPercent, not tokenFitness, unless you specifically want the raw-token number. Every learned rate or delay has an entry in rateEvidence: n (gaps it rests on), gapCV (sample std dev over mean of those gaps; ~1 for exponential timings, near 0 for a true timer) and insufficient when n < 2 — n=0 yields nothing, n=1 a value with no spread. Learned values on a structure that cannot replay the traces would be numerology — read fittingPercent before trusting them. Costs 3 tokens from your account's compute bucket (a replay of the log, 2, and the stored model, 1).
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id to calibrate |
| log | string | yes | the event log, as CSV text |
No output schema declared.
No examples provided.
sim_canonical ~310
Tell whether two differently-labelled models are actually the same net: an isomorphism-invariant id computed from the model's EXACT automorphism orbits (orbits.go), not the colour-refinement (WL) kind sim_classify falls back to when the exact search can't decide. Two models differing only by renaming places or transitions share the same canonicalId even though their content-addressed ids (from sim_get_model) differ — this is the id to compare, not the model id, when checking whether a catalog already holds this net. Also returns the non-trivial automorphism orbits and generator count the id was computed from: zero generators means the net is rigid (no symmetry at all), which is itself a fact about the net's structure. Refuses (as a tool error) when the exact search would spend more than its 1,000,000-step budget (refinement steps, about half a second) — too large or too symmetric for this implementation, per orbits.go — rather than silently falling back to a weaker answer; sim_classify's own fallback covers that case for classification specifically. Costs 1 compute token (one search), as GET /api/models/{id}/canonical does. Equal canonical ids mean the same net under the comparison sim_prove uses for isomorphicTo; to get the place/transition bijection and record it as a witnessed edge, call sim_prove(subject, "isomorphicTo", object).
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id |
No output schema declared.
No examples provided.
sim_check_witness ~912
Re-check a stored structural witness against both stored models with the independent checker (pkg/morphism), which does no search. Given a structural edge's id, checks every witness of that edge; an edge with none answers unwitnessed (unproven, not disproved). Verdicts: valid, invalid (the map is not a morphism of the stored models), or uncheckable (a model was deleted, a net is malformed, or the predicate is now checked under a newer definition). Public: no sign-in. A witness or edge id is free (no compute tokens). With derivation (from sim_query): re-checks every step's witness, the chain, the composed map's digest and the composed map against both end models, and answers {verdict, reason, hops} (the body POST /api/derivation/check returns); a derivation naming a definition other than the predicate's current one is uncheckable; costs 1 compute token. With reach (a sim_reach answer): replays a trace through metamodel.Enabled/Fire and the guards, or re-checks an invariant witness against the stored model, answering {verdict, reason}; from and to are held to the scenario caps (1,000,000 per place, 4,000,000 in total), and a replay is priced before its first firing and is uncheckable over 200,000,000 work units; an exhaustive no is uncheckable (re-run sim_reach); an unknown answer is refused; costs 1 compute token (POST /api/reach/check). With reach on a system's answer, via is re-checked whole with it: the system is stored and holds the net, every other model has exactly one embedding, each embedding's witness or derivation re-checks valid now, and any translation of component places follows them. With reachResult (the result id sim_reach returns): re-checks a stored answer end to end — the record (its bytes hash to its id, its stored question asks what the answer answers under the budgets it records, and over names what it rests on), via as above, and the witness — answering {verdict, reason, parts, answer, currency}; an unknown answer stays unknown (its witness pa…
| Name | Type | Req | Description |
|---|---|---|---|
| derivation | string | – | a sim_query derivation as a JSON string: {"predicate", "definition", "subject", "object", "steps": [{"edge", "witness", "inverse"}], "composed"} |
| id | string | – | a witness id, or a structural edge's relation id |
| reach | string | – | a sim_reach answer as a JSON string: the object exactly as returned, serialized |
| reachResult | string | – | the content id of a stored sim_reach answer (sim_reach's result) |
| refutation | string | – | a refuted sim_prove answer's refutation as a JSON string: the object exactly as returned, serialized ({"predicate", "subject", "object", "counterexample"}) |
No output schema declared.
No examples provided.
sim_classify ~252
Discover the parameter classes of a stored model and return them as JSON-LD with empty annotation slots for you to fill in (label, comment, unit, domain, substitutes — nothing else; membership/kind/evidence are derived and settled by measurement, not yours to edit). With verify=true a shared colour is checked by exact automorphism proof where the search can decide it (settling interchangeability outright, the stronger claim), falling back to the sampled permutation experiment only where it can't — the exact search refuses past its 1,000,000 refinement-step budget on nets too large or too symmetric for it. Read the sim://docs/classification resource once for the colour-refinement caveat and the annotation contract in full.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id |
| inline_context | boolean | – | embed the full JSON-LD @context map in the result instead of the URL it is served from (https://sim.pflow.xyz/ns/v1/context). Default false: the URL resolves to the identical map, so only set this fo… |
| verify | boolean | – | run the permutation experiment (costs simulation; default false, and classes then say they are candidates) |
No output schema declared.
No examples provided.
sim_code_to_flow ~179
Derive a Petri-net model from source code with the configured LLM (control flow, state machine, resources or concurrency focus), validate it, and store it as a NEW model you own. Runs generator.CodeToFlow directly — this tool is its only surface on sim.pflow.xyz, which mounts no code-to-flow HTTP endpoint; refused when this deployment has no LLM provider configured. Returns the new id when the answer validates, otherwise the raw model JSON and the validation errors so you can fix and sim_create_model it by hand.
| Name | Type | Req | Description |
|---|---|---|---|
| code | string | yes | source code to analyse |
| focus | string | – | control-flow (default), state-machine, resources or concurrency |
| language | string | – | source language hint, e.g. go, python, javascript |
| name | string | – | name for the derived model |
No output schema declared.
No examples provided.
sim_compare ~347
Run several scenarios against one model on one shared seed and return them side by side — the seed sharing is server-enforced, so differences are the scenarios, not the dice. Returns a summary by default (finals, throughput/mean/P95 metrics, contention, depletion — no time series); pass full=true for the complete trajectories, which run to hundreds of KB. A scenario carrying "summary": true stays summarized even under full=true, so one comparison can chart some scenarios and only read the rest. Unset hours default to 8, samples to 60 (the trajectory grid, which only matters under full=true — metrics are time-weighted and do not depend on it) and realizations to 16 per scenario. Each scenario can set its own "engine" (see sim_scenario / docs/engine-selection.md); comparing an "ode" run against an "ssa" one is legitimate but the shared seed only removes dice from scenarios using the same engine. Costs 1 token per scenario from the compute bucket (per address, or per account when signed in).
| Name | Type | Req | Description |
|---|---|---|---|
| full | boolean | – | include the sample-grid time series in every result (large; default false); a scenario with its own "summary": true is left summarized regardless |
| id | string | yes | model id |
| scenarios | string | yes | JSON array of at most 20 scenarios, each with a name, e.g. [{"name":"today","hours":8},{"name":"one more","hours":8,"marking":{"staff/available":3}},{"name":"bigger batches","hours":8,"params":{"batc… |
No output schema declared.
No examples provided.
sim_components ~87
List the component registry: pre-baked subnet templates (arrivals, service, hazard, inventory, decision, mailbox, datastore) with the calibration discipline baked into the arcs and rates. Each entry names its ports (places you can attach onto existing places), its params with recommended defaults, and the discipline notes explaining WHY the template is shaped the way it is. Compose them with sim_compose.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
sim_compose ~245
Instantiate a registry component into a model and store the result as a NEW content-addressed model you own (lineage recorded when composing onto an existing id). Omit id to start a model from the component alone; pass attach to fuse a component port onto one of the model's existing places (e.g. attach {"queue": "tickets_queue"} wires a hazard onto the service's queue). Prefix namespaces the created elements (defaults to the component name). Three calls build a working helpdesk: arrivals, then service attached to its queue, then hazard attached to the same queue — the result passes diagnose because the discipline is in the template.
| Name | Type | Req | Description |
|---|---|---|---|
| attach | string | – | JSON object mapping port name -> existing place id |
| component | string | yes | registry component name (see sim_components) |
| id | string | – | model to compose onto; omit to start fresh |
| name | string | – | model name for the stored result (kept from the base when composing onto an id) |
| params | string | – | JSON object overriding param defaults, e.g. {"staff": 3} |
| prefix | string | – | instance prefix for created elements (default: component name) |
No output schema declared.
No examples provided.
sim_conformance ~186
Check how well a stored model matches an observed event log WITHOUT rewriting its rates — the read sim_calibrate bundles into calibration, offered on its own and in full: fitness (can the model replay each case?), precision (does it allow behaviour never observed?), generalization and simplicity, with per-trace diagnostics naming the activities that could not fire. Log is CSV (case_id, activity, timestamp; the shape sim_dataset emits, activities = transition ids). The log is replayed one case at a time from the model's initial marking, so the model should be the per-case workflow; a resource net whose places are shared across cases will not fit. Caveats name what the analysable net encoded lossily. Costs 2 tokens from your account's compute bucket.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id |
| log | string | yes | the event log, as CSV text |
No output schema declared.
No examples provided.
sim_conformance_stream ~435
Online conformance: replay an ORDERED event stream against a stored model and get a running verdict — does the model still match, or which event was the first that did not, and why. Unlike sim_conformance (whole finished cases, aggregate fitness) the order of events IS the stream's order, cases may interleave, and the answer names the first non-conforming event: its position, case, activity, whether the activity is unknown to the model or the transition was not enabled, the places that blocked it (need vs have), the case's marking just before it, and `repair` — the shortest unobserved transitions that would have enabled it (a local alignment of that one step, bounded; absent when none is found within repairDepth). This is token replay, not trace alignment. A divergent event is force-fired so the case resynchronises and later events are judged on their own. fitness is conforming events / events; tokenFitness is 1 - missing/consumed tokens. Give the stream as `events` (JSON array of {case, activity, timestamp?}) or `log` (CSV with a case_id, activity header, timestamp optional; rows are taken in the order given, not sorted). Activities are transition ids. Each case replays from the model's initial marking, so the model should be the per-case workflow; guard expressions are not evaluated and timestamps are not checked against delays (caveats says so). keepSteps adds the per-event running signal. Costs 2 tokens from your account's compute bucket.
| Name | Type | Req | Description |
|---|---|---|---|
| events | string | – | JSON array of {"case": ..., "activity": ..., "timestamp": ...} in stream order |
| id | string | yes | model id |
| keepSteps | boolean | – | include the per-event running fitness (one entry per event) |
| log | string | – | the stream as CSV text (case_id, activity[, timestamp]) in stream order; used when events is not given |
| repairDepth | number | – | most unobserved transitions a repair may use (default 4; negative turns repair off) |
No output schema declared.
No examples provided.
sim_create_collection ~256
Mint a named Collection you own and return its content id. A collection carries no member list of its own — a mutable list would change the collection's own id every time something joined it, the same reason Lineage lives beside a model rather than inside it. Add members with sim_link(collectionID, "hasMember", memberID) — members must be stored entities — and read them back with sim_neighbors(collectionID, "hasMember") or sim_edges(collectionID). Only you, the owner, may add members: hasMember's write rule is subject-owner (https://sim.pflow.xyz/ns/predicates/v1), so sim_link refuses anyone else, naming the rule. The name and your account together are the content id: creating a collection with a name you already used returns your existing id, and another account's collection with the same name is a different collection. A collection created before collections had owners has none, so its membership is frozen as it stands (still readable); create your own to add to. Members cannot be removed: an edge, once written, is immutable. Needs sign-in with write scope (opens OAuth the first time); costs 1 compute token.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | collection name |
No output schema declared.
No examples provided.
sim_create_model ~136
Store a Petri-net model (JSON with name/places/transitions/arcs) and return its content id. Models are immutable; a changed model is a new id. Structural validation rejects malformed nets with every reason at once. The model is yours: it appears only in your own listing until you dedicate it to the commons with sim_license_model, and you can remove it with sim_delete_model. Anyone you give the id to can use it either way. Needs sign-in (opens OAuth the first time); anonymous callers can POST /api/models over HTTP instead, stored unowned.
| Name | Type | Req | Description |
|---|---|---|---|
| model | string | yes | the model JSON |
No output schema declared.
No examples provided.
sim_create_system ~912
Define a System (ROADMAP.md Phase 11f): a content-addressed, stored set of models and the bindings between them, so the catalog can answer questions about them together. Pass collection (snapshot its model and binding members now; other members are listed under skipped, and a grown collection is a new system, the old id still readable) or models and bindings (JSON arrays of ids), not both. Every binding's endpoints join the models (listed under implied); every binding must pass the check sim_bind applies now (binds-port-v1, or binds-port-v2 for one that declares a unit conversion, or binds-port-v3 for one that declares a delay, and the system then records bindingCheck binds-port-v2 or binds-port-v3, v3 first; a legacy binding sim_bind would refuse today is refused here) and the set must close no loop without a delayed binding, take each input port once, fit the schedule-segment cap and hold no loop over the model limit — the checks sim_run_pipeline applies before it knows the hours. At most 64 models and 64 bindings, and a snapshotted collection of at most 256 members. The id is the hash of the sorted lists, the name and the snapshotted collection (if any), so the same call gives the same id; a snapshot and an explicit list of the same ids are different systems. Returns the id and the view sim_system computes (checks, the structural edges among the models with up to 128 witnesses re-checked now, and the shape: one-net, pipeline, separate or unknown). This is not refines: a system's edges are isomorphicTo and subnetOf (embeds by wiring / is the same coloured net). refines (trace inclusion with transitions matched by id) and preservesInvariant (the object's P-invariants pull back along an embedding) are proved one pair at a time by sim_prove and are never walked by closure, since neither is declared transitive. For "what contains this pattern?" ask sim_query with closure: {"select":["?m"],"where":[{"subject":"<pattern id>","predicate":"subnetOf","object":"?m","mode":…
| Name | Type | Req | Description |
|---|---|---|---|
| bindings | string | – | JSON array of binding ids sim_bind returned; their models are included automatically |
| collection | string | – | a collection id whose model and binding members to snapshot (instead of models/bindings); at most 256 members; part of the id |
| models | string | – | JSON array of model ids, e.g. ["id1","id2"] |
| name | string | – | a name for the system (at most 256 bytes); part of its id |
No output schema declared.
No examples provided.
sim_crosscheck ~191
Run every applicable READING of a model against the others and report agreement or divergence with the reason: discrete SSA means vs the continuous mean-field solve, algebraically derived conservation laws vs simulated means, and (for game-schema models) the closed-form incidence ranking vs rollouts vs exact search. Divergence is a finding, not an error — small-count mean-field gaps and the prior's threat-blindness are named as such. Trust is agreement between independent readings of one structure. Gated nets (read arc, inhibitor, reached capacity, guard) have no ODE reading to compare against at all — see docs/engine-selection.md for the four-rule decision behind which readings even apply.
| Name | Type | Req | Description |
|---|---|---|---|
| hours | number | – | horizon (default 8, max 168) |
| id | string | yes | model id |
| realizations | number | – | SSA runs averaged, max 200 (default 24) |
No output schema declared.
No examples provided.
sim_dataset ~89
Generate a synthetic event log from a stored model (seeded SSA playout; case-per-arrival). Returns CSV. Deterministic: same id, same seed, same bytes.
| Name | Type | Req | Description |
|---|---|---|---|
| cases | number | – | cases to generate (default 200, max 2000 over MCP) |
| id | string | yes | model id |
| seed | number | – | PRNG seed (default 1) |
No output schema declared.
No examples provided.
sim_delete_model ~55
Delete a model you created. Refused for the curated catalog, for models you do not own, and for models already dedicated to the commons (a dedication is irrevocable).
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id to delete |
No output schema declared.
No examples provided.
sim_diagnose ~422
Returns what one more of each resource (and a change in each rate) is worth to the outcome, each ranked against a measured noise floor — no fitness test to write. Also reports generic gates (mass balance, dormant sources, staffing knee, whether any knob binds), the parameter classes among the controls, and four structural readings needing no run (T-invariants, siphons/traps with deadlock witnesses, CTMC lumpability, constrained lumping). Pure read. Loss/success inference and objective framing can be corrected by tagging places or declaring simulation.objective — read the sim://docs/classification resource once for how to read influence and noise, the structural readings, and the corrections.
| Name | Type | Req | Description |
|---|---|---|---|
| hours | number | – | horizon per run (default 8, max 168) |
| id | string | yes | model id |
| inline_context | boolean | – | embed the full JSON-LD @context map in the result instead of the URL it is served from (https://sim.pflow.xyz/ns/v1/context). Default false: the URL resolves to the identical map, so only set this fo… |
| maxRealizations | number | – | bounds how far the adaptive default may escalate (default 200, the same ceiling an explicit realizations refuses above). Ignored once realizations is set. For a caller with its own latency budget, no… |
| realizations | number | – | runs averaged per measurement, max 200. Leave unset and the default ADAPTS: a 24-realization pilot that doubles while the baseline outcome sits inside its own noise floor, up to 200 (or maxRealizatio… |
| seed | number | – | seed shared by every run, so differences measure the knob and not the dice (default 7) |
No output schema declared.
No examples provided.
sim_diff ~92
Structural difference between two stored models: places, transitions and arcs added or removed, and surviving elements whose numbers changed (initial, capacity, rate, stages, arc weight or kind). The readout for what a builder turn, a sim_extend or a sim_refine actually changed between two ids in a lineage.
| Name | Type | Req | Description |
|---|---|---|---|
| a | string | yes | model id (before) |
| b | string | yes | model id (after) |
No output schema declared.
No examples provided.
sim_distill ~425
Distill exact search into the play scorer: fit rate multipliers for named transition groups so play's rankings agree with exact minimax, on positions sampled by random self-play and labeled by search. This is TACTICAL calibration — the counterpart of sim_calibrate, which learns rates from an event log. The division of labor is deliberate (petri-pilot experiments/ode-minimax): structure carries the tactic, and no fitting of an unmodified net's rates can express what its final state cannot separate — declare the structural prior as transitions in the model (e.g. forced-reply copies of the plays, catalyzed by the opponent's pattern) and distill the magnitudes it introduced. Zero agreement improvement is a finding about the structure, not a failed fit. Read agreementBefore/agreementAfter, not the loss: the hinge loss can overstate failure while every argmax is right. At most 16 groups, each non-empty, and no transition in two groups; the estimated work (loss evaluations × candidate moves × realizations × horizon) must stay under a fixed cap, and an over-cap request is refused with the estimate. Costs 5 tokens from your account's compute bucket at the defaults, scaled by that work estimate (rounded up).
| Name | Type | Req | Description |
|---|---|---|---|
| groups | string | yes | JSON object: group name -> transition ids sharing one fitted multiplier, e.g. {"detectors":["x_win_0","o_win_0"],"draw":["call_draw"]} |
| id | string | yes | model id (needs simulation.objective, players with turnPlace) |
| options | string | – | JSON: {"games":20,"positions":40,"iters":40,"horizon":3,"realizations":40,"seed":11,"engine":""} (the defaults shown; 0 or unset takes the default). Caps: games at most 100, positions at most 100, it… |
No output schema declared.
No examples provided.
sim_edges ~200
List every relation touching an entity, as either subject or object. Answered from an index by subject and object; each call re-lists the store so edges written by other instances are seen. Legacy edges whose predicate predates the registry are included with axis "unregistered". Structural edges (isomorphicTo, subnetOf, preservesInvariant, refines) list the witnesses that prove them; one listing none is marked unwitnessed and proves nothing. An isomorphicTo edge is the same net up to renaming, not the same behaviour: its definition (coloured-net-v1) does not compare guards, stages, schedules, constraints, objectives or non-refine tags such as outcome — read the witness (GET /api/lineage/{witnessId}, whose notCompared lists what that pair carries; sim_check_witness re-checks it) before treating two models as behaving alike.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | entity id to look up |
No output schema declared.
No examples provided.
sim_evaluate ~241
Score a player's legal next moves with the PLAY method (the blog post's move picker): apply each candidate hypothetically and score the expected objective of the position it leads to, by seeded SSA rollouts (seed 11, shared across candidates so a difference measures the move, not the dice) — the best move scores highest. Needs the game schema (simulation.objective + simulation.players). The response names the engine. This tool always uses play on SSA: next-move elimination (rate-zero ablation, which reads an ungated net through the continuous ODE relaxation), the closed-form incidence reduction and exact search are the HTTP evaluate endpoint's method option (eliminate | incidence | search), not selectable here.
| Name | Type | Req | Description |
|---|---|---|---|
| horizon | number | – | model time to explore ahead (default 3, max 10000) |
| id | string | yes | model id |
| marking | string | – | JSON object, sparse marking override (the position to evaluate from); default = the initial marking |
| player | string | yes | player name from simulation.players |
| realizations | number | – | SSA rollouts per candidate move (default 40, max 200) |
No output schema declared.
No examples provided.
sim_extend ~200
Apply structural edits to a stored model and store the result as a NEW model you own, with lineage back to the original — the same vocabulary the guided builder uses behind its interview, now callable directly. Operations (JSON array, each with "op"): add_place {id, initial}, add_transition {id, guard, event}, add_arc {from, to, weight, kinetic, type}, remove_place, remove_transition, remove_arc {from, to}, set_rate {id, rate}, set_initial {id, initial}, set_capacity {id, capacity}. The edited model is validated before it is stored; a set of operations that leaves the net malformed is refused with every reason, and nothing is written. Returns the new id, the operations applied, and the structural diff.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id to edit |
| name | string | – | optional name for the edited model |
| operations | string | yes | JSON array of operations |
No output schema declared.
No examples provided.
sim_get_binding ~120
Fetch a stored Binding by id, with its check computed now (binds-port-v1; binds-port-v2 for a binding that declares a unit conversion, which is returned as convert; binds-port-v3 for one that declares a delay, returned as delay in hours): ok (with the unit verdict: agree, converted or unchecked), refused (a binding recorded before the check that sim_bind and sim_run_pipeline would refuse today, flagged legacy) or uncheckable (a model it names was deleted).
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | binding id |
No output schema declared.
No examples provided.
sim_get_model ~34
Fetch a stored model's full Petri-net JSON by id.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id (content hash) |
No output schema declared.
No examples provided.
sim_invariants ~162
Derive a model's full algebraic invariant structure: conservation laws (Farkas P-invariants — weighted place sums every run preserves, the arithmetic a trust panel should show), firing cycles (T-invariants, named per-cycle with a readable detail sentence, each tagged StructuralProof), and the siphon/trap report (every minimal siphon and trap found from the arc structure, plus deadlock witnesses — minimal siphons holding no tokens at this model's own initial marking, which proves every transition needing one permanently disabled). This is the same computation sim_diagnose's structural fields read from, not a lesser copy of it. Pure structure, no simulation; every claim holds for every trajectory from this initial marking.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id |
No output schema declared.
No examples provided.
sim_license_model ~158
Dedicate a model you created to the commons under CC0-1.0, CC-BY-4.0, CC-BY-SA-4.0. It then appears in every user's listing with the license shown, and the dedication is IRREVOCABLE — it cannot be changed or deleted afterwards, which is what makes it safe for others to build on. CC0-1.0 is the cleanest choice for a model: attribution terms are hard to honor for a net someone folds into a larger one.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id to dedicate |
| license | string | yes | one of CC0-1.0, CC-BY-4.0, CC-BY-SA-4.0 |
No output schema declared.
No examples provided.
sim_link ~557
Record a typed edge between two stored entities (models, prompts, artifacts, maps, collections, bindings, relations — not witnesses), using a registered predicate. sim_link writes these (subject → object): @type (model → a https://sim.pflow.xyz/ns/models/v1 type name); about (artifact/prompt/map/collection → model/collection/binding/system); broader (model/collection/system → model/collection/system); cites (any entity → any entity); closeMatch (model → model); hasMember (collection → any entity); related (model/collection/system → model/collection/system). from, to and feeds are recorded only by sim_bind, produced only by sim_prompt/sim_reroll, supersededBy only by sim_supersede_model, migratedFrom only by sim_accept_migration; narrower is broader read backwards and is never stored; structural predicates (isomorphicTo, subnetOf, preservesInvariant, refines) are recorded only by sim_prove, together with the witness that proves them. Each is refused here, naming the tool that records it (or the reversed call, for narrower). Subject and object must be stored entities of the kinds the predicate relates, passed by content id (for @type, the object is a /ns/models/v1 type name). Full definitions at https://sim.pflow.xyz/ns/predicates/v1. Distinct from the Lineage a model/prompt/artifact already carries, which is specifically derivation (parent -> prompt -> child). Who may write an edge is its predicate's write rule (writeRule in the registry): hasMember is subject-owner — only the collection's owner (who created it with sim_create_collection) adds members, and a collection created before collections had owners takes no new ones; every other predicate sim_link writes is any-signed-in, an assertion attributed to you. A refusal names the rule. Edges are immutable and are never retracted. Linking the same subject/predicate/object again as the same user — either direction for a symmetric predicate — is idempotent: it returns the existing relation's id (existing: true) rather…
| Name | Type | Req | Description |
|---|---|---|---|
| object | string | yes | content id of the stored entity the edge points to; for @type, a type name from https://sim.pflow.xyz/ns/models/v1 |
| predicate | string | yes | one of @type, about, broader, cites, closeMatch, hasMember, related |
| subject | string | yes | content id of the stored entity the edge starts from |
No output schema declared.
No examples provided.
sim_list_bindings ~19
List the content id of every stored Binding.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
sim_list_models ~71
List the models visible to you: the curated catalog, models dedicated to the commons (their entry carries the license), and your own (marked mine). Other users' undedicated models are not listed, but any model id works with every sim_* tool — an id someone shares with you is the model.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
sim_map_get ~30
Fetch a stored Map's key->value data by id.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | map id |
No output schema declared.
No examples provided.
sim_map_list ~18
List the content id of every stored Map.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
sim_map_put ~96
Store a key->value lookup table as its own content-addressed entity — a generated parameter sweep, a rate table, a component registry, anything shaped as key->value rather than free text (an artifact) or a Petri net (a model). Returns its content id; the same data, even with keys inserted in a different order, returns the same id.
| Name | Type | Req | Description |
|---|---|---|---|
| data | string | yes | the table as a JSON object |
No output schema declared.
No examples provided.
sim_migration_offers ~476
List what happens to the edges of a superseded model. Taxonomic edges (hasMember, @type, broader, related, closeMatch, cites, about) are OFFERED: each row gives the edge as it would read on the model's current successor (followed through its supersession chain), whether sim_link's checks pass for it now (passes, refused, or unchecked when the store could not answer), any earlier migrations of it, and the sim_accept_migration call that accepts it. Nothing moves automatically, the old edge stays, and this read writes nothing: offers are computed on read and never stored. Tool-written edges (from/to/feeds, produced, supersededBy), structural edges (isomorphicTo, subnetOf, preservesInvariant, refines) and legacy unregistered predicates STAY with the old model, each with its reason; a structural row names its witnesses and the sim_prove call that would make a new edge for the successor. Stored systems naming the model are listed under systems (sim_system {naming}'s answer, at most 100 rows): a System names exact ids, so supersession changes none of them, and systemsNote names the sim_create_system call with the successor. A chain that cycles, runs past 64 hops, ends at a deleted model or reaches a model now owned by someone else is reported as such, with no target. Accepting needs you to own the superseded model or to have authored the edge, and the edge it becomes must pass its predicate's write rule for you, as sim_link would (hasMember: you own the collection); youMayAccept says whether you may, per edge, and writeRule says why not when only the write rule refuses. 100 edges per page (pass next as after); predicate narrows to one stored predicate (narrower is refused: pass broader). Needs sign-in with read scope (opens OAuth the first time); anonymous over HTTP as GET /api/models/{id}/migrations, with no youMayAccept. Costs 1 compute token per call.
| Name | Type | Req | Description |
|---|---|---|---|
| after | string | – | the next value a previous call returned, for the following page |
| model | string | yes | content id of the superseded model |
| predicate | string | – | read only this predicate's edges |
No output schema declared.
No examples provided.
sim_my_sheets ~22
List the sheets this user has published, with their URLs.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
sim_neighbors ~298
One-hop traversal from an entity, read through the predicate registry. With no predicate: the object of every relation where the entity is the subject. With a predicate: the entities one hop along it — for an inverse name that is never stored (narrower) the stored predicate is read backwards (the subjects of the broader edges pointing at the entity), and for a symmetric one (related, closeMatch) both directions count, since an edge recorded from the other end says the same thing. A legacy free-form predicate still answers from its stored edges; a name that is neither registered nor used by any stored edge is refused. Pass a collection's id with predicate hasMember to list its members. A structural neighbour (isomorphicTo, subnetOf, preservesInvariant, refines) is a bare id here: sim_edges lists the edge's witnesses, and isomorphicTo does not compare guards, objectives or outcome tags. Ordered by timestamp, then relation id: tool-recorded edges (from/to/feeds, supersededBy, and edges carried forward by sim_accept_migration, unless it reused one you had already linked) carry no timestamp, come first and are in no particular order among themselves, so the last supersededBy neighbor is not necessarily the current successor. Not de-duplicated.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | subject id to traverse from |
| predicate | string | – | restrict to this predicate; omit for every outgoing relation |
No output schema declared.
No examples provided.
sim_optimize ~255
Multi-objective optimisation over transition rates for a stored model: Monte Carlo samples the rate ranges, runs each combination to the horizon with the continuous engine, and returns every sample with a Pareto flag — the non-dominated set is the trade-off frontier ('which staffing is non-dominated on served vs walked out'). Continuous reading: a model with a schedule or a gate is refused with the reason (use sim_compare with explicit scenarios for those). Costs 1 token per 50 samples (rounded up) from your account's compute bucket; rate ranges must be non-negative.
| Name | Type | Req | Description |
|---|---|---|---|
| hours | number | – | horizon per run (default 8, above 0 and at most 10000) |
| id | string | yes | model id |
| objectives | string | yes | JSON array of {"place": id, "direction": "max"|"min"} |
| parameters | string | yes | JSON object transition_id → [min, max] rate range, e.g. {"finish_brew": [10, 40]} |
| samples | number | – | Monte Carlo samples (default 100, 1..1000; outside that is refused) |
| seed | number | – | sampling seed, a whole number (default 42) |
No output schema declared.
No examples provided.
sim_param_heatmap ~259
Two-rate grid for a stored model: vary two transition rates over ranges, run each combination to the horizon with the continuous engine, and return the observable's final value as a grid — 'which regime of arrivals × restock keeps the queue empty'. Continuous reading: a model with a schedule or a gate is refused with the reason. Costs 1 token per 50 grid cells (rounded up; a 40x40 grid empties the bucket) from your account's compute bucket.
| Name | Type | Req | Description |
|---|---|---|---|
| hours | number | – | horizon per run (default 8, above 0 and at most 10000) |
| id | string | yes | model id |
| log_scale | boolean | – | space the grid in log10 (default false) |
| observable | string | yes | place id whose final value fills the grid |
| param_x | string | yes | first transition id |
| param_y | string | yes | second transition id |
| range_x | string | yes | JSON [start, stop, n] for param_x: non-negative rates, n a whole number 2..40 |
| range_y | string | yes | JSON [start, stop, n] for param_y: non-negative rates, n a whole number 2..40 |
No output schema declared.
No examples provided.
sim_prompt ~316
Ask an LLM to derive something from a stored entity: a variant model, a report, a piece of generated code — whatever the prompt asks for. The parent's JSON rides along as context, the same way the guided builder gives its interviewer the draft. The parent is looked up as a model first, then a prompt, then an artifact, then a map — whichever resolves — and the context block is labelled by what kind it found ("## Parent model", "## Parent prompt", ...), so the LLM is never told a report is a Petri net. The prompt is stored first and content-addressed like a model, so it has an id of its own before the LLM ever answers; both the prompt and whatever came back are placed in lineage under the parent (sim_prompt as the activity), so Ancestry walks parent -> prompt -> result. A Relation{prompt, "produced", result} is recorded alongside — sim_reroll's forward index, and queryable directly via sim_edges/sim_neighbors. If the response parses and validates as a Petri-net model it is stored as a NEW model you own; otherwise the raw text is stored as an artifact. Refused if this deployment has no LLM provider configured.
| Name | Type | Req | Description |
|---|---|---|---|
| parent | string | yes | id to run the prompt against — a model, prompt, artifact, or map |
| system | string | – | optional system-level instructions, in addition to the parent context this tool always supplies |
| text | string | yes | the natural-language instruction |
No output schema declared.
No examples provided.
sim_propose_types ~335
Propose candidate @type values for one or more stored models, e.g. "QueueingSystem" or "ResourcePool", from a small Diagnose run this tool performs on each model (nothing is cached or reused between calls). Every rule is a hand-written assumption about what a shape of knobs/loss/siphons/classes tends to mean, not a structural proof or a measurement, so results are ASSUMPTION-grade until a human reviews one and applies it — apply with sim_link(id, "@type", "<Type>"), there is no separate apply tool. Pure read; nothing here is written to any model. Defaults to scanning the visible catalog (up to limit) when ids is omitted. Costs one Diagnose run per model — 5 tokens each from the compute bucket (per address, or per account when signed in), charged as each model is reached — so limit and realizations are both capped.
| Name | Type | Req | Description |
|---|---|---|---|
| ids | string | – | JSON array of model ids to consider, e.g. ["id1","id2"]. Omit to scan every model ListFor("") would list (the public catalog), truncated to limit. |
| limit | number | – | maximum number of models to diagnose (default 10, 1..25; over 25 is refused, and so are explicit ids naming more models than limit) — a cost control, since this runs a simulation per model |
| realizations | number | – | realizations per model's Diagnose run (default 8, 1..16; outside that is refused) — deliberately small, this only needs to name a shape, not measure precise influence |
No output schema declared.
No examples provided.
sim_prove ~1,186
Prove a structural relation between two stored models and record it with its witness. isomorphicTo: an exact canonical-labelling search (the one behind sim_canonical, seeded with exactly what the check compares) finds a place/transition bijection preserving arcs (direction, type, weight, kinetic), place sort, initial marking, capacity, rate or delay and refine.* tags. It does not compare guards, stages, schedules, constraints, non-refine tags (outcome, port.*), data-place types and initial values, objectives, players or asserted classes; those the pair carries are listed as notCompared, so proved is not 'behaves the same'. subnetOf: a bounded embedding search finds an injective, sort-preserving map (token places to token places, data places to data places, transitions to transitions) of the subject's places and transitions into the object's whose arcs among the image are exactly the subject's (initial markings, capacities, rates, delays and tags are not compared). preservesInvariant (invariant-pullback-v1): an induced embedding as subnetOf's along which every P-invariant of the object pulls back to a P-invariant of the subject (the incidence the shared firing rule implies: consuming and producing arcs on token places). Proved carries the map and a cover — per subject transition, rational coefficients of object transitions with the same incidence — which proves it for every invariant at once, plus invariantDimension (0 means vacuous: the object conserves nothing). Embeddings are tried one image at a time (embeddings onto one image differ by a symmetry of the subject, which keeps or breaks the pullback with them), at most 16 images. refines (id-simulation-v1): every firing sequence of the subject from its initial marking, transitions the object has no transition of (by id) dropped as silent, is one of the object from its own; untimed, guards and fixed delays refused (unknown: a delay is a timer whose in-flight markings an atomic step skips), rates not compared, at le…
| Name | Type | Req | Description |
|---|---|---|---|
| object | string | yes | content id of the stored model the edge points to |
| predicate | string | yes | isomorphicTo, subnetOf, preservesInvariant or refines |
| record | boolean | – | when proved, store the witness and then the edge; false answers without writing (default true) |
| subject | string | yes | content id of the stored model the edge starts from |
| via | string | – | promote a fact sim_query derived instead of searching (JSON, as a string or an object): {"derivation": <a row's support[].derivation>} or {"result": "<sim_query result id>", "row": n, "support": k} (… |
No output schema declared.
No examples provided.
sim_publish ~126
Publish a stored model into the signed-in user's Google Sheets: the model workbook (live formulas when honest, a refusal tab when not), a server-run scenario as data tabs, and trajectory + contention charts. Returns the sheet URL. Counts against the daily quota, and costs 1 token from your account's compute bucket for the run.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id |
| scenario | string | – | optional scenario JSON to run for the data tabs; sim_scenario's defaults (hours 8, realizations 16, seed 20260809) fill whatever is omitted |
No output schema declared.
No examples provided.
sim_publish_app ~356
Publish the generated application for a model you own — the single-file HTML a generator produced from the model's `view` prompt. Served at /app/<id> in a sandboxed opaque origin (no cookies, no session; only the CORS-open public API is reachable). START FROM THE RUNTIME, not from scratch: /lib/app-template.html is a working console that imports /lib/sim-console.js and composes <sim-controls>, <sim-disruptions>, <sim-net>, <sim-timeline>, <sim-trajectory> and <sim-results> — the same components the generic console at /whatif/ runs. Composing them is how an app inherits role derivation, the fungible-set collapse, the influence ranking that never filters, the contention ledger and the verbatim caveats, none of which the checks below can verify you reimplemented correctly. Root-relative /lib/ imports are allowed. Off-origin loading is stopped in two places: the upload checks refuse an off-origin <script src> or <link href>, and the app is served under a Content-Security-Policy that confines scripts, styles, fetches, images and fonts to this origin — which is what stops the forms the checks do not parse (an inline module's import "https://…", a dynamic import(), a CSS @import). Checks refuse an app that is empty, oversized, never references its model id, or carries an off-origin <script src>/<link href>; behavioral correctness (does the app actually do what the view says) is on the generator and any browser gate you run.
| Name | Type | Req | Description |
|---|---|---|---|
| html | string | yes | the complete self-contained HTML document |
| id | string | yes | model id the app presents |
No output schema declared.
No examples provided.
sim_publish_compare ~198
Publish a multi-scenario comparison into the signed-in user's Google Sheets — sim_compare's export, the counterpart of sim_publish for a single scenario. Runs every scenario on one shared seed (the same server-enforced sharing sim_compare uses, so differences are the scenarios and not the dice) and writes a comparison table plus a trajectory chart, rather than one scenario's own data tabs. Returns the sheet URL. Counts against the same daily publish quota as sim_publish, and costs 1 token per scenario from your account's compute bucket.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id |
| scenarios | string | yes | JSON array of scenarios, each with a name, e.g. [{"name":"today","hours":8},{"name":"one more","hours":8,"marking":{"staff/available":3}}]; sim_compare's defaults (hours 8 and realizations 16 per sce… |
No output schema declared.
No examples provided.
sim_query ~783
Answer a question over the edge graph between stored models: bounded paths, closure over transitive predicates, and conjunctive patterns of up to 4 triples joined on shared ?variables. The query argument is JSON: {"select": ["?m"], "where": [{"subject": "?m", "predicate": "subnetOf", "object": "<content id>", "mode": "closure"}, {"subject": "?m", "predicate": "@type", "object": "QueueingSystem"}]}; a term starting with ? is a variable, anything else a constant (a 24-hex content id, or for @type's object a model kind). Modes: edge (default; one stored edge, read through the registry: narrower is read as broader turned round, symmetric predicates match either way round), path (1..maxHops hops, maxHops 1 to 8 required; a row says reached by a path unless the predicate is transitive), closure (no maxHops; allowed only on the transitive predicates broader, isomorphicTo, migratedFrom, narrower, subnetOf, supersededBy). Put the bound term in object to walk backwards. Unregistered (legacy) predicates are one stored edge in their stored direction only, never walked or closed over. A structural edge (isomorphicTo, subnetOf, preservesInvariant, refines) counts only when one of its stored witnesses re-checks valid now; a derived structural fact carries a derivation (the chain of witnesses and the composed map's digest) that sim_check_witness(derivation=…) re-checks, and is never stored; excluded lists the edges not walked and why. Closure runs per predicate (isomorphicTo hops never feed a subnetOf closure). status complete means complete over the eligible edges (and, for path, within maxHops: hopLimitReached names patterns with edges beyond); truncated means a bound was reached, rows is absent and the rows found so far are in partialRows (true, but not all of them). A query with no variables answers yes, no or unknown (a bound stopped it, or a stored row could not be decoded); a no's caveat says how far the search looked (only closure rules out a derived edge, and a path cut a…
| Name | Type | Req | Description |
|---|---|---|---|
| query | string | yes | the query as JSON: {"select": [variables], "where": [{"subject", "predicate", "object", "mode", "maxHops"}]} |
No output schema declared.
No examples provided.
sim_reach ~1,049
Returns whether the marking to is reachable from the marking from in ONE stored net (a model, or a system that is one net): yes with a firing trace, no with a re-checkable P-invariant (or after an exhaustive search), or unknown with every reason. A sim_compose result is one fused net, so it qualifies; a sim_bind binding or a collection links rates, not tokens, and answers unknown (not-one-net). A system id (sim_create_system) is answered on its one net when one member has every other embedded in it by a witnessed subnetOf or isomorphicTo edge or a chain of edges of one predicate (the answer carries via: an edge and witness per member, or the derivation sim_check_witness(derivation=…) re-checks); otherwise it answers unknown: not-one-net when it holds bindings (they link rates, not tokens) or no member qualifies, system-truncated when its witness bound was reached or the chain search stopped at a bound. On a one-net system, a key in from or to may name a member's place as <model>:<place> (the member's id, or its name when no other member shares it): it is translated into the net place that member's embedding maps it to, the answer's from and to are the translated question, and via.translation lists each key's member, place and net place, which sim_check_witness(reach=…) re-checks against the stored witnesses. Refused, naming the key: a member or place the system does not have, a data place, a key that reads more than one way, a place two valid witnesses of the member's edge map differently, and two keys landing on one net place with different counts; more than 16 other witnesses to compare answers unknown (translation-budget). from is a sparse override on the model's declared initial marking (unset = declared). to constrains only the places it names, each to exactly that count; naming every token place asks for an exact marking. Unknown or data places, negative or fractional counts and counts over the scenario caps (1,000,000 per place, 4,000,000 in total) are refus…
| Name | Type | Req | Description |
|---|---|---|---|
| from | string | – | JSON object of place -> whole token count overriding the declared initial marking, e.g. {"queue": 3}; unset = the declared marking. On a system, a key may be <model>:<place> for a member's place |
| system | string | yes | content id of one stored model, or of a system (sim_create_system) |
| to | string | yes | JSON object of the places to constrain, each to exactly that count, e.g. {"done": 1}. On a system, a key may be <model>:<place> for a member's place, translated into the net's |
No output schema declared.
No examples provided.
sim_receipt ~274
Run a seeded scenario and get back the result PLUS a signed run receipt: an Ed25519 certificate over (model id, scenario, result hash, service revision). Anyone can check it two ways — verify the signature offline against the embedded public key (proves this service reported this result), and POST it to /api/receipts/verify (no auth) to replay the run and confirm the result hash reproduces (proves the run is reproducible, not invented). The current signing key is at GET /api/receipts/key. Reproducibility is the bottom rung of the trust ladder receipts build: play the model, check the anchors, re-run the seed, verify the certificate. Costs 1 token from your account's compute bucket.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | model id to run |
| scenario | string | – | scenario JSON (hours, samples, seed, marking, rates, schedule, summary — the same shape sim_scenario takes); sim_scenario's defaults (hours 8, realizations 16, seed 20260809) fill whatever is omitted… |
No output schema declared.
No examples provided.
sim_refine ~338
Refine a model's parameter classes by editing what the model SAYS (tags on a place or transition, or assertedClasses), then re-derive. Returns a NEW model id (ids are content addresses, so the original stays reachable) plus a before/after class diff. tags can only split classes; assertedClasses declares a merge and gets re-verified and costed, never trusted blind. Read the sim://docs/classification resource once for why the two levers are not symmetric. Costs 2 tokens from your account's compute bucket (the stored model, 1, and the verified re-classification, 1).
| Name | Type | Req | Description |
|---|---|---|---|
| assertedClasses | string | – | JSON array, e.g. [{"id":"items","members":["item0","item1"],"note":"one stocking decision"}] |
| id | string | yes | model id to refine |
| signature | string | – | optional hex signature over the CID of the signed claim; see modelstore.SignedClaim for the exact bytes. An unverifiable signature is refused, not stored with a flag. |
| signer | string | – | optional {"type":"eth"|"ed25519","address":"..."} — signs the lineage claim so it is the refiner's word rather than the server's account of a session |
| tags | string | – | JSON object of place OR transition id -> {key: value}, e.g. {"nurse_avail":{"refine.shift":"night"}}. Keys not prefixed refine. are stored as metadata and refine nothing. classify.go's colour refinem… |
No output schema declared.
No examples provided.
sim_reroll ~276
Re-run a stored sim_prompt against the SAME parent it originally ran against — a sibling attempt, never a chain: it never derives from the previous attempt's output, only from the original parent, so rerolling ten times leaves ten independent siblings in lineage rather than a chain of ten. Reuses the original prompt's text and system unless you override them here. The original prompt and its result are left untouched; this stores a new prompt and a new result (model or artifact, same rule as sim_prompt) under Activity sim_reroll. When called with neither override and the deployment's LLM provider and model are unchanged since the original ran, the response carries a reproducibility field checked against every prior result this exact prompt has ever produced (via the same forward "produced" relation sim_edges/sim_neighbors can query directly): "verified" if this result content-matches one of them, "diverged" if it doesn't, "not verified" if there's no prior result on record yet.
| Name | Type | Req | Description |
|---|---|---|---|
| prompt | string | yes | id of the sim_prompt (or earlier sim_reroll) to re-run |
| system | string | – | override the original prompt's system text; default reuses it verbatim |
| text | string | – | override the original prompt's text; default reuses it verbatim |
No output schema declared.
No examples provided.
What is the xyz.pflow.sim/whatif MCP server?
xyz.pflow.sim/whatif is an MCP server listed in the public MCP registry as xyz.pflow.sim/whatif. Conversational what-if simulation: build, diagnose and compare Petri-net models; CC0 catalog. This page covers its hosted endpoint (https://sim.pflow.xyz/mcp).
Is the xyz.pflow.sim/whatif MCP server safe to use?
xyz.pflow.sim/whatif scores 69 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the xyz.pflow.sim/whatif MCP server expose?
xyz.pflow.sim/whatif exposes 55 tools: sim_accept_migration, sim_bind, sim_calibrate, sim_canonical, sim_check_witness, and 50 more. Their descriptions and schemas cost roughly 19,475 tokens of context every time the server is loaded.
Does the xyz.pflow.sim/whatif MCP server require authentication?
No. We connected to xyz.pflow.sim/whatif without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the xyz.pflow.sim/whatif MCP server still maintained?
xyz.pflow.sim/whatif is still listed as active in the MCP registry. We last reached this channel on 7 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.