
Sipflow
- Updated May 14, 2026
- cmendes0101/sipflow-cursor-plugin
SIP/VoIP/telecom grounding for AI agents: vendor docs, RFCs, STIR/SHAKEN, traces, configs.
About
SIP/VoIP/telecom grounding for AI agents: vendor docs, RFCs, STIR/SHAKEN, traces, configs. Exposes 22 MCP tools including dev.sipflow/sipflow. Covers setup, configuration, and when-to-use guidance from upstream documentation for Sipflow. Install via Claude Desktop, Cursor, or any MCP-compatible client using the upstream server manifest.
- **Live endpoint:** `https://mcp.sipflow.dev/mcp` (Streamable HTTP)
- **Web app:** <https://www.sipflow.dev>
- **Install page (one-click + all clients):** <https://www.sipflow.dev/tools/mcp>
- H "Content-Type: application/json" \
- H "Accept: application/json, text/event-stream" \
Sipflow by the numbers
- Exposes 22 verified tools (MCP introspection)
- Data as of Jul 9, 2026 (Skillselion catalog sync)
claude mcp add --transport http sipflow https://mcp.sipflow.dev/mcpAdd your badge
Show developers this MCP server is listed on Skillselion. Paste this into your README.
| Transport | HTTP |
|---|---|
| Auth | None |
| Tools | 22 |
| Last updated | May 14, 2026 |
| Repository | cmendes0101/sipflow-cursor-plugin ↗ |
How do I connect Sipflow to my MCP client?
SIP/VoIP/telecom grounding for AI agents: vendor docs, RFCs, STIR/SHAKEN, traces, configs.
Who is it for?
Teams wiring Sipflow into Claude, Cursor, or custom agents for communication.
Skip if: Skip when you need a non-MCP SDK or hosted API without stdio/SSE transport.
What you get
Working Sipflow MCP server with verified tool registration and client config.
- Registered remote Sipflow MCP connection in your agent
- Agent answers grounded in SIP/VoIP and STIR/SHAKEN context during integration work
- Faster iteration on configs and traces with less generic hallucination
By the numbers
- [object Object]
Sipflow capabilities & compatibility
- Capabilities
- sipflow mcp tool registration · sipflow client configuration · sipflow agent workflow integration
- Use cases
- orchestration
- Runs
- Remote server
What Sipflow says it does
SIP/VoIP/telecom grounding for AI agents: vendor docs, RFCs, STIR/SHAKEN, traces, configs.
SIP/VoIP/telecom grounding for AI agents: vendor docs, RFCs, STIR/SHAKEN, traces, configs.
Tools 22
Public tool metadata - what this server can do for an agent.
search_sip_docs4 params[cost: rag (one embed + one vector search) | read-only, network: outbound to embed model only] Vector search over Sipflow's curated VoIP knowledge base: vendor docs (Asterisk, FreeSWITCH, Kamailio, OpenSIPS, Twilio, Cisco, etc.), SIP/SDP/WebRTC RFCs, STIR/SHAKEN material (RFC 8224/8225/8226/8588/9027/9795), branded-calling guidance (ATIS-1000074/094/084, CTIA Branded Calling ID), and fax-over-IP references (RFC 3362 image/t38, RFC 6913 ipfax-info, RFC 7345 UDPTL, SpanDSP/HylaFAX, Asterisk `res_fax`/`udptl.conf`, FreeSWITCH `mod_spandsp`/`t38_gateway`, Cisco CUBE T.38). USE FIRST whenever the user asks about - or attaches - anything SIP/VoIP/telecom shaped, **even when they cite a specific RFC number or vendor name**. The corpus has the current text and your training data may not. Trigger conditions: vendor configs (kamailio.cfg, sip.conf, pjsip.conf, FreeSWITCH XML profile, opensips.cfg, `res_fax.conf` / `udptl.conf`), dialplan / routing scripts, modules / loadparams / route blocks,
querystringrequiredNatural-language question or keywords. Be specific - include vendor name, header, error code, module, or RFC if known. Multi-sentence queries are fine.vendorstringRestrict results to a single vendor/stack (e.g. "asterisk", "kamailio"). Omit to search all vendors.sourceTypeRestrict by document type. Available: rfc | pbx (Asterisk/FreeSWITCH/Kamailio/OpenSIPS) | sbc (SBCs) | cpaas (Twilio/Telnyx/...) | uc-cloud (Teams/Zoom/...) | endpoint (phones/softphones) | stir-shaken | transport (RTP/SRTP/DTLS/ICE/STUN/TURN RFCs) | regulatory | observability.limitintegerMaximum number of snippets to return (1-15).
lookup_response_code1 param[cost: free (pure CPU, no network) | read-only] Instant static lookup of a SIP response code (100-699). Returns name, RFC anchor, category, description, common operator-flavored causes, and known vendor-specific reason-phrase variants (e.g. OpenSIPS emits 484 'Invalid FROM' on From-header parse failure). USE FIRST when the user pastes or asks about any 3-digit SIP code - sub-millisecond, no API cost. Pair with: `troubleshoot_response_code` for vendor-specific RAG hits beyond the static entry; `lint_sip_request` when the code is 4xx and the user has the offending request; `stir_attestation_explainer` for STIR-shaped codes (428/436/437/438/608); `validate_stir_shaken_identity` when the code is 438 and they have the JWS.
codeintegerrequiredSIP response code (e.g. 488 for Not Acceptable Here).
lookup_sip_header1 param[cost: free (pure CPU, no network) | read-only] Instant lookup of a SIP header by canonical or compact form (e.g. "Via" / "v", "Diversion", "P-Asserted-Identity", "Identity", "Session-Expires"). Returns canonical form, compact alias, RFC anchor, where it appears (request / response / both), cardinality (exactly-one / at-most-one / one-or-more / any), allowed/forbidden URI parameters with RFC citations, short description, and related headers. USE FIRST when the user asks about a specific header they saw in a trace - sub-millisecond, no API cost. The cardinality + paramRules fields surface failure modes (e.g. two From: headers, ;tag= on P-Asserted-Identity) without needing a RAG round-trip. Pair with: `lint_sip_request` to mechanically check a real request against these rules; `search_sip_docs` for vendor-specific or 3GPP P-headers not in the bundled registry.
namestringrequiredHeader name (canonical, e.g. "Via", or compact, e.g. "v"). Case-insensitive.
detect_sip_stack3 params[cost: free (pure CPU, no network) | read-only] Identify the SIP product behind a piece of input. Works on both: - a SIP trace (User-Agent / Server headers from PCAP/sngrep/syslog), and - a vendor config blob (kamailio.cfg, sip.conf, pjsip.conf, FreeSWITCH XML, opensips.cfg) detected via structural signatures (loadmodule, route blocks, [transport-*] sections, <profile name=>, etc.). Returns a vendor slug (e.g. "kamailio", "freeswitch", "asterisk", "twilio", "cisco-cube") aligned with the `vendor` filter on `search_sip_docs`, so you can pipe the output of this tool directly into a follow-up doc search. Pair with: `search_sip_docs(vendor=<slug>, ...)` for grounded vendor docs; `review_sip_config` when the input is a config and you also want extracted modules + risk flags; `troubleshoot_response_code(vendorHint=<slug>, ...)` when chasing a status code.
textstringrequiredRaw SIP trace text OR a vendor config blob.kindstringWhat the input is. "trace" looks at SIP headers only, "config" runs vendor-config heuristics, "auto" tries trace first then falls back to config detection.filenameHintstringOptional filename (e.g. "kamailio.cfg", "pjsip.conf"). Strongly improves config-mode detection when supplied.
detect_sip_vendor_from_config2 params[cost: free (pure CPU, no network) | read-only] Heuristic-only sibling of `detect_sip_stack`, scoped to vendor configs. Returns the matched vendor slug, a confidence level, and the structural signals that fired (loadmodule syntax, route blocks, profile elements, etc.). Use this when the user asks 'what is this config?' or attaches a SIP config file. Detect-only - does not extract directives or flag risks. Pair with: `review_sip_config` for the structured outline + risk flags; `search_sip_docs(vendor=<slug>, ...)` to ground each directive.
textstringrequiredConfig blob (UTF-8 plaintext).filenameHintstringOptional filename ("kamailio.cfg", "pjsip.conf", "sofia/external.xml") to bias detection.
minimize_sip_trace2 params[cost: free (pure CPU, no network) | read-only, no persistence] Reduce a raw SIP trace to a compact form suitable for sending to an LLM. Preserves SDP bodies and routing/auth/dialog headers; prunes well-known noise (User-Agent, Server, Allow, Accept-*, Date, P-* informational, etc.). Expected input format: raw SIP messages separated by blank lines, each starting with a request line (`INVITE sip:...@... SIP/2.0`) or status line (`SIP/2.0 200 OK`). PCAP-decoded text from sngrep / ngrep / tcpdump / tshark, syslog with SIP body, sipflow's own export format, or a hand-pasted INVITE/200 dialog all work. Annotation lines like `# [timestamp] sender -> receiver` or ngrep-style `U <ip>:<port> -> <ip>:<port>` between blocks are tolerated. Safe to run on production traces - the input is processed in-memory and is not persisted or sent off-server. Pair with: `detect_sip_stack` to identify the vendor, then `search_sip_docs(vendor=...)` for vendor-grounded analysis; `render_sip_ladder` to visuali
textstringrequiredRaw SIP trace text. Multiple messages may be concatenated.maxBytesintegerTruncate the minimized output if it exceeds this many bytes (default 200000, matches Sipflow's analyze pipeline).
render_sip_ladder11 params[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_si
textstringrequiredRaw SIP trace text. Multiple messages may be concatenated.callIdstringRender only this Call-ID. Required when the trace contains multiple calls; otherwise the only call is used.compactbooleanDrop OPTIONS keepalives and retransmissions. Hidden counts are summarized in a `Note over` line.includeTimingbooleanAppend `+Nms` (delta from previous arrow) to each arrow label.maxMessagesintegerHard cap on rendered arrows. Extra messages produce a truncation note. Hard ceiling is 200.aliasesobjectFriendly 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"}`.groupRetransmitsbooleanCollapse adjacent identical retransmissions on the same direction into a single arrow + `Note over: xN over Tms`. Independent of `compact` (which drops them entirely).highlightFailuresbooleanBold the first non-1xx final response per request leg (CSeq) so the failure jumps out in the ladder.splitOnNewBranchbooleanEmit a `--- failover to <ip[:port]> ---` separator before any request sent to a previously-unseen destination. Useful when the trace fails over between gateway IPs.groupByIpbooleanCollapse 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.correlationHeadersarrayHeader 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"]`.
sip_ladder_example4 params[cost: free (pure CPU, no network) | read-only] Return a hand-curated SIP scenario as a Mermaid `sequenceDiagram` plus a bullet list of step-by-step explanations with RFC references. Use this when the user asks 'show me what X looks like' and you don't have a real trace handy. Available scenarios: basic-call, auth-challenge, cancel-before-answer, early-media, hold-resume, refer-blind, proxy-with-record-route, shaken-attested-invite, bye-glare, redirect-302. Pair with: `search_sip_docs` for vendor-specific quirks of the scenario; `render_sip_ladder` if the user does have a real trace.
scenariostringrequiredWhich scenario to render. Valid ids: basic-call, auth-challenge, cancel-before-answer, early-media, hold-resume, refer-blind, proxy-with-record-route, shaken-attested-invite, bye-glare, redirect-302.actorNamesobjectOverride the default actor display names (Alice/Bob/Proxy). Maps to the first/second/third lane in left-to-right order.includeExplanationbooleanAppend a bulleted **Notes** section with RFC references for each step.verbosebooleanAlso include the scenario's long Markdown explanation. Useful when the LLM is going to teach the user; off by default to keep responses small.
lint_sip_request1 param[cost: free (pure CPU, no network) | read-only, no persistence] Run RFC 3261 / RFC 3325 / RFC 8224 / RFC 8225 / CTIA BCID compliance checks on a single raw SIP request (typically an INVITE) and return a list of findings. Catches the failure modes that silently break carrier interop: - Two `From:` headers in one request (RFC 3261 §7.3 / §20.20). - Missing CRLF between consecutive header lines (RFC 3261 §7.3). - `;tag=` (or any other) parameter on P-Asserted-Identity / P-Preferred-Identity (RFC 3325 §9.1). - PASSporT `orig.tn` not matching the From caller TN (RFC 8224 §5). - PASSporT `dest.tn` not matching the To callee TN (RFC 8224 §5). - Non-canonical TN inside a PASSporT claim (RFC 8225 §5.2.1). - Branded display name in From with no `ppt=rcd` Identity header (CTIA BCID §5). Use FIRST when chasing 422 / 400 Bad Request / 484 Invalid FROM on a single INVITE - these usually have a structural cause this tool catches mechanically. Pair with: `parse_sip_message` for purel
textstringrequiredRaw SIP request text. Should start with the request line (e.g. `INVITE sip:...@... SIP/2.0`). Headers must be CRLF or LF separated.
parse_sip_message1 param[cost: free (pure CPU, no network) | read-only, no persistence] Parse a single raw SIP message (request OR response) and return a structured view: start line (method/status), every header in order with line numbers, body, duplicate-header counts, and a list of structural flags the parser noticed (`missing-crlf`, `tag-on-pai`, `tag-on-ppi`, `invalid-folding`, `duplicate-single-instance`, `content-length-mismatch`). Use FIRST when the user pastes a single INVITE / 200 / NOTIFY and asks 'what does this look like to a parser?' or 'is this even valid?'. The output makes header-level bugs (two `From:` headers, `;tag=` on PAI/PPI, missing CRLF between headers, broken Identity folding) obvious without an LLM having to scan visually. Pair with: `lint_sip_request` for the full RFC compliance suite (request only); `diff_sip_messages` to compare two parsed messages structurally; `validate_stir_shaken_identity` if the message carries an Identity header.
textstringrequiredRaw SIP message text. Should start with a request line (`INVITE sip:...@... SIP/2.0`) or status line (`SIP/2.0 200 OK`). Headers must be CRLF or LF separated.
diff_sip_messages4 params[cost: free (pure CPU, no network) | read-only, no persistence] Take two SIP messages (typically the same request observed at two adjacent hops - e.g. the INVITE leaving FreeSWITCH and the INVITE arriving at Kamailio) and surface a structured per-header diff: `added`, `removed`, `mutated` (with old/new value), `duplicated` (single header → many), `de-duplicated`, `whitespace-only-change`, `parameter-reorder` (Via params, From tag), and `body-changed`. SDP bodies on both sides are delegated to `compareSdp` for codec / DTLS / ICE diffs. Use FIRST when the user has two captures or two log lines that should be carrying the same message and wants to know what an intermediate proxy / SBC / B2BUA changed. Far more reliable than visual inspection. Pair with: `parse_sip_message` to inspect either side in isolation; `lint_sip_request` if the diff reveals the downstream side became malformed; `search_sip_docs(vendor=<intermediate>)` once you know which hop's behavior is the source of the chang
beforestringrequiredSIP message as observed at the *upstream* hop (e.g. what FreeSWITCH believes it sent).afterstringrequiredSIP message as observed at the *downstream* hop (e.g. what Kamailio believes it received).labelBeforestringDisplay label for the upstream side. Default "before".labelAfterstringDisplay label for the downstream side. Default "after".
review_sip_config3 params[cost: free (pure CPU, no network) | read-only] Use this when the user asks 'review my config' or attaches a kamailio.cfg, sip.conf, pjsip.conf, FreeSWITCH XML profile, opensips.cfg, `res_fax.conf` / `udptl.conf` / `spandsp.conf` (fax-relay tuning), or a SIP-shaped source file from a repo. This tool: 1. Detects the vendor from filename + structural signatures (loadmodule, route blocks, [transport-*] sections, <profile name=>, KEMI calls). 2. Extracts a structured outline: loaded modules, modparams, listen lines, route blocks, profiles, gateways, dialplan extensions. 3. Surfaces risk flags - e.g. websocket loaded without TLS, nathelper without rtpengine, chan_sip used in modern Asterisk, AND the Kamailio/OpenSIPS lump-vs-subst race (`subst('/^From:.../...')` colliding with `KSR.hdr.append/remove` or `uac_replace_*` or `append_hf/remove_hf` on the same header - corrupts the buffer at serialization). 4. Returns a list of `suggestedQueries` for `search_sip_docs` so you can ground
textstringrequiredThe full config blob (or a representative excerpt). UTF-8 plaintext.filenameHintstringOptional filename or path (e.g. "kamailio.cfg", "etc/asterisk/pjsip.conf", "sofia/external.xml"). Strongly improves vendor detection.vendorHintstringSkip auto-detection and force a specific vendor. Use when the heuristics return low confidence or the wrong vendor.
webrtc_sip_checklist3 params[cost: free (pure CPU, no network) | read-only] Return a curated checklist of WebRTC ↔ SIP requirements (WSS transport, ICE gathering, DTLS-SRTP fingerprint, rtcp-mux + BUNDLE, media relay / rtpengine, STUN/TURN, secure-context Origin allowlist, Opus codec, session-timer behavior across the bridge, STIR/SHAKEN signing). When `configText` is supplied, each item is marked as 'looks present' or 'check needed' based on simple regex signals. Use when the user is building a WebRTC ↔ SIP bridge or troubleshooting one (no media, one-way audio, ICE failures). Pair with: `review_sip_config` for the full structured outline; `search_sip_docs(vendor=...)` to ground each unchecked item in vendor docs; `parse_sdp` / `compare_sdp_offer_answer` when the bug is in SDP negotiation.
vendorstringVendor slug. Omit and supply `configText` to auto-detect.configTextstringOptional config blob. When supplied, items with matching signals are marked as present; vendor is auto-detected if not supplied.filenameHintstringOptional filename ("kamailio.cfg", etc.) to bias auto-detection.
parse_sdp1 param[cost: free (pure CPU, no network) | read-only] Parse a Session Description Protocol body and return a structured view: origin, session, timing, per-media codecs (rtpmap + fmtp), direction, DTLS setup + fingerprint, ICE credentials + candidates, rtcp-mux, BUNDLE groups, fax-relay (`m=image udptl t38` plus the `a=T38Fax*` attribute family), and crypto attributes. Useful for debugging WebRTC ↔ SIP interop (codec negotiation, DTLS-SRTP fingerprints, ICE candidate gathering, bundle alignment), and for inspecting fax negotiation (T.38 reinvite SDP, `T38FaxMaxBuffer`/`T38FaxUdpEC`/`T38FaxRateManagement`) without an LLM having to re-derive the SDP grammar each call. Pair with: `compare_sdp_offer_answer` when the user has both halves of the negotiation (including T.30→T.38 reinvites); `webrtc_sip_checklist` for the bridge-config angle.
sdpstringrequiredSDP body - the section after the empty line in an INVITE/200/UPDATE.
compare_sdp_offer_answer2 params[cost: free (pure CPU, no network) | read-only] Diff a SIP/SDP offer and answer and surface the issues that actually break calls in practice: codec intersection per m-line, direction compatibility (sendrecv ↔ recvonly), DTLS setup-role conflicts (active+active / passive+passive), rtcp-mux / BUNDLE asymmetry, missing DTLS fingerprints when DTLS-SRTP is negotiated, ICE asymmetry, and fax reinvite mismatches (e.g. offer `m=image udptl t38` answered with audio-only, or `T38FaxVersion` / `T38FaxMaxBuffer` / `T38FaxRateManagement` drift). Use when the user has both halves of a negotiation and is debugging 488 Not Acceptable Here, no-audio, one-way-audio, or a failed T.38 reinvite (488 / 415 / 606 on a `m=image` offer). Pair with: `parse_sdp` to inspect either side in isolation; `search_sip_docs(vendor=...)` to ground vendor-specific fixes (FreeSWITCH `mod_spandsp`, Cisco CUBE `fax protocol t38`); `lookup_response_code(488)` for the static SIP-side context.
offerstringrequiredSDP offer body.answerstringrequiredSDP answer body.
validate_stir_shaken_identity8 params[cost: external_io (HTTPS fetch of the x5u cert) | read-only] Verify a SIP `Identity:` JWS (RFC 8224 / SHAKEN). Fetches the x5u certificate, parses it, verifies the ES256 signature against the cert's public key, and optionally validates the RCD icon hash (RFC 9795). The icon-hash check accepts both `payload.rcdi["/icn"]` (RFC 9795 §6.1 spec form) and the legacy `payload.rcdi["icn"]` form deployed in the wild - the legacy form raises a warning unless `strictRfc9795: true` (then it fails). Returns per-check pass/fail/warning with details - useful for diagnosing 438 Invalid Identity Header rejections, expired certs, and tampered PASSporTs. Pair with: `stir_attestation_explainer` for the human-readable A/B/C interpretation; `lookup_response_code(438)` for the SIP-side context; `lint_sip_request` for non-cryptographic structural checks on the host INVITE.
infoUrlstringCert URL from the SIP Identity header `info=` param (or the JWT `x5u`). If omitted, signature verification is skipped.headerB64stringrequiredBase64url-encoded JWS protected header (the first dot-separated segment).payloadB64stringrequiredBase64url-encoded JWS payload (the second segment).signatureB64stringrequiredBase64url-encoded ES256 signature (the third segment, raw R||S, 64 bytes).iconUrlstringRCD icon URL - `payload.rcd.icn`. Omit if no Rich Call Data icon.expectedIconHashstringPre-extracted icon hash, e.g. `sha256-XYZ` (RFC 9795 §6.1 form `<algorithm>-<base64>`). Pass this OR `rcdi`.rcdiobjectFull `payload.rcdi` claim. The validator looks up `/icn` first (RFC 9795 §6.1 spec form), then falls back to the legacy `icn` key (still seen in the wild). A legacy hit produces a `rcdi-pointer-form` warning unless `strictRfc9795: true` (then it fails).strictRfc9795booleanWhen true, reject the legacy `rcdi['icn']` key as a hard failure rather than warning. Default false.
stir_attestation_explainer2 params[cost: free (pure CPU, no network) | read-only] Static explainer for STIR/SHAKEN: maps attestation levels (A / B / C per RFC 8588) to plain-English requirements + common scenarios, and SIP codes commonly emitted by signing/verification (428 / 436 / 437 / 438 / 608) to their RFC anchors and operator causes. Provide either `attestation` (A/B/C) or `code` (e.g. 438). Pair with: `validate_stir_shaken_identity` when the user has the JWS segments and wants the cryptographic verdict; `search_sip_docs({ sourceType: 'stir-shaken', ... })` for ATIS / CTIA / RFC depth.
attestationstringAttestation level: "A" Full / "B" Partial / "C" Gateway.codeintegerSIP response code commonly seen in STIR/SHAKEN flows (428, 436, 437, 438, 608).
validate_e164_number1 param[cost: free (pure CPU, no network) | read-only] Parse a phone number, normalize to E.164, and classify it. International coverage is via libphonenumber-js (every country, line type when known). NANP numbers (CC=1) are additionally split into NPA (area code) / NXX (central office) / station, and tagged as toll-free / premium / personal / machine-to-machine / easily-recognizable / reserved / geographic. Use when validating `From` / P-Asserted-Identity / SHAKEN `orig.tn`, deciding whether an outbound call needs full attestation, or sanity-checking caller ID format. Pair with: `lint_sip_request` to validate that PASSporT `orig.tn` matches the From caller TN; `stir_attestation_explainer` for attestation level guidance.
numberstringrequiredPhone number in any common form. E.164 (+CCNNN…) is preferred; 10-digit US numbers are accepted as a convenience.
troubleshoot_response_code3 params[cost: rag (one embed + one vector search) | read-only, network: outbound to embed model only | rate-limited per IP] Like `lookup_response_code` but augmented: returns the static RFC entry PLUS the top vendor-specific RAG hits for the exact code (and any free-text context the user pasted). When the static entry carries known vendor-specific reason-phrase variants (e.g. 484 + opensips → 'Invalid FROM' from `parse_from.c`), those phrases are folded into the embed query so the right vendor docs surface. Use when the user asks 'why did <vendor> reject this with <code>?' and you want vendor-grounded common causes, not just the RFC text. Especially helpful for fax-rejection paths - 488 / 415 / 606 on a T.38 reinvite (`m=image udptl t38`) is one of the most common 488 variants and the tool surfaces FreeSWITCH `mod_spandsp` / Cisco CUBE / AudioCodes T.38 docs alongside the RFC text. Pair with: `lookup_response_code` first (cheaper); `lint_sip_request` when the code is 4xx and they have the
codeintegerrequiredSIP response code (e.g. 488, 503, 438).vendorHintstringVendor slug to filter the RAG search (e.g. "kamailio", "freeswitch", "twilio"). Strongly recommended.contextstringOptional free-text context: a snippet of the trace, the Reason header, the Warning header, or a one-line description of what the user was trying to do.
dns_diagnose_sip_target2 params[cost: external_io (DNS via Cloudflare + Google; TLS handshake + a SIP OPTIONS keepalive to public targets when applicable) | read-only | rate-limited per IP: 10/min, 200/day] Walk DNS the same way a SIP UA does (RFC 3263 §4.1): NAPTR → SRV → A/AAAA. Given a SIP URI ("sip:example.com"), bare hostname ("example.com"), or "host:port" string, return the records that exist and the resolution ladder a UA would try. When the queried target uses TLS (`sips:` URI, `transport=tls/wss`, or any `_sips._tcp` SRV record), the tool also performs a TLS handshake against each resolved sips target and reports the negotiated TLS version + cipher, the leaf certificate's subject / issuer / SANs / validity, the chain length and whether it validates against Node's default trust store, plus two cert-domain checks: RFC 5922 §7.2 strict (cert must cover the original SIP domain) and a lenient SAN match against the SRV target hostname. SIP liveness: DNS resolving and a TLS handshake succeeding do NOT prove th
targetstringrequiredSIP URI ("sip:example.com"), "example.com:5060", or bare hostname ("example.com"). Userinfo is stripped before lookup.transportstringTransport hint. "any" surfaces all NAPTR services; specific transports filter the SRV walk to that service.
fetch_sipflow_share1 param[cost: external_io (Mongo + S3 fetch on the Sipflow backend) | read-only, no persistence | rate limit: shared with the public share endpoint] Given a Sipflow share URL (https://sipflow.dev/share/<token>, or any sipflow.dev subdomain that serves /share/<token>), load the shared SIP trace AND any prior AI analysis attached to it in a single round trip. Use this whenever a user pastes a `/share/<token>` URL: the tool fetches the redacted trace text, the AI executive summary / root-cause / remediation steps (if present), and metadata (vendor, filename, source format, pseudonymized flag), so the agent can review the trace alongside the user's own configs without manual download + paste. In addition to the AI output, the response includes rule-based diagnostics: detected issues (severity-tagged SIP/SDP/media problems with RFC references), WebRTC signal checklist scores, multi-leg call correlation (Session-ID grouping), and detected SIP stacks (User-Agent/Server header values). These diagno
urlstringrequiredFull Sipflow share URL. Example: "https://sipflow.dev/share/eyJqb2JJZCI6Ii4uLiJ9.abc123". The path must be /share/<token>; /api/share/... endpoints are not accepted.
submit_sipflow_feedback9 params[cost: write (single MongoDB row) | rate-limited per IP: 3/min, 20/day] Send the Sipflow team feedback when something doesn't work, a vendor or RFC isn't covered, or a tool produced a wrong/incomplete answer. Categories: - docs_gap: search_sip_docs returned nothing useful, vendor missing, coverage incomplete - tool_bug: a tool errored, returned garbage, or behaved unexpectedly on a real input - wrong_answer: the answer it produced was incorrect for the SIP/VoIP question asked - feature_request: a new tool, dataset, or behavior the user wants - general: anything else PRIVACY CONTRACT (MUST FOLLOW): 1. Use this tool only when the user explicitly asks to send feedback, OR when you have completed the user's primary task and there is a clear, actionable gap worth reporting. 2. ALWAYS show the user the exact `summary` + `details` + other fields you plan to send and wait for an explicit yes before calling this tool. Set `userConsent: true` only after that confirmation. 3. NE
categorystringrequiredBucket. Use docs_gap for missing RAG coverage, tool_bug for broken behavior, wrong_answer for incorrect output, feature_request for new asks, general for anything else.summarystringrequiredShort one-line description of the feedback. Will be shown to humans triaging. PII-free.detailsstringLonger description: what the user was trying to do, what happened, what they expected. PII-free.relatedToolstringName of the Sipflow MCP tool the feedback relates to, if any (e.g. `search_sip_docs`, `troubleshoot_response_code`).relatedQuerystringThe search query / question that failed or returned poor results. PII-free.vendorOrTopicstringVendor slug, RFC number, or topic the feedback relates to (e.g. 'freeswitch', 'RFC 3261', 'fax-over-IP').contactstringOptional email the user can be reached at. Only include when the user explicitly provides one and asks you to attach it.traceExcerptstringOptional sanitized SIP message text the user explicitly approved attaching. Use the output of `minimize_sip_trace` (or a hand-scrubbed Via/From/To/Call-ID/CSeq block, optionally with minimal SDP). NEVER paste raw INVITE / REGISTER bodies, full pcap text, or anything containing phone numbers / IPs / Call-IDs you have not already redacted. The server runs a backstop sanitizer that redacts phones, IPs, and emails. Hard cap 32 kB.userConsentbooleanrequiredMUST be true. Set this only after you have shown the user the exact payload above (including any `traceExcerpt`) and they have confirmed they want it sent.
README.md
Sipflow MCP
SIP/VoIP/telecom grounding for AI agents. Vendor docs across ~40 stacks, 60+ RFCs, STIR/SHAKEN, trace and config analysis - every answer cites a verbatim
source_url.
Sipflow is a hosted, read-only Model Context Protocol server. It gives your editor or agent ~20 tools that ground SIP/VoIP answers in a curated corpus instead of training-data recall.
- Live endpoint:
https://mcp.sipflow.dev/mcp(Streamable HTTP) - Web app: https://www.sipflow.dev
- Install page (one-click + all clients): https://www.sipflow.dev/tools/mcp
Install
Cursor (one-click)
Or from the Cursor Marketplace. This repo also ships as a Cursor plugin with a bundled Skill and Rule (see What's in this repo below).
Cursor (manual) - ~/.cursor/mcp.json
{
"mcpServers": {
"sipflow": { "url": "https://mcp.sipflow.dev/mcp" }
}
}
VS Code - .vscode/mcp.json or user settings.json
{
"servers": {
"sipflow": {
"type": "http",
"url": "https://mcp.sipflow.dev/mcp"
}
}
}
Requires VS Code 1.99+ with the GitHub Copilot extension.
Claude Desktop - claude_desktop_config.json
Claude Desktop is stdio-only, so use the mcp-remote shim:
{
"mcpServers": {
"sipflow": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.sipflow.dev/mcp"]
}
}
}
Claude Code (CLI)
claude mcp add --transport http sipflow https://mcp.sipflow.dev/mcp
Codex CLI - ~/.codex/config.toml
[mcp_servers.sipflow]
url = "https://mcp.sipflow.dev/mcp"
Cline - Settings -> MCP Servers -> Edit JSON
{
"mcpServers": {
"sipflow": { "url": "https://mcp.sipflow.dev/mcp" }
}
}
Continue - ~/.continue/config.yaml
mcpServers:
- name: sipflow
transport:
type: streamable-http
url: https://mcp.sipflow.dev/mcp
Windsurf - ~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"sipflow": {
"serverUrl": "https://mcp.sipflow.dev/mcp"
}
}
}
Goose - ~/.config/goose/config.yaml
extensions:
sipflow:
type: http
uri: https://mcp.sipflow.dev/mcp
enabled: true
Generic / curl smoke-test
curl -sS -X POST https://mcp.sipflow.dev/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
What's in this repo
| File / Folder | Marketplace | Purpose |
|---|---|---|
server.json |
Official MCP Registry | Canonical server descriptor. PulseMCP auto-ingests from here. |
smithery.yaml |
Smithery | Remote HTTP listing. |
.cursor-plugin/plugin.json |
Cursor Marketplace | Plugin manifest. |
mcp.json |
Cursor plugin auto-discovery | Points the plugin at the remote endpoint. |
skills/sip-debugger/ |
Cursor plugin | "When to use Sipflow" playbook surfaced as /sip-debugger. |
rules/sip-grounding.mdc |
Cursor plugin | Auto-attaches when editing .pcap, kamailio/opensips/freeswitch/asterisk configs, dialplans, .sdp. |
assets/logo.svg |
All | Logo. |
The Cursor-specific files (.cursor-plugin/, mcp.json, skills/, rules/)
are silently ignored by non-Cursor marketplaces - they only parse their own
manifest.
Tool catalog
All tools are read-only. The only outbound IO is dns_diagnose_sip_target
(DNS + TLS handshake) and validate_stir_shaken_identity (cert fetch).
Discovery / grounding - search_sip_docs, lookup_response_code,
lookup_sip_header
Detection - detect_sip_stack, detect_sip_vendor_from_config
Traces - minimize_sip_trace, render_sip_ladder,
sip_ladder_example, lint_sip_request, parse_sip_message,
diff_sip_messages
Config review - review_sip_config, webrtc_sip_checklist
SDP - parse_sdp, compare_sdp_offer_answer
STIR/SHAKEN - validate_stir_shaken_identity,
stir_attestation_explainer
Telecom - validate_e164_number, troubleshoot_response_code
Network - dns_diagnose_sip_target (rate-limited)
Share hydration - fetch_sipflow_share for sipflow.dev/share/<token> URLs
Resource - sipflow://docs/{vendor}/{id} for a single corpus chunk
Corpus coverage
- ~40 vendor stacks: Kamailio, OpenSIPS, FreeSWITCH, Asterisk (PJSIP + chan_sip), SIP.js, JsSIP, FreePBX, 3CX, OpenSER, Twilio, Cisco, ...
- 60+ RFCs: SIP, SDP, RTP, WebRTC core
- STIR/SHAKEN: RFC 8224/8225/8226/8588/9027/9795
- Branded calling: ATIS-1000074, ATIS-1000094, ATIS-1000084, CTIA BCID
Local development (Cursor plugin)
Test the plugin locally by symlinking this repo into Cursor's local plugin folder:
ln -s "$PWD" ~/.cursor/plugins/local/sipflow
Run Developer: Reload Window in Cursor. You should see:
sipflowserver in Settings -> Features -> Model Context Protocolsip-debuggerskill under Settings -> Rules (Agent Decides)sip-groundingrule under Settings -> Rules
Submitting updates
When the MCP server changes, bump version in three places to keep
registries in sync:
server.json-> Official MCP Registry.cursor-plugin/plugin.json-> Cursor Marketplace- The hosted server's
serverInfo.version
Then re-run mcp-publisher publish for the Official Registry. Cursor,
Smithery, and Glama auto-track the default branch.
License
MIT - see LICENSE.
Recommended MCP Servers
How it compares
Telecom domain MCP grounding server, not a hosted PBX or generic web-search skill.
FAQ
What does Sipflow do?
SIP/VoIP/telecom grounding for AI agents: vendor docs, RFCs, STIR/SHAKEN, traces, configs.
When should I use Sipflow?
User asks about Sipflow mcp, sip/voip/telecom grounding for ai agents: vendor docs, rfcs, stir/shak.
Is this MCP server safe to install?
Review the Security Audits panel on this page before installing in production.