Skip to main content
Glama
PNX89

QUENCHZ

by PNX89

QUENCHZ

Un servidor MCP stdio recibe cuatro cosas gratis por tener un único llamador que comparte su contexto. Una vez que el transporte es remoto, cada una se convierte en una decisión, y todas ellas se toman aquí a la vista y se demuestran desde fuera del árbol de Python.

CI Python TypeScript client License: MIT Data: ECB

Sirviendo herramientas MCP a llamadores que no has escrito. Las cuatro son audiencia, alcance, presupuesto y cobertura, y cada una es refutable mediante una prueba que un revisor puede ver fallar.

{
  "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."
}

Se pidieron doce días naturales y volvieron ocho, y la respuesta es completa. El Viernes Santo, el Lunes de Pascua y el fin de semana son cierres, no huecos, y la carga útil del proveedor no dice absolutamente nada sobre ninguno de ellos. Distinguirlos requiere el calendario de publicación y el reloj de pared, y eso es lo que es el bloque coverage: [src/quenchz/coverage.py].

No modela todo. Reconstruye tres causas nombradas de ausencia y una cuarta para fechas anteriores a la existencia de la serie, y una quinta que nadie haya pensado se contaría como un hueco real. El certificado es un campo obligatorio sin valor predeterminado, por lo que una herramienta que devuelve observaciones no puede responder sin él.

Fuente: estadísticas del ECB.

Doce días pedidos, ocho entregados

El certificado anterior no es un resumen escrito junto a los datos. Es un campo obligatorio en la respuesta, reconstruido a partir del calendario de publicación y no leído de la respuesta, porque la respuesta no lo contiene.

campo

qué responde

requested_calendar_days

lo que el llamador pidió

expected_observations

lo que el calendario dice que se debía en algún momento

delivered_observations

lo que llegó

absent.target_closed

el mercado estaba cerrado

absent.not_yet_published

se debe hoy y aún no ha salido

absent.no_such_observation

se debía, está retrasado y alguien debería saberlo

absent.before_the_series

nunca se debió nada, porque la serie no había comenzado

La última se añadió después de que una revisión pidiera una ventana en 1990. El euro no existía en 1990, y el certificado respondió expected_observations: 261 con los 261 contados como huecos reales, que es la peor respuesta disponible: un informe seguro de 261 tipos de cambio ausentes en días en que no se debía ninguno.

Related MCP server: OPNsense MCP

Un token válido que no llega a nada

Un token emitido por el emisor de confianza, firmado correctamente, sin expirar, con el ámbito correcto, y emitido para un recurso diferente, no llega a nada aquí.

Esa comprobación hay que escribirla a mano. El SDK lleva un campo resource RFC 8707 en AccessToken y nunca lo compara con nada: BearerAuthBackend comprueba el prefijo bearer, la veracidad y la caducidad, y luego pasa resource intacto. El SDK sí le dice al emisor que restrinja por audiencia el token que emite, y no dice nada en absoluto sobre que el servidor de recursos lo compruebe. Dos pruebas verifican que el SDK sigue comportándose así, de modo que si una versión empieza a imponerlo, esta afirmación falla ruidosamente en lugar de volverse silenciosamente falsa.

También se rechaza un token cuya audiencia es una lista, y PyJWT lo aceptaría. RFC 7519 trata la audiencia como una prueba de pertenencia, por lo que un token emitido para este recurso y para otro pasa la librería. Aquí no pasa: un token que también es válido en otro lugar es un token que otro lugar puede presentar en esta puerta, que es la situación que RFC 8707 existe para evitar.

Un llamador tampoco puede conocer lo que no puede usar. Una herramienta fuera de su ámbito concedido no aparece en su listado, y pedirla de todos modos devuelve bytes idénticos a pedir un nombre que nunca existió. Eso tiene un coste real: alguien que de verdad tecleó mal un ámbito recibe un mensaje menos útil del que podría haber tenido. Vale la pena porque la denegación de ámbito del propio SDK responde Required scope: <name>, lo que confirma que la herramienta existe y nombra el permiso que habría funcionado, y cien intentos contra eso son un mapa de la superficie dibujado por el servidor para un llamador al que nunca se le permitió verlo.

Iniciar el servidor

uv sync --dev
uv run pytest

El servidor, con un emisor en proceso que acuña sus propios tokens en un archivo:

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

La clave de firma se genera en memoria y nunca toca el disco. Cada nombre de host usa el TLD reservado .invalid de RFC 2606 y no puede resolverse nunca.

Dos llamadores y un presupuesto que ninguno puede ver

El proveedor no documenta ningún límite de tasa en ninguna página, no envía ninguna cabecera de límite de tasa en ninguna respuesta y no incluye 429 entre sus códigos de estado. Así que un limitador reactivo aquí no es imperfecto, es imposible: no existe ninguna de las dos señales convencionales, y no puedes retroceder ante algo que no puedes observar. Por tanto, el presupuesto se elige de antemano y es autoimpuesto. No se corresponde con nada que el proveedor haga cumplir y no se afirma que lo haga.

El diseño ingenuo se conserva en el código fuente para que la diferencia sea una medición y no una afirmación. El mismo patrón de llegada, ambos diseños:

diseño

voraz admitido

tranquilo después admitido

un único cubo compartido

60

0 de 60

una reserva para cada uno, más un extra compartido

45

15 de 60, exactamente su reserva

Una llamada rechazada también se cobra. Si los rechazos fueran gratis, el cuidado puesto en hacerlos idénticos se desperdiciaría: un llamador no tendría que leerlos en absoluto, pediría cien nombres y observaría cuáles movían su propia tasa de admisión.

Demostrándolo desde fuera de Python

[clients/typescript/src/prove.ts] dirige el servidor en ejecución con el SDK oficial de MCP para TypeScript, en su propio trabajo de CI. No comparte código con lo que prueba, lo cual importa: la suite de Python y el servidor de Python pueden estar de acuerdo entre sí sobre algo que no es cierto respecto al protocolo.

Dieciséis comprobaciones. Un token para este recurso se admite con 200; uno para otro recurso, para dos recursos o para ninguno se rechaza con 401 y un desafío Bearer. Una herramienta no concedida y una inexistente rechazan con bytes idénticos. El llamador que hace ráfagas se detiene donde la aritmética dice que debe, y el tranquilo sigue obteniendo exactamente su reserva.

Esa prueba tenía un defecto propio digno de registro. Su primera versión preguntaba si connect() lanzaba una excepción y trataba cualquier lanzamiento como un rechazo, así que cuando una compilación deliberadamente rota hacía que el verificador fallara y que el servidor respondiera 500, la prueba informaba de éxito. Un servidor que respondiera 500 a todo habría satisfecho todas las comprobaciones de audiencia de la página. Ahora lee el estado.

Lo que el proveedor escribe y la carga útil no

Hay tres horas aquí y solo dos de ellas son visibles para un cliente.

hora

qué es

dónde vive

alrededor de las 14:10 CET

la concertación entre bancos centrales

la prosa del proveedor

14:15 CET

el momento al que se refiere el tipo

en la carga útil, como TITLE_COMPL

alrededor de las 16:00 CET

cuando el tipo se publica realmente

solo en la prosa del proveedor

Un cliente que lee los metadatos de la propia carga útil y concluye que el tipo está disponible a las 14:15 se equivoca por casi dos horas, y cada tarde llamará hueco real a un día aún no publicado. La carga útil no se limita a omitir la restricción. Lleva una hora distinta que parece autorizada y que es la incorrecta para usar.

La codificación de la ausencia también cambió, y eso se descubrió escribiendo un cliente que contaba filas y obteniendo un número 62 mayor que el que contaba valores. La serie completa es 7.140 filas que contienen 7.078 valores y 62 marcadores de posición: hasta mayo de 2012 un día de cierre llegaba como una fila con un valor vacío y OBS_STATUS de H, y después, como ninguna fila en absoluto. El mismo calendario, dos codificaciones, y solo contar valores es lo correcto en ambas épocas.

Las cuatro decisiones y lo que costó cada una

La audiencia es la puerta, no la firma. Coste: un token que es válido en otro lugar se rechaza aquí, por lo que un llamador que tiene un token de ámbito amplio tiene que volver a su emisor para obtener uno más restringido.

El ámbito se deniega en el despacho, nunca por el transporte. Coste: un llamador legítimo con un ámbito mal escrito recibe un rechazo que no le dice nada.

Cada llamador tiene una reserva que nadie más puede gastar. Coste: un llamador solitario no gana nada con ello, y una ráfaga ya no puede usar todo el presupuesto cuando el otro llamador está inactivo.

El certificado es obligatorio y no tiene valor por defecto. Coste: toda herramienta que devuelve observaciones tiene que calcular uno, incluidas aquellas en las que la respuesta es que no faltaba nada.

Limitaciones

  • El emisor es local y está en proceso. No se hace ninguna afirmación sobre ningún proveedor de identidad real, y nada de esto ha estado cerca de uno.

  • El presupuesto es autoimpuesto. No se corresponde con ningún límite que el proveedor publique, porque el proveedor no publica ninguno.

  • El certificado reconstruye cuatro causas nombradas. Una quinta que no haya pensado se cuenta como un hueco real, que es la dirección segura pero no es lo mismo que estar completo.

  • Los tipos de referencia del ECB son una referencia publicada a diario, no un precio negociable, y nada aquí los trata como tal. No hay libro de órdenes, ni motor de emparejamiento, ni ruta de ejecución.

  • Las cintas están fechadas. Prueban lo que el proveedor devolvió el día en que se grabaron y nada sobre lo que devuelve hoy.

  • Nada de esto está respaldado por el ECB ni afiliado a él.

Desarrollo

uv run pytest
uv run python scripts/readme_block.py

Cada número y cada bloque de esta página se comprueban con tests/test_readme.py contra lo que describen. El cuerpo de la respuesta anterior se genera, no se transcribe.

Licencia

MIT. Ver LICENSE.

Los datos se reutilizan conforme a la política del ESCB sobre la reutilización de estadísticas, que lo permite gratuitamente con tres condiciones: se cita la fuente, las estadísticas y los metadatos no se modifican, y no hay datos de terceros. Las tres son pruebas en [tests/test_licence.py], no promesas. Fuente: estadísticas del ECB.

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