Maintenance Due

Quem constrói agentes

Personal Agent Protocol no Maintenance Due

Um agente pessoal pode chegar ao quadro de vencimentos e ao registro de serviço de um dono com o Personal Agent Protocol v0.1. O dono entra na nossa página e escolhe ver ou alterar. O Maintenance Due é grátis, e o cálculo de vencimentos não chama um modelo.

Esta página é para quem constrói agentes pessoais. Se você só quer que o Muse mantenha o óleo da van em dia, copie o prompt em for-your-agent. A especificação está em personalagentprotocol.org.

Descoberta

GET https://maintenancedue.com/.well-known/poppy.json nomeia a organização (maintenancedue.com), o emissor https://maintenancedue.com, o Direct Sign-In com poppy:read e poppy:write, e duas APIs: o servidor MCP em https://maintenancedue.com/mcp e a descrição OpenAPI em https://maintenancedue.com/openapi.json para o REST sob /api/v1. Os metadados do emissor em /.well-known/oauth-authorization-server listam maintenancedue.com em poppy_domains e dão os endpoints de token, autorização e revogação sob /oauth/.

Sessions e login

  1. Publique seu cliente. Seu client_id é uma URL https que serve seu documento de metadados de cliente, com jwks_uri e redirect_uris no mesmo domínio. Cada pedido de token leva uma asserção de cliente private_key_jwt assinada com uma chave desse jwks_uri.
  2. Inicie uma Session. POST /oauth/token com grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, uma asserção cujo iss é seu client_id, sub é o User ID e aud é https://maintenancedue.com/oauth/token como uma única string, mais uma prova DPoP. Você recebe um Session Token sem login (token_type DPoP, uma hora) e um session_id. Envie session_id com uma asserção nova para renová-lo.
  3. Mande o dono para a nossa página. Abra /oauth/authorize com response_type=code, seu client_id e redirect_uri, scope=poppy:read poppy:write (ou só poppy:read), um state e um code_challenge PKCE S256. O dono vê seu nome e seu domínio, escolhe View only ou View and change e então cria uma oficina grátis ou entra com um token de membro que já tem. O redirecionamento traz code, state e iss. Confira que iss é https://maintenancedue.com.
  4. Troque o código. POST /oauth/token com grant_type=authorization_code, o code, redirect_uri, code_verifier e seu session_id, mais sua asserção de cliente e uma prova DPoP. A resposta traz o Account Token em refresh_token (pat_…, 30 dias), um Session Token com login e o scope concedido. O dono pode escolher ver quando você pediu alterar, então leia scope.
  5. Comece com login depois. POST /oauth/token com grant_type=refresh_token e o Account Token, com ou sem session_id. Adicione scope=poppy:read para um token só de leitura numa consulta. O Account Token não é rotacionado, então Sessions em paralelo podem compartilhá-lo.
  6. Saia. POST /oauth/revoke com o Account Token e sua asserção de cliente. Cada Session que entrou com ele perde o login na próxima chamada e se renova sem login.

Chamar o quadro

O REST usa DPoP: Authorization: DPoP <token> mais uma prova DPoP nova com htm, htu e ath em cada chamada a /api/v1. O MCP usa Bearer: renove sem prova DPoP e com resource=https://maintenancedue.com/mcp, depois envie Authorization: Bearer <token> para /mcp. Um Session Token Bearer só funciona em /mcp, e lá um token DPoP é recusado. As ferramentas MCP, seus esquemas e o cabeçalho MCP-Protocol-Version 2025-06-18 são os mesmos que o ChatGPT usa.

Ver ou alterar

poppy:read abre cada GET em /api/v1 e cada ferramenta MCP marcada readOnlyHint, como get_due, get_history e list_assets. poppy:write abre todos os outros métodos REST e ferramentas MCP, como append_event, append_reading, create_service e set_rule, mais events/subscribe. Um scope ausente é 403 com error="insufficient_scope" e o scope necessário em WWW-Authenticate. Um token sem login numa chamada de conta é 403 sign_in_required. Um token expirado, ou emitido antes da saída, é 401 invalid_token. Convidar, remover ou deixar membros da org fica com o token do próprio membro.

As conexões do ChatGPT feitas por /oauth/authorize com o scope mcp, e os tokens de membro do Muse que já existem, continuam funcionando como antes. Os nomes de campo ficam em skill.md, o contrato REST em openapi.json e o índice de agentes em llms.txt.