Skip to content

v0.5.0 - drop the awslabs_openapi_mcp_server dependency

Choose a tag to compare

@newgene newgene released this 02 Sep 21:42
· 5 commits to main since this release

Second of the two planned releases. 0.4.0
was the fastmcp 3.x migration; this one removes the awslabs_openapi_mcp_server
wrapper and calls fastmcp directly.

Upgrading

Two breaking changes:

  • Per-operation MCP prompts are no longer generated, so prompts/list is
    empty where it previously was not. They restated their own tool's name,
    method, path and parameters, and unlike tools they are not collapsed by
    --tool-search.
  • Config no longer subclasses the awslabs config dataclass. Any
    isinstance(config, awslabs...Config) check needs updating, and the awslabs
    environment variables (AUTH_*, INCLUDE_TAGS, VALIDATE_OUTPUT, …) are no
    longer recognised. None of them affected this package's behaviour.

Runtime dependencies are now fastmcp>=3.3.1,<4, httpx and loguru.
A clean install drops from 87 packages / 91 MB to 68 / 56 MB.


Added

  • smartapi_mcp/openapi.py: fetch_spec(), validate_spec(),
    reject_external_refs(), resolve_internal_refs() and
    build_openapi_server(), replacing the awslabs loader, validator and server
    builder. Specs are cached for an hour (the --facade-strict path loads a spec
    to inspect it, then loads it again to build from it).

  • smartapi_mcp/log.py: the logger / get_format() that the other modules
    previously imported from awslabs. Same loguru format, same stderr sink, same
    default level, so log output is unchanged.

Changed

  • Config is now a standalone dataclass and no longer subclasses
    awslabs.openapi_mcp_server.api.config.Config. It carries the 17 fields this
    package reads; the ~35 inherited ones covered authentication schemes, Cognito,
    tag filtering and multi-spec composition that SmartAPI's public APIs never
    used. Code doing isinstance(config, awslabs...Config) will need updating.

  • SERVER_HOST, SERVER_PORT, SERVER_TRANSPORT, API_SPEC_URL and
    API_BASE_URL are now read by this package's own load_config rather than
    inherited from awslabs. The remaining awslabs environment variables
    (AUTH_*, INCLUDE_TAGS, EXCLUDE_TAGS, VALIDATE_OUTPUT,
    ADDITIONAL_SPECS, API_SPEC_PATH, SERVER_DEBUG,
    SERVER_MESSAGE_TIMEOUT, ALLOW_*) are no longer recognised; none of them
    affected this package's behaviour.

  • tests/test_config.py was rewritten against real behaviour. It previously
    spent most of its length mocking the awslabs base config and the
    dataclasses.fields copy loop, and asserted exact logger call strings; it now
    covers defaults, environment parsing, integer/bool coercion, CLI precedence
    and the malformed-value fallbacks. New tests/test_openapi.py covers the
    replacement module offline via httpx.MockTransport, including the ref-cycle,
    depth-cut, SSRF-refusal, retry and cache paths. Test count 143 → 208.

  • Dropped two stale pyproject.toml references to smartapi_mcp/awslabs_server.py,
    a file that has not existed for several releases.

Fixed

  • Response $refs are now resolved for tool descriptions. fastmcp resolves
    references for the input schemas it generates but leaves them in the response
    schemas it hands to the description formatter, so an operation whose response
    is a $ref was documented as returning nothing in particular. awslabs papered
    over this with prance, which fails on the recursive schemas TRAPI APIs use and
    silently fell back to unresolved parsing. resolve_internal_refs() handles
    them, which accounts for 33 of the 45 changed tools across 6 APIs — every one
    of them longer (ClinGen: +426 to +642 characters per tool; one Translator
    status endpoint +1,637).
    Only the description path uses the resolved copy; the pristine spec still
    goes to fastmcp, so shared and recursive definitions stay behind $defs.
    Pre-resolving the whole spec instead inflated one TRAPI tool's input schema
    from 67 KB to 115 KB.

  • $refs standing in for a whole Parameter Object are now inlined. fastmcp
    resolves references inside schemas but ignores one used in place of an
    entire Parameter / Request Body / Response Object, so such a parameter arrived
    with an empty schema — MyTaxon.info's callback parameter came through as
    {}, losing its type and description. The awslabs loader avoided this only
    incidentally, by pre-resolving the whole document with prance.
    build_openapi_server() now inlines every internal $ref except
    #/components/schemas/ ones, which are left for fastmcp to hoist into
    $defs.

  • Sibling keys alongside a $ref now win over the referenced target, as
    JSON Schema specifies. prance discarded them, so a field written as
    {"$ref": ".../BiolinkEntity", "description": "Subject node category...", "example": "biolink:ChemicalEntity"} was documented with BiolinkEntity's
    generic description and example instead of its own. This accounts for 12 of
    the 45 changed tools, all in the two BTE TRAPI APIs: 8 input schemas gained
    per-field descriptions, examples and patterns, and 4 descriptions now quote
    the spec's own example (which is 20 characters shorter than the generic one it
    replaces).

  • --tool-search-threshold had no effect. The flag and its
    TOOL_SEARCH_THRESHOLD environment variable were parsed into Config but
    never passed to build_server_for_set(), so the threshold was always the
    50-tool default no matter what was configured.

  • --port was ignored, and would have shadowed SERVER_PORT if wired up.
    load_config never read args.port or args.host, so only the environment
    variables worked; and --port's argparse default of 8000 would have
    overwritten SERVER_PORT on every run once it was read (the same bug class
    fixed for --facade / --tool-search earlier in this release). Both flags now
    work, with CLI > environment > default precedence, and --port's default is
    None.

  • An unusable spec now raises instead of being logged as
    "validation failed, but continuing anyway" and passed on regardless.
    build_api_servers() already catches per-API failures and skips that API with
    a warning, so the caller gets a clean skip rather than a spec that fastmcp will
    choke on later. SpecError subclasses ValueError, so existing handlers still
    catch it.

  • A 4xx spec fetch is no longer retried three times with exponential backoff. An
    unknown SmartAPI id returns 404 on every attempt, so the retries only added
    ~3 s per bad id when building a large set.

Removed

  • Dropped the awslabs_openapi_mcp_server dependency. By its 1.x line that
    package had converged on being a thin wrapper over FastMCP.from_openapi(),
    so smartapi_mcp/openapi.py now calls fastmcp directly. Verified against a
    recording of the old path over 107 of the registry's 108 uptime-passing
    APIs
    (scripts/check_spec_parity.py): 92 of 107 build, exactly as before,
    with identical tool names and no API newly failing. Of the 592 resulting
    tools, 547 are byte-identical; the other 45 all gain detail rather than
    lose it (see Fixed below). A clean install goes from 87 packages /
    91 MB to 68 packages / 56 MB
    — 18 transitive dependencies removed and none
    added. The largest is boto3/botocore (20 MB), pulled in only for a Cognito
    auth provider this package never used, and which no longer even imported
    cleanly in a fresh 3.14 environment. Also gone: prance, ruamel.yaml, bcrypt,
    openapi-spec-validator, openapi-schema-validator, tenacity, requests,
    urllib3, chardet, charset-normalizer, jmespath, s3transfer, python-dateutil,
    rfc3339-validator, lazy-object-proxy and six. httpx and loguru become
    direct dependencies; both were already installed transitively, so neither is
    a new download.

  • Per-operation MCP prompts are no longer generated. The awslabs wrapper
    emitted one prompt per operation for specs carrying operationIds — 10 of the
    30 APIs measured, all non-BioThings — and each prompt restated its own tool's
    name, method, path, parameters and response codes. Beyond being redundant,
    prompts are not collapsed by --tool-search (the transform filters
    tools/list only), so on a large set they were context cost that search could
    not hide. This changes behaviour for sets containing such APIs:
    prompts/list is now empty.

  • Several awslabs features were never reachable and are simply gone: a
    health_check tool that was defined but never registered, an API resource
    handler registered against a server.register_resource_handler hook that
    FastMCP does not have, route maps forcing GET-with-query-params to
    MCPType.TOOL (fastmcp 3 already defaults every route to a tool), five unused
    auth providers, and a metrics registry that only awslabs' own
    make_request_with_retry recorded to — so the "Final metrics" line logged on
    shutdown was always an empty summary. That line is removed.