{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Sauna Guide Quotes MCP API","version":"1.1.0","description":"Machine-readable contract for the Sauna Guide Quotes MCP Streamable HTTP endpoint. The prepare tool is read-only. The submit tool stores and sends a request only after the user explicitly approves the complete, unchanged brief.","contact":{"name":"Sauna Guide","email":"david@sauna.guide","url":"https://sauna.guide/contact"},"license":{"name":"All rights reserved","url":"https://sauna.guide/terms"}},"servers":[{"url":"https://sauna.guide"}],"security":[],"externalDocs":{"description":"Sauna Guide Quotes integration guide","url":"https://sauna.guide/integrations/sauna-guide-quotes"},"tags":[{"name":"MCP","description":"Model Context Protocol over Streamable HTTP."}],"paths":{"/mcp":{"post":{"tags":["MCP"],"summary":"Send an MCP JSON-RPC request","operationId":"handleMcpRequest","description":"Supports MCP initialization, tool discovery, and tool calls. Clients must send application/json and accept both application/json and text/event-stream.","parameters":[{"name":"Accept","in":"header","required":true,"description":"MCP Streamable HTTP response media types.","schema":{"type":"string","example":"application/json, text/event-stream"}},{"name":"MCP-Protocol-Version","in":"header","required":false,"description":"Protocol version negotiated during initialization.","schema":{"type":"string"}},{"name":"Mcp-Session-Id","in":"header","required":false,"description":"Session identifier when returned by the MCP transport.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/McpRequest"},{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/McpRequest"}}]}}}},"responses":{"200":{"description":"MCP JSON-RPC response or event stream.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpResponse"}},"text/event-stream":{"schema":{"type":"string"},"example":"event: message\ndata: {\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{}}\n\n"}}},"202":{"description":"MCP notification accepted without a response body."},"400":{"description":"Malformed JSON-RPC or MCP request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpErrorResponse"}}}},"415":{"description":"The request did not use application/json.","content":{"text/plain":{"schema":{"type":"string"}}}},"429":{"description":"The quote tool rate limit was exceeded.","headers":{"Retry-After":{"description":"Seconds before another request should be attempted.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpErrorResponse"}}}},"503":{"description":"Quote request protection or a downstream service is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpErrorResponse"}}}}}}}},"components":{"schemas":{"JsonRpcId":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}]},"PrepareSaunaQuoteArguments":{"type":"object","properties":{"postalCode":{"type":"string","pattern":"^\\d{5}(?:-\\d{4})?$","description":"US ZIP code where the sauna will be installed."},"state":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"Two-letter US state code for the project."},"city":{"type":"string","minLength":2,"maxLength":100,"description":"City where the sauna will be installed."},"contactName":{"type":"string","minLength":2,"maxLength":100,"description":"Name of the person requesting the quote."},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"Email address for personal provider-search updates."},"phone":{"type":"string","maxLength":30,"description":"US phone number for questions about the project."},"projectType":{"type":"string","enum":["prebuilt","custom_indoor","custom_outdoor","not_sure"],"description":"Prebuilt, custom indoor, custom outdoor, or not yet decided."},"heatType":{"type":"string","enum":["traditional_electric","wood_fired","infrared","hybrid_or_unsure"],"description":"Preferred sauna heat type, or hybrid_or_unsure when not decided."},"electricalReadiness":{"type":"string","enum":["240v_ready","120v_only","no_site_power","not_sure"],"description":"Optional description of the electrical power currently available at the site."},"budget":{"type":"string","enum":["under_5k","5k_10k","10k_20k","20k_plus","not_sure"],"description":"Expected project budget range in US dollars."},"timeline":{"type":"string","enum":["within_30_days","1_3_months","3_6_months","researching"],"description":"Expected purchase or installation timeline."},"brandOrModel":{"type":"string","maxLength":160,"description":"Optional sauna brand or model already under consideration."},"notes":{"type":"string","maxLength":2000,"description":"Optional project details such as space, access, foundation, or electrical work."}},"required":["postalCode"],"additionalProperties":false},"SubmitSaunaQuoteArguments":{"type":"object","properties":{"requestId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The requestId returned by prepare_sauna_quote_request for this project."},"postalCode":{"type":"string","pattern":"^\\d{5}(?:-\\d{4})?$","description":"US ZIP code where the sauna will be installed."},"state":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"Two-letter US state code for the project."},"city":{"type":"string","minLength":2,"maxLength":100,"description":"City where the sauna will be installed."},"contactName":{"type":"string","minLength":2,"maxLength":100,"description":"Name of the person requesting the quote."},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"Email address for personal provider-search updates."},"phone":{"type":"string","maxLength":30,"description":"US phone number for questions about the project."},"projectType":{"type":"string","enum":["prebuilt","custom_indoor","custom_outdoor","not_sure"],"description":"Prebuilt, custom indoor, custom outdoor, or not yet decided."},"heatType":{"type":"string","enum":["traditional_electric","wood_fired","infrared","hybrid_or_unsure"],"description":"Preferred sauna heat type, or hybrid_or_unsure when not decided."},"electricalReadiness":{"type":"string","enum":["240v_ready","120v_only","no_site_power","not_sure"],"description":"Optional description of the electrical power currently available at the site."},"budget":{"type":"string","enum":["under_5k","5k_10k","10k_20k","20k_plus","not_sure"],"description":"Expected project budget range in US dollars."},"timeline":{"type":"string","enum":["within_30_days","1_3_months","3_6_months","researching"],"description":"Expected purchase or installation timeline."},"brandOrModel":{"type":"string","maxLength":160,"description":"Optional sauna brand or model already under consideration."},"notes":{"type":"string","maxLength":2000,"description":"Optional project details such as space, access, foundation, or electrical work."},"confirmRequest":{"type":"boolean","const":true,"description":"Set to true only after the user explicitly approves storing the request and sending confirmation and internal notification emails."}},"required":["requestId","postalCode","state","city","contactName","email","phone","projectType","heatType","budget","timeline","confirmRequest"],"additionalProperties":false},"PrepareSaunaQuoteOutput":{"type":"object","properties":{"status":{"type":"string","const":"draft_ready"},"requestId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"readyToSubmit":{"type":"boolean"},"missingFields":{"type":"array","items":{"type":"string"}},"reviewUrl":{"type":"string","format":"uri"},"contactDetailsSharedWithProvider":{"type":"boolean","const":false},"newsletterOptIn":{"type":"boolean","const":false},"nextStep":{"type":"string"}},"required":["status","requestId","readyToSubmit","missingFields","reviewUrl","contactDetailsSharedWithProvider","newsletterOptIn","nextStep"],"additionalProperties":false},"SubmitSaunaQuoteOutput":{"type":"object","properties":{"status":{"type":"string","enum":["provider_search_started","review_fixture_validated"]},"requestId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"duplicate":{"type":"boolean"},"testMode":{"type":"boolean"},"contactDetailsSharedWithProvider":{"type":"boolean","const":false},"newsletterOptIn":{"type":"boolean","const":false},"updateTiming":{"type":"string","enum":["within_one_business_day","not_applicable"]}},"required":["status","requestId","duplicate","testMode","contactDetailsSharedWithProvider","newsletterOptIn","updateTiming"],"additionalProperties":false},"McpInitializeRequest":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"method":{"type":"string","const":"initialize"},"params":{"type":"object","additionalProperties":true}},"required":["jsonrpc","id","method","params"],"additionalProperties":false},"McpToolsListRequest":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"method":{"type":"string","const":"tools/list"},"params":{"type":"object","additionalProperties":true}},"required":["jsonrpc","id","method"],"additionalProperties":false},"McpPrepareToolCallRequest":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","properties":{"name":{"type":"string","const":"prepare_sauna_quote_request"},"arguments":{"$ref":"#/components/schemas/PrepareSaunaQuoteArguments"}},"required":["name","arguments"],"additionalProperties":false}},"required":["jsonrpc","id","method","params"],"additionalProperties":false},"McpSubmitToolCallRequest":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"method":{"type":"string","const":"tools/call"},"params":{"type":"object","properties":{"name":{"type":"string","const":"submit_sauna_quote_request"},"arguments":{"$ref":"#/components/schemas/SubmitSaunaQuoteArguments"}},"required":["name","arguments"],"additionalProperties":false}},"required":["jsonrpc","id","method","params"],"additionalProperties":false},"McpRequest":{"anyOf":[{"$ref":"#/components/schemas/McpInitializeRequest"},{"$ref":"#/components/schemas/McpToolsListRequest"},{"$ref":"#/components/schemas/McpPrepareToolCallRequest"},{"$ref":"#/components/schemas/McpSubmitToolCallRequest"}]},"McpSuccessResponse":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"result":{"type":"object","additionalProperties":true}},"required":["jsonrpc","id","result"],"additionalProperties":false},"McpErrorResponse":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"$ref":"#/components/schemas/JsonRpcId"},"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"},"data":{}},"required":["code","message"],"additionalProperties":true}},"required":["jsonrpc","id","error"],"additionalProperties":false},"McpResponse":{"oneOf":[{"$ref":"#/components/schemas/McpSuccessResponse"},{"$ref":"#/components/schemas/McpErrorResponse"}]}}},"x-mcp":{"transport":"streamable-http","endpoint":"/mcp","authentication":"none","tools":["prepare_sauna_quote_request","submit_sauna_quote_request"],"toolSchemas":{"prepare_sauna_quote_request":{"input":{"$ref":"#/components/schemas/PrepareSaunaQuoteArguments"},"output":{"$ref":"#/components/schemas/PrepareSaunaQuoteOutput"}},"submit_sauna_quote_request":{"input":{"$ref":"#/components/schemas/SubmitSaunaQuoteArguments"},"output":{"$ref":"#/components/schemas/SubmitSaunaQuoteOutput"}}}}}