Releases: jonnybottles/patch-tuesday-mcp
Release list
v0.9.1 — new hosted endpoint, 2x resources, tested autoscaling
Finishes the migration of the hosted MCP endpoint to a new Azure subscription, right-sizes it, and proves it scales.
🔗 New hosted endpoint
https://patch-tuesday-mcp.agreeabledesert-d0b8e491.eastus2.azurecontainerapps.io/mcp
The old endpoint keeps working until August 11, 2026 (next Patch Tuesday), then retires. Nothing breaks today — but update the URL in your MCP client config before then. The old endpoint now announces its own deprecation via standard Deprecation / Sunset / Link headers (RFC 9745 / 8594 / 5829), a deprecation block in tool responses, and /health.
Local installs are unaffected. uvx patch-tuesday-mcp talks to no hosted endpoint at all.
More resources, real autoscaling
The hosted deployment went from 0.25 vCPU / 0.5 GiB with no scale rule to:
- 0.5 vCPU / 1 GiB per replica
- min 2 / max 6 replicas — no scale-to-zero, no cold starts, and zero-downtime revision rolls
- an
http-concurrencyautoscale rule with 5x headroom over the trigger
Scaling is now tested, not assumed
New opt-in tests/test_scale.py (never runs in CI) asserts the replica floor and ceiling, CPU/memory, ingress and revision health, and drives dozens of concurrent MCP sessions in ramped waves to confirm real scale-out and a scale-in floor.
It earned its keep immediately, catching two genuine misconfigurations: an autoscale trigger sitting above the server's own connection limit (so replicas would start refusing requests before the platform ever added one), and headroom too thin for the autoscaler's ~60s reaction time.
Notes
- No changes to the default response shape — the deprecation block only appears on a deployment explicitly configured with
MCP_DEPRECATION_SUNSET+MCP_DEPRECATION_REPLACEMENT_URL. - Self-hosters can use the same mechanism to retire their own endpoints; see the README.
- All deprecation text is declarative fact, never instructions aimed at a model — enforced by a test.
Full changelog: v0.9.0...v0.9.1
v0.9.0 — include_update_summary
What's new
include_update_summary=Trueonmsrc_searchKB lookups (single and batchedkb=[...]): attaches a per-KBupdate_summaryblock — the KB support page's Summary/Highlights text plus its Improvements bullet list ("what this update changes") — complementinginclude_known_issues(what it breaks) and the MSRC security data (what it fixes).- Honest three-way status per block (
published/none_published/unavailable); a fetch/parse failure is never reported as "none". - Both support-page blocks are served by a single fetch and one shared cache record; output is size-capped with a
truncatedmarker; link-only reference items are skipped. - Default JSON output is unchanged — the new block is strictly opt-in.
Full change: #21
v0.8.1
Data-quality fixes
- EPSS values at source precision — EPSS scores/percentiles are rounded once at parse time to FIRST.org's published 5-decimal precision, so tool output can never surface float-repr artifacts (e.g.
0.016540000000000003). - Reconciling
include_statsbreakdowns — entries without a severity rating or impact category (e.g. Chromium CVEs) now appear as explicitUnrated/Unspecifiedbuckets, so severity/impact counts always sum to the reported total. Buckets are only emitted when non-zero; default JSON shape unchanged. - Known-issues retrieval fixed for migrated KB pages — support.microsoft.com moved KB articles to
/servicing/os/...URLs (a second redirect hop + new page markup). The fetcher now follows a bounded, validated same-host redirect chain and parses both markup generations; the honestpublished/none_published/unavailablestatus contract is unchanged.
v0.8.0 — opt-in known issues for KB lookups
What's new
msrc_search KB lookups (single kb="5094126" or batched kb=[...]) accept a new opt-in parameter, include_known_issues=True, returning the issues Microsoft has publicly confirmed each update introduces — title, symptoms, workaround, and the resolving KB when stated, plus the source URL — best-effort from the KB's public support.microsoft.com page (no credentials, keeping the project's no-API-keys promise).
- Honest per-KB status:
published/none_published(Microsoft publishes no known-issues data for that KB — the norm outside Windows OS updates) /unavailable(retrieval or parse failure — never conflated with "no issues"). - Landing pages are verified against the requested KB (URL slug or title) so Microsoft's fuzzy
/help/{kb}resolver can never attribute another update's issues. - Also attaches to
not_foundKB results, since preview-only updates publish known issues without being MSRC security entries. - Bounded reads (
MCP_KNOWN_ISSUES_MAX_RESPONSE_BYTES, 4 MiB default), 6 h in-process cache, semaphore-bounded fetches. - Default JSON output is unchanged — the block only exists when requested.
Full details in #17.
v0.7.0 — batched KB lookup
New
Batched KB lookup — msrc_search now accepts a list of KB numbers: kb=["5094123", "KB5094127", ...] (up to 30 per call, deduplicated, order preserved). Feed in a machine's installed-update list and get one grouped response with a per-KB entry each: kb, found, and either the familiar single-KB body (month, CVEs, optional supersedence chain) or a per-KB not_found/upstream error. The top-level total_found sums across all KBs.
- A plain-string
kb=keeps the exact same response shape as before (compatibility contract). - Each monthly MSRC document is fetched upstream at most once per batch — the in-process cache does the rest.
- A malformed list entry fails the whole call with
invalid_inputrather than silently dropping a KB from your report. include_chain,month=,limit/offset(applied per KB), and allinclude_*row options work in batch mode.
🤖 Generated with Claude Code
v0.6.3
What's changed
- Startup log no longer echoes
MCP_TRUSTED_PROXIESvalues — it now reportsTrusting X-Forwarded-For: via N pinned proxy entries (MCP_TRUSTED_PROXIES). Removes the value flow that tripped CodeQL's clear-text-logging heuristic on every refactor touching the line; behavior of XFF trust handling is unchanged (#10, #11) - New test pins the summarized line and asserts raw proxy values never appear in startup output
- Docs: README/CLAUDE.md note that the startup log reports only the count of pinned proxies
Full Changelog: v0.6.2...v0.6.3
v0.6.2
What's Changed
- kb= round-trip affordance (#7, #8):
kb_articlessummaries can contain non-KB vendor-fix labels like "Release Notes" (published by MSRC verbatim). Thekbparameter description now documents that it accepts numeric KB ids only, and passing a label returns aninvalid_inputerror that points at picking a numerickb_articlesentry. Default output shape unchanged. - Deterministic endpoint test suite (#9): new
tests/test_endpoint.pydriven by--endpoint-url(markersendpoint/endpoint_upstream/endpoint_burst), covering/healthversion match, MCP tool + prompt round-trips, middleware behavior, and real searches through the wire.server.py's HTTP middleware stack moved unchanged intobuild_http_app()so tests exercise the exact production composition. CI gains an upstream-free endpoint smoke; a daily canary workflow runs the suite against the hosted endpoint and files an issue on failure.
Full Changelog: v0.6.1...v0.6.2
v0.6.1 — Python 3.14 runtime
Maintenance release: the container base image moves from python:3.12-slim to python:3.14-slim (digest-pinned, Debian trixie), and CI now runs the test suite on Python 3.14 alongside 3.11/3.12. No functional or API changes; the PyPI package still supports Python 3.11+.
- Bump Docker base image to python:3.14-slim (#4, Dependabot)
- Add Python 3.14 to the CI test matrix; add 3.13/3.14 trove classifiers
v0.6.0 — product profiles (watchlists) and monthly triage prompt
What's new
Product profiles / watchlists (#6, contributed by @mrbodean)
Scope any msrc_search to the products you actually run:
product_profile="identity-core"— built-in profiles:identity-core,endpoint,server-infrastructure- Ad-hoc
products=[...]andproduct_families=[...]matcher lists (union: keep a vuln matching any listed product OR family) - Override/extend built-ins via a JSON file at
MSRC_PROFILES_PATH - Matching is entirely local — profile contents are never sent to MSRC, FIRST.org, CISA, or telemetry
- Unknown/invalid profile fails closed with
error_kind="invalid_input"instead of an unscoped result
monthly_triage MCP prompt (#6)
The server now registers a monthly_triage prompt — a guided analyst workflow (publicly disclosed zero-days → CISA KEV → exploited → network/no-auth/no-UI criticals → identity/endpoint focus → briefing) built entirely on msrc_search. Optional product_profile and month arguments.
Portable copies ship in-repo: prompts/monthly_triage.md (plain text) and skills/patch-tuesday-triage/ (agent skill), both deployable independently of the server.
Compatibility
All new parameters are opt-in; the default JSON response shape is unchanged.
Full Changelog: v0.5.0...v0.6.0
v0.5.0
v0.5.0 — security hardening, perf/ops, and seven opt-in triage capabilities
Default JSON output is unchanged; every new field/behavior is opt-in.
Security
- Bounded, redirect-free upstream reads (MSRC/EPSS/KEV) so a misbehaving upstream can't exhaust container memory
X-Forwarded-Forhonored only from private/loopback peers without a proxy allowlist (no forged-header rate-limit bypass on directly-exposed deployments)msrc_searchnever leaks raw exceptions — structurederror_kind="internal"; KB/chain scans report upstream failures instead of false "not found"
New opt-in msrc_search parameters
include_references, exploitation_likely, ransomware, include_kev_details, include_kb_details (incl. restart-required), cwe, include_temporal, list_months
Quality / performance / ops
LRU + right-sized caches (12-month), concurrent EPSS batches, uvicorn concurrency/keep-alive limits, MCP_LOG_LEVEL, lifespan client cleanup, and telemetry for 429/413/cache-hit/enrichment paths
Supply chain
CI (pytest 3.11/3.12 + ruff + 90% coverage gate + Trivy scan + SBOM), CodeQL, Dependabot, SHA-pinned Actions, committed uv.lock, multi-stage digest-pinned non-root Dockerfile with HEALTHCHECK, build-provenance attestation, and SECURITY.md
Full details in #3.