Skip to content

Releases: secure-ssid/hpe-networking-mcp

Release list

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 25 Aug 15:34

Version 0.10.0 is the first published release after 0.8.0. It makes the structured API corpus work on a clean clone with no network, denies platform writes unless they are asked for, removes the standalone client in favour of a real MCP host, and replaces a set of CI gates that reported success over comparisons they never made.

0.9.0 was never published as a GitHub Release. If you are upgrading from 0.8.0 you receive its changes too — see Upgrading from 0.8.0 below.

Highlights

Offline API lookup — the OpenAPI corpus ships in the repository

The New Central and Juniper Mist OpenAPI corpora are vendored into vendor/openapi/, digest-pinned in vendor/openapi/MANIFEST.json, and the spec index is built from those committed documents rather than fetched. A clean checkout with no network and no local build can answer lookup_api.

  • 31 vendored specs, 1,535 API paths, each with its source_url, SHA-256,
    fetch date and upstream registry pin (vendor/openapi/MANIFEST.json). Licences stay separated: 30 documents are proprietary HPE Aruba Networking material redistributed verbatim for reference, 1 is MIT — see vendor/openapi/NOTICE.md.
  • scripts/build_spec_index.py builds data/specs.sqlite from that corpus
    offline. A missing index now raises one actionable error naming the build command instead of degrading silently.
  • The index is baked into the published container image and published as a
    reproducible spec-index-<tag>.tar.gz release archive. The router overlay no longer shadows the baked index.
  • That shipped index is roughly a fifth of its former size. Schema identity
    is a fingerprint that was repeated verbatim on every field row, so a 200-field schema stored its whole field list 200 times. Storing a 128-bit blake2b digest of the same serialization instead — hashlib, never the per-process-salted hash(), so builds stay deterministic — took data/specs.sqlite from 243.2 MB to 45.6 MB as measured by the change that made it (4cbdccc), with idx_fields_identity alone falling 107.6 MB to 3.6 MB. Nothing read the inlined value: every remaining use compares it for equality. The image bake precedes that change, so the 0.10.0 image and archive are built from the reduced database.

Writes are denied by default — BREAKING

HPE_MCP_CENTRAL_WRITES must be set to a truthy value (1, true, yes or on, case-insensitive) — or HPE_MCP_ACCESS_PROFILE=full-read-write — to expose Central write and destructive tools. Previously Central alone defaulted to enabled, so import hpe_networking_mcp with no configuration produced a server willing to dispatch reboot_device and disconnect_client.

Two adjacent holes closed with it: a backend with no registered write gate now denies writes rather than allowing them, and a dispatcher re-install that would drop the write gate is refused. The three write-gate mechanisms are pinned to each other by test, so removing one fails the suite instead of quietly widening the surface.

The standalone hpe-mcp client is removed — BREAKING

Use an MCP host — VS Code/Copilot, Copilot CLI, Claude, or any other stdio or streamable-HTTP client — against hpe-mcp-router. Personal document ingestion remains available through scripts/ingest_personal_docs.py. The environment variables that only cli_client/ consumed (HPE_MCP_CLIENT_CONFIG, HPE_MCP_HTTP_URL, HPE_MCP_MAX_RESULT_CHARS, HPE_MCP_SHELL_HISTORY, HPE_MCP_AI_PROVIDER, and the ANTHROPIC_*/OPENAI_*/OLLAMA_* keys) are gone from the documented set.

invoke_tools_batch — a write-capable batch dispatcher

The mixed read+write sibling of invoke_read_tool_batch. Every step dispatches through the same _dispatch_tool path a single invoke_tool call uses, so global read-only gates, per-platform deny-by-default write gates, per-call rate charging and response bounding all apply per step with no duplicated enforcement. Destructive steps keep their per-step confirmation elicitation.

on_error="stop" (the default) halts at the first non-ok step — including a gate-blocked write — and reports halted/remaining; on_error="continue" reproduces the read batch's collect-all semantics. Batch metrics and audit labels resolve to the most severe step, so a batch containing a write is never labelled read.

Prometheus text exposition on /metrics

The bounded metrics snapshot renders as Prometheus text (version 0.0.4) by default; the JSON snapshot (schema_version 1, still unstable) is retained via ?format=json or a JSON-only Accept header. Zero new runtime dependencies — render_prometheus() is a pure function over the snapshot dict.

Outcomes and capabilities render as two separate marginal counter families: the registry never stores a joint capability×outcome count, so no joint series is fabricated. Exclusive per-bin latency buckets convert to cumulative le counts, with latency_over_max folded into le="+Inf" so sum(le) equals latency_count. Route registration and auth posture are unchanged — still gated by HPE_MCP_METRICS_HTTP plus HPE_MCP_METRICS, still inheriting bearer auth and allow-lists. Design and the emitted name set are documented in observability.md.

corpus_provenance — weigh an answer by what produced it

One read-only rag-core tool reporting what backs a result, for both corpora in one call, because a caller cannot know which one served it. For the committed spec corpus it answers on a clean checkout with no network: document count, API paths, fetch dates and the per-licence split, with each document's source_url, SHA-256 and upstream pin available on request (detail=True, or spec= taking a lookup_api file_path verbatim). For the locally built prose corpus it reports per-source chunk counts and refresh times when the index exists, and names the command that builds it when it does not.

Three absences stay three distinct answers, each with its own remedy: no corpus, a corpus whose declared files are gone (a git restore, not a re-fetch), and a corpus with no index built over it. A malformed manifest degrades rather than raising.

Errors are envelopes everywhere, and credentials do not ride in them

  • Response envelope on every backend. A tool that raises now produces the
    same {ok, status, data, message, tool, platform} payload a returned error dict gets — on every standalone backend chain and through the router alike — delivered as an isError=true result instead of bare ToolError text. Elicitation, protocol errors and cancellation still propagate untouched.
  • Credential redaction on the raised-exception paths. The SDK reframes a
    raise as ToolError('Error executing tool <name>: <message>'), embedding a bearer credential mid-string where the prefix rule missed it. Both the router dispatch path and the standalone middleware on_error path now redact before the envelope is built, with the two duplicate helpers consolidated into one shared.redact_tool_error_text — exactly one such regex repo-wide. The mask requires 8+ characters so ordinary 401 prose is not over-masked; a shorter credential would slip past it, which is an accepted tradeoff because the vault tokenizer still catches known secrets.
  • Pooled HTTP clients are drained on shutdown and restart.
    aclose_pooled_clients() had a docstring saying "call from server shutdown" and zero production call sites; every transport leaked pooled httpx.AsyncClient objects to GC, and an in-process restart inherited a registry of unclosable dead-loop clients. Every transport now runs under a serve-plus-finally-drain wrapper.
  • Reads retry, writes never do. A bounded retry on safe verbs only:
    429/502/503/504 and transport errors retry up to twice, with exponential backoff on a base capped at 8s and ±20% jitter — or, when the response carries Retry-After (delta-seconds or HTTP-date), that hint as-is, hard capped at 60s with no jitter. No write is ever retried. The guardrail is structural rather than a policy flag: the helper takes no method parameter, and the generic-executor dispatcher routes only a bodiless GET into it, so a caller whose verb is decided at runtime cannot re-send a mutation.
  • The token cache fails closed. An unwritable cache directory raises with a
    remedy instead of silently falling back to the working directory, where a token file could leak into a checkout, archive or container layer. Point TOKEN_CACHE_DIR somewhere writable.

Container distribution

main and v* tag pushes build linux/amd64 + linux/arm64, push under a non-promoted sha-<short> tag, apply the fixable CRITICAL/HIGH Trivy policy to that exact manifest list, and only then promote the digest to :latest and the semver tags via imagetools. A dirty scan never yields a pullable release tag. Base images are digest-pinned and inlined so Dependabot can see them (a ${VAR} tag is skipped outright by its Docker parser), sidecars are digest-pinned, and the secrets bridge exports only recognized families, announcing every fill and skipping unknown *_FILE vars loudly.

The README quickstart is now pull-first against ghcr.io/secure-ssid/hpe-networking-mcp, with the <host>:* port-wildcard allow-list form the router's non-loopback bind check actually requires.

Benchmark harness and CI regression gate

tools/benchmark, tests/benchmark and a fake Central API substrate land with a scheduled/per-PR workflow, a recorded baseline, and the methodology contract in benchmark-methodology.md.

Four gate defects were fixed in the same range, all of the same class — a comparison that silently passes by not looking. The allowances were wired to undefined repository variables (GitHub substitutes an empty string, so the default never fired and float('') raised after all scenarios had run — and at ...

Read more

v0.8.0

Choose a tag to compare

@secure-ssid secure-ssid released this 21 Aug 02:33

hpe-networking-mcp 0.8.0

Released 2026-08-12.

Version 0.8.0 launches secure-ssid/hpe-networking-mcp as the clean,
product-neutral successor to secure-ssid/centralmcp. The legacy repository
and its history remain untouched as a rollback and reference point. The new
repository uses an installable src/hpe_networking_mcp/ package, hpe-mcp-*
commands, HPE_MCP_* project configuration, and product-specific MCP server
IDs.

This is a breaking pre-1.0 rename. Follow
MIGRATION.md
when moving an existing checkout or MCP client configuration.

Highlights

MCP 2 transport and runtime

  • Uses the MCP Python SDK 2.x MCPServer API.
  • Repairs streamable HTTP and bearer-protected HTTP startup by passing host,
    port, and transport-security settings through supported APIs.
  • Preserves the Starlette lifespan/session-manager context when static bearer
    authentication is enabled.
  • Covers health, initialize, tools/list, tools/call, bearer rejection, and
    authenticated round trips with real protocol tests.
  • Rejects unknown toolsets, products, RAG backends, unsafe HTTP wildcard
    configuration, malformed infrastructure URLs, and invalid credential
    structures with explicit errors.

Low-token router and complete catalog

Canonical facts are generated by scripts/project_facts.py and tracked in
project-facts.json:

Surface Tools
Minimal router 3
Recommended default profile 18
Platform API backends 6,703
Complete registered backend catalog 6,715
Direct-all client-visible surface 6,722

The complete catalog comprises 6,703 platform API tools, 7 credential-free
design-core tools, and 5 credential-free interop-core tools. Direct-all
adds seven router-native tools whose names do not duplicate backend
identities.

Privacy, elicitation, and interoperability

  • Adds opt-in reversible PII tokenization around unified-router dispatch.
  • Retains capability annotations, write confirmation/elicitation, and the
    skills/runbook execution model.
  • Adds interop-core with Central-to-Mist and Mist-to-Central WLAN/site
    translation plus bounded vendor-neutral trend normalization.
  • Adds HPE_MCP_ACCESS_PROFILE with safe-read-only, compatibility-preserving
    custom, and full-read-write modes across router, direct, stdio, HTTP, and
    standalone backend execution.
  • Full read/write mode keeps write-capable dispatch explicitly destructive and
    preserves dry-run, confirmation, elicitation, and dedicated rollback guards.

GLP Reporting and Service Catalog

  • Reconciles all 105 curated GLP tools with their inventory buckets.
  • Includes GreenLake Reporting and Service Catalog coverage.
  • Keeps the 920 generated GLP operations available behind the generated-tool
    gate.
  • Labels community-derived GLP specifications separately from
    HPE-authoritative sources.

RAG and exact API lookup

The validated local release snapshot contains:

Artifact content Count
Prose chunks 96,256
Declared sources 16
Exact endpoints 4,106
Schemas 8,890
Fields 50,675
Security advisories 104
Lifecycle records 346
Generated manifest operations 6,144

Evaluation results are source_hit@k=0.97, MRR=0.923, and 1.0 for
how-to recall, exact API lookup, structured exact lookup, and structured-list
lookup.

No upstream API or documentation source was refreshed while preparing 0.8.0.
The index manifest records source_refresh_performed: false and preserves the
actual modification time and content hash for each local artifact.

Drift and refresh safety

  • Classifies content drift, source additions/removals, pointer movement,
    stale pins, unavailable networks, parser failures, and known coverage gaps
    independently.
  • Runs scheduled checks as separate jobs with JSON artifacts and an aggregate
    summary.
  • Makes refresh planning declarative over the source manifest, including
    pre-discovery and post-scrape phases.
  • Treats expected classified drift as actionable, but refuses to plan from
    incomplete, malformed, or unavailable checks unless the operator explicitly
    permits a partial check.
  • Snapshots and rolls back docs, tools, exact API data, generated manifests,
    and local index manifests when any refresh or evaluation step fails.

Dependency snapshot

The 0.8.0 lock refresh includes MCP 2.0.0, LanceDB 0.37.1, FastEmbed 0.8.0,
Playwright 1.62.0, Redis 8.1.0, pypdf 6.15.0, pytest 9.1.1, and Ruff 0.16.2.
LanceDB full-text index creation now uses the current FTS index API.

Validation

The release baseline completed:

  • 3,816 unit tests passed and 4 were skipped.
  • 6,144 generated operations validated.
  • All 6,715 registered backend identities matched the tool index exactly.
  • Strict RAG/API evaluation and local source/index manifest reconciliation
    passed.
  • The targeted changed-file lint set passed.

The source-manifest validator reports ten documented warnings for intentionally
structured-only or not-yet-ingested source families; it reports zero failures.

Known boundaries

  • The Mist OpenAPI pin remains intentionally stale/review-needed and was not
    advanced without review.
  • Generated GLP specifications remain community-derived until official HPE
    registry coverage is available.
  • RAG-first behavior is advisory and guarded through prompts, discovery,
    diagnostics, and tests; direct MCP clients are not protocol-forced through a
    discovery token.
  • Credentials, .env, generated indexes, runtime outputs, and private vendor
    icon packs are not committed.

See the compact changelog
and prebuilt index guide for release assets and restore
instructions.