• v1.14.0 966cb0e8fe

    1.14.0 — tools borrowed from MCP servers
    All checks were successful
    CI / build-and-test (push) Successful in 2m21s
    CI / docker-build (push) Successful in 58s
    Stable

    joeyr released this 2026-09-10 21:05:39 -05:00 | 60 commits to main since this release

    Tools borrowed from MCP servers

    MCP_SERVERS takes comma-separated name=url pairs. At startup the bot connects to each,
    asks what tools it publishes, and hands them to Claude alongside the built-in web_search
    and web_fetch. A tool added on the server appears in Discord on the next restart, with
    no change to this repo
    — which is the point, and also the gotcha: the tool list is no
    longer in this repo, so "where is get_standings implemented" is answered by the server
    rather than by grep.

    The first consumer is mcp-gateway's ESPN fantasy football tenant, so
    /aufhocker query-chat can now answer about a league roster, matchups, standings, the
    waiver wire and recent transactions.

    Four deliberate non-behaviours

    • connect() never throws. Plugin init() errors are fatal to startup, so a fantasy
      server restarting for thirty seconds would otherwise take Discord's general-purpose chat
      down with it. It reports instead, and the bot starts with whatever tools it got.
    • Borrowed names are not prefixed. The servers' own descriptions cross-reference each
      other by name — "get the team_id from list_teams first" — so prefixing would silently
      break every one of those sentences. The cost is possible collisions, so a name matching a
      built-in is refused rather than overwritten.
    • A server refusal comes back as content, not an error. Those refusals are written for
      the model to read and act on: "that week has not been played yet; get_matchups shows the
      scheduled pairings instead". Throwing would replace that with "tool execution failed".
    • Nothing is reached over the public internet. Service aliases on the Swarm's internal
      network, not proxied hostnames.

    Authenticated with a single bearer token (MCP_AUTH_TOKEN) rather than OAuth: a bot has no
    browser to complete a consent screen with, which is why the server side runs in token mode.

    An eighth preflight check

    preflight/mcp reaches every configured server at boot and reports its tool count — the
    same "prove it works before something needs it hours later" the other seven exist for. It
    connects separately from the session the query plugin holds and pays a second handshake
    to do it: a line reporting what some other component happened to find is a line that goes
    stale when that component changes. A server that connects but publishes zero tools is a
    failure rather than an ok carrying a zero — that is what a misconfigured tenant looks
    like, and a green line is exactly what gets read as fine.

    Also

    • browserslist pinned to ^4.28.7 in overrides (High: unbounded memory growth, and a
      prototype write in normalizeStats). Dev-only — reached solely via jest → babel, so
      never in the production image. Newly published rather than newly introduced: it would have
      failed npm audit --audit-level=high on the next push regardless.

    833 tests green.

    Deploying this

    Two one-time prerequisites on rpi5a:

    docker network create -d overlay mcp_net
    printf %s '<token>' | docker secret create espnff_mcp_token -
    

    Then a yaml stack update for both aufhocker and mcp-gateway.

    Downloads