Ir al contenido

Desarrollo

  • Directorioavenir_mcp/ — el servidor (vea Arquitectura)
    • …
  • Directoriotests/ — pruebas unitarias, del protocolo, de la documentación y de higiene
    • …
  • Directorioevals/ — el plan de demostración, un sustituto de la API de YNAB, la evaluación con agente
    • …
  • Directoriodocsgen/ — genera la referencia de herramientas, el catálogo de errores y los ejemplos
    • …
  • Directoriodocs/ — este sitio (Astro Starlight, inglés, francés, español, alemán, neerlandés)
    • …
  • AGENTS.md — el contrato de los colaboradores, humanos o no
  • justfile — todos los comandos de abajo
  • pyproject.toml, uv.lock — el proyecto Python, bloqueado
Ventana de terminal
git clone https://github.com/mathbeal/avenir-mcp && cd avenir-mcp
uv sync # Python 3.14 y las dependencias bloqueadas
just check # todos los controles de la CI

just check ejecuta, en el orden de la CI:

Control Comando Falla cuando
formato ruff format --check un archivo no está formateado
lint pylint la nota es inferior a 10,00
ruff ruff check un docstring del paquete no sigue el estilo Google u omite un argumento, el valor devuelto o una excepción lanzada; los imports no están ordenados; los controles de seguridad de bandit encuentran un patrón de riesgo (TLS sin verificar, un comando shell, una contraseña en el código…)
docstrings pydoclint un docstring del paquete enumera los argumentos en otro orden que la firma, da un tipo que la anotación ya da, o se reduce a un resumen en una función que recibe argumentos o devuelve un valor
Condiciones de la API de YNAB pytest -m ynab_terms, python -m docsgen.terms no se cumple una regla de las condiciones de la API de YNAB (nombre, mención palabra por palabra, imagen oficial de YNAB, token solo para su titular, límite de solicitudes por hora), o YNAB cambió sus condiciones desde la fecha comprobada; el distintivo del README lo muestra
dependencias deptry . el código importa un paquete que pyproject.toml no declara, o declara uno que no usa
tipos mypy (estricto) cualquier error de tipos
pruebas pytest una prueba falla, se emite cualquier aviso, o la cobertura de líneas o ramas es inferior al 100 %
vocabulario lexdrift check avenir_mcp --baseline lexdrift.lock aparece una palabra nueva para una idea ya nombrada
bloqueo uv lock --check uv.lock no corresponde a pyproject.toml

La CI ejecuta además lychee sobre cada enlace del README y de la documentación (just links, y cada lunes, porque una página externa puede desaparecer), gitleaks sobre cada commit del historial (just secrets, con Docker), typos, zizmor sobre los workflows, reuse lint (cada archivo indica su copyright y su licencia), dos construcciones del wheel y del sdist que deben ser idénticas bit a bit (just reproducible), pip-audit sobre las dependencias bloqueadas, la construcción de la documentación con las pruebas de su propio código, CodeQL y el OpenSSF Scorecard (una vez público el repositorio), una comparación semanal de la API de YNAB con su instantánea (just api-drift), y el MCP Inspector oficial (just inspect), que comprueba el servidor como lo ve un cliente, sobre el plan de demostración: sus listas, la portabilidad de los esquemas de sus herramientas y una llamada de cada tipo. La batería de pruebas se ejecuta en Linux y macOS con Python 3.12, 3.13 y 3.14, y en Windows con Python 3.14 (en una pull request, macOS solo prueba 3.14: sus máquinas cuestan diez veces las de Linux); la cobertura se exige en Linux y macOS, donde se aplican los controles de permisos de archivos. Python 3.15 también se ejecuta, como experimento: un fallo allí es un aviso, no un control en rojo. En una pull request, cada commit debe llevar sign-off y el título debe empezar por el tipo de cambio. Dos controles deben estar en verde: CI passed, que resume todos los jobs del workflow de calidad, y MCP Inspector, un workflow aparte para que su badge lo muestre solo.

Renovate abre pull requests cada lunes por la mañana:

Actualización Tratamiento
herramientas de desarrollo, acciones de CI, sitio de documentación (menores y parches) agrupadas, fusionadas solas cuando la CI pasa
fastmcp, httpx, pydantic — se ejecutan frente a los planes de los usuarios una pull request cada una, revisada a mano; la evaluación se ejecuta antes de actualizar fastmcp
cualquier versión mayor una pull request cada una, revisada a mano
una vulnerabilidad conocida de inmediato, sea el día que sea

Una versión nueva espera siete días antes de que Renovate la proponga: una versión rota o maliciosa retirada rápido nunca llega al proyecto.

Tipo Archivos Qué comprueban
Unitarias test_classifier, test_triage, test_writes, test_reconcile, test_forecast, test_analytics, test_journal, test_client la lógica pura y el cliente HTTP, con datos inventados
Propiedades test_properties con Hypothesis, reglas que se cumplen para cualquier entrada: ida y vuelta de importes, reparto sin perder un céntimo, meses que se encadenan, cursores, texto bancario, huellas de confirmación
Protocolo test_protocol*, test_context, test_policy las herramientas a través de un cliente MCP en memoria: esquemas, anotaciones, caminos de confirmación, deshacer
Documentación test_docs las páginas y ejemplos generados corresponden al código; cada página existe en cada traducción; cada variable de entorno está documentada
Cobertura de la API test_api_coverage cada operación de la API de YNAB la usa una herramienta, está prevista o se descarta con su razón; el cliente solo llama a rutas documentadas
Higiene test_hygiene ni IBAN, ni token, ni extracto, ni ruta personal, ni copia del Finder en el repositorio
Evaluación test_evals las comprobaciones de la evaluación son correctas

Las pruebas se escriben primero. Ninguna prueba llama a YNAB.

just mutate ejecuta las pruebas de mutación (mutmut) sobre los módulos de cálculo: modifica a propósito el código, unas 1.500 veces, y comprueba que una prueba falla cada vez. Los cambios que ninguna prueba detecta señalan las pruebas que escribir; muchos son inofensivos, como la redacción de un mensaje.

just bench mide cuánto tardan los módulos de cálculo sobre un plan generado de cinco años, unas 9.000 transacciones (pytest-benchmark). En un portátil, la operación más lenta (preparar una página de sugerencias) tarda unos 30 ms: el tiempo de una herramienta se va en esperar a YNAB, no en calcular.

just fuzz ejecuta las propiedades Hypothesis con 50.000 ejemplos cada una en lugar de 100 (unos minutos; just fuzz 200000 para ir más lejos), sobre lo que viene de fuera: etiquetas bancarias, diarios dañados, cabeceras HTTP, importes, cursores de paginación. Un fallo se guarda y se vuelve a ejecutar, reducido al caso más pequeño, en la ejecución siguiente. La CI lo hace cada noche con 200.000. La primera pasada encontró un byte del diario que no era texto (0x80) y aparecía como un error de códec en bruto en lugar de nombrar la línea que corregir.

Ventana de terminal
uv run python -m docsgen # páginas de herramientas, catálogo de errores, ejemplos
just docs # construye el sitio en todos los idiomas; un enlace roto falla
just docs-serve # vista previa en vivo en http://localhost:4321/avenir-mcp/

docsgen ejecuta avenir-mcp sobre el plan de demostración y escribe lo que realmente responde, con la fecha fijada y los ids aleatorios sustituidos. Las páginas escritas a mano existen en inglés, francés, español, alemán y neerlandés; una prueba falla si falta una.

El sitio se publica en GitHub Pages con el workflow docs, y en Cloudflare Pages (avenir-mcp.pages.dev), que lo construye desde el repositorio con npm run build:cloudflare. Ambos lo sirven bajo /avenir-mcp/; en Cloudflare, la raíz redirige allí. GitHub Pages no puede enviar cabeceras de seguridad; Cloudflare Pages envía las de docs/cloudflare/_headers con cada archivo: una Content-Security-Policy, HSTS, X-Content-Type-Options: nosniff, X-Frame-Options: DENY, una política de referente, una política de permisos y una política de apertura. La política autoriza los archivos del sitio y cada script o estilo en línea de las páginas construidas por su SHA-256, calculado al construir; 'wasm-unsafe-eval' permite que la búsqueda ejecute su WebAssembly, y los atributos de estilo solo se autorizan mediante style-src-attr. La construcción falla, también en CI, si falta una cabecera requerida o se debilita. La variable de entorno DOCS_SITE fija la dirección de los enlaces canónicos y del mapa del sitio.

Ventana de terminal
just evaluate # todas las tareas, Sonnet, alrededor de 1 USD de su plan de Claude
uv run python -m evals.run --task classify --model haiku

Vea Evaluación.

  • Los mensajes de commit empiezan por un tipo — feat:, fix:, docs:, refactor:, test:, build:, ci:, chore: — porque CHANGELOG.md se genera a partir de ellos con git-cliff.
  • Para publicar: just changelog, commit, etiqueta vX.Y.Z igual a avenir_mcp.__version__, y una release de GitHub. El workflow publish construye dos veces con la fecha del commit etiquetado, se detiene si las dos construcciones difieren, ejecuta twine check --strict y sube a PyPI mediante Trusted Publishing: no se guarda ningún token.
  • Después, el registro de servidores MCP: server.json lleva la misma versión (una prueba lo comprueba); ejecute mcp-publisher login github y luego mcp-publisher publish. La línea mcp-name: del README demuestra que el paquete de PyPI es suyo.

Proyecto no oficial. «We are not affiliated, associated, or in any way officially connected with YNAB or any of its subsidiaries or affiliates. The official YNAB website can be found at https://www.ynab.com. The names YNAB and You Need A Budget, as well as related names, tradenames, marks, trademarks, emblems, and images are registered trademarks of YNAB.» No estamos afiliados, asociados ni conectados oficialmente de ninguna manera con YNAB ni con sus filiales o empresas afiliadas. El sitio web oficial de YNAB se encuentra en https://www.ynab.com. Los nombres YNAB y You Need A Budget, así como los nombres, nombres comerciales, marcas, emblemas e imágenes relacionados, son marcas registradas de YNAB. avenir-mcp se ofrece tal cual, sin garantía, y no es asesoramiento financiero. Aviso legal · Privacidad