Skip to content

v0.1.1

Choose a tag to compare

@malkreide malkreide released this 27 Jul 14:24
185e0dc

[0.1.1] — 2026-07-27

Fixed

  • MCP Registry publish was blocked by a missing ownership marker. The
    registry verifies ownership of a PyPI package by looking for an
    mcp-name: <server-name> marker in the published package README. The marker
    was added to README.md after 0.1.0 shipped, so it never reached PyPI — and
    PyPI releases are immutable, so it cannot be added to the 0.1.0 artifact
    retroactively. This release carries it into the package metadata.
  • Search was confined to the VARIA classification (#11, reported by
    @dfch). /v2/Search restricts an ID-less query to a "default set (=VARIA)",
    so every unfiltered search covered 1 of 23 subject areas — and reported the
    result as a normal empty answer. search_terms, translate_term and
    check_terms now send the full classification set unless the caller narrows
    it. «Quellensteuer» 0 → 3 entries, «Pensionskasse» 1 → 21.
  • fields could widen a search but never narrow it. Unsent Field.* flags
    keep their API-side default (Terminus, Name, Abbreviation,
    Phraseology = true), so fields="Terminus" was a no-op. All eleven flags
    are now sent explicitly.
  • Default field set widened to include Definition, Note and Source;
    translate_term and check_terms stay on the four designation fields, so a
    term merely mentioned in a definition is never reported as an equivalent.
  • Misleading scope caveat. The search_terms docstring presented an empty
    result as probable out-of-scope, which invited models to invent a designation
    instead of retrying. It now documents Lucene wildcards and asks for a retry;
    an empty SearchResult carries a hint field saying the same.

Security

  • SEC-016 (NeighborJack): the SSE transport now binds to 127.0.0.1 by
    default instead of 0.0.0.0. Binding to 0.0.0.0 is an explicit opt-in that
    logs a stderr warning when used outside a container. README/SECURITY updated.
  • SEC-021: code-layer egress allow-list (ALLOWED_HOSTS + assert_host_allowed),
    enforced before every request; docs/network-egress.md.
  • SEC-018: input bounds at the tool boundary — max_results 1–100, plus
    string/list length limits on search_term, term, terms, entry_ids, fields.
  • SEC-007: hardened non-root Dockerfile for SSE deployments.
  • SEC-005 / SCALE-002: accepted-risk ADRs for DNS pinning and stateful load
    balancing (docs/adr/0001, 0002).

Added

  • Typed configuration via pydantic-settings (settings.py); new env vars
    TERMDAT_MCP_LOG_LEVEL, TERMDAT_MCP_CORS_ORIGINS, TERMDAT_MCP_VOCAB_TTL.
  • Structured logging via structlog, pinned to stderr as JSON (logging_config.py).
  • FastMCP lifespan owning the shared HTTP client (cleanup on shutdown).
  • Explicit CORS for the SSE transport, exposing only Mcp-Session-Id.
  • CONTRIBUTING.md / CONTRIBUTING.de.md; scheduled/manual live-test workflow.
  • Expanded test suite (12 → 28 offline tests): per-tool coverage, error paths,
    egress allow-list, tool-schema input bounds.
  • MCP best-practice audit against the portfolio catalog (68 checks, 36
    applicable) under audits/: production-ready; the 19-item hardening
    backlog from that audit is addressed by the changes above.

Changed

  • api_status and the client no longer forward raw upstream exception strings to
    the model (OBS-002 error-detail masking); detail goes to the structured log.
  • check_terms runs its per-term lookups concurrently (asyncio.gather) and
    reports progress via ctx when available (ARCH-007 / SDK-003).
  • Tools grouped rationale + MCP-primitives note documented in the READMEs.