render_sip_ladder
ActiveTool of Sipflow
[cost: free (pure CPU, no network) | read-only] Parse a raw SIP trace (PCAP-decoded text, sngrep export, syslog, or pasted INVITE/200 dialog) and emit a Mermaid `sequenceDiagram` block visualizing the call flow. Most chat hosts (Claude, ChatGPT, Cursor, GitHub) render Mermaid inline. Lane keying: by default participants are keyed by IP, not `ip:port`, so an endpoint that sends from an ephemeral source port and listens on 5060 collapses into one column. Multi-port IPs list their ports in the participant label (e.g. `10.0.0.1 :5060,:53412`) and arrows touching them get a `(:srcPort→:dstPort)` suffix. Pass `groupByIp: false` to restore the legacy one-column-per-`ip:port` layout. Lane labeling: aliases are matched against (in order) `${ip}:${port}` from message source/dest, then bare `${ip}`, then top-Via host, then Contact host. The most-specific match wins. When no alias matches the renderer falls back to the peer's address rather than emitting `unknown:5060`. Pair with: `minimize_sip_trace` first to compact a noisy trace; `diff_sip_messages` when two adjacent INVITEs in the ladder differ unexpectedly; `lint_sip_request` to validate a single message you pulled from the ladder.
Parameters schema
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 2000000,
"minLength": 1,
"description": "Raw SIP trace text. Multiple messages may be concatenated."
},
"callId": {
"type": "string",
"description": "Render only this Call-ID. Required when the trace contains multiple calls; otherwise the only call is used."
},
"aliases": {
"type": "object",
"description": "Friendly lane labels. Match order: exact \"ip:port\" → bare \"ip\" → top-Via host (with or without port) → Contact host (with or without port). Most-specific match wins; otherwise the lane is labeled with its raw \"ip:port\" (never \"unknown\"). Example: `{\"192.0.2.10:5060\":\"Alice\",\"203.0.113.50\":\"Carrier\"}`.",
"additionalProperties": {
"type": "string"
}
},
"compact": {
"type": "boolean",
"default": false,
"description": "Drop OPTIONS keepalives and retransmissions. Hidden counts are summarized in a `Note over` line."
},
"groupByIp": {
"type": "boolean",
"default": true,
"description": "Collapse multiple ports on the same IP into one participant lane (default). Set to `false` to fall back to the legacy one-column-per-`ip:port` layout when you specifically need port-level granularity in the rendered Mermaid."
},
"maxMessages": {
"type": "integer",
"default": 60,
"maximum": 200,
"minimum": 1,
"description": "Hard cap on rendered arrows. Extra messages produce a truncation note. Hard ceiling is 200."
},
"includeTiming": {
"type": "boolean",
"default": false,
"description": "Append `+Nms` (delta from previous arrow) to each arrow label."
},
"groupRetransmits": {
"type": "boolean",
"default": true,
"description": "Collapse adjacent identical retransmissions on the same direction into a single arrow + `Note over: xN over Tms`. Independent of `compact` (which drops them entirely)."
},
"splitOnNewBranch": {
"type": "boolean",
"default": false,
"description": "Emit a `--- failover to <ip[:port]> ---` separator before any request sent to a previously-unseen destination. Useful when the trace fails over between gateway IPs."
},
"highlightFailures": {
"type": "boolean",
"default": true,
"description": "Bold the first non-1xx final response per request leg (CSeq) so the failure jumps out in the ladder."
},
"correlationHeaders": {
"type": "array",
"items": {
"type": "string"
},
"description": "Header names to use for cross-leg call correlation (value-equality). When provided, calls sharing the same value for any listed header are merged into one ladder. Example: `[\"X-ACME-Session-ID\",\"X-ACME-Call-ID\"]`."
}
},
"additionalProperties": false
}No endpoints wrapped at confidence ≥ 0.70.
Parent server
Sipflow
https://github.com/cmendes0101/sipflow-cursor-plugin
1/7 registries