Renames the package from `mcp-cucm-axl` to `mcaxl` to fit the
operator's mc<interface> naming convention (mcusb, mcaxl, …),
and scrubs Bingham-specific defaults so the package works for
anyone, anywhere.
Rename:
- pyproject.toml: name, scripts entry point, description
- src/mcp_cucm_axl/ → src/mcaxl/ (git mv preserves history)
- All Python imports updated via sed
- Cache directory: ~/.cache/mcp-cucm-axl/ → ~/.cache/mcaxl/
- Log prefix [mcp-cucm-axl] → [mcaxl]
- Package version lookup: importlib.metadata.version("mcaxl")
- .mcp.json command updated to invoke `mcaxl` script
- All 155 tests pass under the new name (verified)
Bingham-specific scrubs:
- docs_loader._DEFAULT_INDEX_DIR: hardcoded /home/rpm/bingham/...
path removed; defaults to None. Operators set CISCO_DOCS_INDEX_PATH
env var; without it, prompts gracefully degrade with a fallback
notice instructing the LLM to use the cisco-docs MCP search_docs
tool instead.
- prompts/_common.docs_or_empty_msg: removed the explicit
/home/rpm/bingham/... path from the fallback message text.
- server.py: removed dead-code copy of _docs_or_empty_msg() that
was leftover from before the prompts package extraction.
- README.md: completely rewritten as a public-facing readme. Lead
paragraph names CUCM as the target platform, install instructions
cover uvx / pip / Claude Code MCP add. Recommends cisco-cucm-mcp
as the operations counterpart.
PyPI metadata:
- Initial CalVer version: 2026.04.27
- License: MIT (LICENSE file added)
- Project URLs: Homepage / Source / Issues / Changelog all point
at git.supported.systems/mcp/mcaxl (newly-created Gitea repo
in the mcp/ org for PyPI releases)
- Classifiers: Beta / Telecommunications Industry / Topic:Telephony
- Keywords: mcp, cisco, cucm, axl, risport, voip, sip, audit
- sdist excludes: CLAUDE.md, .env*, axlsqltoolkit.zip, audits/,
tests/, pytest/ruff caches. Verified clean: wheel ships only the
mcaxl/ source tree + LICENSE + METADATA + entry_points.
CHANGELOG.md added with a 2026.04.27 initial-release entry,
documenting tool/prompt counts, structural read-only guarantees,
Hamilton review closure, live-cluster verification, and known
limitations.
Build verification:
- `uv build` produces clean wheel + sdist
- Wheel: 22 source files, 195KB total, no Bingham-specific files
- Sdist excludes verified: no CLAUDE.md, no axlsqltoolkit.zip
- Entry point: `mcaxl = mcaxl.server:main`
- Package installs as mcaxl==2026.4.27
Closes bingham/mcp-cucm-axl#1
route_devices_using_css missed device.fkcallingsearchspace_cgpntransform
and _cdpntransform — the columns trunks use to attach calling-party and
called-party number transformation CSSs. A CSS only referenced via these
columns showed up as "0 references" in impact analysis, leading an
operator to conclude safe-to-delete and break outbound transformations.
Same failure shape as Hamilton CRITICAL #2 (false-zero impact analysis)
but at a different schema layer: that fix added 7 reference points
covering the obvious cases; this fix closes the rest.
What's covered now (71 fkcallingsearchspace_* columns total across 14
tables in CUCM 15):
Templates added for the bulk cases:
_device_query(suffix) — device.fkcallingsearchspace_<suffix>
_devicepool_query(suffix) — devicepool.fkcallingsearchspace_<suffix>
_numplan_query(suffix) — numplan.fkcallingsearchspace_<suffix>
Categories added (51 new):
11× device variants (incl. _cgpntransform and _cdpntransform — the issue)
17× devicepool inheritance variants (closes M1 caveat from audit reports)
13× numplan forwarding/transformation variants (cfbint/cfhr/etc.)
site, externalcallcontrolprofile, recordingprofile, usageprofile,
vipre164transformation×2, incomingtransformationprofile×4
Schema gotchas discovered and codified:
- devicepool, externalcallcontrolprofile, recordingprofile have no
`description` column (verified against syscolumns 2026-04-26)
- site has neither `name` nor `description` — uses `tksite` enum joined
against `typesite.name` for the human-readable form
Live verification on cucm-pub.binghammemorial.org (CUCM 15.0.1.12900-234):
XFORM-Outbound-ANI: 0 → 1 ref (PSTN-Router-SIP-Trk via _cgpntransform)
XFORM-Outbound-DNIS: 0 → 1 ref (PSTN-Router-SIP-Trk via _cdpntransform)
E911CSS: unchanged at 0, but now with `complete: True`
— upgrades from "appears orphan with caveat" to
"confirmed orphan" since DP variants now covered
Internal-CSS: 163 → 174 refs (DP + extra numplan variants)
Tests (128 → 134, +6):
test_issue_1_cgpntransform_column_enumerated
test_issue_1_cdpntransform_column_enumerated
test_finds_trunk_via_cgpntransform_reference (mock-driven E2E)
test_complete_schema_coverage_against_known_columns
— encodes the 71-column snapshot from CUCM 15. If a future CUCM
version adds a new fkcallingsearchspace_* column, the test fires
red so the contributor knows to add it to _CSS_REFERENCE_QUERIES.
test_no_duplicate_table_column_pairs
— guards against double-counting if two categories accidentally
reference the same column.
test_error_in_multiple_tables_propagates
— verifies error reporting works across the new shared-suffix cases
(e.g., _cgpnunknown on both device AND devicepool).
Three findings from a margaret-hamilton-style review of the MCP server,
fixed with regression tests written first (red → green). One bonus
finding (huntpilotqueue column name) was surfaced by the third fix
itself — exactly the audit-trust failure mode that fix exists to expose.
CRITICAL #1 — sql_validator: comment-strip mutated string literals.
The cleaned query returned by validate_select() is what travels to AXL.
Previously, the comment-strip pass ran before the literal-aware pass,
so `--` or `/* */` markers inside a string literal were silently eaten:
input: WHERE description = 'Smith -- old line'
to AXL: WHERE description = 'Smith (truncated mid-literal)
The LLM saw rows that looked plausible but were not what its query
asked for. "Confidently wrong" is exactly the failure mode the review
was hunting.
Fix: only strip comments on the analysis-only copy used for keyword
detection. The cleaned output preserves the input verbatim (modulo
trailing semicolon and outer whitespace). 6 new tests covering literal
preservation across `--`, `/* */`, LIKE patterns with embedded comment
markers, and forbidden keywords inside real comments.
CRITICAL #2 — cache key omitted cluster identity.
The on-disk cache key was `method::args_json`. An operator swapping
AXL_URL between test and prod (or between two clusters) would silently
serve stale data from cluster A as if from cluster B. The audit
report would be confidently wrong with no signal anything happened.
Fix: AxlCache now takes cluster_id and prefixes all keys with it.
Server bootstrap derives cluster_id as a 12-char SHA-256 prefix of
AXL_URL. cache_stats() surfaces both the current cluster_id and a
`foreign_cluster_entries` count so an env-swap is visible. Schema
migration handles pre-fix cache files via PRAGMA table_info introspection
plus a one-shot ALTER TABLE ADD COLUMN. 5 new tests covering isolation,
shared-id sharing, stats reporting, legacy DB upgrade, and per-cluster
clear() scoping.
MAJOR #3 — find_devices_using_css summary undercounted partial failures.
The function is per-category resilient (one failed query doesn't kill
the whole impact analysis), but the resilience never propagated up to
the response. total_returned and any_truncated only reflected SUCCESSFUL
categories. An LLM consuming "47 references" had no way to know 5
categories errored and the real number was likely much higher.
Fix: response now includes complete: bool, categories_with_errors: int,
and error_categories: [list]. The LLM/auditor sees the partial-failure
state and can decide whether to act on incomplete data. 5 new tests
using a FakeAxlClient stand-in to simulate per-category failures.
BONUS finding (uncovered by Major #3 fix): huntpilotqueue join used
the wrong column. Three CSS impact categories (huntpilot_max_wait_css,
huntpilot_no_agent_css, huntpilot_queue_full_css) were silently
erroring with "Column (fknumplan) not found" because huntpilotqueue
joins via fknumplan_pilot, not fknumplan. With the Major #3 fix in
place, this surfaced immediately as `complete: False, error_categories:
[3 huntpilot_*]` against the live cluster. Fixed inline; live re-run
now reports `complete: True, total_returned: 163` for Internal-CSS.
87 unit tests passing (up from 70). Live cluster smoke test
(cucm-pub.binghammemorial.org, CUCM 15.0.1.12900-234) verifies all
three fixes plus the bonus finding work end-to-end.