Skip to content

Releases: SolaceProducts/solace-broker-mcp

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 20:07
3ecb960

Release: v1.0.0, first GA
Date: 2026-10-14
License: Apache 2.0
MCP specification: 2025-11-25 (latest stable)
Platforms: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64
Brokers: Solace event brokers, software and appliance, on LTS and rolling releases currently under Solace support

Tools

  • 47 tools: 29 read-only and 18 write. Write tools are disabled by default and require explicit opt-in via enable_write_tools.
  • Read tools cover broker discovery, broker status and redundancy, replication, message rates, Message VPNs, queues, clients, client usernames and client profiles, slow subscribers, REST Delivery Points, bridges, Kafka receivers and senders, discard diagnostics, and SEMP schema introspection.
  • Write tools disconnect clients, delete queued messages, and clear client and queue statistics. They also create, update, and delete Message VPNs, queues, topic endpoints, and REST Delivery Points, and create and delete queue subscriptions.
  • Multi-broker support, with each broker addressed by configured alias from a single server instance.

Clients

  • Compatible with any MCP client that supports the Streamable HTTP transport. Setup documented for Claude Code and Claude Desktop.
  • Solace Agent Mesh integration, wiring the server into an Agent Mesh project as an MCP-tooled agent.

Authentication and authorization

  • OAuth 2.1 / OIDC for production, validated with Keycloak and Microsoft Entra ID. Unauthenticated and static-token modes available for development.
  • End-user identity propagation to the broker, through OAuth token exchange or Entra On-Behalf-Of, so broker audit logs record the calling user rather than a shared service account.
  • Claim-based tool authorization, gating individual tools by the group or role claim in the caller's token.

Observability

  • Prometheus metrics and OpenTelemetry tracing.
  • Correlation ID on every request, returned to the caller and recorded in server logs and audit records.
  • Metrics for tool invocations, SEMP requests, broker reachability, authentication and authorization failures, audit pipeline health, and panic recovery.
  • Audit log covering every destructive operation.
  • Importable Grafana dashboard and an operator runbook.
  • Kubernetes liveness and readiness probes.

Deployment

  • Standalone binary, Docker image, or go install. Kubernetes manifests included.
  • TLS terminated at the server or upstream at a proxy or ingress.
  • Per-broker rate limiting, retry and backoff, and concurrency caps.
  • Published checksums, plus a build provenance attestation on the release archives and the container image, verifiable against the release workflow.

Upgrading

The server is a replacement upgrade. It holds no persistent state, so a new instance starts serving as soon as it is healthy. Open MCP sessions do not survive the swap, and clients reconnect.

Version numbering also changes at 1.0. Through the 0.x line a breaking change raised the middle number. From 1.0 it raises the first.

Upgrading from a pre-GA release may need configuration changes, and some behaviour has changed with it. The changelog lists every breaking change in the 0.x line. One is worth calling out, because it can break broker connectivity with an unchanged configuration file: broker traffic now follows the standard proxy environment variables where it previously went direct, so exempt your brokers, and your OTLP collector if telemetry is enabled, before upgrading.

Links

What's Changed

  • SOL-155413: list tools report a missing VPN or client as not-found by @solace-awaheed in #483
  • docs(DOC-8761): First pass of editorials - more to come by @gilyusolace in #482
  • SOL-155412: show the agent and operator why a request body was rejected by @amitmorade in #487
  • SOL-155411: report a timed-out create/update as outcome-unknown, not "try again later" by @bczoma in #488
  • SOL-155451: document offline_access in scopes_supported for Entra setups by @amitmorade in #490
  • SOL-155480: remaining VPN-scoped list tools report a missing VPN as not-found by @solace-awaheed in #486
  • SOL-155426: fix list-queue-discards token-budget overflow at its documented default by @solace-lootii in #484
  • SOL-155432: strip broker self-referential links/meta URIs from tool results by @solace-lootii in #489
  • SOL-155668: Fix follow-up doc errors and drop rename history by @amitmorade in #492
  • Bump the go-minor-patch group across 1 directory with 2 updates by @dependabot[bot] in #480
  • SOL-155670: Remove the retired OBS_METRICS_ENABLED flag handling by @amitmorade in #493
  • SOL-155414: warn when /metrics is reachable beyond the loopback-only MCP listener by @solace-lootii in #485
  • Bump the third-party-actions group across 1 directory with 2 updates by @dependabot[bot] in #491
  • SOL-155864: bump golang.org/x/net v0.58.0 -> v0.60.0 (CVE-2026-78663 et al.) by @DevSol-UQ in #494
  • SOL-155918: log structured owner-validation fields when the owner check blocks a write by @solace-lootii in #497
  • SOL-154679: add mcp_owner_validation_total for writes blocked by the owner check by @solace-lootii in #498
  • SOL-155938: fix increase() alert guidance for mcp_authz_denied_total, trim SOL-155918 CHANGELOG entry by @solace-lootii in #499
  • SOL-155075: restore the nightly LLM eval beside the release gate by @amitmorade in #502
  • Update SEMP schemas to latest rolling release (10.26.8) by @bczoma in #501
  • SOL-156024: Prepare release v1.0.0 by @solace-awaheed in #505

New Contributors

Full Changelog: v0.11.0...v1.0.0

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 19:56
34bd00f

What's new in 0.11.0

Microsoft Entra ID support is complete, plus a Windows build and a few fixes.

Full details are in
CHANGELOG.md.

Added

  • Microsoft Entra ID support is complete. Entra On-Behalf-Of no longer needs a feature
    flag, and the Authentication Guide
    covers setting up Entra end to end.
  • A Windows (amd64) binary build is now included in the release assets
    (solace-broker-mcp-<version>-windows-amd64.zip).

Removed

  • The HOP2_JWT_BEARER_ENABLED environment variable. It was the feature flag for Microsoft
    Entra ID support, which is no longer behind a feature flag, so you can delete it.

Fixed

  • list-brokers and describe-semp-schema now validate their input like every other tool,
    and report bad input as a readable tool error.
  • The token-exchange audience-mismatch message is now logged at INFO instead of WARN, once
    per broker, requested audience and returned audience, so Entra deployments no longer see it
    on every exchange.
  • create-queue-subscription rejects topics containing HTML-encoded characters (such as
    &gt;) instead of subscribing to the wrong topic.

What's Changed

  • SOL-155015: bound loadgen memory and add the Box C observability stack by @solace-awaheed in #470
  • SOL-155161: warnIfAudienceMismatch logs a false-positive WARN on every successful Entra exchange by @solace-lootii in #468
  • SOL-153693: Validate input for list-brokers and describe-semp-schema by @solace-lootii in #475
  • Bump the internal-reusable-workflows group across 1 directory with 6 updates by @dependabot[bot] in #469
  • Bump the third-party-actions group across 1 directory with 2 updates by @dependabot[bot] in #474
  • SOL-152578: State a policy for what may live in .githooks/ by @McCly-Solace in #472
  • SOL-154049: reject HTML-entity-encoded topics on create-queue-subscription by @solace-lootii in #446
  • SOL-154663: Document the macOS Gatekeeper block and its workarounds by @McCly-Solace in #471
  • SOL-155349: remove the HOP2_JWT_BEARER_ENABLED soak door by @amitmorade in #478
  • SOL-154399: document Entra ID for operators by @amitmorade in #479
  • SOL-153187: Add windows/amd64 to the release matrix by @McCly-Solace in #477
  • SOL-155401: Prepare release v0.11.0 by @solace-awaheed in #481

Full Changelog: v0.10.0...v0.11.0

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 19:36
eaa22dc

What's new in 0.10.0

New client-access tools, Entra On-Behalf-Of support, outbound proxy support, an
owner-validation security fix, and a round of observability additions. This release has breaking changes — see
Before you upgrade.

Full details are in
CHANGELOG.md.

Before you upgrade

  • YAML config: auth.audience is now auth.target, and
    broker_oauth.audience_parameter_name is removed. A config file using either fails to
    load. Token-exchange error logs also say target instead of audience.
  • Environment variable: OBS_METRICS_ENABLED is now OBS_METRICS_SCRAPE_ENABLED. The
    old name is ignored.
  • The OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES environment variables are now
    honoured
    , so service.name can change. Set observability.service_name in the YAML
    config to keep the old value.
  • list-vpns real-clients.byKey[vpn] now returns only hasRealClient or
    indeterminate.
  • Go 1.26.0 is the new minimum for building from source.
  • Queue/topic-endpoint owner must be an existing client username. Create the client
    username first.
  • Broker traffic now follows the HTTPS_PROXY environment variable. If one is already
    set, add your brokers to NO_PROXY.
  • YAML config: an unquoted ${VAR} inside [...] or {...} must now be quoted.

Added

  • Read-only tools: list-client-usernames, get-client-username,
    list-client-profiles, get-client-profile.
  • Broker traffic honours the HTTP_PROXY / HTTPS_PROXY / NO_PROXY environment variables.
  • YAML config field mcp_client_auth.scopes_supported sets the OAuth scopes the server
    advertises.
  • YAML config field broker_oauth.token_expiry_fallback supports IdPs that omit expires_in.
  • Entra On-Behalf-Of: the jwt-bearer grant type for broker_oauth.grant_type now obtains
    broker tokens, behind the HOP2_JWT_BEARER_ENABLED environment variable.
  • Observability: a Grafana dashboard, an operator runbook, Kubernetes metrics port and
    NetworkPolicy, and new metrics for broker authorization denials, dropped audit
    records, and token-exchange circuit-breaker state.
  • Extra startup and debug log lines for troubleshooting OAuth and identity settings.

Changed

  • Embedded SEMPv2 specs updated to 10.26.7.
  • The Kubernetes deployment now sets GOMEMLIMIT to 75% of the memory limit.
  • docs/observability.md rewritten to describe the shipped behaviour, including every
    OBS_* flag's default.

Fixed

  • Security: queue/topic-endpoint write tools no longer accept a nonexistent owner,
    which could leave the object open to every client on the VPN.
  • list-vpns no longer reports most active VPNs as idle.
  • Config comments containing an apostrophe or quote no longer trigger ${VAR}
    substitution.
  • Tool errors now return valid JSON-RPC codes, and describe-semp-schema declares an
    output schema.
  • Blank identity values are now treated as unset.

Security

  • Environment-variable substitution in the config can no longer inject extra YAML keys.

What's Changed

  • SOL-154042: record each observability flag's default and flip-condition by @solace-aross in #408
  • SOL-153332: emit a broker_authz_denied audit event and counter for hop-2 authorization denials by @solace-lootii in #389
  • SOL-151608: optional token expiry fallback when IdP omits expires_in by @amitmorade in #410
  • Log advertised OAuth PRM at startup (SOL-154210) by @amitmorade in #415
  • SOL-152284: alertable token-exchange circuit breaker state metric by @amitmorade in #414
  • SOL-154328: set GOMEMLIMIT in the shipped Kubernetes manifest and condition the 512Mi claim by @bczoma in #413
  • Bump softprops/action-gh-release from 3.0.2 to 3.0.3 in the github-actions group by @dependabot[bot] in #417
  • Record hop-2 expiry fallback first use at INFO (SOL-154334) by @amitmorade in #419
  • SOL-154238: add CI check validating docs/observability.md against the live Prometheus registry by @solace-lootii in #407
  • SOL-153694: declare an output schema for describe-semp-schema by @solace-awaheed in #418
  • Bump docker/setup-qemu-action from 4.2.0 to 4.3.0 in the github-actions group by @dependabot[bot] in #422
  • SOL-152423: Ship a reference OTel collector deployment and tested-backend matrix so tracing is usable on day one (Story 40) by @solace-wmaryam in #412
  • Update SEMP schemas to latest rolling release (10.26.6) by @solace-wmaryam in #426
  • SOL-152424: ship a ServiceMonitor and NetworkPolicy for the metrics e… by @solace-awaheed in #423
  • SOL-154446: accept "already absent" wording in the d2 nightly llm-eval scenario by @McCly-Solace in #425
  • SOL-153295: route broker SEMP traffic through HTTP_PROXY/HTTPS_PROXY/… by @solace-awaheed in #428
  • SOL-154339: memory provenance, gctrace and log-volume guards in the perf harness by @bczoma in #421
  • SOL-153079: fix YAML comment substitution, reorder Quickstart, and un-hardcode the example VPN by @McCly-Solace in #420
  • SOL-152092: Ship an importable reference Grafana dashboard (Story 37) by @solace-lootii in #424
  • SOL-153692: give tool-handler errors a valid JSON-RPC code at the withRecovery seam by @solace-awaheed in #430
  • SOL-152098: add the operator runbook so Tier-1 can work a failure without paging an engineer (Story 36) by @solace-wmaryam in #429
  • SOL-153076: Add read-only client-username and client-profile management tools by @solace-wmaryam in #431
  • SOL-154545: verify the published Grafana dashboard and collector metrics pipeline nightly, on both ingestion paths by @solace-lootii in #432
  • SOL-154569: wire mcp_audit_events_dropped_total so audit drops are vi… by @solace-awaheed in #436
  • SOL-154607: rename OBS_METRICS_ENABLED to OBS_METRICS_SCRAPE_ENABLED … by @solace-awaheed in #438
  • SOL-153545: Distinguish waiters of a concurrent broker-token exchange by @amitmorade in #440
  • SOL-154608: honour OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES whe… by @solace-awaheed in #441
  • SOL-154727: treat empty and whitespace-only identity values as unset,… by @solace-awaheed in #443
  • SOL-153080: reject queue/topic-endpoint owner bindings to nonexistent client usernames by @solace-lootii in #439
  • SOL-154397: configurable mcp_client_auth.scopes_supported for RFC 9728 PRM by @amitmorade in #447
  • SOL-154318: correct drifted citations and audit status in internal architecture docs by @amitmorade in #445
  • SOL-154315: enforce changelog entry length limits in /changelog skill by @McCly-Solace in #433
  • SOL-154871: Remove the Entra laptop lab from the public repo by @amitmorade in #448
  • SOL-154365: expose a test-only reset for the panics package counter by @solace-awaheed in #449
  • SOL-153116: Re-organize README Quickstart into a single happy path by @McCly-Solace in #444
  • Bump the go-minor-patch group across 1 directory with 6 updates by @dependabot[bot] in #435
  • SOL-153071: fix list-vpns zeroConnectionCount false positives by @McCly-Solace in #437
  • Bump github.com/modelcontextprotocol/go-sdk from 1.7.0 to 1.8.0 in /test/e2e-basic-mcp/agent in the go-minor-patch group by @dependabot[bot] in #434
  • chore(DATAGO-154672): split internal GitHub Actions updates and drop their cooldown by @artyom-morozov in #456
  • SOL-154894: rewrite operator observability docs as a shipped snapshot by @amitmorade in #451
  • SOL-154398: Entra 2: Optional tool RBAC honors one named inbound claim by @solace-lootii in #453
  • SOL-152815: hold image publish on the LLM eval suite by @amitmorade in #450
  • SOL-154654: rename Hop 2 auth.audience to auth.target and drop audien… by @solace-awahe...
Read more

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 18:03
0884acd

[0.9.0] - 2026-09-11

Added

  • Three new Prometheus gauges expose passive per-broker reachability on /metrics (SOL-152088, metrics_schema 1.2→1.3): mcp_broker_reachable{broker} (1 when last SEMP call succeeded, 0 otherwise), mcp_broker_unreachable_reason{broker,reason} (one-hot across all failure reasons ever seen — credential_invalid for 401/403, unreachable for transport failures, broker_error_NNN for 5xx/429), and mcp_broker_last_result_timestamp_seconds{broker} (Unix timestamp of the most recent result, for detecting silently idle brokers). All three are updated passively from real SEMP calls with no added broker load and no heartbeat goroutine. They are decoupled from /readyz (ADR-004): a broker outage sets the gauge to 0 but never marks the MCP pod unready.

  • Three new write/read tools close the gap where a queue created through create-queue had no way to be given a topic subscription without leaving the MCP tool set: create-queue-subscription, delete-queue-subscription, and list-queue-subscriptions. Without a subscription a queue attracts no messages regardless of its other settings, so create-queue's description now names create-queue-subscription as the required follow-up rather than leaving the caller to discover the gap by failure. create-queue-subscription/delete-queue-subscription follow the flat-sub-resource-tool convention (one MCP tool per SEMP operation on the sub-resource, not a nested parameter on create-queue): a queue's subscriptions are added and removed over its lifetime, and the SEMPv2 create/delete operations for MsgVpnQueueSubscription take one topic at a time — there is no update-queue-subscription, since a subscription is immutable (SEMP has no update operation for it; changing one is delete-and-recreate). Both accept Solace wildcards (>, *) in subscriptionTopic, which can contain / — the first MCP tool parameter in this codebase to put an arbitrary, slash-bearing string into a SEMP path segment (delete-queue-subscription's URL). list-queue-subscriptions verifies the queue exists before listing (a monitor/getMsgVpnQueue preflight step): SEMP's own collection GET returns 200 with an empty list for a nonexistent queue, which would otherwise be indistinguishable from "queue exists, has no subscriptions" — the preflight surfaces the broker's own not-found error instead. delete-queue's description and confirmation preamble now state that deleting a queue also removes any subscriptions attached to it, since deleting a queue cascades to its subscriptions with no separate detach step and no error if it does. delete-queue-subscription's own confirmation preamble likewise now states the silent-traffic-loss consequence in the restate clause itself (previously only in the description body, so the model wasn't instructed to say it back to the user before proceeding). Tracked under SOL-153868.

  • Every release now publishes a CycloneDX SBOM (solace-broker-mcp-<tag>.cdx.json), generated by cyclonedx-gomod (pinned v1.10.0, matching this repo's Go version) against the same dependency closure THIRD_PARTY_LICENSES.md inventories, checksummed alongside the binary archives. A new .github/scripts/sbom-check.sh (with its own self-test, sbom-check.test.sh) verifies the SBOM's dependency set matches THIRD_PARTY_LICENSES.md before it's attached — resolving both sides to their Go module first, since the SBOM lists components at module granularity while the document lists some rows a package deeper (e.g. golang.org/x/sys/cpu inside module golang.org/x/sys), which a naive string comparison would misread as drift on every run. Per SOL-148440, the SBOM does not gate on its own absence — cyclonedx-gomod failing degrades the release to "no SBOM attached," never "no release" — but once an SBOM exists, a real divergence from THIRD_PARTY_LICENSES.md does fail the release, the same as any other compliance drift here.

  • New deploy/kubernetes/ingress.yaml.example, and docs/authentication.md § "Session Routing at the Ingress" documenting it as a required step rather than a caveat. Now that the manifests default to replicas: 2 (SOL-152089), an operator following the TLS-terminated-upstream pattern gets a deployment that fails on essentially the first call: an Ingress load-balances to pod IPs and so bypasses the Service's sessionAffinity: ClientIP, and MCP sessions live in a single pod's memory, so each call after initialize has roughly a 1/replicas chance of reaching the pod that owns the session — a 10-call session survives with probability (1/2)^10 ≈ 0.1%, and worse in practice, since nginx's default round-robin is deterministic rather than random. The working annotation is nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr", which restores at the ingress what sessionAffinity: ClientIP gave on the ClusterIP path, inheriting its NAT caveat. The docs now also name the two configurations that look correct and silently are not: cookie affinity, which needs a cookie jar no MCP client has, and hashing on $http_mcp_session_id, which fails because the initialize POST carries no such header — the server mints the ID onto the response, so that request hashes on an empty key and lands anywhere while the ID it returns hashes independently, stranding half of all sessions at two replicas. Gateway API's sessionPersistence fails for the same reason cookies do; controller-specific source-address hashing is the portable answer. The example routes the whole /.well-known prefix rather than just /.well-known/oauth-protected-resource, because clients probe several paths under it before they hold a token and the server answers the unregistered ones with a JSON 404 that nginx's plain-text default backend would otherwise replace; /livez and /readyz are deliberately left unexposed. Named .example so the directory-wide kubectl apply skips it. Documentation and example manifests only — no code change. Tracked under SOL-153834.

  • New THIRD_PARTY_CLASSIFICATION.md: a committed green/yellow/red classification of every dependency in the shipped closure, sourced directly from FOSSA's policy result for SolaceProducts_solace-broker-mcp (Issues tab: zero active violations) rather than inferred from licence type alone. Zero dependencies are classified red, stated explicitly. The two MPL-2.0 dependencies (github.com/hashicorp/go-cleanhttp, github.com/hashicorp/go-retryablehttp) are classified yellow, per policy — see that file for approval status. Unlike the SBOM, this file is a committed snapshot, not a generated artifact — a yellow approval is a human decision that must survive a re-run. Tracked under SOL-153188.

  • A Prometheus-format /metrics endpoint is now served on a dedicated listener (default :9091), separate from the main MCP port, so operators can apply an independent network policy to metrics scraping without changing MCP traffic rules. The capability is gated by the new OBS_METRICS_ENABLED environment flag and is off by default (v1 door-closing policy): when off, no second listener is started and no instruments are registered; when on, the listener is registered as a required metrics_endpoint readiness probe, so a bind failure (for example, the port already in use) surfaces on /readyz as metrics_endpoint: <err> instead of failing silently. The bind address is configurable through the new observability.metrics_bind_address YAML field (default :9091, ${VAR} substitution supported). When metrics are enabled, config load now rejects a metrics_bind_address that shares the MCP server's own port — the two listeners would otherwise race for it at startup, and the loser, being a required readiness probe, would hold /readyz unready and crash-loop the pod; the guard is wildcard-aware ("", 0.0.0.0, :: overlap any host on the same port), and the :9090/:9091 defaults never collide. The endpoint serves Go runtime and process collectors plus three self-observation instruments — mcp_build_info{version}, mcp_schema_version{metrics_schema,audit_schema}, and the mcp_metrics_scrape_total counter — on an OpenTelemetry meter provider that later metrics work registers additional instruments against; OpenMetrics exposition is enabled on the handler. Tracked under SOL-152091.

  • On graceful shutdown, the metrics meter provider (SOL-152091) is now flushed and stopped through the shared shutdown-hook registry (SOL-152449). The Prometheus exporter is pull-based, so nothing is buffered to lose today — this is for a clean shutdown and to carry any future push-based exporter. Tracked under SOL-153884.

  • An OpenTelemetry tracer provider with OTLP gRPC export is now wired at startup, gated by OBS_TRACING_ENABLED (off by default, door-closing policy): off, New does nothing, leaving the OTel API's own non-recording global default in place; on, it installs a real provider, so the span-instrumentation stories that follow (MCP entry, executor, SEMP-per-attempt, retry, token-exchange spans) call otel.Tracer(name) today with no wiring of their own. OTLP endpoint and TLS come from the standard OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_INSECURE env vars with no code in this binary. Sampling honors OTEL_TRACES_SAMPLER / OTEL_TRACES_SAMPLER_ARG when both are set; with neither set, the SDK's own default applies (parentbased_always_on — sample everything, the v1 pilot intent), and OTEL_TRACES_SAMPLER_ARG alone, with no OTEL_TRACES_SAMPLER, is not read at all — set both together, per docs/observability.md. Two new self-observation instruments, mcp_otel_spans_exported_total and mcp_otel_spans_dropped_total{reason} (export_timeout, export_error, shutdown, and a reserved queue_full — see the known limitation below), register against the metrics meter provider (SOL-152091) whenever one exists; otherwise (metrics off, or its endpoint failed to start) a periodic `event=otel_s...

Read more

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 21 Aug 14:00
65fe9bf

What's new in 0.8.0

Stricter output contracts on the write tools, a faster CallTool path, four security
hardening fixes, and the embedded SEMPv2 specs moved to the 10.26.4 rolling release.

The full, verbose entry for each item is in
CHANGELOG.md.

Added

  • make refresh-third-party-inventory regenerates THIRD_PARTY_LICENSES.md and
    THIRD_PARTY_BUILD_TEST.md from what the repository actually uses, instead of
    hand-deriving the dependency closure. It rewrites only the rows that actually
    changed and refuses outright — leaving the files untouched — on anything it
    doesn't recognize. Still a manual step on Dependabot PRs.

Changed

  • Embedded SEMPv2 OpenAPI specs updated to the 10.26.4 rolling release
    (10.26.4.10725), so tool schemas track current broker attributes.
  • The eight create/update composite tools (create-message-vpn, update-message-vpn,
    create-queue, update-queue, create-topic-endpoint, update-topic-endpoint,
    create-rdp, update-rdp) now declare strict, spec-derived output schemas that
    reject undeclared fields and require the resource's own identifier. A future SEMP
    release that reshapes a response field now fails validation instead of silently
    passing through. Read-only tools are unchanged.
  • Each tool's input/output JSON Schema is now compiled once at registration rather
    than re-compiled on every CallTool. Internal change only — the on-the-wire MCP
    schemas, tool behavior, and response bytes are unchanged.
  • A /mcp request body over the 4 MiB cap that doesn't declare an oversized
    Content-Length now returns 413 instead of 400. The negotiated protocol
    revisions are unchanged by the underlying go-sdk v1.7.0 bump.
  • THIRD_PARTY_LICENSES.md's source of truth is now documented as the Go module
    graph, replacing the standing instruction to hand-reconcile it against the FOSSA
    scan. FOSSA remains the authoritative policy gate.
  • The release pipeline now executes every matrix leg's archived binary before it can
    publish, asserting a clean exit and a version matching the tag — closing a gap
    where cross-compiled darwin/arm64 and linux/arm64 archives were never run.

Fixed

  • The token-exchange circuit breaker's consecutive_failure_threshold rule now trips
    on a slow, low-traffic IdP outage, not only a fast-failing one. Its state-change
    WARN also now carries a consecutive_failures attribute, so an operator can tell
    which rule opened the breaker from the log line alone.
  • OAuth Protected Resource Metadata is now also served at the RFC 9728 canonical path
    /.well-known/oauth-protected-resource/mcp. Clients that follow the
    WWW-Authenticate challenge verbatim are unaffected; clients that build the
    canonical path directly now get a 200 instead of a 404.
  • CallTool now returns a structured tool result (isError: true, with retryable)
    instead of a bare JSON-RPC protocol error on every local failure path — unknown
    broker, schema validation, nil/invalid result, marshal failure. This matters most
    for destructive tools, where the broker-side action may already have succeeded by
    the time the failure is caught.

Security

  • Cross-origin protection on /mcp now runs outside the auth middleware. A
    browser-initiated cross-origin POST or DELETE gets the 403 it earned — before any
    JWT or JWKS work — instead of a 401 that masked a CSRF-shaped probe as an ordinary
    auth failure. What passes on the wire is otherwise unchanged; protection stays on by
    default with no new configuration.

  • Broker URLs logged at four runtime sites now go through the same sanitizer
    BrokerConfig.LogValue already applied, rather than being logged raw.
    Defense-in-depth: config-load validation already rejects embedded userinfo.

  • Token exchange now logs a diagnostic WARN when the IdP-issued token's aud claim
    doesn't include the audience this process requested, surfacing an inert per-broker
    audience config. It never fails the exchange. The exchange dedup/cache key now
    includes the requested audience.

  • The container health check (--health) now verifies the server's TLS certificate
    instead of accepting any certificate, closing CWE-295.

    Upgrading a TLS-enabled container: the probe now reports unhealthy — while the
    server keeps serving TLS correctly — if the certificate at tls_cert_file is
    unreadable from the probe's process, carries no DNS or IP SAN, has expired, or is not
    the one the server presents. Failure reasons go to stderr, which Docker records in
    State.Health.Log.

What's Changed

  • SOL-152372 test: add stub AccessLevelGroups to opt-in ToolAuthorization subtests by @amitmorade in #292
  • Bump github.com/modelcontextprotocol/go-sdk from 1.6.1 to 1.7.0 in the go-minor-patch group by @dependabot[bot] in #289
  • SOL-153050: retire the DCO workflow, keep the identity check it carried by @bczoma in #294
  • SOL-153050: state the registered ruleset, not the work to register it by @bczoma in #298
  • Bump the github-actions group across 1 directory with 5 updates by @dependabot[bot] in #295
  • SOL-151996: Backfill get-redundancy-status parser tests with active/standby (HA) fixtures by @helen-zhu-solace in #300
  • SOL-152979: sanitize broker URLs in log output as defense-in-depth by @solace-aross in #279
  • SOL-153089: Publish PRM at the RFC 9728 canonical path (keep WWW-Authenticate URI unchanged) by @solace-wmaryam in #297
  • SOL-152856: Add a required CI gate that runs actionlint and zizmor over every GitHub Actions by @solace-awaheed in #299
  • SOL-152286: Track consecutive exchange failures outside gobreaker so slow outages trip the breaker by @amitmorade in #296
  • SOL-153167: verify the server certificate in the --health probe by @bczoma in #301
  • SOL-152980: return structured results, not bare errors, from CallTool's local failure paths by @solace-aross in #280
  • SOL-152971: Restore cross-origin protection on the /mcp endpoint by @helen-zhu-solace in #303
  • SOL-152947: SEMPv2 config/action output-schema drift guard (write tools) by @solace-lootii in #302
  • SOL-152981: warn on token-exchange audience mismatch; include audience in dedup key by @solace-aross in #281
  • SOL-153184: Create daily job that runs in GHA for e2e-llm by @helen-zhu-solace in #305
  • SOL-153255: Refresh understand-anything knowledge graph by @solace-aross in #307
  • Bump the github-actions group with 5 updates by @dependabot[bot] in #304
  • SOL-153086: Give fork pull requests a vulnerability verdict before merge by @solace-awaheed in #306
  • SOL-153285: Update allowrance words in d1 scenario for e2e-llm by @helen-zhu-solace in #309
  • SOL-152741: KTLO: Upgrade MCP Go SDK to v1.7.0 and pin E2E to protocol revision 2025-11-25 by @helen-zhu-solace in #310
  • Bump github.com/getkin/kin-openapi from 0.145.0 to 0.146.0 in the go-minor-patch group by @dependabot[bot] in #312
  • SOL-153190: Settle third-party licence inventory source of truth by @solace-lootii in #313
  • SOL-153189: Smoke-test every release archive and surface the released version in the README by @solace-lootii in #311
  • SOL-153334: cache compiled JSON-schema validators per tool by @solace-aross in #314
  • SOL-153359: Gitignore make build's binary output at the repo root by @bczoma in #318
  • SOL-153337: Update e2e-llm scenarios and reduce flakey runs by @helen-zhu-solace in #321
  • SOL-152956: Add make refresh-third-party-inventory to close the drift-gate toil by @solace-lootii in #316
  • Update SEMP schemas to latest rolling release (10.26.4) by @solace-wmaryam in #319
  • SOL-152858: Document the static-analysis posture and the required CodeQL check by @bczoma in #323
  • SOL-153346: Add a Claude Code skill for third-party inventory refresh by @solace-lootii in #317
  • SOL-153335: verify composite output schema is not rebuilt per call by @solace-aross in #315
  • SOL-152974: Adopt GitHub merge queue by @solace-awaheed in #322
  • SOL-153411: Migrate CodeQL to advanced setup with a blocking gate job by @bczoma in #325
  • Bump the g...
Read more

v0.7.1

Choose a tag to compare

@github-actions github-actions released this 11 Aug 15:03
6f98089

[0.7.1] - 2026-08-11

v0.7.0 was tagged but its release pipeline failed before publishing anything, so it has no binary archives, no container image, and no GitHub Release — only a git tag and a Go module version. 0.7.1 is the first published release of the 0.7 line, and because git history is cumulative it contains everything listed under 0.7.0 below in addition to the change here. Anyone looking for 0.7.0 downloads wants 0.7.1.

Taken together with 0.7.0, this is the first release published from the public repository, and the first whose artifacts can be verified: every binary archive and the container image now carries a build provenance attestation tracing it to the workflow run and commit that produced it, with the commands in README.md. Also new since 0.6.0 — the describe-semp-schema tool, which lets an agent enumerate a SEMPv2 operation's configurable attributes before attempting a write; an optional filter_tools_list flag narrowing tools/list to what the caller is actually authorized to invoke; and a second third-party inventory, THIRD_PARTY_BUILD_TEST.md, covering the components used to build and test the project rather than ship in it.

Two breaking changes, both from the move to the SolaceProducts GitHub organization. The Go module path is now github.com/SolaceProducts/solace-broker-mcp. The container image is published to ghcr.io/solaceproducts/solace-broker-mcp — and the old path does not fail loudly, it keeps serving the last image pushed there, so a stale reference silently stops receiving updates. Migration notes are in the Changed section under 0.7.0.

Changed

  • Updated the embedded SEMPv2 OpenAPI specs to the 10.26.3 rolling release (10.26.3.10320), so tool schemas track current broker attributes. The three spec files are renamed to semp-v2-swagger-{action,config,monitor}.10.26.3.json and continue to be sourced from the private-extended variant. Loading is unaffected — specs are picked up by the embed glob and typed from their basePath, not their filename. Tracked under SOL-152939.

What's Changed

Full Changelog: v0.7.0...v0.7.1

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 28 Jul 15:47
33f5569

[0.6.0] - 2026-07-28

Added

  • Broker auth.mode: oauth (RFC 8693 token exchange, "Hop 2") is now a fully supported broker authentication mode alongside basic and bearer. A broker configured with auth.mode: oauth obtains its broker-bound token by exchanging the calling agent's Hop 1 token via the broker_oauth: block's IdP coordinates — see docs/authentication.md for the full Hop 1 / Hop 2 model, config shape, and operational behavior (retries, circuit breaker, Retry-After handling, token caching). mcp_client_auth.mode: oauth is required whenever any broker uses auth.mode: oauth, since Hop 2 consumes the agent's Hop 1 token as the RFC 8693 subject_token.
  • New MCP tools list-kafka-receivers, get-kafka-receiver-status, list-kafka-senders, and get-kafka-sender-status for Kafka Receiver/Sender monitoring — the same list-then-drill-down pattern as list-rdps/get-rdp-status and list-bridges/get-bridge-status. A Kafka Receiver pulls messages from an external Kafka cluster into a Message VPN; a Kafka Sender pushes messages from a VPN's queues out to an external Kafka cluster. Unlike bridges' two-directional connection-state model, both objects use a single up/enabled/failureReason status shape (the same shape as RDPs) and a single-name identifier (kafkaReceiverName/kafkaSenderName, not a compound key). list-kafka-receivers/list-kafka-senders return up to 100 by default (max 500 via maxResults), with a summary block (downCount, disabledCount, byFailureReason); get-kafka-receiver-status/get-kafka-sender-status return additional per-object detail including topic-binding status (topicBindingUpCount/topicBindingCount) or queue-binding status (queueBindingUpCount/queueBindingCount). Read-only monitoring only; write tools and live-broker E2E fixture coverage are deferred to follow-up tickets. Unlike bridges, this implementation is spec-derived rather than lab-verified: neither lab appliance available at implementation time (sempVersion 100.0main.0.7305 and 10.26.0.8586) exposes the kafkaReceivers/kafkaSenders SEMP paths at all, so whether failureReason reliably populates on a real down receiver/sender — versus staying empty the way bridges' inboundFailureReason did — remains unconfirmed; a follow-up should verify against a broker with the feature licensed/enabled. Tracked under SOL-152328.
  • New MCP tools list-bridges and get-bridge-status for Bridge monitoring — the same list-then-drill-down pattern as list-rdps/get-rdp-status. list-bridges returns enabled state, inbound/outbound connection state, and last inbound failure reason for every bridge in a VPN (default 100, max 500 via maxResults), with a summary block (downCount, disabledCount, byInboundFailureReason). get-bridge-status returns additional per-bridge diagnostic detail — connection establisher, failure category, and client name — for one bridge, identified by msgVpnName + bridgeName + bridgeVirtualRouter (bridges are the only object in this server keyed by two names rather than one, since a bridge's config can differ between a broker's primary and backup virtual router in an HA pair). Tracked under SOL-152124.
  • Process-level circuit breaker in front of RFC 8693 token exchange to the IdP, so a sustained IdP outage fails fast instead of driving every broker's requests into the full retry/timeout budget. One breaker per process guards the single shared IdP; because the deployment has one IdP, one client credential, and one shared availability dependency, all brokers and tenants share it. A "request" for the breaker is one complete logical exchange after the retry loop has finished — a chain that retries a 5xx three times before giving up records one failure, not three. Failure classification is owned by the server, not the operator: transient network errors, upstream 5xx, and response-body-read failures count toward the breaker; HTTP 429 is excluded (the IdP is reachable and throttling, so counting it would let one tenant's rate-limit trip the shared breaker); token rejections, caller cancellations, and local request-build errors are excluded (they say nothing about IdP availability). Endpoint misconfiguration — an untrusted/expired TLS certificate, a hostname mismatch, or a DNS name-not-found for the configured IdP — is also excluded: it is a permanent operator fault, not an outage, and counting it would let one bad config value trip the shared breaker for every tenant with no chance to heal (a DNS timeout, by contrast, is transient and does count). Once open, exchanges are rejected immediately with a new ErrExchangeCircuitOpen sentinel — classified transient like a transport failure but distinct in the audit line ("we did not try" vs. retries-exhausted's "we tried and gave up"); state transitions log at WARN. Configured under a new optional broker_oauth.circuit_breaker: block (nested there because the breaker only protects OAuth token exchange, which exists only when broker_oauth does): enabled (default true; false is an operational escape hatch that disables the breaker while leaving retries intact and logs a WARN), failure_rate_window, minimum_requests, failure_rate_threshold_percent, consecutive_failure_threshold (fast-trips a fast-failing outage without waiting for the rate rule's sample; the count is window-bound, so failures spaced out by long retry chains may not accumulate; 0 disables it), open_state_duration, and half_open_probe_requests. Every field is optional and falls back to a production-safe default, so omitting the block (or the whole thing) yields the shipped defaults with the breaker on; out-of-bounds values are rejected at config load alongside every other broker_oauth error. The internal bucket granularity and breaker name are derived, not operator-configurable. Tracked under SOL-151600.
  • Shared, process-wide backoff that honors an IdP's Retry-After header on an exhausted RFC 8693 token-exchange 429 chain, closing a gap in the circuit breaker's 429-exclusion policy (SOL-151600): because a 429 is deliberately excluded from breaker failure counting, and gobreaker refunds a half-open probe slot for excluded outcomes, a still-throttling IdP could previously admit unbounded sequential probes with no pacing between them. Retry-After is parsed per RFC 9110 §10.2.3 (both delta-seconds and HTTP-date forms; an HTTP-date at or before the current instant, or a negative delta-seconds value, floors to no gate rather than a negative one, so IdP clock skew cannot produce a nonsensical result) only when a 429 retry chain fully exhausts — not on an intermediate 429 a later retry in the same chain resolves — and only holds off subsequent exchange calls; it does not change the 429-excluded classification itself, nor retry pacing within a single exchange's own chain (which already honors Retry-After uncapped per SOL-151520 and is unaffected). The gate is shared across every broker and tenant, deliberately: it sits in front of the same one-shared-IdP circuit breaker (SOL-151600), so a 429 from one broker's exchange paces back every other caller against that IdP, not just the one that triggered it. A gated call fails fast with a new ErrExchangeRateLimited sentinel — distinct from ErrExchangeCircuitOpen so an operator (or alerting keyed on either) can tell "the IdP is unhealthy" apart from "the IdP is healthy but asked us to wait" — before any breaker bookkeeping or IdP round-trip occurs. The honored duration is capped (default 60s, double the breaker's default 30s open-state window) via a new optional broker_oauth.retry_after: block with a single max_honored_duration field; omitting the block or the field keeps the shipped default, and an operator-set value replaces it entirely in both directions (a smaller cap can clamp tighter than the default, a larger one can honor longer). Three distinct WARN log lines cover the operator-visible outcomes on every exhausted 429 chain: the gate was set (with the honored duration and expiry), the gate was set but the IdP's requested duration was clamped to the configured cap, or the gate could not be set at all because the IdP sent no Retry-After (or sent one that didn't parse) — the last of these is called out explicitly because it means this protection cannot engage for that IdP, distinct from a routine "everything working as intended" log line. Tracked under SOL-152285.
  • Server-side retry loop for RFC 8693 token exchange to the IdP. Previously a single 5xx, HTTP 429, or connection error to the IdP failed the tool call outright; the loop now transparently retries up to three attempts total against transient signals (5xx, 429, and connection-level errors — DNS, TLS handshake, body-read partials), honoring the IdP's Retry-After header uncapped between attempts via jittered linear backoff. 4xx client errors (400, 401, 403) are deliberately not retried — they will not fix themselves on repeat. The whole retry loop is fenced by a chain-deadline (context.WithTimeout derived from the retry knobs — currently 19s worst case with the shipped defaults of 5s per attempt, 2 retries, and 1–2s backoff), which also bounds a hostile Retry-After value. When all attempts fail, a new ErrExchangeRetriesExhausted sentinel distinguishes "we tried and gave up" from a single-shot transport failure; the last attempt's HTTP status and IdP endpoint survive on the same *ExchangeError envelope for the audit line. JWKS refresh and OIDC discovery paths deliberately keep the non-retrying HTTP client — they are read-only lookups where a single failure is the correct signal. Tracked under SOL-151520.
  • New top-level tool_authorization: configuration block for per-tool authorization based on the caller's group or role memberships as carried by a configurable OIDC claim. Required under mcp_client_auth.mode: oauth and refused under any other mode — the enabled field must be set explicit...
Read more

v0.5.0

Choose a tag to compare

@solace-awaheed solace-awaheed released this 10 Jul 15:43
fa903d2

What's Changed

  • SOL-150717: Add unit test for auth mode: disabled (no-auth-required p… by @solace-wmaryam in #107
  • SOL-150878: Fix flakey slow-subscriber, clean up e2e-monitoring and gitignore by @helen-zhu-solace in #108
  • SOL-150796: add OAuth broker config schema (mcp_client_auth rename, banner consolidation) by @amitmorade in #110
  • SOL-150797: capture raw subject token on ctx after SDK validation by @amitmorade in #111
  • SOL-151114: F7-ttl fixture flaky in e2e-monitoring: maxTtlExpiredDiscardedMsgCount stays 0 by @helen-zhu-solace in #113
  • SOL-150799 (T5 prep): extract internal/idpclient by @amitmorade in #114
  • SOL-148462: Implement Action Tools (Queue Actions, Client Actions) by @solace-lootii in #88
  • SOL-151052: Implement composite-tool postprocessor + first handler for list-queues by @helen-zhu-solace in #112
  • SOL-150789: Productionize the LLM e2e eval harness (Mode 2) by @helen-zhu-solace in #106
  • SOL-151278: Observability package skeleton and flag plumbing by @solace-aross in #115
  • SOL-151283: /livez endpoint with /health as alias by @solace-aross in #116
  • SOL-151279: Correlation-ID HTTP middleware by @solace-aross in #118
  • SOL-151286: HTTP panic-recovery middleware (whole-mux, unconditional) by @solace-aross in #122
  • SOL-151284: /readyz endpoint reflecting MCP-server readiness (decoupled from broker) by @solace-aross in #123
  • SOL-151281: forward correlation ID to SEMPv1/v2 broker requests by @solace-aross in #125
  • SOL-150799: RFC 8693 token-exchange Exchanger (T5) by @amitmorade in #131
  • SOL-151282: return correlation ID in MCP response header and CallToolResult.Meta by @solace-aross in #126
  • SOL-151288: SIGTERM in-process drain (/readyz 503 → sleep → graceful shutdown) + terminationGracePeriodSeconds by @solace-aross in #130
  • SOL-150690: Add listen_address server config with loopback default fo… by @solace-awaheed in #133
  • SOL-151280: emit correlation_id as a slog attribute on every request-scoped log line by @solace-aross in #129
  • SOL-150860: complete remaining user documentation by @solace-aross in #117
  • SOL-151468: lift SafeCookieJar to broker level, delegate 401 recovery to Authenticator by @amitmorade in #136
  • SOL-150260: report accurate live queue depth by @solace-lootii in #137
  • SOL-151315: list-slow-subscribers aggregations by @helen-zhu-solace in #135
  • SOL-151285: k8s split probes + startupProbe; alias /ready to /readyz by @solace-aross in #127
  • SOL-148460: Implement Core Management tools (VPN, Queue) by @solace-wmaryam in #124
  • SOL-151316: list-queue-discards aggregations by @helen-zhu-solace in #134
  • SOL-151314: list-vpns aggregations by @helen-zhu-solace in #132
  • SOL-151313: list-rdps aggregations by @helen-zhu-solace in #128
  • SOL-150800, SOL-150801: OAuthAuthenticator, exchanger wiring, and exchange error visibility by @amitmorade in #138
  • fix(sempv1): bound broker error text at capture [SOL-151516] by @solace-aross in #140
  • fix(safego): recover panics in errgroup worker goroutines [SOL-151514] by @solace-aross in #139
  • SOL-148461: Adding RDP Write Tools by @solace-awaheed in #144
  • fix(config): refuse insecure broker TLS in production unless opted in [SOL-151517] by @solace-aross in #141
  • SOL-151343: get-rdp-status aggregations by @helen-zhu-solace in #145
  • fix(resilience): bound the overall SEMP retry chain with a deadline [SOL-151518] by @solace-aross in #142
  • SOL-151574: gate Hop-2 OAuth runtime resources on ENABLE_UNRELEASED_BROKER_OAUTH by @amitmorade in #147
  • SOL-151552: Unify downCount semantics across list-* aggregating tools by @helen-zhu-solace in #148
  • feat(cmd/server): second signal forces immediate shutdown [SOL-151437] by @solace-aross in #143
  • SOL-151506: harden BasicAuthenticator with nil-jar panic by @amitmorade in #149
  • SOL-151627: fix latent SA5011 nil-deref warnings in test files by @amitmorade in #152
  • ci(lint): disable stale analysis cache and uncap issue reporting by @amitmorade in #157
  • SOL-151500: Extract shared field-coercion helpers into one file for postprocess aggregation handlers by @helen-zhu-solace in #153
  • SOL-151442: add in-memory OAuth token cache with exchanger wiring by @amitmorade in #150
  • SOL-150725: E2E functional tests for MCP server management tools (manage-vpn, manage-queue) by @solace-wmaryam in #154

Full Changelog: v0.4.0...v0.5.0

v0.4.0

Choose a tag to compare

@solace-awaheed solace-awaheed released this 16 Jun 17:31
9bc8a14

What's Changed

  • SOL-150025: E2E functional tests for all supported MCP server monitoring tools by @helen-zhu-solace in #82
  • SOL-150440: Add 4 new tools to README and user-guide tools reference by @solace-lootii in #83
  • SOL-150248: Refactoring e2e-basic-mcp, docs, and health by @helen-zhu-solace in #84
  • SOL-148434: Implement Error Translation and Output Sanitization by @solace-wmaryam in #85
  • SOL-148434: Implement Error Translation and Output Sanitization by @solace-wmaryam in #87
  • SOL-150663: Truncate broker-controlled error text at capture by @solace-aross in #92
  • SOL-150660: Cap inbound /mcp request body at 4 MiB by @solace-aross in #89
  • SOL-150664: Enable retries for read-only SEMPv1 show commands by @solace-aross in #93
  • SOL-150661: Close response body when SEMP retries are exhausted by @solace-aross in #90
  • SOL-150665: Enforce per-broker connection bound via MaxConnsPerHost by @solace-aross in #94
  • SOL-150666: Keep secrets out of YAML config parse errors in startup logs by @solace-aross in #95
  • fix(tools): recover tool-handler panics instead of crashing the server [SOL-150685] by @solace-aross in #96
  • SOL-150689: Fix flaky e2e-monitoring F4 txMsgRate assertion (get-message-rates) by @helen-zhu-solace in #100
  • SOL-150707: Updating get-broker-health to be get-broker-status by @solace-awaheed in #99
  • fix(semp): enforce MaxConcurrentPerBroker with shared in-flight semaphore [SOL-150116] by @solace-aross in #97
  • Freshen agent context: CLAUDE.md commands and tool guidance, fix architecture.md drift by @solace-aross in #98
  • SOL-150749: Re-arm F6 slowSubscriber flag before Tool 10 assertions (fix flaky e2e-monitoring) by @solace-aross in #101
  • SOL-150724: Add get-broker-status in e2e-monitoring by @helen-zhu-solace in #102
  • docs: add RELEASING.md describing the release model by @solace-aross in #86
  • SOL-150815: Add logging to e2e-monitoring for list-slow-subscribers by @helen-zhu-solace in #103
  • SOL-150708: Creating get-hardware-details step for appliances by @solace-awaheed in #104
  • Authenticator interface and SEMP protocol-client migration (SOL-150794, SOL-150795) by @amitmorade in #105

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@bczoma bczoma released this 03 Jun 17:33
f9691f8

What's Changed

  • SOL-149478: MCP minimum documentation to support release by @solace-wmaryam in #57
  • fix(server): close broker pool on graceful shutdown [SOL-149926] by @solace-aross in #59
  • fix(config): redact userinfo in broker-URL validation errors [SOL-149923] by @solace-aross in #56
  • SOL-149904: Skip env var substitution in YAML comments by @solace-aross in #60
  • fix(semp): wrap cookie jar in atomic SafeCookieJar to remove 401 race [SOL-149922] by @solace-aross in #55
  • SOL-149989: Consolidate client auth config to single client_auth.mode enum by @solace-aross in #62
  • fix(semp): cap broker response body at 16 MiB [SOL-149920] by @solace-aross in #54
  • fix: cap semp.max_concurrent_per_broker at 1024 [SOL-149924] by @solace-aross in #51
  • fix(server): set ReadTimeout and IdleTimeout on the MCP HTTP server [SOL-149914] by @solace-aross in #53
  • fix(semp): set granular timeouts on the SEMP HTTP transport [SOL-149925] by @solace-aross in #58
  • test(config): add client_auth.mode to PR 51's max-concurrent fixtures [SOL-150117] by @solace-aross in #66
  • SOL-150126: Refactor directory structure of the test folder by @helen-zhu-solace in #65
  • chore: add Makefile with build/test/lint/docker targets by @solace-aross in #68
  • SOL-150167: fix broken broker healthcheck in e2e-basic-mcp by @helen-zhu-solace in #70
  • chore: ignore git worktree directories by @solace-aross in #69
  • SOL-149789: Define and enforce a contract for broker aliases by @amitmorade in #64
  • fix(config): warn on insecure_skip_verify=true in production mode [SOL-149928] by @solace-aross in #52
  • SOL-150200: Backport E2E harness cleanups by @helen-zhu-solace in #73
  • fix(config): reject unknown YAML fields in config decoder [SOL-149927] by @solace-aross in #49
  • docs(readme): add scannable tools table after Quickstart by @solace-aross in #77
  • SOL-148426: Implement Basic Health Endpoints by @solace-wmaryam in #67
  • SOL-150064: Restore e2e OAuth integration test — add TLS to test Keycloak by @solace-wmaryam in #72
  • DOC-8001: Docs edits on 4 md files by @SeanWray89 in #63
  • SOL-149606 Capture per-user identity in tool-invocation audit logs (production OAuth mode) by @amitmorade in #74
  • SOL-150316: Removing get-dmr-status tool by @solace-awaheed in #78
  • fix(auth): bound OIDC HTTP client timeout for JWKS refresh [SOL-150219] by @solace-aross in #75
  • SOL-150024: E2E Monitoring Suite by @helen-zhu-solace in #71
  • SOL-150080: Adding SAM integration to the docs by @solace-awaheed in #76
  • SOL-150328: Fix slow-consumer detection clarity in broker MCP tools by @solace-awaheed in #79
  • SOL-150344: Update slow-consumer and clean up e2e-monitoring test by @helen-zhu-solace in #81
  • SOL-150364: add followPages, fix per-page count for list-client-subsc… by @solace-awaheed in #80
  • SOL-148432: Implement Advanced Monitoring Tools (Replication, Discards, Slow Subscribers) by @solace-lootii in #61

New Contributors

Full Changelog: v0.2.0...v0.3.0