{"server":{"name":"STRALO","version":"1.0.0","description":"STRALO REST surface exposed as an MCP-compatible server. Every tool maps 1:1 to a route handler under /api/*; protected tools accept Authorization: Bearer or X-API-Key, and auth requirements mirror the live API.","protocolVersion":"2025-03-26","transport":{"type":"streamable-http","url":"https://stralo.polsia.app/api/mcp"},"baseUrl":"https://stralo.polsia.app","authentication":{"type":"bearer-or-api-key","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential header; protected calls forward it to the inner route."}},"tools":[{"name":"post_agents","description":"First-agent bootstrap: omit credentials and send bootstrap:true exactly once while no Agent exists, or use a valid credential to create a child agent. The public_token is returned once and must be saved for all follow-up calls.","method":"POST","path":"/api/agents","endpoint":"https://stralo.polsia.app/api/agents","auth":{"type":"conditional-bootstrap-or-bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"For the first request only, omit credentials and send bootstrap:true. After the first agent exists, send Authorization: Bearer <public_token> or X-API-Key: <public_token> for child-agent creation."},"inputSchema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"metadata":{"type":"object","additionalProperties":{}},"config":{"type":"object","additionalProperties":{}},"idempotency_key":{"type":"string","minLength":1,"maxLength":255},"bootstrap":{"type":"boolean","const":true}},"required":["name"],"additionalProperties":false},"responses":{"201":{"description":"Agent created. Body includes id, one-time public_token, created_at, and next_step guidance. Save public_token, then send Authorization: Bearer <public_token> or X-API-Key: <public_token> on subsequent calls.","schema":{"type":"object","properties":{"id":{"type":"string","minLength":1},"public_token":{"type":"string","minLength":1},"created_at":{"type":"string","format":"date-time"},"next_step":{"type":"object","properties":{"save_public_token":{"type":"boolean","const":true},"authorization":{"type":"string","const":"Authorization: Bearer <public_token>"},"x_api_key":{"type":"string","const":"X-API-Key: <public_token>"},"message":{"type":"string","minLength":1}},"required":["save_public_token","authorization","x_api_key","message"],"additionalProperties":false}},"required":["id","public_token","created_at","next_step"],"additionalProperties":false}},"400":{"description":"Request body failed Zod validation.","schema":{"type":"object","properties":{"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of field name to first validation message."}},"required":["errors"]}},"401":{"description":"Missing credential on ordinary creation, or a supplied invalid credential. Explicit bootstrap:true is the only credential-free alternative.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"409":{"description":"The idempotency_key has already been used, or bootstrap_claimed means another first agent already exists. No token is returned for the bootstrap conflict.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"post_bookings","description":"Confirm a booking on the authenticated agent calendar. The resolved agentId MUST match the body agentId. Overlap rejections return 409 slot_taken (the database EXCLUDE constraint raises 23P01 at commit time).","method":"POST","path":"/api/bookings","endpoint":"https://stralo.polsia.app/api/bookings","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"maxLength":128},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"}},"required":["agentId","startsAt","endsAt"],"additionalProperties":false},"responses":{"201":{"description":"Booking persisted.","schema":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"maxLength":128},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"status":{"type":"string"},"rrule":{"type":["string","null"]},"warningSentAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"}},"required":["agentId","startsAt","endsAt","id","status","warningSentAt","createdAt"],"additionalProperties":false}},"400":{"description":"Validation error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"403":{"description":"Bearer mismatched the body agentId.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"409":{"description":"Slot overlap (slot_taken) or another conflict.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"get_bookings","description":"List bookings owned by the authenticated agent (confirmed AND cancelled), ordered by startsAt ascending. Optional ?from / ?to narrow to bookings whose [startsAt, endsAt) window intersects [from, to); half-open [) so back-to-back bookings do not collide.","method":"GET","path":"/api/bookings","endpoint":"https://stralo.polsia.app/api/bookings","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":200,"description":"Cap on returned rows. Default 50."},"from":{"type":"string","format":"date-time","description":"Inclusive lower bound (RFC 3339 with offset) for the overlap window."},"to":{"type":"string","format":"date-time","description":"Exclusive upper bound (RFC 3339 with offset). Cross-field check enforces to >= from."}}},"responses":{"200":{"description":"List of bookings.","schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"agentId":{"type":"string","minLength":1,"maxLength":128},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"id":{"type":"string"},"status":{"type":"string"},"rrule":{"type":["string","null"]},"warningSentAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"}},"required":["agentId","startsAt","endsAt","id","status","warningSentAt","createdAt"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}},"400":{"description":"Validation error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"delete_bookings_id","description":"Soft-cancel a booking (status=\"cancelled\"); the audit row is preserved. Idempotent — cancelling an already-cancelled id returns 204. The bearer must own the row.","method":"DELETE","path":"/api/bookings/{id}","endpoint":"https://stralo.polsia.app/api/bookings/{id}","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Path parameter — booking id owned by the authenticated agent."}},"required":["id"]},"responses":{"204":{"description":"Soft-cancel succeeded, or row was already cancelled.","schema":{"type":"null"}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"403":{"description":"Bearer does not own this booking.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"404":{"description":"No row matches {id}.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"post_proposals","description":"Open a slot-transfer proposal. proposerAgentId is set server-side from the authenticated credential — never trusted from the body. The proposal starts in status=\"pending\"; the target agent must accept or reject before any Booking row exists.","method":"POST","path":"/api/proposals","endpoint":"https://stralo.polsia.app/api/proposals","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"targetAgentId":{"type":"string","minLength":1,"maxLength":128},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"}},"required":["targetAgentId","startsAt","endsAt"],"additionalProperties":false},"responses":{"201":{"description":"Proposal persisted in status=\"pending\".","schema":{"type":"object","properties":{"id":{"type":"string"},"proposerAgentId":{"type":"string"},"targetAgentId":{"type":"string"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","proposerAgentId","targetAgentId","startsAt","endsAt","status","createdAt"],"additionalProperties":false}},"400":{"description":"Validation error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"patch_proposals_id_accept","description":"Target agent accepts the proposal — transfers ownership of the resulting Booking to the proposer (Booking.agentId = proposal.proposerAgentId), so the slot flips to the proposer's calendar; a booking.created webhook fires for the new owner.","method":"PATCH","path":"/api/proposals/{id}/accept","endpoint":"https://stralo.polsia.app/api/proposals/{id}/accept","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Path parameter — proposal id."}},"required":["id"]},"responses":{"200":{"description":"Proposal accepted; booking.created fires for the new owner.","schema":{"type":"object","properties":{"id":{"type":"string"},"proposerAgentId":{"type":"string"},"targetAgentId":{"type":"string"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","proposerAgentId","targetAgentId","startsAt","endsAt","status","createdAt"],"additionalProperties":false}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"403":{"description":"Bearer is not the target agent.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"404":{"description":"No row matches {id}.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"409":{"description":"Proposal already terminal.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"patch_proposals_id_reject","description":"Target agent rejects the proposal — resets status to \"pending\" (not terminal) so a future transfer attempt remains possible. The conditional UPDATE keeps concurrent accepts from double-flipping.","method":"PATCH","path":"/api/proposals/{id}/reject","endpoint":"https://stralo.polsia.app/api/proposals/{id}/reject","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Path parameter — proposal id."}},"required":["id"]},"responses":{"200":{"description":"Proposal reset to pending.","schema":{"type":"object","properties":{"id":{"type":"string"},"proposerAgentId":{"type":"string"},"targetAgentId":{"type":"string"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","proposerAgentId","targetAgentId","startsAt","endsAt","status","createdAt"],"additionalProperties":false}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"403":{"description":"Bearer is not the target agent.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"404":{"description":"No row matches {id}.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"409":{"description":"Proposal already terminal.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}},{"name":"get_bookings_id_occurrences","description":"Expand a booking's RRULE into the next N concrete tstzrange slots starting from now (default 50, max 200). Returned in chronological order. The id must belong to the authenticated agent.","method":"GET","path":"/api/bookings/{id}/occurrences","endpoint":"https://stralo.polsia.app/api/bookings/{id}/occurrences","auth":{"type":"bearer","header":"Authorization","scheme":"Bearer","acceptedHeaders":["Authorization","X-API-Key"],"description":"Send exactly one credential: Authorization: Bearer <sk_…> or X-API-Key: <sk_…> from POST /agents."},"inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Path parameter — booking id owned by the authenticated agent."},"limit":{"type":"integer","minimum":1,"maximum":200,"description":"Cap on the number of expanded slot rows. Default 50."}},"required":["id"]},"responses":{"200":{"description":"Concrete slot items.","schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"}},"required":["startsAt","endsAt"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}},"400":{"description":"The stored RRULE did not parse — body { error: \"bad_rrule\", message }.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"401":{"description":"Missing or unparseable Authorization or X-API-Key header.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"403":{"description":"Bearer does not own this booking.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"404":{"description":"No row matches {id}.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}},"500":{"description":"Unexpected server error.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."}},"required":["error"]}}}}]}