dlg_end
Terminate active SIP dialogs by providing Call-ID, From-tag, and To-tag. Use to tear down unwanted or stuck calls.
Instructions
End (tear down) an active dialog.
Parameters
callid: The Call-ID of the dialog to terminate. from_tag: The From-tag of the dialog. to_tag: The To-tag of the dialog.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| callid | Yes | ||
| from_tag | Yes | ||
| to_tag | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- The actual MCP tool handler for 'dlg_end'. Decorated with @mcp.tool(), @audited('dlg_end'), and @require_permission('mi.write'). Accepts callid, from_tag, and to_tag parameters, builds a dialog_id, then executes the 'dlg_end_dlg' MI command via mi_client.execute().
@mcp.tool() @audited("dlg_end") @require_permission("mi.write") async def dlg_end( ctx: Context, callid: str, from_tag: str, to_tag: str, ) -> dict[str, Any]: """End (tear down) an active dialog. Parameters ---------- callid: The Call-ID of the dialog to terminate. from_tag: The From-tag of the dialog. to_tag: The To-tag of the dialog. """ app = ctx.request_context.lifespan_context result = await app.mi_client.execute( "dlg_end_dlg", {"dialog_id": f"{callid}:{from_tag}:{to_tag}"}, ) return result - MI command registry entry for 'dlg_end_dlg' — declares its module ('dialog'), description, required params (dialog_id, extra_hdrs), permission ('mi.write'), and category ('dialog'). This is the schema/definition of the underlying MI command that dlg_end invokes.
_r("dlg_end_dlg", "dialog", "End (tear down) a dialog", ["dialog_id", "extra_hdrs"], "mi.write", "dialog") _r("profile_get_size", "dialog", "Get number of dialogs in a profile", ["profile", "value"], category="dialog") _r("profile_list_dlgs", "dialog", "List dialogs in a profile", ["profile", "value"], category="dialog") _r("profile_get_values", "dialog", "Get values in a dialog profile", ["profile"], category="dialog") _r("profile_end_dlgs", "dialog", "End all dialogs in a profile", ["profile", "value"], "mi.write", "dialog") - src/opensips_mcp/tools/dialog_tools.py:40-63 (registration)The @mcp.tool() decorator on line 40 registers 'dlg_end' as an MCP tool with the FastMCP server instance.
@mcp.tool() @audited("dlg_end") @require_permission("mi.write") async def dlg_end( ctx: Context, callid: str, from_tag: str, to_tag: str, ) -> dict[str, Any]: """End (tear down) an active dialog. Parameters ---------- callid: The Call-ID of the dialog to terminate. from_tag: The From-tag of the dialog. to_tag: The To-tag of the dialog. """ app = ctx.request_context.lifespan_context result = await app.mi_client.execute( "dlg_end_dlg", {"dialog_id": f"{callid}:{from_tag}:{to_tag}"}, - src/opensips_mcp/mi/client.py:26-48 (helper)The _is_idempotent() helper function. For dlg_end_dlg, it returns False (non-idempotent) because the command has 'mi.write' permission, which means the MI client will not retry dlg_end_dlg on 5xx errors.
def _is_idempotent(method: str | None) -> bool: """Return True if it is safe to retry *method* on a server 5xx. Reads the per-command permission from the MI registry as a proxy for idempotency: anything labelled ``mi.read``, ``stats.read``, ``health.read``, ``db.read``, ``config.read``, ``docs.read``, or ``resource.read`` is read-only and therefore safe to retry. Any write / execute / reload / process.manage permission is treated as non-idempotent and will NOT be retried on 5xx. Unknown methods default to **non-idempotent** — the safe choice when we cannot verify the command's effect. """ if not method: return False # Lazy import to avoid a circular at module load time. from opensips_mcp.mi.commands import MI_COMMANDS cmd = MI_COMMANDS.get(method) if cmd is None: return False perm = (cmd.permission or "").lower() return perm.endswith(".read") or perm in {"health.read", "docs.read"}