The original 2026.04.27 was published-then-deleted from PyPI within
hours after a stricter audit (against the unpacked sdist, not just
curated source paths) found cluster-fingerprint content that the
pre-publish grep had missed. This release supersedes the deleted one;
no functional differences.
Issues found in 2026.04.27 that this fixes:
1. docs/query-patterns/sip-trunk-report.md — "Live result snapshot"
section (38 lines) contained the live cluster's actual SIP trunk
inventory: real hostnames (exp-c-p.binghammemorial.org), real
internal IPs (172.20.6.99, .104, .105, .114, .120, .222, plus
172.20.2.22, 172.20.14.105, 172.24.10.10), real trunk-name +
description rows. Section removed entirely. The query-pattern doc
itself still ships — schema/SQL guidance is generic and useful.
One inline FQDN example (`exp-c-p.binghammemorial.org`) replaced
with `exp-c-p.example.com`. Status line that named the specific
maintenance release (`Validated against CUCM 15.0.1.12900-234 on
2026-04-25.`) genericized to `Validated against CUCM 15.`
2. .mcp.json shipping in sdist with `/home/rpm/bingham/axl` as the
`--directory` argument. Local filesystem path = hostname leak.
Added to `[tool.hatch.build.targets.sdist] exclude`. File stays
in the source repo for development; no longer ships.
3. pyproject.toml comment about the audit workflow ironically
contained the literal word "bingham" as the example grep token.
Rewritten to use "site-specific tokens" generically.
Audit verification (against the unpacked sdist this time):
tar -xzf dist/mcaxl-2026.4.27.1.tar.gz -C /tmp/sdist-inspect
grep -rnEi 'bingham|binghammemorial|10\.[0-9]+\.[0-9]+\.[0-9]+|
172\.(1[6-9]|2[0-9]|3[01])\.[0-9]+\.[0-9]+|
192\.168\.[0-9]+\.[0-9]+|SupportedSystems|CCX-AXL|
CER-AXL|CUC-AXL|TabSync|variphy|15\.0\.1\.12900|
production cluster|/home/rpm|cucm-pub\.bingham'
/tmp/sdist-inspect/
→ returns empty (verified)
Tests still 155/155.
Lesson encoded for next time: the pre-publish audit MUST run against
the unpacked sdist, not just the four explicitly-named paths in the
python.md rule (src/, tests/, README.md, pyproject.toml, .env.example).
The sdist also pulls in docs/, top-level dotfiles, and uv.lock.
CHANGELOG.md spells this out in the post-release note for next time.
4.1 KiB
Changelog
This project uses CalVer — version numbers
encode the date the package was tested against the upstream Cisco APIs
and published. Format: YYYY.MM.DD with optional .N post-release
suffix for same-day fixes.
2026.04.27.1 — same-day PII scrub
Post-release fix per the python.md immutability rule. The original
2026.04.27 was published-then-deleted from PyPI after a stricter
audit found cluster-fingerprint content in the shipped sdist that the
pre-publish audit had missed:
docs/query-patterns/sip-trunk-report.mdcontained a "Live result snapshot" section with the test cluster's actual SIP trunk inventory (real hostnames, real internal IPs). The query-pattern doc itself still ships; the snapshot section has been removed and one inline FQDN example replaced with.example.com..mcp.jsonwas shipping in the sdist with a local filesystem path. Added to[tool.hatch.build.targets.sdist] exclude. The file remains in the source repo for development; it no longer ships.
Lesson encoded for next time: the pre-publish PII audit must run
against the unpacked sdist, not just curated source paths. The
sdist also pulls in docs/, top-level dotfiles like .mcp.json, and
uv.lock. The python.md rule's example grep covers fewer paths than
the actual sdist blast surface; the durable fix is tar -xzf dist/*.tar.gz -C /tmp/inspect && grep -rnE 'site-token' /tmp/inspect
before every publish.
No functional changes between 2026.04.27 and 2026.04.27.1 — just metadata and shipped-doc content.
2026.04.27 — initial public release (deleted)
Yanked-and-deleted from PyPI on the publish date due to a sdist PII leak. Superseded by
2026.04.27.1. Retained here as a marker.
First public release on PyPI as mcaxl. Renamed from the internal
working name mcp-cucm-axl to fit the operator's mc<interface>
naming convention.
Tools (19 total)
Foundational: axl_version, axl_sql, axl_list_tables,
axl_describe_table, cache_stats, cache_clear, health.
Route plan: route_partitions, route_calling_search_spaces,
route_patterns, route_inspect_pattern, route_lists_and_groups,
route_translation_chain, route_digit_discard_instructions,
route_device_pool_route_groups, route_devices_using_css,
route_filters.
Real-time registration (RisPort70): device_registration_status,
device_registration_summary.
Prompts (10 total)
Schema-grounded conversation seeds: route_plan_overview,
investigate_pattern, audit_routing, cucm_sql_help,
sip_trunk_report, phone_inventory_report, user_audit,
inbound_did_audit, hunt_pilot_audit, whoami.
Engineering rigor
- Read-only by structural guarantee: no AXL write methods are registered; the SQL validator rejects non-SELECT/WITH queries as defense-in-depth.
- Hamilton-style review closed: 7 findings (2 Critical, 3 Major, 2 Minor) addressed during pre-release hardening, each with a regression test.
- Live-cluster verified: every tool path verified against a live CUCM 15 cluster before release.
- 155 unit tests, schema drift guard for all 71 known
fkcallingsearchspace_*columns (viatest_complete_schema_coverage_against_known_columns).
Known limitations
route_translation_chainevaluates CUCM wildcards (X,!,[0-9],@,\\+) but does not model route-filter constraints on@patterns — use as guidance, not authoritative.- AXL WSDL must be supplied externally (Cisco-licensed; not bundled).
See
README.mdfor bootstrap instructions. - RisPort
state_infocursor pagination is implemented but not yet stress-tested on clusters with > 1000 devices in a single class.
Acknowledgments
Borrowed two ideas from
@calltelemetry/cisco-cucm-mcp
(MIT licensed): the RisPort70 SOAP envelope shape and the
exponential-backoff retry policy on HTTP 503. Their tool covers
operational debugging (logs, perfmon, packet capture) — install both
side-by-side for compound questions like "audit found CSS X
unreferenced AND RisPort confirms zero phones registered against it."