Maintenance Due

Para quienes construyen agentes

Personal Agent Protocol en Maintenance Due

Un agente personal puede llegar al tablero de vencimientos y al registro de servicio de un dueño con Personal Agent Protocol v0.1. El dueño inicia sesión en nuestra página y elige ver o cambiar. Maintenance Due es gratis, y la ruta de vencimientos no llama a un modelo.

Esta página es para quienes construyen agentes personales. Si solo quieres que Muse lleve al día el aceite de la van, copia el prompt en for-your-agent. La especificación está en personalagentprotocol.org.

Descubrimiento

GET https://maintenancedue.com/.well-known/poppy.json nombra la organización (maintenancedue.com), el emisor https://maintenancedue.com, Direct Sign-In con poppy:read y poppy:write, y dos APIs: el servidor MCP en https://maintenancedue.com/mcp y la descripción OpenAPI en https://maintenancedue.com/openapi.json para REST bajo /api/v1. Los metadatos del emisor en /.well-known/oauth-authorization-server listan maintenancedue.com en poppy_domains y dan los endpoints de token, autorización y revocación bajo /oauth/.

Sesiones e inicio de sesión

  1. Publica tu cliente. Tu client_id es una URL https que sirve tu documento de metadatos de cliente, con jwks_uri y redirect_uris en el mismo dominio. Cada petición de token lleva una aserción de cliente private_key_jwt firmada con una clave de ese jwks_uri.
  2. Inicia una Session. POST /oauth/token con grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, una aserción cuyo iss es tu client_id, sub es el User ID y aud es https://maintenancedue.com/oauth/token como una sola cadena, más una prueba DPoP. Recibes un Session Token sin sesión iniciada (token_type DPoP, una hora) y un session_id. Envía session_id con una aserción nueva para renovarlo.
  3. Manda al dueño a nuestra página. Abre /oauth/authorize con response_type=code, tu client_id y redirect_uri, scope=poppy:read poppy:write (o solo poppy:read), un state y un code_challenge PKCE S256. El dueño ve tu nombre y tu dominio, elige View only o View and change, y luego crea un taller gratis o inicia sesión con un token de membresía que ya tiene. La redirección devuelve code, state e iss. Comprueba que iss sea https://maintenancedue.com.
  4. Canjea el código. POST /oauth/token con grant_type=authorization_code, el code, redirect_uri, code_verifier y tu session_id, más tu aserción de cliente y una prueba DPoP. La respuesta trae el Account Token en refresh_token (pat_…, 30 días), un Session Token con sesión iniciada y el scope concedido. El dueño puede elegir ver cuando pediste cambiar, así que lee scope.
  5. Empieza con sesión iniciada más tarde. POST /oauth/token con grant_type=refresh_token y el Account Token, con o sin session_id. Añade scope=poppy:read para un token de solo lectura en una consulta. El Account Token no rota, así que varias Sessions en paralelo pueden compartirlo.
  6. Cierra sesión. POST /oauth/revoke con el Account Token y tu aserción de cliente. Cada Session iniciada con él queda sin sesión en su próxima llamada y se renueva sin sesión.

Llamar al tablero

REST usa DPoP: Authorization: DPoP <token> más una prueba DPoP nueva con htm, htu y ath en cada llamada a /api/v1. MCP usa Bearer: renueva sin prueba DPoP y con resource=https://maintenancedue.com/mcp, y luego envía Authorization: Bearer <token> a /mcp. Un Session Token Bearer solo funciona en /mcp, y allí se rechaza un token DPoP. Las herramientas MCP, sus esquemas y la cabecera MCP-Protocol-Version 2025-06-18 son las mismas que usa ChatGPT.

Ver o cambiar

poppy:read abre cada GET en /api/v1 y cada herramienta MCP marcada readOnlyHint, como get_due, get_history y list_assets. poppy:write abre cada otro método REST y herramienta MCP, como append_event, append_reading, create_service y set_rule, más events/subscribe. Un scope que falta es 403 con error="insufficient_scope" y el scope que necesita en WWW-Authenticate. Un token sin sesión en una llamada de cuenta es 403 sign_in_required. Un token vencido, o uno emitido antes del cierre de sesión, es 401 invalid_token. Invitar, quitar o abandonar miembros de la org se queda con el token propio del miembro.

Las conexiones de ChatGPT hechas por /oauth/authorize con el scope mcp, y los tokens de membresía de Muse que ya existen, siguen funcionando como antes. Los nombres de campo viven en skill.md, el contrato REST en openapi.json y el índice de agentes en llms.txt.