Skip to main content
Glama
petri-net-sim

pns-server MCP Server

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
APP_ENVNoEnvironment (local / stage / prod)local
DB_HOSTYesPostgreSQL host
DB_NAMEYesPostgreSQL database name
DB_PORTYesPostgreSQL port
REDIS_HOSTYesRedis host
REDIS_PORTYesRedis port
REDIS_ENABLEDNoEnable Redistrue
OPENAI_API_KEYYesOpenAI API key
AGENT_LLM_MODELNoModel namegpt-4o
ANTHROPIC_API_KEYYesAnthropic API key
LLM_BYOK_REQUIREDNoRequire user-provided LLM credentialstrue
AGENT_LLM_PROVIDERNoLLM provider (openai / anthropic / ollama)openai
CREDENTIALS_CIPHERNoEncryption mode (fernet / noop)fernet
AUTH_JWT_SECRET_KEYYesJWT signing key (min 32 chars)
SIMULATION_REMOTE_URLNoOptional external simulation backend
CREDENTIALS_MASTER_KEYYes32-byte base64 key for Fernet

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
create_networkA

Create a new empty Petri Net, clearing any previous network.

Use this FIRST when building a new model from scratch.

Args: name: Name for the new network (default: "PetriNet")

add_generatorA

Add a Generator (Source) pattern that creates tokens at regular intervals.

Use this for arrival processes. Specify EITHER interval OR rate (not both):

Using RATE (preferred for "N items per time unit"):

  • "4 parts per minute" -> rate=4, time_unit="min"

  • "10 customers per hour" -> rate=10, time_unit="h"

Using INTERVAL (for "every N time units"):

  • "every 3 minutes" -> interval=3, time_unit="min"

  • "every 30 seconds" -> interval=30, time_unit="s"

BATCH GENERATION (multiple items per arrival):

  • "5 items arrive every 5 minutes" -> interval=5, time_unit="min", batch_size=5

DISTRIBUTION SELECTION:

  • "exp": For random/Poisson arrivals

  • "norm": For arrivals with deviation ("every 3±1 min" -> norm, std=1, time_unit="min")

  • "unif": For uniformly distributed arrivals

  • "det": For fixed/constant intervals

UNITS — TWO INDEPENDENT KNOBS:

  • time_unit applies to interval / rate.

  • deviation_unit applies to standard_deviation. If omitted, it inherits from time_unit. Use it when the mean and the ± are in DIFFERENT units.

Canonical translations:

  • "1 per minute ±10 sec" -> interval=1, time_unit="min", standard_deviation=10, deviation_unit="s"

  • "every 5 min ±30 sec" -> interval=5, time_unit="min", standard_deviation=30, deviation_unit="s"

  • "every 5 min ±1 min" (same units) -> interval=5, time_unit="min", standard_deviation=1 (deviation_unit omitted)

Args: name: Name for this generator (e.g., "CustomerArrivals", "PartsInput") interval: Mean time BETWEEN arrivals in time_unit (use this OR rate, not both) rate: Number of arrivals PER time_unit (use this OR interval, not both) distribution: "exp", "norm", "unif", or "det" standard_deviation: Spread for "norm"/"unif" distributions (in deviation_unit, or time_unit if deviation_unit omitted) batch_size: Number of tokens per arrival (default: 1) time_unit: Unit for interval/rate — "s", "min", "h", "d". PASS THIS EXPLICITLY when the user describes the mean in non-second terms; the response echoes the resulting duration/rate in all four units so you can sanity-check. deviation_unit: Unit for standard_deviation. Pass ONLY when it differs from time_unit (e.g. mean in minutes, ± in seconds).

add_machineA

Add a Machine (Server) pattern with multiple processing channels.

Use this for processing stations like machines, servers, workstations.

UNITS — TWO INDEPENDENT KNOBS:

  • time_unit applies to processing_time.

  • deviation_unit applies to standard_deviation. If omitted, inherits time_unit. Use when mean and ± are in DIFFERENT units (e.g. "60s ±5 min" or "5 min ±10 s").

Args: name: Name for this machine (e.g., "Lathe", "Checkout", "Server") processing_time: Mean processing time in time_unit channels: Number of parallel channels distribution: Time distribution - "exp", "norm", "unif", or "det" standard_deviation: Spread for "norm"/"unif" (in deviation_unit, or time_unit if omitted) auto_connect: If True (default), auto-connects to previous output. Set to False for PARALLEL machines from same queue! time_unit: Unit for processing_time — "s", "min", "h", "d". deviation_unit: Unit for standard_deviation. Pass ONLY when it differs from time_unit.

add_controllerA

Add a Controller (Gate) pattern that allows flow only when a signal is present.

The signal is read but NOT consumed (information link).

Args: name: Name for this controller (e.g., "TrafficLight", "Permission") initial_signal: If True, the signal starts enabled (gate open)

add_assemblyA

Add an Assembly (Join) pattern that synchronizes multiple flows into one.

Creates one new input place per slot named "{name}In{slot_name}" and a transition that fires when ALL slots have tokens. The caller must wire external sources to those slots via connect_patterns — the slot place_ids are returned in the response and in metadata.

WEIGHTED INPUTS (for multiple tokens required):

  • Simple: inputs=["PartA", "PartB"] - requires 1 token from each

  • Weighted: inputs=[{"name": "Type1", "weight": 10}, {"name": "Type2", "weight": 10}]

Args: name: Name for this assembly (e.g., "CarAssembly", "SectionFill") inputs: Names for the input slots created by this assembly assembly_time: Mean firing time in time_unit distribution: Time distribution priority: Transition priority (higher = fires first in conflict) time_unit: Unit for time values — "s", "min", "h", or "d" (days)

add_routerA

Add a Router (Splitter) pattern that branches flow into multiple paths.

Args: name: Name for this router (e.g., "QualityCheck", "LoadBalancer") routes: List of route configurations: For probability: [{"name": "Accept", "prob": 0.9}, {"name": "Reject", "prob": 0.1}] For priority: [{"name": "Primary", "priority": 2}, {"name": "Backup", "priority": 1}] PRIORITY RULE: higher "priority" number fires first (same as add_transition). The route with the highest priority number is tried first; lower numbers are fallbacks. strategy: "probability" for random split, "priority" for ordered selection

add_conveyorA

Add a Conveyor pattern with sequential processing stations.

Every item is processed at every station (no bypass option). For stations with bypass logic, use add_conveyor_line instead.

Args: name: Name for this conveyor (e.g., "AssemblyLine", "Pipeline") stations: List of station configs: [{"name": "Stage1", "time": 60.0, "distribution": "exp"}, ...] transport_time: Time to move between stations

add_conveyor_lineA

Add a COMPLETE conveyor line with Try-or-Bypass workstations.

THIS IS THE PREFERRED TOOL for conveyor systems with bypass logic. Creates N workstations, all bypass connections, and return loop in ONE call.

How it works:

  • Each station: if resource FREE -> process; if BUSY -> bypass to next

  • After last station: unprocessed items return to first with delay

  • Processed items exit at their processing station

Args: station_count: Number of workstations processing_time: Mean processing time at each station in time_unit distribution: Processing time distribution transport_time: Time to move between stations in time_unit return_delay: Time for items to return from last to first station in time_unit channels: Number of parallel resources per station station_prefix: Name prefix for stations (default: "Device") time_unit: Unit for all time values — "s", "min", or "h"

add_conveyor_workstationA

Add a SINGLE ConveyorWorkstation with Try-or-Bypass logic.

For multiple workstations in a chain, prefer add_conveyor_line instead.

Args: name: Name for this workstation (e.g., "Device1") processing_time: Mean processing time in time_unit distribution: Processing time distribution transport_time: Time to bypass to next station in time_unit channels: Number of parallel resources time_unit: Unit for time values — "s", "min", "h", or "d" (days)

connect_workstation_bypassA

Connect bypass output of one workstation to input of next.

Prefer add_conveyor_line which creates all connections automatically.

Args: source_workstation_name: Source workstation name target_workstation_name: Target workstation name

connect_return_loopA

Create return loop from last workstation back to first.

Prefer add_conveyor_line which creates return loop automatically.

Args: last_workstation_name: Last workstation name first_workstation_name: First workstation name return_delay: Time to return in time_unit (default: 5.0) time_unit: Unit for time values — "s", "min", "h", or "d" (days)

add_transport_agentA

Add a TransportAgent (cyclic resource) pattern.

Models any resource that picks up, moves, releases, and returns: robots, forklifts, AGVs, cranes, couriers.

Cycle: [Queue]+[Free] -> Grab -> Move -> Release -> Return -> [Free]

Args: name: Name for this agent (e.g., "Robot1", "Forklift", "AGV") grab_time: Mean time to grab/pick item in time_unit grab_deviation: Standard deviation for grab in time_unit grab_distribution: Distribution for grab time move_time: Time to move WITH item in time_unit move_distribution: Distribution for move release_time: Mean time to release/place item in time_unit release_deviation: Standard deviation for release in time_unit release_distribution: Distribution for release return_time: Time to return EMPTY in time_unit (default: same as move_time) return_distribution: Distribution for return time_unit: Unit for all time values — "s", "min", or "h"

add_priority_choiceA

Add a PriorityChoice pattern for resource-dependent branching.

Implements "do X if resources available, otherwise do Y" logic. Primary transition has higher priority and fires first if resources available.

Args: name: Name for this choice point (e.g., "SectionFill") resource_place_ids: Resource requirements for primary path. Each dict: {"place_id": "p5", "weight": 10} primary_delay: Delay for primary/success transition in time_unit alternative_delay: Delay for alternative/fallback transition in time_unit primary_name: Name suffix for success output alternative_name: Name suffix for fallback output time_unit: Unit for time values — "s", "min", "h", or "d" (days)

add_mergeA

Add a Merge (OR-join / Funnel) pattern — combines multiple streams into one output.

Fires as soon as ANY input has a token (unlike Assembly which waits for ALL). Creates one input place per stream named "{name}In{stream_name}". Wire each producer's output into the corresponding place via connect_patterns.

Use this for:

  • Orders from web, phone and fax all going to one processing queue

  • Parts from parallel machines going to one inspection station

Args: name: Name for this merge point (e.g., "OrderMerge") inputs: Stream names (e.g., ["Web", "Phone", "Fax"])

add_duplicateA

Add a Duplicate (Broadcast) pattern — copies one token into N independent copies.

One arriving token produces one token in each output place simultaneously. Use for parallel processing of the same item by independent services.

Use this for:

  • One purchase order triggers parallel handling in warehouse, accounting, logistics

  • One lab sample sent to multiple independent test stations

Args: name: Name for this broadcast point (e.g., "OrderBroadcast") outputs: Output branch names (e.g., ["Warehouse", "Accounting", "Logistics"])

add_multi_resourceA

Add a MultiResource (AND-Resource) pattern — op requiring multiple simultaneous resources.

Seizes one token from each resource pool simultaneously and releases all upon completion. Unlike Machine (homogeneous channels), each pool can have a different name and capacity.

Use this for:

  • Painting: worker + spray gun + booth must all be free

  • Surgery: doctor + room + equipment required simultaneously

  • Welding: welder + welding machine + jig

Args: name: Instance name (e.g., "PaintBooth", "SurgeryRoom") resources: List of resource pool definitions. Each dict: {"name": str, "pool_size": int} Example: [{"name": "Worker", "pool_size": 3}, {"name": "Booth", "pool_size": 2}] processing_time: Mean processing time in time_unit distribution: Time distribution — "exp", "norm", "unif", "det" standard_deviation: Std dev for norm/unif (in time_unit) time_unit: Unit for time values — "s", "min", "h", or "d"

add_nonstationary_generatorA

Add a NonStationaryGenerator — arrival rate changes over cyclic time windows.

Each time window has its own arrival rate. The schedule repeats cyclically.

Use this for:

  • Morning rush (rate 20/h, 2h) + afternoon (rate 5/h, 6h)

  • Factory: day shift (rate 10/min, 8h) + night shift (rate 3/min, 16h)

  • Call center: peak hours vs off-peak

Args: name: Name for this generator (e.g., "CoffeeShop", "CallCenter") schedule: List of time windows. Each dict: {"duration": float (seconds), "rate": float (arrivals/sec)} Example: [{"duration": 7200, "rate": 0.33}, {"duration": 21600, "rate": 0.083}] batch_size: Tokens per arrival (default: 1)

connect_bounded_consumerA

Wire capacity recycling between a BoundedQueue and its consumer.

Looks up the queue's capacity place by naming convention ('{queue_name}_Capacity') and the consumer's start transition ('{consumer_name}_Start' for Machine, '{consumer_name}_Do' for Assembly), then adds an arc consumer->capacity so each dequeue recycles a slot.

Args: queue_name: Instance name passed to add_bounded_queue consumer_name: Instance name of the downstream consumer (Machine or Assembly)

add_fork_joinA

Add a ForkJoin (AND-split / AND-join) pattern for parallel branch execution.

A single entity enters, splits into N independent parallel branches, and continues ONLY when ALL N branches have completed. Essential for modeling parallel workflows that must synchronize before proceeding.

Difference from other patterns:

  • Assembly: waits for N entities from different arrival streams

  • Duplicate: copies diverge and NEVER rejoin

  • ForkJoin: one entity → N parallel branches → all must complete before output

Args: name: Instance name (e.g., "PatientExam", "QualityGate") n_branches: Number of parallel branches (default: 2) branch_times: Mean processing time per branch in time_unit. Length must equal n_branches. Default: [30.0] * n_branches branch_distribution: Distribution for branches — "exp", "norm", "unif", "det" time_unit: Time unit for branch_times — "s", "min", "h"

Returns branch IDs in the response for manual wiring when branches are processed by external patterns (retrial queues, machines, etc.).

connect_blocking_consumerA

Wire capacity recycling between a BlockingMachine and its downstream consumer.

When the downstream machine starts processing an entity from the blocking machine's output buffer, one capacity slot is returned — allowing the blocking machine to release its next held entity.

Call this AFTER connecting BlockingMachine output to downstream input.

Args: blocking_machine_name: Instance name passed to add_blocking_machine downstream_name: Instance name of the downstream consumer (Machine, etc.)

add_resource_setA

Add a ResourceSet — entity seizes the first available resource from alternatives.

Models "try resource A first; if busy, try B; if busy, try C." Resources are listed in preference order (index 0 = highest priority). Each resource has its own service time, channel count, and distribution.

Args: name: Instance name (e.g., "MachinePool", "NursePool") resources: List of resource dicts, ordered by preference. Each dict: - "name": str (required) - "service_time": float (default 60.0, in time_unit) - "distribution": str "exp"|"norm"|"unif"|"det" (default "exp") - "channels": int (default 1) Example: [{"name": "FastMachine", "service_time": 30.0}, {"name": "SlowMachine", "service_time": 90.0}] standard_deviation: Global std dev fallback for norm/unif resources (in time_unit) time_unit: Time unit for service_time values — "s", "min", "h"

connect_wip_returnA

Wire the WIP return arc — recycle a WIP slot when an entity reaches the exit place.

For every transition that already produces tokens into exit_place_id, an extra output arc to the controller's WIPSlots place is added. Tokens are NOT consumed — the entity continues to flow through the exit place to its downstream consumer.

Call AFTER wiring the WIP-controlled section, so the producer transitions of exit_place_id exist.

Args: wip_controller_name: Instance name passed to add_wip_controller exit_place_id: Output place ID of the last pattern in the controlled section

connect_schedule_gateA

Gate a machine with a shift schedule via READ arc.

Adds a READ arc from the schedule's Active signal place to the machine's Start transition. During off-periods the machine is blocked; items wait in the queue and processing resumes when the next active window starts.

Call AFTER both add_scheduled_availability and add_machine / add_breakdown.

Args: schedule_name: Name passed to add_scheduled_availability (e.g., "DayShift") machine_name: Name passed to add_machine or add_breakdown (e.g., "Press")

connect_patternsC

Connect the output of one pattern to the input of another.

Args: source_output_id: Output place ID from the source pattern target_input_id: Input place ID of the target pattern

get_network_statusA

Get current status of the Petri Net being built.

Returns summary of places, transitions, arcs, and validation status.

add_placeA

Add a single place (position) to the Petri net.

LOW-LEVEL TOOL — use only when no existing pattern (add_generator, add_machine, etc.) covers the required topology. For standard queueing and production constructs, prefer the high-level pattern tools.

Layout: ALWAYS call find_free_position(near_element_id, direction) first to get collision-free coordinates near the element you will connect to, then pass the returned x and y here. Without explicit coordinates the auto-cursor places the element at the far right, colliding with existing elements on follow-up edits.

Args: name: Human-readable place name tokens: Initial token count (marking) tag: Optional semantic tag (e.g. "throughput" for counter places) x: Canvas X coordinate — obtain from find_free_position y: Canvas Y coordinate — obtain from find_free_position

add_transitionA

Add a single transition (event) to the Petri net.

LOW-LEVEL TOOL — use only when no existing pattern covers the required topology. For standard constructs, prefer high-level pattern tools.

Layout: ALWAYS call find_free_position(near_element_id, direction) first to get collision-free coordinates, then pass the returned x and y here.

Args: name: Human-readable transition name distribution: Time distribution ("exp", "norm", "unif", "det"), omit for immediate mean_delay: Mean delay time in time_unit standard_deviation: For norm/unif distributions (in time_unit) priority: Firing priority (higher = fires first in conflict) probability: Firing probability for stochastic conflict resolution (0.0-1.0) time_unit: Unit for time values — "s", "min", "h" x: Canvas X coordinate (see list_elements for existing coords) y: Canvas Y coordinate

add_arcA

Add an arc connecting a place to a transition or vice versa.

LOW-LEVEL TOOL — use only when no existing pattern covers the required topology. Arcs enforce bipartite constraint: Place↔Transition only.

Args: source_id: ID of the source node (place or transition) target_id: ID of the target node (place or transition) weight: Arc weight (tokens consumed/produced per firing) arc_type: Arc type — "normal", "inhibitor", or "read"

validate_netA

Validate the current Petri net topology.

Checks bipartite constraint, dangling transitions (no input/output arcs), and duplicate IDs. Call this after building custom topology with add_place, add_transition, add_arc to catch errors before export.

modify_placeA

Modify an existing place in the Petri net.

Only provided fields are updated — omitted fields stay unchanged. Use list_elements or get_network_status to discover place IDs first.

Args: place_id: ID of the place to modify (e.g. "p1") name: New name (omit to keep current) tokens: New token count (omit to keep current) tag: New semantic tag (omit to keep current)

modify_transitionA

Modify an existing transition in the Petri net.

Only provided fields are updated — omitted fields stay unchanged. Use list_elements or get_network_status to discover transition IDs first.

Args: transition_id: ID of the transition to modify (e.g. "t3") name: New name (omit to keep current) distribution: New distribution ("exp", "norm", "unif", "det") — omit to keep current mean_delay: New mean delay in time_unit (omit to keep current) standard_deviation: New std deviation in time_unit (omit to keep current) priority: New firing priority — higher number fires first in conflict (omit to keep current) probability: New firing probability 0.0-1.0 (omit to keep current) time_unit: Unit for time values — "s", "min", "h"

modify_arcA

Modify an existing arc in the Petri net.

Only provided fields are updated — omitted fields stay unchanged. Use list_elements to discover arc IDs first.

Args: arc_id: ID of the arc to modify weight: New arc weight (omit to keep current) arc_type: New arc type — "normal", "inhibitor", or "read" (omit to keep current)

remove_placeA

Remove a place and all its connected arcs from the Petri net.

WARNING: Destructive — the place and ALL arcs connected to it are deleted.

Args: place_id: ID of the place to remove

remove_transitionA

Remove a transition and all its connected arcs from the Petri net.

WARNING: Destructive — the transition and ALL arcs connected to it are deleted.

Args: transition_id: ID of the transition to remove

remove_arcC

Remove a single arc from the Petri net.

Args: arc_id: ID of the arc to remove

list_elementsA

List all places, transitions, and arcs with their current parameters.

Use this before modify/remove operations to discover element IDs and current values. Returns detailed info for every element in the net.

set_positionsA

Set canvas coordinates for places and transitions by ID.

Use after adding new elements or to clean up a cluttered layout. Typical workflow:

  1. list_elements — note current x,y of existing elements

  2. set_positions — assign new x,y for any subset of elements

Elements not listed keep their current positions.

Args: positions: List of {"id": "", "x": , "y": } Example: [{"id": "p1", "x": 100, "y": 200}, {"id": "t1", "x": 200, "y": 200}]

find_free_positionA

Find canvas coordinates for a new element near an existing one, avoiding overlaps.

Call this BEFORE add_place or add_transition to get good x,y coordinates. Then pass those coordinates directly to add_place/add_transition.

Recommended workflow when adding a place connected to an existing element:

  1. find_free_position(near_element_id=, direction=)

  2. add_place(name=..., tokens=..., x=, y=)

  3. add_arc(source_id=..., target_id=...)

Args: near_element_id: ID of the place or transition to position near (use list_elements to find IDs and current coordinates) direction: Where to place the new element relative to the anchor: "above" (same x, lower y) | "below" | "left" | "right"

find_elementsA

Search places and transitions by name substring.

Use this to locate element IDs before calling find_free_position, set_positions, or move_elements_by. Much faster than list_elements when you only need a specific pattern's elements.

Typical workflow for placing a new element near an existing one:

  1. find_elements("Generator") — find anchor element ID and its x,y

  2. find_free_position(near_element_id=, direction="above") — clear coordinates

  3. add_place(name=..., x=, y=)

Args: name_pattern: Case-insensitive substring (e.g. "Generator", "Queue"). Empty string returns all elements of the requested type. element_type: "place", "transition", or omit for both.

get_network_boundsA

Return the spatial bounding box of all elements in the net.

Use to understand the current layout extent before adding new elements or deciding where to place a new pattern relative to existing ones.

Returns: min_x, max_x — horizontal extent min_y, max_y — vertical extent center_x, center_y — geometric center of all elements width, height — overall canvas span element_count — total places + transitions

move_elements_byA

Shift one or more elements by a relative offset.

Use when the user says "move the generator 200px to the right" or "push the machine down by 100px", without needing to query current coordinates first.

To move all elements of a named pattern, call find_elements first to collect the IDs, then pass them here.

Args: element_ids: List of place/transition IDs to move dx: Horizontal shift in canvas units (positive = right) dy: Vertical shift in canvas units (positive = down)

auto_layoutA

Re-layout the entire net using topological left-to-right layering.

Assigns x,y coordinates to every element based on the arc topology. Elements with no predecessors get layer 0; successors get later layers. Elements in the same layer are distributed symmetrically around center_y.

Call this after building the complete net when the automatic cursor placement produced a cluttered or overlapping layout.

Args: start_x: X coordinate for the first (leftmost) layer (default 100) center_y: Vertical center for all layers (default 200) x_step: Horizontal distance between layers in canvas units (default 150) y_step: Vertical distance between elements in the same layer (default 120)

add_terminatorD

Add terminator pattern.

add_bufferD

Add buffer pattern.

add_quality_checkC

Add quality_check pattern.

add_feedback_loopC

Add feedback_loop pattern.

add_threshold_activationC

Add threshold_activation pattern.

add_bounded_queueD

Add bounded_queue pattern.

add_batchC

Add batch pattern.

add_unbatchA

Unbatch (Split / Unpack) pattern.

One incoming token (representing a batch or container) is expanded into batch_size individual tokens. The inverse of Batch.

Structure: [P: Input] -(weight=1)-> [T: Split] -(weight=N)-> [P: Output]

Use cases:

  • One received pallet token expanded into 48 individual box tokens

  • One batch job record split into individual work orders

  • One container unloaded into individual items for independent processing

add_breakdownD

Add breakdown pattern.

add_scheduled_availabilityD

Add scheduled_availability pattern.

add_reneging_queueD

Add reneging_queue pattern.

add_setup_machineD

Add setup_machine pattern.

add_server_vacationD

Add server_vacation pattern.

add_balking_queueD

Add balking_queue pattern.

add_timed_batchD

Add timed_batch pattern.

add_preemptive_machineD

Add preemptive_machine pattern.

add_retrial_queueC

Add retrial_queue pattern.

add_blocking_machineD

Add blocking_machine pattern.

add_finite_population_queueA

Closed queueing network: N entities recirculate through a c-server queue.

Models M/M/c/∞/N systems where N customers alternate between "thinking" (off-system rest) and waiting for service. After service completes the entity rests for thinking_time then re-enters the queue. No new entities are ever created; the same N circulate indefinitely.

Structure: [IdlePool(N)] --[Request DET=0]--> [Queue] [Queue] + [FreeChannels(c)] --[Start DET=0]--> [InService] [InService] --[EndService]--> [Done] + FreeChannels returned [Done] --[Measure DET=0]--> [Resting] + [Counter(throughput)] [Resting] --[EndRest]--> [IdlePool]

Token conservation: IdlePool + Queue + InService + Resting = N at all times. Counter accumulates as a monotone throughput counter (same convention as Terminator).

Use cases:

  • Manufacturing: N pallets / fixtures circulating through work cells

  • Repair: N tools shared by technicians (tool → use → return to pool → reuse)

  • Taxi fleet: N taxis (idle → pickup → ride → return → idle)

  • Call centre agents: N agents serve customers, then become available again

  • Finite population M/M/c: classic Engset-style model

When thinking_time=0 entities return immediately (pure circulation, no idle phase).

add_wip_controllerA

WIP (Work In Progress) limiter — Kanban / CONWIP entry gate.

Limits the number of entities in a controlled section to at most wip_limit simultaneously. When the limit is reached, entry is blocked (not rejected) until an entity exits the section and returns a WIP slot.

Structure: [Input] + [WIPSlots(K)] --[Enter DET=0]--> [Output]

After wiring the controlled section, call connect_wip_return to close the loop: each transition T that produces tokens into the section's exit place gets an extra output arc T -> [WIPSlots]. The entity is NOT consumed — it continues to flow through the exit place to its downstream consumer (terminator, next stage, etc.) while a WIP slot is recycled.

Use cases:

  • CONWIP production lines: at most K pallets in the system at once

  • Kanban pull control: K kanban cards gate work entry

  • Pipeline stages: limit concurrent requests to K

  • Thread pool / worker pool modelling

optimize_networkA

Optimize the Petri Net by removing redundant elements.

Call this AFTER the network is fully built, BEFORE exporting. Removes intermediate Transfer transitions and simplifies the topology while preserving semantic behavior, markings, and timing.

export_pnmlA

Export the current Petri Net to PNML XML format.

Returns the full PNML XML content as a string. Compatible with TINA, PetriObjModel, and CPN Tools.

run_simulationA

Run a discrete-event simulation of the current Petri Net.

Executes the simulation for the given time and returns statistics: final markings, mean values, and observed min/max for all places and transitions, plus a Terminators (throughput) block sourced from places tagged "throughput".

IMPORTANT: simulation_time MUST use the same conceptual unit as the transition delays you set when building the net. Pass time_unit explicitly — the response echoes the duration in s/min/h/d so you can verify the interpretation matches your intent.

Args: simulation_time: Total simulation time in time_unit time_unit: "s" (seconds, default), "min", "h", or "d" (days)

get_simulation_resultsA

Get the results of the last simulation run.

Returns formatted statistics from the most recent run_simulation call.

Prompts

Interactive templates invoked by user choice

NameDescription
build_queueing_systemBuild a Petri net model from a queueing system description.
build_production_lineBuild a Petri net model for a production/manufacturing line.

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/petri-net-sim/pns-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server