{"manifest":{"id":"miro","name":"Miro","description":"Stateful Miro MCP emulator: the OAuth 2.1 authorization server at the origin root (Dynamic Client Registration, S256 PKCE, HS256 OIDC ID tokens signed with the client secret and, like real Miro, without the nonce claim) plus the remote MCP server at / with read-only board tools over seeded state.","docsUrl":"https://docs.emulators.dev/miro","surfaces":[{"id":"oauth","kind":"oauth","title":"Miro MCP OAuth and OIDC","status":"partial","basePath":"/","notes":"authorization_code and refresh_token grants. The jwt-bearer grant is advertised, as on the real server, but answers unsupported_grant_type. ID tokens are HS256 signed with the client secret, carry iss/sub/aud/exp/iat/email/email_verified, and omit nonce even when the authorization request sent one (seed id_token_nonce: echo to change that)."},{"id":"mcp","kind":"mcp","title":"Miro MCP server","status":"partial","basePath":"/","notes":"Streamable HTTP JSON-RPC at the origin root. Every request without a valid bearer token, on any unknown path, answers 401 with the resource_metadata challenge like Miro's gateway."},{"id":"consent","kind":"ui","title":"OAuth consent page","status":"supported","basePath":"/authorize"}],"auth":[{"id":"dcr","title":"Dynamic Client Registration","type":"dynamic-client-registration","status":"supported","notes":"POST /register (RFC 7591). Also available through POST /_emulate/credentials."},{"id":"oauth","title":"OAuth authorization code with PKCE","type":"oauth-authorization-code","status":"supported","notes":"client_secret_post or client_secret_basic, S256 PKCE required, refresh token rotation."}],"scenarios":[{"id":"id-token-nonce-omitted","title":"ID token without nonce (default)","description":"Miro's real behaviour. The ID token never carries nonce, so OIDC clients that send one and validate it fail."},{"id":"id-token-nonce-echoed","title":"ID token with nonce","description":"POST /_emulate/seed with {\"id_token_nonce\":\"echo\"} to echo the authorization request nonce, as OIDC Core requires."}],"specs":[{"kind":"oauth-metadata","title":"Miro MCP authorization server","coverage":"hand-authored","operations":[{"operationId":"miro.oauth.authorizationServerMetadata","method":"GET","path":"/.well-known/oauth-authorization-server","status":"hand-authored"},{"operationId":"miro.oidc.configuration","method":"GET","path":"/.well-known/openid-configuration","status":"hand-authored"},{"operationId":"miro.oauth.register","method":"POST","path":"/register","status":"hand-authored"},{"operationId":"miro.oauth.authorize","method":"GET","path":"/authorize","status":"hand-authored"},{"operationId":"miro.oauth.approve","method":"POST","path":"/authorize","status":"hand-authored"},{"operationId":"miro.oauth.token","method":"POST","path":"/token","status":"hand-authored"},{"operationId":"miro.oauth.revoke","method":"POST","path":"/oidc/revoke","status":"hand-authored"},{"operationId":"miro.oauth.jwtBearer","status":"unsupported","summary":"jwt-bearer grant"},{"operationId":"miro.oauth.teamSelection","status":"unsupported","summary":"Team selection during consent"}]},{"kind":"mcp","title":"Miro MCP tool subset","coverage":"partial","operations":[{"operationId":"miro.mcp.protectedResourceMetadata","method":"GET","path":"/.well-known/oauth-protected-resource","status":"hand-authored"},{"operationId":"board_search_boards","status":"hand-authored"},{"operationId":"canvas_search","status":"hand-authored"},{"operationId":"canvas_read_as_svg","status":"unsupported","summary":"SVG canvas, comment, image, prototype, table, and write tools are not emulated."}]}],"seedSchema":{"description":"Seed the users who can approve consent, the boards the MCP tools read, optional preregistered OAuth clients, and the ID token nonce behaviour.","fields":[{"key":"users","title":"Users","description":"Each user becomes a sign in button on the consent page. Their email lands in the ID token.","example":[{"email":"user@example.com","name":"Miro User"}]},{"key":"boards","title":"Boards","description":"Boards with items for board_search_boards and canvas_search.","example":[{"name":"Product Roadmap","items":[{"type":"sticky_note","content":"Ship it"}]}]},{"key":"oauth_clients","title":"OAuth clients","description":"Preregistered clients. Omit client_id and client_secret to get generated ones.","example":[{"client_name":"My app","redirect_uris":["http://localhost:3000/callback"]}]},{"key":"id_token_nonce","title":"ID token nonce","description":"\"omit\" (default, matches real Miro) or \"echo\".","example":"omit"}],"example":{"users":[{"email":"user@example.com"}],"boards":[{"name":"Product Roadmap"}]}},"stateModel":{"description":"Miro users, boards, and OAuth state.","collections":[{"name":"miro.users"},{"name":"miro.boards"},{"name":"miro.oauth_clients"},{"name":"miro.oauth_grants"},{"name":"miro.oauth_tokens"}]},"connections":[{"id":"mcp-endpoint","title":"MCP endpoint","kind":"mcp","description":"Point an MCP client here. It discovers OAuth from the 401 and registers itself.","template":"{{baseUrl}}/"},{"id":"register","title":"Register a client","kind":"curl","template":"curl -X POST {{baseUrl}}/register \\\n  -H 'content-type: application/json' \\\n  -d '{\"client_name\":\"My app\",\"redirect_uris\":[\"http://localhost:3000/callback\"]}'"},{"id":"base-url","title":"Base URL (env)","kind":"env","language":"bash","description":"Point your SDK or app at the emulator instead of the real provider.","template":"{{SERVICE_UPPER}}_BASE_URL={{baseUrl}}"},{"id":"create-credential","title":"Create a credential","kind":"curl","language":"bash","description":"Mint a working credential for this instance.","template":"curl -s -X POST {{controlBaseUrl}}/credentials \\\n  -H \"content-type: application/json\" \\\n  -d '{\"type\":\"{{defaultAuthType}}\"}'"},{"id":"inspect-ledger","title":"Inspect requests","kind":"curl","language":"bash","description":"Read the request ledger to validate how your app called the service.","template":"curl -s {{controlBaseUrl}}/ledger"}],"resetBehavior":{"description":"Resets the instance to its seeded baseline.","reseeds":true,"clearsLedger":true,"clearsWebhooks":true},"ledger":{"description":"Recent provider requests with sensitive headers and fields redacted.","recordsFields":["timestamp","method","host","path","route","operationId","correlationId","identity","request","response","summary","sideEffects","webhookDeliveries","durationMs"],"redactsSensitive":true,"correlationId":true,"webhookDeliveries":true,"sideEffects":true,"persistent":true,"maxEntries":1000},"inspectorTabs":[{"id":"overview","title":"Overview","kind":"landing","description":"Service surfaces, base URLs, and connection snippets."},{"id":"ledger","title":"Ledger","kind":"ledger","description":"Recent provider requests recorded by the emulator."},{"id":"state","title":"State","kind":"state","description":"Current seeded and mutated instance state."},{"id":"credentials","title":"Credentials","kind":"credentials","description":"Mint tokens, API keys, or OAuth clients."},{"id":"seed","title":"Seed","kind":"seed","description":"Seed state or load a scenario."}]},"instance":null,"sampleInstance":{"service":"miro","instance":"your-instance","baseUrl":"https://miro.your-instance.emulators.dev","providerBaseUrl":"https://miro.your-instance.emulators.dev","controlBaseUrl":"https://miro.your-instance.emulators.dev/_emulate"},"connections":[{"id":"mcp-endpoint","title":"MCP endpoint","kind":"mcp","description":"Point an MCP client here. It discovers OAuth from the 401 and registers itself.","template":"{{baseUrl}}/","body":"https://miro.your-instance.emulators.dev/"},{"id":"register","title":"Register a client","kind":"curl","template":"curl -X POST {{baseUrl}}/register \\\n  -H 'content-type: application/json' \\\n  -d '{\"client_name\":\"My app\",\"redirect_uris\":[\"http://localhost:3000/callback\"]}'","body":"curl -X POST https://miro.your-instance.emulators.dev/register \\\n  -H 'content-type: application/json' \\\n  -d '{\"client_name\":\"My app\",\"redirect_uris\":[\"http://localhost:3000/callback\"]}'"},{"id":"base-url","title":"Base URL (env)","kind":"env","language":"bash","description":"Point your SDK or app at the emulator instead of the real provider.","template":"{{SERVICE_UPPER}}_BASE_URL={{baseUrl}}","body":"MIRO_BASE_URL=https://miro.your-instance.emulators.dev"},{"id":"create-credential","title":"Create a credential","kind":"curl","language":"bash","description":"Mint a working credential for this instance.","template":"curl -s -X POST {{controlBaseUrl}}/credentials \\\n  -H \"content-type: application/json\" \\\n  -d '{\"type\":\"{{defaultAuthType}}\"}'","body":"curl -s -X POST https://miro.your-instance.emulators.dev/_emulate/credentials \\\n  -H \"content-type: application/json\" \\\n  -d '{\"type\":\"dynamic-client-registration\"}'"},{"id":"inspect-ledger","title":"Inspect requests","kind":"curl","language":"bash","description":"Read the request ledger to validate how your app called the service.","template":"curl -s {{controlBaseUrl}}/ledger","body":"curl -s https://miro.your-instance.emulators.dev/_emulate/ledger"}]}