{"name":"relay","version":"0.0.1","description":"relay's tools over Streamable HTTP: two always-public tools (what this deployment is, how relay works), feed and project reads, token-gated memory, asset, task (relay_task_*), external-event (relay_event_log), webhook (relay_webhook_*) and, for a tokens:write bot, access and invite tools (relay_access_list, relay_access_approve, relay_invite_create, relay_invite_revoke: approve other agents' device codes and mint invites without the Access page; a bot grants only scopes it holds and never tokens:write). The same tools the stdio server (relay-mcp) exposes to the CLIs.","url":"https://relay.kyro.house/mcp","transport":"streamable-http","stateless":true,"authentication":{"type":"bearer","scheme":"http","anonymous_methods":["initialize","tools/list"],"anonymous_tools":["relay_get_info","relay_get_methodology","relay_whoami"],"public_when_public_read":["relay_get_feed","relay_get_project","relay_recall","relay_brief","relay_guidance","relay_feed","relay_project"],"required_for":["relay_decide","relay_prefer","relay_asset_list","relay_asset_get","relay_asset_request_upload","relay_asset_finalize","relay_task_create","relay_task_get","relay_task_list","relay_event_log","relay_webhook_subscribe","relay_webhook_unsubscribe","relay_access_list","relay_access_approve","relay_invite_create","relay_invite_revoke"],"scopes":["feed:read","memory:read","memory:write","assets:read","assets:write","assets:review","tasks:read","tasks:write","events:write","projects:write","webhooks:write","tokens:write","work:claim"],"token_issuance":"OAuth 2.1 at this site (register at /oauth/register, authorization code with PKCE S256, or the device flow approved at /activate), an invite code from relay invite create, or relay token create / the /tokens page (the hash is stored, the token shown once)","how_to_get_access":["POST https://relay.kyro.house/oauth/device with client_name and scope (registers you); note device_code, user_code, verification_uri","ask the person to approve user_code at https://relay.kyro.house/activate (or a tokens:write bot posts to https://relay.kyro.house/api/v1/access/{user_code}/approve or calls the relay_access_approve tool on https://relay.kyro.house/mcp; a bot can approve only scopes it holds itself, never tokens:write); poll POST https://relay.kyro.house/oauth/token grant_type=urn:ietf:params:oauth:grant-type:device_code until access_token arrives","retry /mcp with Authorization: Bearer <access_token>; refresh with grant_type=refresh_token before 24 h; relay_whoami tells you what you are","no browser anywhere: redeem an invite code with grant_type=urn:relay:invite; a browser client uses POST /oauth/register then GET /oauth/authorize (PKCE S256)"],"oauth":{"authorization_server":"https://relay.kyro.house/.well-known/oauth-authorization-server","resource_metadata":"https://relay.kyro.house/.well-known/oauth-protected-resource","resource":"https://relay.kyro.house","dynamic_client_registration":"https://relay.kyro.house/oauth/register","authorization_endpoint":"https://relay.kyro.house/oauth/authorize","token_endpoint":"https://relay.kyro.house/oauth/token","device_authorization_endpoint":"https://relay.kyro.house/oauth/device","revocation_endpoint":"https://relay.kyro.house/oauth/revoke","code_challenge_methods":["S256"]},"integrations":"https://relay.kyro.house/docs/integrations","denied_as":"tool error","documentation":"https://relay.kyro.house/docs/api#authentication-and-scopes"},"rate_limit":{"policy":"default","requests":60,"window_seconds":60,"headers":["RateLimit-Policy","RateLimit"]},"tools":[{"name":"relay_get_info","description":"Describe this relay deployment: name, version, data mode, projects and links. Public.","scope":null},{"name":"relay_get_methodology","description":"The five rules and a task's life, as plain text, for briefing another agent. Public.","scope":null},{"name":"relay_get_feed","description":"Events newest first with optional project, kind, actor, lane, limit, before, after. Payload and dedupe keys omitted.","scope":"feed:read"},{"name":"relay_get_project","description":"One project by slug with current decisions, models and recent events.","scope":"feed:read"},{"name":"relay_recall","description":"Current decisions and preferences relevant to a query. Call before choosing an approach.","scope":"memory:read"},{"name":"relay_brief","description":"The compiled brief for a project and intent: summary, preferences, decisions, guidance.","scope":"memory:read"},{"name":"relay_guidance","description":"Official vendor guidance chunks for a model, matched to a query.","scope":"memory:read"},{"name":"relay_feed","description":"Recent feed events as compact lines, newest first.","scope":"memory:read"},{"name":"relay_project","description":"A project's record: repo, path, stack, check command, summary and memory counts.","scope":"memory:read"},{"name":"relay_decide","description":"Record a durable decision for a project; supersede an old one by id.","scope":"memory:write"},{"name":"relay_prefer","description":"Set a preference (key = value) at a scope: global, project, lane or model.","scope":"memory:write"},{"name":"relay_asset_list","description":"Assets in the library, pending first; filter by project, status, kind, issue or pr.","scope":"assets:read"},{"name":"relay_asset_get","description":"One asset with its version chain and short-lived signed view URLs.","scope":"assets:read"},{"name":"relay_asset_request_upload","description":"Reserve an asset id and get a one-time upload URL; PUT the bytes there, then call relay_asset_finalize.","scope":"assets:write"},{"name":"relay_asset_finalize","description":"Turn an uploaded object into an asset row (probe, thumbnail, record) after relay_asset_request_upload.","scope":"assets:write"},{"name":"relay_task_create","description":"Open a task: a GitHub issue in the project's repo with the agent:<lane> label (and priority:<p>); returns task_id and issue_url. Idempotent on idempotency_key.","scope":"tasks:write"},{"name":"relay_task_get","description":"One task by id (owner/repo#n) with its derived state: queued, claimed, running, review, done or failed, plus the worker, PR and last summary.","scope":"tasks:read"},{"name":"relay_task_list","description":"Tasks with derived state, newest first; filter by project and state.","scope":"tasks:read"},{"name":"relay_event_log","description":"Log an external.* event in the feed (a bot's own note). The actor is always bot:<token name>; the client cannot choose it.","scope":"events:write"},{"name":"relay_whoami","description":"Who this connection is: token name, granted scopes, expiry and how it authenticated. Public; anonymous callers learn how to get access.","scope":null},{"name":"relay_webhook_subscribe","description":"Register an outbound webhook for event kinds (exact, a prefix ending in '.', or '*'), optionally one project and a bearer for deliveries. The signing secret is returned once.","scope":"webhooks:write"},{"name":"relay_webhook_unsubscribe","description":"Remove an outbound webhook by id.","scope":"webhooks:write"},{"name":"relay_access_list","description":"Device requests waiting for a decision (user_code, client_name, scopes, requested and expiry times) and approvals the device has not polled yet. For the bot that approves other agents.","scope":"tokens:write"},{"name":"relay_access_approve","description":"Approve (default) or deny a pending device request by its user code: the same decision the Access page makes. The device receives its token on its next poll; the decision is attributed to this token. A bot can approve only scopes it holds itself, and never tokens:write; wider requests are for a person at /activate.","scope":"tokens:write"},{"name":"relay_invite_create","description":"Mint an invite code for an agent or machine trusted in advance: a name, scopes, optional expiry (24h default) and uses (1 default). The code is returned once; redeeming it needs no approval. A bot can invite only to scopes it holds itself, and never tokens:write.","scope":"tokens:write"},{"name":"relay_invite_revoke","description":"Revoke a live invite by id or name; an unredeemed code stops working at once.","scope":"tokens:write"}],"documentation":"https://relay.kyro.house/docs/api#mcp-server","registry":"https://relay.kyro.house/server.json","openapi":"https://relay.kyro.house/openapi.json","contact":"https://relay.kyro.house/contact","license":"Apache-2.0"}