Agent builders
Personal Agent Protocol on Maintenance Due
A personal agent can reach an owner's due board and service log through Personal Agent Protocol v0.1. The owner signs in on our page and picks view or change. Maintenance Due is free, and the due path does not call a model.
This page is for people who build personal agents. If you only want Muse to keep the van's oil on schedule, copy the prompt at /for-your-agent instead. The spec lives at personalagentprotocol.org.
Discovery
GET https://maintenancedue.com/.well-known/poppy.json names the organization (maintenancedue.com), the issuer https://maintenancedue.com, Direct Sign-In with poppy:read and poppy:write, and two APIs: the MCP server at https://maintenancedue.com/mcp and the OpenAPI description at https://maintenancedue.com/openapi.json for REST under /api/v1. The issuer metadata at /.well-known/oauth-authorization-server lists maintenancedue.com in poppy_domains and gives the token, authorization, and revocation endpoints under /oauth/.
Sessions and sign-in
- Publish your client. Your
client_idis an https URL that serves your client metadata document, withjwks_uriandredirect_urison the same domain. Every token request carries aprivate_key_jwtclient assertion signed with a key from thatjwks_uri. - Start a Session.
POST /oauth/tokenwithgrant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, an assertion whoseissis yourclient_id,subis the User ID, andaudishttps://maintenancedue.com/oauth/tokenas a single string, plus a DPoP proof. You get a signed-out Session Token (token_typeDPoP, one hour) and asession_id. Sendsession_idwith a fresh assertion to renew it. - Send the owner to our page. Open
/oauth/authorizewithresponse_type=code, yourclient_idandredirect_uri,scope=poppy:read poppy:write(or onlypoppy:read), astate, and a PKCE S256code_challenge. The owner sees your name and domain, picks View only or View and change, then creates a free shop or signs in with a membership token they already hold. The redirect brings backcode,state, andiss. Check thatissishttps://maintenancedue.com. - Exchange the code.
POST /oauth/tokenwithgrant_type=authorization_code, thecode,redirect_uri,code_verifier, and yoursession_id, plus your client assertion and a DPoP proof. The response carries the Account Token inrefresh_token(pat_…, 30 days), a signed-in Session Token, and the grantedscope. The owner may pick view when you asked for change, so readscope. - Start signed in later.
POST /oauth/tokenwithgrant_type=refresh_tokenand the Account Token, with or withoutsession_id. Addscope=poppy:readfor a read-only token on a lookup. The Account Token is not rotated, so parallel Sessions can share it. - Sign out.
POST /oauth/revokewith the Account Token and your client assertion. Every Session signed in with it is signed out on its next call and renews signed out.
Calling the board
REST takes DPoP: Authorization: DPoP <token> plus a fresh DPoP proof with htm, htu, and ath on every call to /api/v1. MCP takes Bearer: renew without a DPoP proof and with resource=https://maintenancedue.com/mcp, then send Authorization: Bearer <token> to /mcp. A Bearer Session Token works only on /mcp, and a DPoP token is refused there. The MCP tools, their schemas, and the MCP-Protocol-Version 2025-06-18 header are the same ones ChatGPT uses.
View or change
poppy:read opens every GET on /api/v1 and every MCP tool marked readOnlyHint, such as get_due, get_history, and list_assets. poppy:write opens every other REST method and MCP tool, such as append_event, append_reading, create_service, and set_rule, plus events/subscribe. A missing scope is 403 with error="insufficient_scope" and the scope it needs in WWW-Authenticate. A signed-out token on an account call is 403 sign_in_required. An expired token, or one issued before sign-out, is 401 invalid_token. Inviting, removing, or leaving org members stays with the member's own token.
ChatGPT connections made through /oauth/authorize with the mcp scope, and existing Muse membership tokens, keep working as they did. Field names live on /skill.md, the REST contract on /openapi.json, and the agent index on /llms.txt.