Monedula
monedula-sim-link docs menu

MCP tools

The four tools of the monedula-sim-link MCP server: build_playground_url, open_scenario, validate_actions and cluster_to_url, with inputs and outputs.

Reference 1 of 5

12 min read

Updated 16 October 2026

Markdown

On this page

monedula-sim-link mcp serves four tools over the Model Context Protocol on stdio, and an MCP client shows each tool’s input schema to the agent. Use the MCP server shows how to register the server.

Every tool validates its input and returns a link only when it decodes back to the identical action list; a validation error names the offending field, separator or config path. Self-validation before printing lists the checks.

Tool Use it to
build_playground_url Build a free-play session from a description of a cluster and a list of timed actions.
open_scenario Get the deep link of a curated scenario.
validate_actions Check what the playground would actually load from an actions string or a link.
cluster_to_url Visualize a live cluster, snapshotted read-only.

build_playground_url

A free-play session from a declarative description. Every input is optional, and an empty call opens the default cluster.

Input Meaning
cluster The topology: single-dc (the default), active-passive, active-active, stretched-2-5 or stretched-3.
shape The starting cluster, described below. Omit it for the topology’s default. Not supported for stretched-2-5.
actions An ordered list of timed actions to replay on the starting cluster. It may be empty, to just open the cluster.

The shape object has these fields:

Field Meaning
brokers The total broker count of a single-zone topology (single-dc).
brokersPerZone The broker count per zone, for multi-zone topologies, in topology order: [primary, dr] for active-passive, [west, east] for active-active, [dc-a, dc-b, dc-c] for stretched-3.
topics The topics to create. A topic named orders shapes the primary topic, and every other topic becomes an extra topic, at most 6. Omit it to keep the default single orders topic.
rackAware true turns on rack-aware placement (single-dc).

Each entry of topics has name, partitions and replicationFactor, and optionally minInSyncReplicas and cleanupPolicy:

Field Meaning
name Letters, digits, ., _ and -, at most 40 characters. An add_group can subscribe to a name with a ., but the actions with a topic field, such as produce and reassign_partition, cannot reference it, because their grammar reserves the dot, so prefer _ or -.
partitions The partition count, at least 1, and at most the limit of the topology: 24 for single-dc, 6 for active-passive and active-active, and for stretched-3 the largest count from 1 to 6 that keeps the busiest broker within 3 partitions at the chosen replication factor. 9 brokers at RF 3 allow 6 partitions and reject 7, and 9 brokers at RF 4 allow 3 (the mapping reference).
replicationFactor At least 1, and at most the broker count of the hosting zone set.
minInSyncReplicas Optional min.insync.replicas, from 1 to the replication factor. Unset means the simulator’s default: 1 for an extra topic, which is Kafka’s own default, and max(1, replicationFactor-1) for orders.
cleanupPolicy Optional: delete, compact or compact,delete. Unset means delete.

Leaving minInSyncReplicas or cleanupPolicy out is safe: the tool writes the defaults into an extra topic’s segment of the size parameter. The segment for orders carries only a value that differs from its default, so minInSyncReplicas: 2 at replication factor 3, or cleanupPolicy: delete, adds nothing to its size, which stays 6x4x3 for 6 brokers and 4 partitions. Before 0.11.0 an extra topic with no minInSyncReplicas was written with an empty field, and the simulator dropped the whole topic from the session.

Diskless topics, from the KIP-1163 draft, add three inputs:

  • cluster also takes diskless-3az: one cluster whose three availability zones are racks, with rack-aware placement and a diskless clicks topic next to orders. Its default is 6 brokers and 3 partitions with replication factor 3; shape.brokers sets at most 9 brokers, and a topic has at most 6 partitions.
  • A topics entry may set disklessEnable: true, except with a compact or compact,delete cleanup policy or on active-passive and active-active.
  • shape.disklessTiming overrides the diskless timing of the session with commitIntervalMs, the diskless.append.commit.interval.ms, and uploadMs, the object-storage upload latency. Both are optional, in milliseconds from 100 to 5000. The override needs a diskless topic, from disklessEnable or the diskless-3az preset; without one, the call fails.

The shape describes no producers or consumer groups, so it cannot set the client.rack that the simulator’s size format can give each initial producer and consumer group.

Every action has a kind and an at, the simulation time in milliseconds at which it fires, 0 or more. Actions are replayed sorted by at, and spacing them about 1000 ms apart lets the playground animate them one at a time. The other fields depend on the kind:

Kind Required fields Optional fields
produce producerId, topic key, and either value or tombstone: true. The two are mutually exclusive.
kill_broker brokerId graceful: true for a graceful shutdown, otherwise a hard kill.
restart_broker brokerId
add_broker brokerId rack: pin the broker’s placement to a rack.
remove_broker brokerId
add_producer producerId topic: pin the producer to a topic.
remove_producer producerId
add_group groupId, topics (at least one; the first is the primary) autoOffsetReset: earliest, latest or none. Omitted, a new group starts at the high watermark.
remove_group groupId Removes a whole consumer group with its members.
add_consumer groupId, memberId
add_share_group groupId, topic members: explicit member ids.
config_change path, and either value or clear: true clear is allowed only for the paths the URL format marks as clearable.
reassign_partition topic, partition, replicas (the full target list of broker ids)
change_replication_factor topic, targetReplicationFactor
set_replica_speed brokerId, slow slow: true throttles the broker’s follower replication, false restores full speed.
tier_offload topic, partition, toOffset Offloads the local log up to that offset, exclusive, to remote storage.

Broker ids are broker-1 to broker-N. A default free-play cluster starts with the producer p1, the consumer group c1 and the primary topic orders. A config_change path is one the URL format whitelists, such as producers.p1.config.acks or topics.orders.retentionMs.

The tool does not write the optional settings field of add_group. An add_group with a settings object fails with an error that names the field: settings only appears in the output of validate_actions, which decodes it.

Example input:

{
  "shape": {
    "brokers": 6,
    "topics": [
      { "name": "orders", "partitions": 4, "replicationFactor": 3 },
      { "name": "payments", "partitions": 6, "replicationFactor": 3,
        "minInSyncReplicas": 2, "cleanupPolicy": "delete" }
    ]
  },
  "actions": [
    { "kind": "add_group", "at": 1000, "groupId": "analytics", "topics": ["orders"] },
    { "kind": "produce", "at": 2000, "producerId": "p1", "topic": "orders", "key": "O1" },
    { "kind": "config_change", "at": 3000, "path": "producers.p1.config.acks", "value": "all" },
    { "kind": "kill_broker", "at": 8500, "brokerId": "broker-2" },
    { "kind": "restart_broker", "at": 22000, "brokerId": "broker-2" }
  ]
}

It returns the link and the fields below:

https://monedula.dev/kafka-simulator/playground?scenario=free&actions=...&size=6x4x3xpayments~6~3~2~d~~~~
Output Meaning
url The full playground link. The actions are percent-encoded, and compressed automatically past the plain threshold.
cluster, size The cluster and size parameters the link carries, if any.
actionCount The number of encoded actions.
plainLength The length of the plain action string. The compressed form starts past 1500 characters.
compressed true when the link carries the compressed ~1 form.
decodedActions The actions decoded back out of the generated link. Compare them with your input.
notes Non-fatal adjustments or hints.

open_scenario

The deep link of a curated scenario, paused on its scripted walkthrough.

Input Meaning
scenarioId The scenario id in dotted form, such as 00.1.3.
{ "scenarioId": "00.1.3" }
https://monedula.dev/kafka-simulator/playground?scenario=00.1.3

The output has url, scenarioId and an optional note.

validate_actions

What the playground would actually load from an actions string. The playground drops entries it cannot parse without saying so, and this tool reports them.

Input Meaning
actions The raw actions value: the plain grammar (K:broker-2@8500,...), the compressed ~1 form, a percent-encoded value, or a full playground link, from which the actions parameter is extracted.
{ "actions": "K:broker-2@8500,NOPE,AG:analytics:orders@1000" }

The result has 2 surviving entries, sorted by at, and one dropped entry: NOPE, with the reason missing @<at>.

Output Meaning
entries The decoded actions the playground would load, sorted by at, in the action shape of build_playground_url. An add_group that carries the settings field also has a settings object, described below.
keptCount The number of actions that survive, after the cap.
droppedCount, dropped The entries the playground would silently drop, each with its entry text and a reason.
truncatedCount Decodable actions beyond the cap that the playground would discard. The earliest 2000 win.
compressed, plainLength Whether the value used the compressed form, and the length of the plain string.
compressionThreshold 1500: plain strings longer than this are emitted compressed.
maxUrlActions 2000: the action cap.
canonicalEncoding The surviving actions re-encoded canonically, sorted and plain. Absent when no action survives. Also absent when the actions decode but the tool’s generator rules refuse to write them back, such as a produce to a dotted region topic like west.orders; a note then says why.
notes Non-fatal hints.

Group settings

An add_group can carry the group’s settings in an optional fourth field, which the playground URL format specifies. The playground writes it when kafka-consumer-groups --reset-offsets rebuilds a configured group, and when it pins a new group on an active-active cluster to its region. validate_actions decodes the field and echoes it as a settings object on the entry. The field is strict, like the playground’s decoder: an empty field, an unknown or repeated setting, or a value outside its domain drops the whole add_group, which then appears in dropped.

{ "actions": "AG:g1:west.orders~east.orders:e:region=west~assignor=range~principal=User:CN=west~_OU=apps@9000" }

The entry it returns:

{
  "kind": "add_group",
  "at": 9000,
  "groupId": "g1",
  "topics": ["west.orders", "east.orders"],
  "autoOffsetReset": "earliest",
  "settings": { "region": "west", "assignor": "range", "principal": "User:CN=west,OU=apps" }
}

The settings object has a field only for each setting the group carries, with its value unescaped, so the ~_ in the link is a , in principal. An add_group without the settings field has no settings object.

Field Meaning
region The region the group is pinned to. It reads only that region’s copies of its topics.
assignor partition.assignment.strategy: range, roundrobin, sticky or cooperative-sticky.
isolationLevel isolation.level: read_committed or read_uncommitted.
autoCommit enable.auto.commit, true or false.
pollMs The poll interval in milliseconds, any integer. 0 or less stops the poll loop.
maxPollRecords max.poll.records, at least 1.
maxPollIntervalMs max.poll.interval.ms, at least 1.
rack The group’s client.rack.
principal The principal the group authenticates as.

canonicalEncoding writes the settings back in the order of this table, whatever order the link used. The settings object is output only: build_playground_url refuses it as input and never writes the field.

cluster_to_url

The live-cluster counterpart to build_playground_url. It connects read-only to a real Kafka cluster, through the same path as connect, and returns the link that visualizes it. It sends the same read requests, plus DescribeProducers only when producers is true: the read-only guarantee lists them.

Input Meaning
brokers The bootstrap brokers as host:port, at least one. Required.
topics Exact topic names to include. It fails if one is missing, and it is the only way to include internal topics. Listed topics are always kept when the selection is over the limit of 6 extra topics.
topicsRegex Additionally include non-internal topics that match this Go regular expression.
tls Connect over TLS. Implied when caCert, clientCert or clientKey is set.
caCert, clientCert, clientKey PEM file paths, resolved on the machine where the MCP server runs, not on the client’s. clientCert and clientKey go together.
saslMechanism, username, password SASL: plain, scram-sha-256 or scram-sha-512, which requires username. Prefer the MONEDULA_SIM_LINK_PASSWORD environment variable on the server’s machine to password; the variable is the fallback when password is empty.
timeoutSeconds The overall snapshot timeout in seconds. The default is 15.
maxRecordsPerPartition The cap on synthetic trailing records per partition. The default is 8.
clamp Trim a cluster over 10 brokers or 24 partitions per topic, or a topics list of more than 6 topics besides orders, deterministically, with warnings. Without it, such a selection fails with the list of violations. More topics or consumer groups than the simulator shows never fail: the most eventful are kept, with a warning.
producers Also read the idempotent and transactional producers with DescribeProducers (Kafka 2.8 or newer), and add up to 4 of them to the link: the ones whose last write to a shown topic is in the last 15 minutes, ranked by the number of partitions they wrote to, each pinned to the topic it wrote to most and named pid-<producerId>. Off by default, because the request needs READ on every selected topic; with it off, no DescribeProducers request is sent. A producer that is neither idempotent nor transactional never appears, and one with an open transaction is shown as an idempotent producer. A refused or unsupported read is a warning, never a failure. Unlike the CLI, the tool has no input for the 15-minute window.

Omit topics and topicsRegex to include every non-internal topic.

{ "brokers": ["broker1:9092", "broker2:9092"], "topics": ["orders", "payments"] }
Output Meaning
url, cluster, size, actionCount, plainLength, compressed As for build_playground_url. The size parameter carries each topic’s real min.insync.replicas, cleanup.policy, retention.ms and retention.bytes.
decodedActions The actions decoded back out of the link, including add_group and add_consumer for every mapped consumer group and its members, up to 4 members per group, and add_producer for every producer when producers is true. It starts with remove_producer for p1 and remove_group for c1, the template producer and group of free play.
brokerNames, topicNames, groupNames The real-to-simulator tables, as lists of real and simulator pairs. A group with no committed offset on a shown topic is absent from groupNames, and so is a group outside the 4 kept.
warnings Unreadable offsets, approximations, the topics and groups kept from a larger selection, any clamps applied and, with producers, an open transaction, a producer read that was refused or unsupported, and a window with no producer in it.
notes Non-fatal hints.

A selection that matches nothing is an error with an explanation.