{"_id":"@calltelemetry/cisco-cucm-mcp","name":"@calltelemetry/cisco-cucm-mcp","dist-tags":{"latest":"0.7.1"},"versions":{"0.7.1":{"name":"@calltelemetry/cisco-cucm-mcp","version":"0.7.1","type":"module","description":"MCP server for CUCM operational debugging: DIME logs, AXL config, RIS device status, PerfMon counters, service health, packet capture, and pcap analysis","license":"MIT","repository":{"type":"git","url":"git+https://github.com/calltelemetry/cisco-cucm-mcp.git"},"bin":{"cisco-cucm-mcp":"build/index.js"},"publishConfig":{"access":"public"},"keywords":["mcp","model-context-protocol","cisco","cucm","unified-communications","voip","sip","dime","packet-capture","wireshark","axl","perfmon","risport","serviceability"],"engines":{"node":">=18"},"packageManager":"yarn@4.12.0","scripts":{"build":"vite build && chmod +x build/index.js","start":"node build/index.js","dev":"tsx src/index.ts","typecheck":"tsc --noEmit","lint":"eslint src/ test/ --max-warnings=20","lint:fix":"eslint src/ test/ --fix","format":"prettier --write 'src/**/*.ts' 'test/**/*.ts'","format:check":"prettier --check 'src/**/*.ts' 'test/**/*.ts'","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","validate":"yarn typecheck && yarn lint && yarn test","prepack":"yarn build && yarn test"},"dependencies":{"@modelcontextprotocol/sdk":"^1.27.1","fast-xml-parser":"^4.5.3","ssh2":"^1.16.0","zod":"^3.24.2"},"devDependencies":{"@eslint/js":"^9.39.3","@types/node":"^25.1.0","@types/ssh2":"^1.15.4","@vitest/coverage-v8":"^4.0.18","eslint":"^9.39.3","prettier":"^3.8.1","tsx":"^4.19.4","typescript":"^5.7.3","typescript-eslint":"^8.56.1","vite":"^7.3.1","vitest":"^4.0.18"},"_id":"@calltelemetry/cisco-cucm-mcp@0.7.1","gitHead":"e670d7742b694108ca9cb70dc26d0b50f32fd3d6","bugs":{"url":"https://github.com/calltelemetry/cisco-cucm-mcp/issues"},"homepage":"https://github.com/calltelemetry/cisco-cucm-mcp#readme","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-jb1FKoyFWz4Ffo2UMo9tOKH15Zz+NZuulhLmbFvTNY7SSmjY0j12qRNZfUC+alfvWipP/rN09inG8kbjdjOPXw==","shasum":"e2c03e170be7b7164f03dbba17494b4aca7bb1ef","tarball":"https://registry.npmjs.org/@calltelemetry/cisco-cucm-mcp/-/cisco-cucm-mcp-0.7.1.tgz","fileCount":5,"unpackedSize":681590,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDrXIKQSrH/wBjgcQhxG6YbtOsKy8Yr8luBU+fjZtvnIgIgEJw5qBAkl1v5MYABm8pzhXYso+K9knZ3SHON1FL0p6k="}]},"_npmUser":{"name":"jasonbarbee","email":"jason.barbee@gmail.com"},"directories":{},"maintainers":[{"name":"jasonbarbee","email":"jason.barbee@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cisco-cucm-mcp_0.7.1_1774068476433_0.1968103002824484"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-21T04:47:56.332Z","0.7.1":"2026-03-21T04:47:56.582Z","modified":"2026-03-21T04:47:56.812Z"},"maintainers":[{"name":"jasonbarbee","email":"jason.barbee@gmail.com"}],"description":"MCP server for CUCM operational debugging: DIME logs, AXL config, RIS device status, PerfMon counters, service health, packet capture, and pcap analysis","homepage":"https://github.com/calltelemetry/cisco-cucm-mcp#readme","keywords":["mcp","model-context-protocol","cisco","cucm","unified-communications","voip","sip","dime","packet-capture","wireshark","axl","perfmon","risport","serviceability"],"repository":{"type":"git","url":"git+https://github.com/calltelemetry/cisco-cucm-mcp.git"},"bugs":{"url":"https://github.com/calltelemetry/cisco-cucm-mcp/issues"},"license":"MIT","readme":"# cisco-cucm-mcp\n\n[![CI](https://github.com/calltelemetry/cisco-cucm-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/calltelemetry/cisco-cucm-mcp/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/@calltelemetry/cisco-cucm-mcp)](https://www.npmjs.com/package/@calltelemetry/cisco-cucm-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/@calltelemetry/cisco-cucm-mcp)](https://www.npmjs.com/package/@calltelemetry/cisco-cucm-mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nBuilt by [Call Telemetry](https://calltelemetry.com) — realtime tools for Cisco Collaboration.\n\n[![Install in Claude Code](https://img.shields.io/badge/Claude_Code-Install-5A28E4?logo=claude)](https://claude.ai/mcp/install?repo=calltelemetry/cisco-cucm-mcp)\n[![Install in Cursor](https://img.shields.io/badge/Cursor-Install-2D2D2D?logo=cursor)](https://cursor.com/mcp/install?repo=calltelemetry/cisco-cucm-mcp)\n\nMCP (Model Context Protocol) server for Cisco CUCM operational debugging — 61 tools covering logs, device inventory, performance monitoring, packet capture, call analysis, service control, AXL discovery, certificates, backups, CTI status, cluster topology, and more.\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        CUCM Cluster                             │\n├──────────┬──────────┬──────────┬──────────────┬────────────────┤\n│ DIME     │ RisPort  │ PerfMon  │ ControlCenter│ ControlCenter  │\n│ :8443    │ :8443    │ :8443    │ :8443        │ Extended :8443 │\n│          │          │          │              │                │\n│ Logs     │ Device   │ Counters │ Service      │ Start/Stop/    │\n│ CDR      │ status   │ Sessions │ status       │ Restart        │\n│ Files    │ CTI      │          │              │ Service list   │\n├──────────┴──────────┼──────────┴──────────────┴────────────────┤\n│ AXL :8443           │ SSH :22                                  │\n│                     │                                          │\n│ Phone config        │ Version, cluster, status, network,       │\n│ 300+ operations     │ certs, backups, packet capture           │\n│ WSDL discovery      │                                          │\n└─────────────────────┴──────────────────────────────────────────┘\n                      ▲\n                      │  cisco-cucm-mcp — 61 MCP tools\n                      ▼\n              ┌───────────────┐\n              │  MCP Client   │\n              │ (Claude, etc) │\n              └───────────────┘\n```\n\n## Capabilities\n\n- **DIME Log Collection** — Query and download trace/log files via CUCM DIME SOAP services on `:8443`\n- **Log Presets** — Schema-aware presets for SIP traces, CTI traces, and CURRI routing logs\n- **Batch Download** — Download multiple log files in one operation with partial failure tolerance\n- **Syslog** — Query and download system log files via DIME\n- **RisPort70 (Real-time Device Status)** — Query phone/gateway/trunk registration status via selectCmDevice, auto-paginating for large clusters (>1000 devices)\n- **CTI Status** — Query real-time CTI ports, route points, and application connections via selectCtiItem\n- **PerfMon (Performance Monitoring)** — Collect real-time counters, open monitoring sessions for continuous polling, add/remove counters\n- **ControlCenter (Service Status)** — Query CUCM service health: Started, Stopped, Not Activated (read-only)\n- **Service Control** — Start, stop, restart CUCM services via ControlCenterServicesEx; list all deployable services\n- **CDR on Demand** — List and download CDR/CMR files by time range via CDRonDemandService + DIME\n- **Cluster Health Check** — One-shot health: devices + counters + services in parallel with partial failure tolerance\n- **AXL Discovery** — Parse WSDL to list all AXL operations and describe their input/output schemas\n- **SSH CLI Tools** — Version info, cluster topology, system status, network details via CUCM CLI over SSH\n- **Certificate Status** — List TLS certificates (own/trust) via CUCM CLI over SSH\n- **DRF Backup Status** — Check backup job status and history via CUCM CLI over SSH\n- **Packet Capture** — Start/stop captures via CUCM CLI over SSH, download `.cap` files via DIME\n- **Pcap Analysis** — Analyze captured pcaps locally via tshark: SIP flows, SCCP messages, RTP quality metrics\n- **SDL Trace Parser** — Parse SDL trace files into structured signals and call flows (local analysis)\n- **Rate Limiting** — Auto-retry with exponential backoff on CUCM rate limits (HTTP 503)\n\n## Installation\n\n```bash\nnpx @calltelemetry/cisco-cucm-mcp\n```\n\n## Quick Start\n\n### Claude Code\n\n```bash\nclaude mcp add cucm -- npx -y @calltelemetry/cisco-cucm-mcp@latest\n```\n\n### Manual Configuration\n\nAdd to your `.mcp.json` (credentials come from env vars — see [Auth Best Practices](#auth-best-practices)):\n\n```json\n{\n  \"mcpServers\": {\n    \"cucm\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@calltelemetry/cisco-cucm-mcp@latest\"]\n    }\n  }\n}\n```\n\nOr pass credentials explicitly via the `env` block (not recommended — prefer shell env vars):\n\n```json\n{\n  \"mcpServers\": {\n    \"cucm\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@calltelemetry/cisco-cucm-mcp@latest\"],\n      \"env\": {\n        \"CUCM_USERNAME\": \"<cucm-user>\",\n        \"CUCM_PASSWORD\": \"<cucm-pass>\",\n        \"CUCM_SSH_USERNAME\": \"<ssh-user>\",\n        \"CUCM_SSH_PASSWORD\": \"<ssh-pass>\"\n      }\n    }\n  }\n}\n```\n\n### Verify Installation\n\nAfter setup, verify the connection by running:\n\n```\n→ guess_timezone_string({})\n{ \"timezone\": \"Client: (GMT-6:0)America/Chicago\" }\n```\n\n## Configuration\n\n### Shared Credentials\n\n| Variable | Description |\n|----------|-------------|\n| `CUCM_USERNAME` | Shared default username (fallback for DIME, AXL, RIS, PerfMon, ControlCenter) |\n| `CUCM_PASSWORD` | Shared default password |\n\n### SSH (CLI)\n\n| Variable | Description |\n|----------|-------------|\n| `CUCM_SSH_USERNAME` | SSH username (often `administrator`) |\n| `CUCM_SSH_PASSWORD` | SSH password |\n| `CUCM_SSH_PORT` | SSH port (default: `22`) |\n\n### AXL Version\n\n| Variable | Description |\n|----------|-------------|\n| `CUCM_VERSION` | AXL API version (default: `15.0`) |\n\n### TLS\n\nCUCM lab environments often use self-signed certificates. By default this server sets `NODE_TLS_REJECT_UNAUTHORIZED=0`.\n\n| Variable | Description |\n|----------|-------------|\n| `CUCM_MCP_TLS_MODE` | `permissive` (default) or `strict` |\n\n### tshark (Pcap Analysis)\n\nThe pcap analysis tools require **tshark** (Wireshark CLI). Discovered automatically:\n\n1. `TSHARK_PATH` env var\n2. `tshark` in PATH\n3. `/Applications/Wireshark.app/Contents/MacOS/tshark` (macOS)\n4. `/usr/bin/tshark` (Linux)\n5. `/opt/homebrew/bin/tshark` (Homebrew)\n\n| Variable | Description |\n|----------|-------------|\n| `TSHARK_PATH` | Override tshark binary location |\n| `CUCM_MCP_TSHARK_TIMEOUT_MS` | Execution timeout (default: `60000`) |\n\n### Serviceability APIs (RIS, PerfMon, ControlCenter)\n\nThese APIs share the same credentials and port as DIME. No additional environment variables needed.\n\n### AXL WSDL Cache\n\nAXL WSDL and XSD schemas are cached to disk so `axl_list_operations` and `axl_describe_operation` return instantly after the first fetch. The cache has no expiration — it persists until manually cleared.\n\n| Variable | Description |\n|----------|-------------|\n| `CUCM_MCP_WSDL_CACHE_DIR` | Cache directory (default: `~/.cisco-cucm-mcp/wsdl-cache/`) |\n\nCache files are stored as `{host}_{port}.json`. To force a re-fetch, delete the cache directory or call `clearWsdlCache()` programmatically.\n\n### Capture State Persistence\n\nPacket capture metadata is persisted to a local JSON file for recovery after MCP restarts.\n\n| Variable | Description |\n|----------|-------------|\n| `CUCM_MCP_STATE_PATH` | State file path (default: `./.cucm-mcp-state.json`) |\n| `CUCM_MCP_CAPTURE_RUNNING_TTL_MS` | Running capture TTL (default: 6 hours) |\n| `CUCM_MCP_CAPTURE_STOPPED_TTL_MS` | Stopped capture TTL (default: 24 hours) |\n\n## Tools\n\n### Log Collection (DIME)\n\n| Tool | Description |\n|------|-------------|\n| `list_node_service_logs` | List CUCM cluster nodes and their available service logs |\n| `select_logs` | Query log files with date/time criteria |\n| `select_logs_minutes` | Convenience: find logs from the last N minutes |\n| `select_syslog_minutes` | Convenience: find system logs from the last N minutes |\n| `select_sip_traces` | Preset: collect SIP traces (CallManager + CTIManager) |\n| `select_cti_traces` | Preset: collect CTI traces (CTIManager + Extension Mobility) |\n| `select_curri_logs` | Preset: collect CURRI external call control logs |\n| `download_file` | Download a single file via DIME |\n| `download_batch` | Download multiple files in one operation (max 20, partial failure tolerant) |\n\n### AXL (Phone Configuration)\n\n| Tool | Description |\n|------|-------------|\n| `axl_execute` | Execute any AXL SOAP operation |\n| `axl_download_wsdl` | Download the AXL WSDL schema |\n| `axl_list_operations` | Parse WSDL — list all AXL operations grouped by type (list/get/add/update/remove) |\n| `axl_describe_operation` | Parse WSDL — describe input/output schema for a specific operation |\n| `get_trace_config` | Get current trace/debug level for a service (via AXL SQL) |\n| `set_trace_level` | Set debug trace level for a service — Error through Detailed |\n| `phone_packet_capture_enable` | Enable packet capture on a phone (updatePhone + applyPhone) |\n\n### RisPort70 (Real-time Device Status)\n\n| Tool | Description |\n|------|-------------|\n| `select_cm_device` | Query device registration status (phones, gateways, trunks) with filters. Returns `stateInfo` pagination cursor. |\n| `select_cm_device_by_ip` | Convenience: look up device registration by IP address |\n| `select_cm_device_all` | Auto-paginating query — iterates StateInfo to return ALL devices (clusters >1000 phones) |\n| `select_cti_item` | Query real-time CTI ports, route points, and application connections |\n\n### PerfMon (Performance Monitoring)\n\n| Tool | Description |\n|------|-------------|\n| `perfmon_collect_counter_data` | Collect counter values for a PerfMon object (e.g. \"Cisco CallManager\") |\n| `perfmon_list_counter` | Discover available PerfMon objects and counters |\n| `perfmon_list_instance` | List instances of a PerfMon object |\n| `perfmon_open_session` | Open a PerfMon monitoring session (returns handle) |\n| `perfmon_add_counter` | Add counters to a session |\n| `perfmon_collect_session_data` | Poll counter values from a session |\n| `perfmon_remove_counter` | Remove counter(s) from a session without closing it |\n| `perfmon_close_session` | Close a session |\n\n### CDR on Demand\n\n| Tool | Description |\n|------|-------------|\n| `cdr_get_file_list` | List CDR/CMR files by UTC time range (max 1 hour) |\n| `cdr_get_file_list_minutes` | List CDR/CMR files from last N minutes (max 60) |\n| `cdr_download_file` | Download a CDR/CMR file by filename (from `cdr_get_file_list` results) |\n\n### ControlCenter (Service Status)\n\n| Tool | Description |\n|------|-------------|\n| `get_service_status` | Query CUCM service status — Started, Stopped, Not Activated (read-only) |\n| `list_services_extended` | List all deployable services with activation status (ControlCenterServicesEx) |\n| `start_service` | Start one or more CUCM services (destructive) |\n| `stop_service` | Stop one or more CUCM services (destructive) |\n| `restart_service` | Restart one or more CUCM services (destructive) |\n\n### Cluster Health\n\n| Tool | Description |\n|------|-------------|\n| `cluster_health_check` | One-shot health: devices + counters + services in parallel |\n\n### Certificate Status (SSH CLI)\n\n| Tool | Description |\n|------|-------------|\n| `cert_list` | List TLS certificates on a CUCM node (own/trust/both) |\n\n### DRF Backup Status (SSH CLI)\n\n| Tool | Description |\n|------|-------------|\n| `drf_backup_status` | Current backup job status |\n| `drf_backup_history` | Past backup history entries |\n\n### SSH CLI Tools\n\n| Tool | Description |\n|------|-------------|\n| `show_version` | Get CUCM version info (active/inactive version + build) |\n| `show_network_cluster` | Get cluster node topology — hostname, IP, type, hub/spoke, replication status |\n| `show_status` | System health: hostname, platform, CPU%, memory, disk usage, uptime |\n| `show_network_eth0` | Network details: IP address, subnet, gateway, DNS, link speed, duplex |\n\n### Packet Capture (SSH + DIME)\n\n| Tool | Description |\n|------|-------------|\n| `packet_capture_start` | Start capture via CUCM CLI over SSH |\n| `packet_capture_stop` | Stop a running capture |\n| `packet_capture_stop_and_download` | Stop + download `.cap` via DIME (with retries) |\n| `packet_capture_list` | List active in-memory captures |\n| `packet_capture_state_list` | List captures from persistent state file |\n| `packet_capture_state_get` | Get one capture record from state |\n| `packet_capture_state_clear` | Delete a capture record from state |\n| `packet_capture_download_from_state` | Download by captureId after MCP restart |\n\n### Pcap Analysis (tshark)\n\nThese tools analyze downloaded `.cap` files so an LLM can reason about VoIP calls without opening Wireshark.\n\n| Tool | Description |\n|------|-------------|\n| `pcap_call_summary` | High-level overview: protocols, endpoints, SIP/RTP counts |\n| `pcap_sip_calls` | SIP call flows grouped by Call-ID with setup timing |\n| `pcap_sccp_messages` | SCCP/Skinny messages with human-readable type names |\n| `pcap_rtp_streams` | RTP quality per stream: jitter, packet loss, codec, duration |\n| `pcap_protocol_filter` | Arbitrary tshark display filter for deeper investigation |\n\n### SDL Trace Parser (Local Analysis)\n\n| Tool | Description |\n|------|-------------|\n| `sdl_trace_parse` | Parse SDL trace into structured signals and call flows |\n| `sdl_trace_call_flow` | Extract call flow for a specific call-id |\n\n### Utility\n\n| Tool | Description |\n|------|-------------|\n| `guess_timezone_string` | Build a DIME-compatible timezone string |\n\n## Examples — LLM Conversations (Real CUCM 15 Output)\n\nAll examples below are real interactions with a live CUCM 15.0.1 cluster, showing how an LLM uses the tools conversationally.\n\n---\n\n### \"What version of CUCM is running?\"\n\n> **User:** What version is my CUCM running?\n\n<details><summary>Tool call: <code>show_version</code></summary>\n\n```json\n{ \"host\": \"192.168.125.10\" }\n```\n\n```json\n{\n  \"activeVersion\": \"15.0.1.12900\",\n  \"activeBuild\": \"234\",\n  \"inactiveVersion\": \"\",\n  \"inactiveBuild\": \"\"\n}\n```\n\n</details>\n\n> **Assistant:** Your CUCM is running **15.0.1.12900** (build 234). There's no inactive version installed — this is a single-partition deployment.\n\n---\n\n### \"How's the cluster health looking?\"\n\n> **User:** Give me a quick health check on the cluster.\n\nThe LLM calls three tools in parallel to assess system health:\n\n<details><summary>Tool call: <code>show_status</code> — CPU, memory, disk</summary>\n\n```json\n{ \"host\": \"192.168.125.10\" }\n```\n\n```json\n{\n  \"hostname\": \"cucm15-cluster1\",\n  \"platform\": \"15.0.1.12900-234.x86_64\",\n  \"cpuPercent\": 49.75,\n  \"memoryTotalMb\": 11718,\n  \"memoryUsedMb\": 7173,\n  \"disks\": [\n    { \"partition\": \"Disk/active\",  \"usedMb\": 15765, \"totalMb\": 19297, \"percent\": 83 },\n    { \"partition\": \"Disk/logging\", \"usedMb\": 24616, \"totalMb\": 67176, \"percent\": 39 }\n  ],\n  \"uptime\": \"12:29\"\n}\n```\n\n</details>\n\n<details><summary>Tool call: <code>show_network_cluster</code> — topology + replication</summary>\n\n```json\n{ \"host\": \"192.168.125.10\" }\n```\n\n```json\n{\n  \"nodes\": [\n    {\n      \"hostname\": \"cucm15-cluster1\",\n      \"ipAddress\": \"192.168.125.10\",\n      \"type\": \"Publisher\",\n      \"replicationStatus\": \"authenticated\"\n    }\n  ]\n}\n```\n\n</details>\n\n<details><summary>Tool call: <code>get_service_status</code> — 81 services</summary>\n\n```json\n{ \"host\": \"192.168.125.10\" }\n```\n\n```json\n[\n  { \"serviceName\": \"Cisco CallManager\",        \"serviceStatus\": \"Started\" },\n  { \"serviceName\": \"Cisco CTIManager\",         \"serviceStatus\": \"Started\" },\n  { \"serviceName\": \"Cisco Tftp\",               \"serviceStatus\": \"Started\" },\n  { \"serviceName\": \"Cisco AXL Web Service\",    \"serviceStatus\": \"Started\" },\n  { \"serviceName\": \"Cisco RIS Data Collector\", \"serviceStatus\": \"Started\" },\n  { \"serviceName\": \"Cisco CDR Agent\",          \"serviceStatus\": \"Started\" },\n  \"... 75 more services ...\"\n]\n```\n\n</details>\n\n> **Assistant:** Cluster looks healthy:\n>\n> - **Node:** cucm15-cluster1 (Publisher, replication authenticated)\n> - **CPU:** 49.75% — moderate load\n> - **Memory:** 7,173 / 11,718 MB (61% used)\n> - **Disk:** Active partition at 83% — keep an eye on this. Logging at 39%, plenty of room.\n> - **Services:** 65 of 81 started — the 16 stopped are all \"Not Activated\" (Bulk Provisioning, DHCP, etc.), which is normal for a lab.\n> - **Uptime:** 12 hours 29 minutes\n\n---\n\n### \"Are all my phones registered?\"\n\n> **User:** Show me which phones are registered.\n\n<details><summary>Tool call: <code>select_cm_device</code> — RIS real-time query</summary>\n\n```json\n{\n  \"host\": \"192.168.125.10\",\n  \"deviceClass\": \"Phone\",\n  \"status\": \"Any\",\n  \"selectItems\": [\"*\"]\n}\n```\n\n```json\n{\n  \"totalDevicesFound\": 3,\n  \"cmNodes\": [\n    {\n      \"name\": \"cucm15-cluster1\",\n      \"returnCode\": \"Ok\",\n      \"devices\": [\n        {\n          \"name\": \"SEP000832C78E0F\",\n          \"ipAddress\": \"192.168.125.85\",\n          \"description\": \"Auto 1001\",\n          \"dirNumber\": \"1001\",\n          \"status\": \"Registered\",\n          \"protocol\": \"SIP\",\n          \"activeLoadId\": \"sip78xx.14-3-1-0001-60\"\n        },\n        {\n          \"name\": \"SEP0022905C7710\",\n          \"ipAddress\": \"192.168.125.178\",\n          \"description\": \"Auto 1000 7975 Phone3\",\n          \"dirNumber\": \"1000\",\n          \"status\": \"Registered\",\n          \"protocol\": \"SCCP\",\n          \"activeLoadId\": \"SCCP75.9-4-2SR4-3S\"\n        },\n        {\n          \"name\": \"SEP505C885DF37F\",\n          \"ipAddress\": \"192.168.125.234\",\n          \"description\": \"Auto 1003 9841\",\n          \"dirNumber\": \"1003\",\n          \"status\": \"Registered\",\n          \"protocol\": \"SIP\",\n          \"activeLoadId\": \"PHONEOS.3-2-1-0003-28\"\n        }\n      ]\n    }\n  ]\n}\n```\n\n</details>\n\n> **Assistant:** All 3 phones are **Registered** on cucm15-cluster1:\n>\n> | Phone | DN | IP | Protocol | Firmware |\n> |-------|----|----|----------|----------|\n> | SEP000832C78E0F (7821) | 1001 | 192.168.125.85 | SIP | sip78xx.14-3-1 |\n> | SEP0022905C7710 (7975) | 1000 | 192.168.125.178 | SCCP | SCCP75.9-4-2SR4 |\n> | SEP505C885DF37F (9841) | 1003 | 192.168.125.234 | SIP | PHONEOS.3-2-1 |\n>\n> No unregistered or rejected devices found.\n\n---\n\n### \"Check the certificates on CUCM\"\n\n> **User:** What TLS certs does CUCM have?\n\n<details><summary>Tool call: <code>cert_list</code> — SSH CLI</summary>\n\n```json\n{ \"host\": \"192.168.125.10\", \"type\": \"own\" }\n```\n\n```json\n[\n  { \"unit\": \"tomcat\",            \"name\": \"tomcat\",            \"issuer\": \"Self-signed\" },\n  { \"unit\": \"tomcat-ECDSA\",     \"name\": \"tomcat-ECDSA\",     \"issuer\": \"Self-signed\" },\n  { \"unit\": \"ipsec\",            \"name\": \"ipsec\",            \"issuer\": \"Self-signed\" },\n  { \"unit\": \"ITLRecovery\",      \"name\": \"ITLRecovery\",      \"issuer\": \"Self-signed\" },\n  { \"unit\": \"CallManager-ECDSA\",\"name\": \"CallManager-ECDSA\",\"issuer\": \"Self-signed\" },\n  { \"unit\": \"CallManager\",      \"name\": \"CallManager\",      \"issuer\": \"Self-signed\" },\n  { \"unit\": \"CAPF\",             \"name\": \"CAPF\",             \"issuer\": \"Self-signed\" },\n  { \"unit\": \"TVS\",              \"name\": \"TVS\",              \"issuer\": \"Self-signed\" }\n]\n```\n\n</details>\n\n> **Assistant:** CUCM has **8 identity certificates**, all self-signed:\n>\n> - **tomcat** / **tomcat-ECDSA** — Web admin UI\n> - **CallManager** / **CallManager-ECDSA** — SIP TLS, phone signaling\n> - **ipsec** — DRF backup encryption, IPSec tunnels\n> - **ITLRecovery** — Initial Trust List recovery\n> - **CAPF** — Certificate Authority Proxy Function (phone certs)\n> - **TVS** — Trust Verification Service\n>\n> All are self-signed, which is typical for a lab. For production you'd want CA-signed certs on at least tomcat and CallManager.\n\n---\n\n### \"Debug a call routing issue\"\n\n> **User:** A call from 1000 to 1001 isn't connecting. Can you capture what's happening?\n\nThe LLM chains multiple tools — starting a packet capture, then analyzing the SIP flow:\n\n<details><summary>Tool call: <code>packet_capture_start</code> — filter SIP port 5060</summary>\n\n```json\n{\n  \"host\": \"192.168.125.10\",\n  \"portFilter\": 5060,\n  \"count\": 5000\n}\n```\n\n```json\n{\n  \"captureId\": \"c2439a09-b082-4c91-ba1e-20b211f1a217\",\n  \"status\": \"running\",\n  \"startedAt\": \"2026-03-11T18:25:44.000Z\"\n}\n```\n\n</details>\n\n> **Assistant:** Capture is running. Go ahead and place the call from 1000 to 1001 now — I'll stop and analyze when you're ready.\n\n> **User:** Ok, call is done.\n\n<details><summary>Tool call: <code>packet_capture_stop_and_download</code></summary>\n\n```json\n{\n  \"host\": \"192.168.125.10\",\n  \"captureId\": \"c2439a09-b082-4c91-ba1e-20b211f1a217\"\n}\n```\n\n```json\n{\n  \"localPath\": \"/tmp/cucm-mcp/readme-demo.cap\",\n  \"fileSize\": 10532,\n  \"status\": \"downloaded\"\n}\n```\n\n</details>\n\n<details><summary>Tool call: <code>pcap_sip_calls</code> — SIP call ladder</summary>\n\n```json\n{ \"filePath\": \"/tmp/cucm-mcp/readme-demo.cap\" }\n```\n\n```json\n{\n  \"calls\": [\n    {\n      \"callId\": \"6e51c0-60e94629-6-64257ec0@192.168.125.10\",\n      \"from\": \"\\\"1000\\\" <sip:1000@192.168.125.10>\",\n      \"to\": \"<sip:1001@192.168.125.10>\",\n      \"messages\": [\n        { \"method\": \"INVITE\",  \"timestamp\": \"18:25:56.742\" },\n        { \"status\": \"100 Trying\",  \"timestamp\": \"18:25:56.743\" },\n        { \"status\": \"180 Ringing\", \"timestamp\": \"18:25:56.754\" },\n        { \"status\": \"200 OK\",      \"timestamp\": \"18:25:57.899\" },\n        { \"method\": \"ACK\",         \"timestamp\": \"18:25:57.901\" },\n        { \"method\": \"BYE\",         \"timestamp\": \"18:26:12.555\" },\n        { \"status\": \"200 OK\",      \"timestamp\": \"18:26:12.556\" }\n      ],\n      \"setupTime\": \"1157 ms\",\n      \"codec\": \"PCMU (G.711 u-law)\"\n    }\n  ]\n}\n```\n\n</details>\n\n<details><summary>Tool call: <code>pcap_rtp_streams</code> — audio quality</summary>\n\n```json\n{ \"filePath\": \"/tmp/cucm-mcp/readme-demo.cap\" }\n```\n\n```json\n{\n  \"streams\": [\n    {\n      \"src\": \"192.168.125.85:29390\",\n      \"dst\": \"192.168.125.10:28770\",\n      \"codec\": \"PCMU (G.711 u-law)\",\n      \"packets\": 748,\n      \"lost\": 0,\n      \"lossPercent\": \"0.00%\",\n      \"maxJitter\": \"0.00 ms\",\n      \"duration\": \"14.9 s\"\n    }\n  ]\n}\n```\n\n</details>\n\n> **Assistant:** The call actually completed successfully:\n>\n> - **INVITE → 100 → 180 → 200 OK → ACK** — clean setup in 1,157ms\n> - **BYE → 200 OK** — clean teardown after ~15 seconds\n> - **RTP:** 748 packets, **0% loss**, **0ms jitter** — perfect audio quality\n> - **Codec:** G.711 u-law (PCMU)\n>\n> The SIP flow looks textbook. If the issue is intermittent, I'd suggest enabling Detailed trace level on Cisco CallManager and reproducing again — we can then pull the SDL traces for deeper analysis.\n\n---\n\n### \"Pull recent CallManager traces\"\n\n> **User:** Get me the last hour of CallManager logs.\n\n<details><summary>Tool call: <code>select_logs_minutes</code></summary>\n\n```json\n{\n  \"host\": \"192.168.125.10\",\n  \"serviceLogs\": [\"Cisco CallManager\"],\n  \"minutesBack\": 60\n}\n```\n\n```json\n{\n  \"fromDate\": \"03/11/26 5:10 PM\",\n  \"toDate\": \"03/11/26 6:10 PM\",\n  \"files\": [\n    {\n      \"absolutePath\": \"/var/log/active/cm/trace/ccm/sdl/SDL001_100_000448.txt.gz\",\n      \"name\": \"SDL001_100_000448.txt.gz\",\n      \"filesize\": 1049171,\n      \"modifiedDate\": \"Tue Mar 11 17:05:28 PDT 2026\"\n    }\n  ]\n}\n```\n\n</details>\n\n<details><summary>Tool call: <code>download_file</code> → <code>sdl_trace_parse</code> (chained)</summary>\n\n```json\n{\n  \"savedPath\": \"/tmp/cucm-mcp/SDL001_100_000448.txt.gz\",\n  \"bytes\": 1049171\n}\n```\n\n```json\n{\n  \"totalLines\": 47896,\n  \"parsedSignals\": 17410,\n  \"signalSummary\": {\n    \"CtiGetDeviceAndLineInfoReq\": 3090,\n    \"CtiExistingCallEventReq\": 3322,\n    \"SIPRegisterInd\": 82,\n    \"StationRegister\": 10\n  }\n}\n```\n\n</details>\n\n> **Assistant:** Downloaded and parsed the SDL trace — **17,410 signals** across 47,896 lines. Key activity:\n>\n> - **CTI events** dominate (3,322 existing call events + 3,090 device info requests) — typical for a monitored cluster\n> - **SIP registrations:** 82 re-registration events\n> - **Station registrations:** 10 (likely phone reboots or config changes)\n>\n> Want me to drill into a specific call ID or look for error signals?\n\n---\n\n### \"What AXL operations can I use for phones?\"\n\n> **User:** What can I do with phones through AXL?\n\n<details><summary>Tool call: <code>axl_list_operations</code> (via <code>axl_execute</code>)</summary>\n\n```json\n{\n  \"operation\": \"listPhone\",\n  \"data\": {\n    \"searchCriteria\": { \"name\": \"SEP%\" },\n    \"returnedTags\": { \"name\": \"\", \"model\": \"\", \"description\": \"\" }\n  }\n}\n```\n\n```json\n{\n  \"phone\": [\n    { \"name\": \"SEP0022905C7710\", \"model\": \"Cisco 7975\",  \"description\": \"Auto 1000 7975 Phone3\" },\n    { \"name\": \"SEP000832C78E0F\", \"model\": \"Cisco 7821\",  \"description\": \"Auto 1001\" },\n    { \"name\": \"SEP505C885DF37F\", \"model\": \"Cisco 9841\",  \"description\": \"Auto 1003 9841\" }\n  ]\n}\n```\n\n</details>\n\n> **Assistant:** Your cluster has 3 phones configured in AXL:\n>\n> | Device | Model | Description |\n> |--------|-------|-------------|\n> | SEP0022905C7710 | Cisco 7975 | Auto 1000 7975 Phone3 |\n> | SEP000832C78E0F | Cisco 7821 | Auto 1001 |\n> | SEP505C885DF37F | Cisco 9841 | Auto 1003 9841 |\n>\n> Via `axl_execute` you can run any AXL operation — `getPhone`, `updatePhone`, `addPhone`, `removePhone`, `listPhone`. Use `axl_describe_operation` to see required fields for any operation.\n\n## What Tool Do I Use?\n\n| I want to... | Use these tools |\n|---|---|\n| Check phone registration | `select_cm_device` or `select_cm_device_all` |\n| Debug SIP call setup | `select_sip_traces` → `download_batch` → `sdl_trace_parse` |\n| Debug CURRI routing | `select_curri_logs` → `download_file` |\n| Monitor call volume | `perfmon_collect_counter_data` (Cisco CallManager object) |\n| Debug call quality | `packet_capture_start` → `pcap_sip_calls` + `pcap_rtp_streams` |\n| Check cluster health | `cluster_health_check` (one-shot parallel) |\n| Find recent logs | `select_logs_minutes` → `download_file` |\n| Download many logs | `select_sip_traces` → `download_batch` |\n| Query phone config | `axl_execute` with listPhone/getPhone |\n| Discover AXL operations | `axl_list_operations` → `axl_describe_operation` |\n| Check system resources | `show_status` (CPU, memory, disk, uptime) |\n| Debug network issues | `show_network_eth0` (IP, gateway, DNS) |\n| Check/change trace level | `get_trace_config` → `set_trace_level` (Detailed for debugging) |\n| Restart stuck service | `restart_service` (requires confirmation) |\n\n## Recommended Workflows\n\n### Cluster Health Assessment\n\n```\n1. show_version             → CUCM version + build number\n2. show_network_cluster     → Node topology, replication status\n3. cluster_health_check     → One-shot: devices + counters + services (parallel)\n4. select_cm_device_all     → Full device inventory (auto-paginates >1000 devices)\n5. cert_list                → TLS certificate inventory (own + trust)\n6. drf_backup_status        → Current backup job status\n7. drf_backup_history       → Last successful backup date\n```\n\n### Log Investigation\n\n```\n1. list_node_service_logs   → Discover available services per node\n2. select_logs_minutes      → Find trace files from last N minutes\n3. download_file            → Download a specific trace to /tmp/cucm-mcp/\n4. sdl_trace_parse          → Parse SDL trace into signals + call flows\n5. sdl_trace_call_flow      → Drill into a specific call-id\n```\n\n### Continuous Performance Monitoring\n\n```\n1. perfmon_open_session     → Get session handle\n2. perfmon_add_counter      → Subscribe to specific counters\n3. perfmon_collect_session_data → Poll (repeat as needed)\n4. perfmon_remove_counter   → Remove counters without closing session\n5. perfmon_close_session    → Cleanup when done\n```\n\n### Packet Capture + Analysis\n\n```\n1. packet_capture_start     → Start capture (runs on CUCM in background)\n2. (reproduce the issue)\n3. packet_capture_stop_and_download → Stop + download .cap file\n4. pcap_call_summary        → Quick triage: what's in the capture?\n5. pcap_sip_calls           → SIP INVITE → 200 OK → BYE flows\n6. pcap_rtp_streams         → Audio quality: jitter, loss, codec\n```\n\n### Auth Best Practices\n\n**Use environment variables for credentials** — never hardcode them in `.mcp.json` or tool parameters. Set credentials in your shell profile (e.g. `~/.zshrc`) or use a secrets manager:\n\n```bash\n# In ~/.zshrc\nexport CUCM_USERNAME=\"your-cucm-admin\"\nexport CUCM_PASSWORD=\"your-password\"\nexport CUCM_SSH_USERNAME=\"your-ssh-user\"\nexport CUCM_SSH_PASSWORD=\"your-ssh-password\"\n```\n\nThen your `.mcp.json` stays credential-free:\n\n```json\n{\n  \"mcpServers\": {\n    \"cucm\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@calltelemetry/cisco-cucm-mcp@latest\"]\n    }\n  }\n}\n```\n\nAll tools accept optional `auth` parameters as overrides, but env vars are the recommended approach. Tool parameters are visible in LLM conversation history.\n\n### Auth Fallback Chains\n\nEach API resolves credentials through its own fallback chain:\n\n| API | Fallback Order |\n|-----|---------------|\n| **DIME** | `auth` param → `CUCM_USERNAME` / `CUCM_PASSWORD` |\n| **AXL** | `auth` param → `CUCM_USERNAME` / `CUCM_PASSWORD` |\n| **SSH** | `auth` param → `CUCM_SSH_USERNAME` / `CUCM_SSH_PASSWORD` |\n| **RIS/PerfMon/ControlCenter** | Same as DIME |\n\nSet `CUCM_USERNAME` / `CUCM_PASSWORD` for all CUCM API access (DIME, AXL, RIS, PerfMon, ControlCenter). SSH uses separate `CUCM_SSH_*` env vars since OS-level credentials often differ.\n\n```bash\n# Verify CUCM credentials (WSDL should return HTTP 200)\ncurl -k -u \"$CUCM_USERNAME:$CUCM_PASSWORD\" \\\n  \"https://<cucm-host>:8443/logcollectionservice2/services/LogCollectionPortTypeService?wsdl\" \\\n  -o /dev/null -w \"%{http_code}\\n\"\n```\n\n## Troubleshooting\n\n| Problem | Solution |\n|---------|----------|\n| Auth failures | Verify with `curl -k -u \"$CUCM_USERNAME:$CUCM_PASSWORD\" \"https://host:8443/logcollectionservice2/services/LogCollectionPortTypeService?wsdl\" -o /dev/null -w \"%{http_code}\\n\"` — should return `200` |\n| Rate limiting (HTTP 503) | RIS/PerfMon enforce ~15 req/min. Auto-retry with 5s→10s→20s backoff is built in. |\n| `tshark` not found | pcap analysis tools require Wireshark CLI — `brew install wireshark` (macOS) or `apt install tshark` (Linux) |\n| Self-signed TLS errors | Set `CUCM_MCP_TLS_MODE=permissive` (default) or add CUCM cert to system trust store |\n| SSH \"too many auth failures\" | CUCM requires `keyboard-interactive` auth — handled automatically by this server |\n| Node.js version | Requires Node.js >= 18 (for native `fetch` API) |\n| Service control fails | ControlCenterServicesEx requires Standard Admin role on the CUCM user account |\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history.\n\n## Development\n\n```bash\nyarn install          # Install dependencies\nyarn build            # Build with Vite\nyarn test             # Run tests (vitest)\nyarn test:coverage    # Run tests with coverage\nyarn typecheck        # TypeScript type checking\nyarn lint             # ESLint\nyarn validate         # typecheck + lint + test\nyarn dev              # Run from source (tsx)\n```\n\n## Publishing\n\nReleases are automated via GitHub Actions on version tags:\n\n```bash\n# Bump version and tag\nnpm version patch     # or minor, major\ngit push --follow-tags\n```\n\nThe publish workflow runs typecheck, tests, builds, publishes to npm, and creates a GitHub release.\n\n## Acknowledgments\n\n- [MCP SDK](https://github.com/modelcontextprotocol/sdk) — Model Context Protocol framework\n- [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) — XML parsing\n- [ssh2](https://github.com/mscdex/ssh2) — SSH client for CUCM CLI\n- [tshark/Wireshark](https://www.wireshark.org/) — Pcap analysis\n\n## License\n\nMIT — see [LICENSE](LICENSE)\n","readmeFilename":"README.md","_rev":"1-d4c7fb8a12b034cdefd12ab58b9e532f"}