Skip to main content
Glama
PNX89

QUENCHZ

by PNX89

QUENCHZ

A stdio MCP server gets four things free from having one caller that shares its context. Once the transport is remote, each becomes a decision, and every one of them is taken here in the open and proved from outside the Python tree.

CI Python TypeScript client License: MIT Data: ECB

Serving MCP tools to callers you did not write. The four are audience, reach, budget and coverage, and each is falsifiable by a test a reviewer can watch fail. If you only open one file, open src/quenchz/coverage.py: it is the certificate below, and the reason twelve days asked for and eight delivered is a complete answer rather than a third of one.

{
  "observations": [
    ["2026-03-30", 1.1484],
    ["2026-03-31", 1.1498],
    ["2026-04-01", 1.1605],
    ["2026-04-02", 1.1525],
    ["2026-04-07", 1.1557],
    ["2026-04-08", 1.1706],
    ["2026-04-09", 1.1685],
    ["2026-04-10", 1.1711]
  ],
  "coverage": {
    "requested_from": "2026-03-30",
    "requested_to": "2026-04-10",
    "requested_calendar_days": 12,
    "expected_observations": 8,
    "delivered_observations": 8,
    "delivered_from": "2026-03-30",
    "delivered_to": "2026-04-10",
    "absent": {
      "target_closed": 4,
      "not_yet_published": 0,
      "no_such_observation": 0,
      "before_the_series": 0
    },
    "window_still_open": false,
    "body_completed_at": "2026-08-26T12:00:00Z",
    "source": "ECB statistics."
  },
  "source": "ECB statistics."
}

Twelve calendar days were asked for and eight came back, and the response is complete. Good Friday, Easter Monday and the weekend are closures rather than gaps, and the vendor's payload says nothing whatever about any of them. Telling the difference needs the publication calendar and the wall clock, and that is what the coverage block is: src/quenchz/coverage.py.

It does not model everything. It reconstructs three named causes of absence and a fourth for dates before the series existed, and a fifth nobody has thought of would be counted as a genuine gap. The certificate is a required field with no default, so a tool that returns observations cannot answer without one.

Source: ECB statistics.

Twelve days asked for, eight delivered

The certificate above is not a summary written beside the data. It is a required field on the return, reconstructed from the publication calendar rather than read out of the response, because the response does not contain it.

field

what it answers

requested_calendar_days

what the caller asked for

expected_observations

what the calendar says was ever due

delivered_observations

what arrived

absent.target_closed

the market was shut

absent.not_yet_published

it is due today and is not out yet

absent.no_such_observation

it was due, it is late, and somebody should know

absent.before_the_series

nothing was ever due, because the series had not started

The last one was added after a review asked for a window in 1990. The euro did not exist in 1990, and the certificate answered expected_observations: 261 with all 261 counted as genuine gaps, which is the worst available answer: a confident report of 261 missing rates on days when none was owed.

Related MCP server: OPNsense MCP

A valid token that reaches nothing

A token minted by the trusted issuer, correctly signed, unexpired, carrying the right scope, and made out to a different resource, reaches nothing here.

That check has to be written by hand. The SDK carries an RFC 8707 resource field on AccessToken and never compares it to anything: BearerAuthBackend checks the bearer prefix, truthiness and expiry, then passes resource through untouched. The SDK does tell the issuer to audience-restrict the token it mints, and says nothing at all about the resource server checking that it was. Two tests assert the SDK still behaves that way, so if a release starts enforcing it this claim breaks loudly instead of quietly becoming untrue.

A token whose audience is a list is refused too, and PyJWT would accept it. RFC 7519 treats audience as a membership test, so a token made out to this resource and another passes the library. It does not pass here: a token that is also valid somewhere else is a token that somewhere else can present at this door, which is the situation RFC 8707 exists to avoid.

A caller cannot learn what it may not use, either. A tool outside its granted scope is absent from its listing, and asking for it anyway returns bytes identical to asking for a name that never existed. That costs something real: somebody who genuinely mistyped a scope gets a less helpful message than they could have had. It is worth it because the SDK's own scope denial answers Required scope: <name>, which confirms the tool exists and names the grant that would have worked, and a hundred guesses against that is a map of the surface drawn by the server for a caller that was never allowed to see it.

Start the server

uv sync --dev
uv run pytest

The server, with an in-process issuer that mints its own tokens into a file:

uv run python -m quenchz.interop_server --port 8931 --tokens-file /tmp/quenchz-tokens.json

The signing key is generated in memory and never touches disk. Every hostname uses the reserved .invalid TLD from RFC 2606 and can never resolve.

Two callers and one budget neither can see

The vendor documents no rate limit on any page, sends no rate-limit header on any response, and does not list 429 among its status codes. So a reactive limiter here is not imperfect, it is impossible: neither conventional signal exists, and you cannot back off from something you cannot observe. The budget is therefore chosen in advance and is self-imposed. It does not match anything the vendor enforces and no claim is made that it does.

The naive design is kept in the source so the difference is a measurement rather than an assertion. Same arrival pattern, both designs:

design

greedy admitted

quiet then admitted

one shared bucket

60

0 of 60

a reserve each, plus a shared spare

45

15 of 60, exactly its reserve

A refused call is charged too. If refusals were free, the care taken over making them identical would be wasted: a caller would not need to read them at all, it would ask a hundred names and watch which ones moved its own admitted rate.

Proving it from outside Python

clients/typescript/src/prove.ts drives the running server with the official MCP TypeScript SDK, in its own CI job. It shares no code with the thing it tests, which matters: the Python suite and the Python server can agree with each other about something that is not true of the protocol.

16 checks. A token for this resource is admitted with 200; one for another resource, for two resources, or for none is refused with 401 and a Bearer challenge. An ungranted tool and a nonexistent one refuse with identical bytes. The bursting caller stops where the arithmetic says it should and the quiet one still gets exactly its reserve.

That proof had a defect of its own worth recording. Its first version asked whether connect() threw and treated any throw as a refusal, so when a deliberately broken build made the verifier raise and the server answer 500, the proof reported success. A server answering 500 to everything would have satisfied every audience check on the page. It reads the status now.

What the vendor writes down and the payload does not

There are three times here and the payload carries only one of them.

time

what it is

where it lives

around 14:10 CET

the concertation between central banks

the vendor's prose

14:15 CET

the moment the rate refers to

in the payload, as TITLE_COMPL

around 16:00 CET

when the rate is actually published

the vendor's prose only

A client that reads the payload's own metadata and concludes the rate is available at 14:15 is wrong by nearly two hours, and will call a not-yet-published day a real gap every afternoon. The payload does not merely omit the constraint. It carries a different time that looks authoritative and is the wrong one to use.

The absence encoding changed too, and that was found by writing a client that counted rows and getting a number 62 larger than the one that counted values. The full series is 7,140 rows carrying 7,078 values and 62 placeholders: until May 2012 a closing day arrived as a row with an empty value and OBS_STATUS of H, and after it, as no row at all. Same calendar, two encodings, and only counting values is right in both eras.

The four decisions, and what each one cost

Audience is the gate, not the signature. Cost: a token that is valid elsewhere is refused here, so a caller holding a broadly scoped token has to go back to its issuer for a narrower one.

Scope is denied at dispatch, never by the transport. Cost: a legitimate caller with a mistyped scope gets a refusal that tells it nothing.

Each caller has a reserve nobody else can spend. Cost: a lone caller gains nothing from it, and a burst can no longer use the whole budget when the other caller happens to be idle.

The certificate is required and has no default. Cost: every tool that returns observations has to compute one, including the ones where the answer is that nothing was missing.

Limitations

  • The issuer is local and in-process. No claim is made about any real identity provider, and nothing here has been near one.

  • The budget is self-imposed. It does not correspond to any limit the vendor publishes, because the vendor publishes none.

  • The certificate reconstructs four named causes. A fifth it has not thought of is counted as a genuine gap, which is the safe direction but is not the same as being complete.

  • ECB reference rates are a daily published reference, not a tradeable price, and nothing here treats them as one. There is no order book, no matching engine and no execution path.

  • The cassettes are dated. They prove what the vendor returned on the day they were recorded and nothing about what it returns today.

  • Nothing here is endorsed by or affiliated with the ECB.

Development

uv run pytest
uv run python scripts/readme_block.py

Every number and every block on this page is checked by tests/test_readme.py against the thing it describes. The response body above is generated, not transcribed.

Part of the Q...Z toolset, all of it designing for the failure that does not announce itself:

  • QUACKZ, deflating a backtest that only looks good because it was picked out of two hundred.

  • QUOTEZ, market data an agent can read and cannot act on.

  • QUELLZ, measuring what prompt-injection containment costs in utility as well as in attack rate.

  • QUIDZ, refusing the outbound payment that would have gone out twice.

  • QUESTZ, stopping a scraper before it writes a CSV from a page that changed shape.

  • QUIZZ, answering what a statistic said at the time, and refusing when it cannot.

  • QUARANTINEZ, treating an outcome the venue never confirmed as terminal rather than as a retry.

  • QUENCHZ, this one: deciding in the open what a tool server gets free while it is still somebody's subprocess.

  • QUILTZ, proving infrastructure code wrong without a cloud account, and saying what that cannot show.

  • QUAYZ, telling a crash loop from an OOMKill, and naming the failure that no single field finds.

  • QUARRYZ, keeping every version a statistical office published, and failing the build when it quietly issues another.

  • QUASHZ, refusing a row whose outcome had not been decided yet when the decision would have been made.

  • QUALMZ, a fixed number of looks at the holdout, where re-running the same configuration does not buy another.

  • QUEUEZ, ordering a feed by its sequence, because on a real recorded session the clock goes backwards.

  • QUANDARYZ, counting the distinct screens a component can settle into when its responses arrive out of order.

  • QUIETZ, watching whether the data arrived rather than whether the server answered.

Licence

MIT. See LICENSE.

The data is reused under the ESCB policy on the reuse of statistics, which permits it free of charge on three conditions: the source is quoted, the statistics and metadata are not modified, and no third-party data. All three are tests in tests/test_licence.py, not promises. Source: ECB statistics.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enforces fine-grained, context-aware access control on MCP tool calls, with a tamper-evident, replayable audit log that records denials and verifies every decision.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables remote agents to securely read firewall and NAT rules, inspect routing tables and logs, and execute safety-gated mutation plans through a bearer-authenticated MCP endpoint.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables policy-governed MCP interactions with deterministic authorization, tenant isolation, minimized PII exposure, and human approval gates for sensitive mutations, while producing structured audit events.
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to govern downstream tool servers by enforcing default-deny authority and attestation on every tool call, with live monitoring, approval, and mid-session revocation.
    3
    Apache 2.0