{"openapi":"3.1.0","info":{"title":"Starlight API","version":"1.0.0","x-versioning":"The MCP surface is versioned by the serverInfo.version reported at initialize; breaking changes ship under a new version with the old one kept for 90 days and a Deprecation header on responses.","summary":"AI sales prospecting and outreach, operable by agents over MCP.","description":"Starlight is an AI-powered sales prospecting platform. Find leads from across the web in natural language, draft personalized outreach in your voice, run multi-step email and LinkedIn sequences, track replies, and sync with your CRM and calendar.\n\nThe programmable surface is a remote MCP server (Streamable HTTP) at /api/mcp, authenticated with OAuth 2.1 (PKCE, dynamic client registration). Each MCP tool is listed below as an operation with its exact input schema. Connect an MCP client with: claude mcp add --transport http starlight https://joinstarlight.com/api/mcp","contact":{"name":"Starlight support","email":"support@joinstarlight.com","url":"https://joinstarlight.com/contact"},"termsOfService":"https://joinstarlight.com/terms","x-logo":{"url":"https://joinstarlight.com/logo-wordmark.png"}},"externalDocs":{"description":"Agents and MCP documentation","url":"https://joinstarlight.com/docs/features/agents"},"servers":[{"url":"https://joinstarlight.com"}],"tags":[{"name":"OAuth","description":"OAuth 2.1 authorization server over Supabase identity."},{"name":"MCP","description":"Model Context Protocol endpoint (JSON-RPC 2.0 over Streamable HTTP)."},{"name":"MCP tools","description":"Tools exposed by the MCP server, one operation per tool."},{"name":"Discovery","description":"Machine-readable site metadata."}],"x-rate-limits":{"description":"Tool calls are metered in blocks deducted from the workspace balance; insufficient_blocks errors carry the amount needed. No fixed request-rate limit beyond that."},"paths":{"/api/oauth/register":{"post":{"operationId":"registerOAuthClient","tags":["OAuth"],"summary":"Dynamic client registration (RFC 7591)","description":"Register a public OAuth client. No authentication; PKCE is mandatory, client secrets are not issued.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["redirect_uris"],"properties":{"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"}},"scope":{"type":"string","description":"Space-separated scopes; defaults to starlight:agent."}}}}}},"responses":{"201":{"description":"Registered client (client_id, redirect_uris, scope)."},"400":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/oauth/authorize":{"get":{"operationId":"authorize","tags":["OAuth"],"summary":"Authorization endpoint (consent page)","description":"Browser consent page. Requires response_type=code, client_id, redirect_uri, code_challenge (S256), state, optional scope and resource.","parameters":[{"name":"client_id","in":"query","schema":{"type":"string"},"required":true},{"name":"redirect_uri","in":"query","schema":{"type":"string"},"required":true},{"name":"state","in":"query","schema":{"type":"string"},"required":false},{"name":"code_challenge","in":"query","schema":{"type":"string"},"required":true},{"name":"code_challenge_method","in":"query","schema":{"type":"string"},"required":false},{"name":"scope","in":"query","schema":{"type":"string"},"required":false},{"name":"resource","in":"query","schema":{"type":"string"},"required":false}],"responses":{"200":{"description":"Consent page (HTML)."},"302":{"description":"Redirect to redirect_uri with code + state."},"400":{"$ref":"#/components/responses/Error"}}}},"/api/oauth/token":{"post":{"operationId":"token","tags":["OAuth"],"summary":"Token endpoint","description":"Form-encoded. grant_type=authorization_code (code, code_verifier, redirect_uri, client_id) or refresh_token (refresh_token, client_id). Access tokens last 30 days; refresh tokens rotate.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type","client_id"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"client_id":{"type":"string"},"code":{"type":"string"},"code_verifier":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"refresh_token":{"type":"string"}}}}}},"responses":{"200":{"description":"Tokens.","content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer"},"scope":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"}}}},"/api/mcp":{"post":{"operationId":"mcp","tags":["MCP"],"summary":"MCP Streamable HTTP endpoint","description":"JSON-RPC 2.0. Methods: initialize, tools/list, tools/call. Bearer OAuth token required; 401 responses carry WWW-Authenticate pointing at /.well-known/oauth-protected-resource/api/mcp.","security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"method":{"type":"string","enum":["initialize","tools/list","tools/call","ping"]},"params":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"JSON-RPC response."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/.well-known/mcp.json":{"get":{"operationId":"mcpManifest","tags":["Discovery"],"summary":"MCP server manifest","responses":{"200":{"description":"Manifest."}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"oauthMetadata","tags":["Discovery"],"summary":"RFC 8414 authorization-server metadata","responses":{"200":{"description":"Metadata."}}}},"/llms.txt":{"get":{"operationId":"llmsTxt","tags":["Discovery"],"summary":"Site index for LLMs (markdown)","responses":{"200":{"description":"text/markdown"}}}},"/api/mcp#get_company_profile":{"post":{"operationId":"get_company_profile","summary":"get company profile","description":"Get the seller's company profile: product description, ideal customer profile (ICP), remaining blocks, and the product and ICP fact sheets (markdown) that ground everything — capabilities, integrations, objections, buyer personas, trigger events, disqualifiers, and the proof points that are the ONLY statistics you may put in a brief. Call this FIRST in any session — search queries and drafting briefs should be grounded in this profile. Free.\n\nCalled over MCP as tools/call with name \"get_company_profile\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_company_profile","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_company_profileInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_searches":{"post":{"operationId":"list_searches","summary":"list searches","description":"List the company's previously-run searches (name, original query, result count, date, searchId), newest first. Read-only. ALWAYS call this before search_leads — if an existing search already covers the request, reuse its leads via get_search_results (a cheap read) instead of paying 12 blocks for a new search.\n\nCalled over MCP as tools/call with name \"list_searches\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_searches","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_searchesInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#search_leads":{"post":{"operationId":"search_leads","summary":"search leads","description":"Search 250M+ B2B contacts with a natural-language query, e.g. 'VP of Engineering at 50-200 person fintech companies in the US'. Persists a Search with scored leads and returns the top results ranked by ICP match. Call this when you need NEW prospects; use list_contacts for people already saved. Costs 12 blocks per search — first check list_searches for an existing search that covers the request, and make queries specific rather than running many broad searches.\n\nCalled over MCP as tools/call with name \"search_leads\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"search_leads","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/search_leadsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_search_results":{"post":{"operationId":"get_search_results","summary":"get search results","description":"Fetch leads from a previous search by searchId, ranked by match score. Use this to page through results of an earlier search_leads call without paying for a new search. Free.\n\nCalled over MCP as tools/call with name \"get_search_results\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_search_results","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_search_resultsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_contacts":{"post":{"operationId":"list_contacts","summary":"list contacts","description":"List the user's saved contacts (leads already added to the contact list), optionally filtered by a name/title/company text query. Free.\n\nCalled over MCP as tools/call with name \"list_contacts\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_contacts","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_contactsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#add_to_contacts":{"post":{"operationId":"add_to_contacts","summary":"add to contacts","description":"Save leads to the user's contact list by leadId. Do this AFTER evaluating fit (evaluate_lead_fit) — only add leads worth pursuing. Blacklisted leads (a previously-suppressed email) are silently skipped — they were blocked because the person doesn't want to be contacted, so don't try to re-add or re-message them. Free.\n\nCalled over MCP as tools/call with name \"add_to_contacts\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"add_to_contacts","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/add_to_contactsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#evaluate_lead_fit":{"post":{"operationId":"evaluate_lead_fit","summary":"evaluate lead fit","description":"Score leads 0–100 against the ICP with an independent LLM judge (with reasons and disqualifiers). ALWAYS run this between search_leads and add_to_contacts/draft_outreach — only pursue leads scoring 50+. Pass a custom `icp` to override the company profile's ICP. Free.\n\nCalled over MCP as tools/call with name \"evaluate_lead_fit\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"evaluate_lead_fit","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/evaluate_lead_fitInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#draft_outreach":{"post":{"operationId":"draft_outreach","summary":"draft outreach","description":"Generate personalized outreach drafts for leads (by leadId). Writes a multi-step sequence per lead using the seller's product context and each lead's data. Drafts are created as PENDING_REVIEW — NOTHING IS SENT by this tool. Leads are auto-added to contacts. `instructions` is the drafting brief (min 120 characters): what to pitch, the angle, the call to action — ground it in get_company_profile. Use only proof points that came from the company profile; never invent statistics, percentages, or named benchmarks to fill the brief (fabricated metrics get rejected at evaluate_draft_quality). Costs 4 blocks per lead, plus 2 blocks (research_scan) per lead that needs fresh web research — research is ON by default because it's what grounds personalization (pass researchEnabled: false only if the user explicitly declines it; cached leads are free). Leads that already have active drafts are rejected UNLESS you pass reengage=true — that unblocks leads whose drafts were all already SENT with no reply (stale opportunities; find them with list_stale_leads) and writes them a fresh follow-up sequence, aware of what was previously sent. Recipients failing email verification are skipped and refunded.\n\nCalled over MCP as tools/call with name \"draft_outreach\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"draft_outreach","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/draft_outreachInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_pending_drafts":{"post":{"operationId":"list_pending_drafts","summary":"list pending drafts","description":"List drafts awaiting review (PENDING_REVIEW), newest first. Set includeBody=true to read the full message text — do this before evaluating or approving. Each written draft may already carry a `qualityScore` and a `verdict` (SEND / REVISE / REJECT) from when it was drafted — that is an existing judge result you can TRUST. Do NOT re-run evaluate_draft_quality on a draft that already has a score; approve the SEND ones and edit the REVISE/REJECT ones. Only judge drafts whose score is null or that you just edited. Re-judging an already-scored batch is redundant and on large batches can exhaust the turn's time budget. LINKEDIN_LIKE rows are actions (like a post), not written messages: `action` is true, body is empty, and they have no score. Do not judge them. Approve them together with the written drafts for that lead when the user authorizes sending. Free.\n\nCalled over MCP as tools/call with name \"list_pending_drafts\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_pending_drafts","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_pending_draftsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#edit_draft":{"post":{"operationId":"edit_draft","summary":"edit draft","description":"Rewrite the subject and/or body of a SINGLE draft — for one targeted change or a rewrite the user dictated. When MULTIPLE drafts are flagged REVISE/REJECT, use repair_drafts instead (one server-side call that regenerates, re-judges, and persists all of them). Pass the full replacement text for whatever you change; partial patches are not supported. Read the draft first (list_pending_drafts with includeBody). When the rewrite deliberately changes the message's strategy from the original brief (e.g. the user asks for a warm, no-pitch close, a softer tone, or a break-up touch), pass `intent` describing what the new message is going for. The quality judge then grades against that intent instead of the now-superseded original brief — without it the judge penalizes the very changes you were asked to make. Works on PENDING_REVIEW drafts AND already-APPROVED (scheduled) drafts: editing an approved draft pulls it back to PENDING_REVIEW so it can't send unreviewed — if it was the next message due to send, its sequence is paused until you re-approve. Editing always clears the draft's prior quality score, so you must re-run evaluate_draft_quality and then approve_drafts to (re-)schedule it. This does NOT send anything. Free. Already-SENT, skipped, or canceled drafts cannot be edited.\n\nCalled over MCP as tools/call with name \"edit_draft\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"edit_draft","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/edit_draftInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#repair_drafts":{"post":{"operationId":"repair_drafts","summary":"repair drafts","description":"Server-side BULK repair of PENDING_REVIEW drafts the quality judge flagged REVISE or REJECT: in one call it regenerates only the failing messages (using the judge's issues as edit instructions and the original brief/voice/research context), re-judges them, and persists each improvement with its new score. A repair is kept only if its score held or improved. Use this INSTEAD of per-draft edit_draft + evaluate_draft_quality loops whenever more than one draft is flagged — it replaces that whole cycle. Reserve edit_draft for a single targeted change or a rewrite the user dictated. Scope with leadIds to specific leads, or omit to sweep the most recent flagged enrollments (up to 25 per call). Nothing is approved or sent; drafts whose repair doesn't clear the bar stay flagged. Drafts you deliberately rewrote via edit_draft with an intent are left alone. Free.\n\nCalled over MCP as tools/call with name \"repair_drafts\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"repair_drafts","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/repair_draftsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#append_sequence_step":{"post":{"operationId":"append_sequence_step","summary":"append sequence step","description":"Add ONE more email to the EXISTING outreach sequence for specific leads (by leadId) — e.g. a final closing note asking if they're still interested, or one extra follow-up. Use this when the leads ALREADY have drafts/an enrollment and draft_outreach would refuse (it only creates NEW sequences and rejects leads with active drafts). The new message is threaded as 'Re: <original subject>' onto each lead's most recent email sequence and created as PENDING_REVIEW — NOTHING IS SENT; call approve_drafts afterward to schedule it. `instructions` is the brief for this one message (what to say, the ask); ground any proof points in get_company_profile and never invent metrics. Costs 4 blocks per lead. A lead is skipped if it has no existing email sequence, has already replied/bounced/unsubscribed, or the sequence has other active enrollments mid-cadence that aren't in this call.\n\nCalled over MCP as tools/call with name \"append_sequence_step\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"append_sequence_step","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/append_sequence_stepInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#evaluate_draft_quality":{"post":{"operationId":"evaluate_draft_quality","summary":"evaluate draft quality","description":"Review drafted messages with an independent LLM judge: 0–100 score, issues, and a send/revise/reject verdict (checks personalization grounding, tone, spam signals). Persists the score onto each draft. ALWAYS run this before approve_drafts; only approve drafts with verdict 'send'. Free.\n\nCalled over MCP as tools/call with name \"evaluate_draft_quality\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"evaluate_draft_quality","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/evaluate_draft_qualityInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#approve_drafts":{"post":{"operationId":"approve_drafts","summary":"approve drafts","description":"Approve PENDING_REVIEW drafts for sending — THIS SCHEDULES REAL OUTREACH TO REAL PEOPLE. Emails go out on the next business-hours send cycle via the user's connected mailbox; LinkedIn drafts are sent automatically by the user's Chrome extension once its Autopilot toggle is on (otherwise they wait under Messages). Before calling: read the drafts (list_pending_drafts with includeBody); trust any existing verdicts rather than re-judging. Approving a draft with a REJECT verdict is allowed but you MUST first tell the user the judge's reason and get their go-ahead for those specific drafts (use repair_drafts to fix them instead when possible). If the user's instruction already authorizes sending (they asked you to approve, send, 'get them out', or 'work through and send' the drafts), treat that as authorization and proceed — then report exactly what you approved, by channel, and how each goes out. Only pause to confirm first when the instruction is ambiguous about whether to actually send. Autonomous agent runs are always authorized by autopilot. Recipients failing email verification are skipped automatically.\n\nCalled over MCP as tools/call with name \"approve_drafts\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"approve_drafts","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/approve_draftsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_outreach_status":{"post":{"operationId":"get_outreach_status","summary":"get outreach status","description":"Status of outreach in motion: per-sequence enrollment counts, drafts by status, sends, and replies. Pass sequenceId to drill into one sequence. Free.\n\nCalled over MCP as tools/call with name \"get_outreach_status\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_outreach_status","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_outreach_statusInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#check_inbox":{"post":{"operationId":"check_inbox","summary":"check inbox","description":"Read recent inbox messages (email + LinkedIn replies from prospects). Use to report on responses or find threads needing attention. Free.\n\nCalled over MCP as tools/call with name \"check_inbox\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"check_inbox","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/check_inboxInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_metrics":{"post":{"operationId":"get_metrics","summary":"get metrics","description":"Outreach KPIs for a period (today / week / month): searches run, contacts added, emails sent, replies, meetings booked, drafts pending. Free.\n\nCalled over MCP as tools/call with name \"get_metrics\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_metrics","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_metricsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_billing_status":{"post":{"operationId":"get_billing_status","summary":"get billing status","description":"Get the company's current billing/subscription status: plan name, monthly block allowance, blocks remaining, billing cycle, any scheduled downgrade, and whether the subscription is set to cancel. Use before discussing plan changes. Read-only, free.\n\nCalled over MCP as tools/call with name \"get_billing_status\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_billing_status","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_billing_statusInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_contact_details":{"post":{"operationId":"get_contact_details","summary":"get contact details","description":"Get full detail for one contact/lead by leadId: name, title, company, location, pipeline status, email, LinkedIn URL, and recent notes. Use this to look up a person's details (e.g. to copy their email or LinkedIn). Return contact info as clean, copyable markdown. Read-only, free.\n\nCalled over MCP as tools/call with name \"get_contact_details\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_contact_details","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_contact_detailsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_stale_leads":{"post":{"operationId":"list_stale_leads","summary":"list stale leads","description":"List stale opportunities — the same list as the Tasks page's 'Stale opportunities' tab: contacts you messaged (email or LinkedIn) who never replied on any channel, with nothing queued to re-touch them (no pending/approved drafts, no active sequence with a future send). Sorted most-stale first. These are prime re-engagement targets: draft them a fresh follow-up sequence with draft_outreach (or start_background_drafting) and reengage=true. Read-only, free.\n\nCalled over MCP as tools/call with name \"list_stale_leads\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_stale_leads","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_stale_leadsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#remove_contact":{"post":{"operationId":"remove_contact","summary":"remove contact","description":"Remove one or more people from the saved contact list by leadId (sets them back to a lead — does NOT delete their record or any outreach already sent). Confirm with the user which contacts before calling. Free.\n\nCalled over MCP as tools/call with name \"remove_contact\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"remove_contact","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/remove_contactInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_scheduling_links":{"post":{"operationId":"list_scheduling_links","summary":"list scheduling links","description":"List the user's bookable meeting types with their public booking links (title, duration, location, full URL). Use this when the user wants to grab, copy, or share a scheduling link. Return the links as clean, copyable markdown. Read-only, free.\n\nCalled over MCP as tools/call with name \"list_scheduling_links\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_scheduling_links","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_scheduling_linksInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#update_contact":{"post":{"operationId":"update_contact","summary":"update contact","description":"Update one contact/lead: change its pipeline status (NEW → CONTACTED → ENGAGED → RESPONDED → MEETING_BOOKED → CONVERTED) and/or append a note. Use remove_contact to take someone off the contact list. Free.\n\nCalled over MCP as tools/call with name \"update_contact\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"update_contact","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/update_contactInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#manage_sequence":{"post":{"operationId":"manage_sequence","summary":"manage sequence","description":"Pause, resume, or delete an outreach sequence. Pausing stops further sends; resuming re-activates it; deleting is permanent. Pausing/deleting a live sequence affects outreach in motion — confirm with the user first, and use get_outreach_status to find the right sequenceId. Free.\n\nCalled over MCP as tools/call with name \"manage_sequence\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"manage_sequence","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/manage_sequenceInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_inbox_message":{"post":{"operationId":"get_inbox_message","summary":"get inbox message","description":"Read the full body of one inbox message by id (check_inbox lists them with previews; use this to read the whole thing). Returns sender, subject, channel, full text, and the current AI-drafted reply shown in the Inbox reply card. Read-only, free.\n\nCalled over MCP as tools/call with name \"get_inbox_message\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_inbox_message","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_inbox_messageInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#edit_inbox_reply":{"post":{"operationId":"edit_inbox_reply","summary":"edit inbox reply","description":"Revise the AI-drafted reply shown in the Inbox reply card for one inbox message (by messageId). Use this WHENEVER the user asks you to change the reply they're looking at in the Inbox — shorter, warmer, answer their question directly, remove an em-dash, etc. Pass the FULL replacement reply text (and a subject for email replies). This updates the editable draft in place on their screen so they can review and send it — it does NOT send anything. Free.\n\nCalled over MCP as tools/call with name \"edit_inbox_reply\". Mutates workspace state.","tags":["MCP tools"],"x-mcp-tool":"edit_inbox_reply","x-read-only":false,"x-side-effect":false,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/edit_inbox_replyInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#send_linkedin_reply":{"post":{"operationId":"send_linkedin_reply","summary":"send linkedin reply","description":"Send a reply to a LinkedIn inbox message (by messageId from check_inbox or the <current_inbox_reply> context). The reply is dispatched through the user's Chrome extension: in the app it opens LinkedIn and prefills the message (and auto-sends if their Autopilot is on) immediately — the same path as the Inbox 'Send via Extension' button; on other surfaces the extension's autopilot delivers it. Pass the exact wording to send (if the user just asked you to edit it, send the edited text). This goes to a real person — get the user's explicit confirmation of the wording first. Free.\n\nCalled over MCP as tools/call with name \"send_linkedin_reply\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"send_linkedin_reply","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/send_linkedin_replyInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#send_email":{"post":{"operationId":"send_email","summary":"send email","description":"Send ONE ad-hoc email to an existing contact, immediately, from the user's connected Gmail/Outlook account. Use this for relationship emails — customer onboarding check-ins, follow-ups after a call, thank-yous, intros, answering something one-on-one — and for CONVERTED customers or anyone the user already has a relationship with. This is NOT cold outreach: use draft_outreach only for net-new prospecting sequences; if draft_outreach rejects a lead because they already have drafts and the user just wants to email that person, use this instead. YOU write the subject and body (want a booking link? get the URL from list_scheduling_links and put it in the body). Show the user the exact subject and body and get their explicit confirmation BEFORE calling — this sends a real email the moment it runs. Threads onto an existing email conversation when one exists. Rejects (without sending) a subject or body containing a dash of any kind, a dead opener, or chatbot phrasing; rewrite and call again. Free (standard per-call charge only).\n\nCalled over MCP as tools/call with name \"send_email\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"send_email","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/send_emailInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#update_company_profile":{"post":{"operationId":"update_company_profile","summary":"update company profile","description":"Update the company profile that grounds all outreach: product description, ideal customer profile (ICP), the product and ICP fact sheets, competitors, website, and preferred message length. Changing the ICP or product affects future searches and drafts — confirm the new wording with the user before saving. Read the current values with get_company_profile first. Free.\n\nCalled over MCP as tools/call with name \"update_company_profile\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"update_company_profile","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/update_company_profileInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_connector_status":{"post":{"operationId":"get_connector_status","summary":"get connector status","description":"Report what's connected: email sending accounts (Gmail/Outlook), calendar, CRM (HubSpot, Salesforce, Attio), the Chrome extension (required for LinkedIn sending — 'linked' means it authenticated at some point; 'recentlyActive' means it talked to Starlight in the last 48h), and scheduling readiness (booking page + active meeting types). Connecting or disconnecting requires an OAuth flow the user does on the Connectors page — this tool only reports status, so if something is missing, point the user to Connectors (or list_scheduling_links to set up a booking page). Read-only, free.\n\nCalled over MCP as tools/call with name \"get_connector_status\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_connector_status","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_connector_statusInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#manage_scheduling_link":{"post":{"operationId":"manage_scheduling_link","summary":"manage scheduling link","description":"Create, update, or delete a bookable meeting type (scheduling link). create needs title, slug, and durationMinutes; update/delete need eventTypeId (from list_scheduling_links). Deleting is blocked if the link has upcoming bookings — toggle isActive:false instead. Confirm changes with the user first. Free.\n\nCalled over MCP as tools/call with name \"manage_scheduling_link\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"manage_scheduling_link","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/manage_scheduling_linkInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_bookings":{"post":{"operationId":"list_bookings","summary":"list bookings","description":"List the user's meetings: upcoming (default), past, or cancelled — with guest name, time, and the booking id (needed to cancel). Read-only, free.\n\nCalled over MCP as tools/call with name \"list_bookings\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_bookings","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_bookingsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#manage_booking":{"post":{"operationId":"manage_booking","summary":"manage booking","description":"Cancel or reschedule a confirmed meeting by bookingId (from list_bookings). The guest is emailed either way. For reschedule, get the exact new time from get_available_slots first and pass its startUtc. Cancelling a real meeting needs the user's confirmation first; an explicit reschedule instruction ('move it to 2PM') is authorization. Free.\n\nCalled over MCP as tools/call with name \"manage_booking\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"manage_booking","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/manage_bookingInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_available_slots":{"post":{"operationId":"get_available_slots","summary":"get available slots","description":"List open meeting slots on the user's calendar for one of their bookable meeting types, honoring their availability schedule, connected-calendar busy times, buffers, and booking caps. Use before book_meeting to find a valid time. Read-only, free.\n\nCalled over MCP as tools/call with name \"get_available_slots\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_available_slots","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_available_slotsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#book_meeting":{"post":{"operationId":"book_meeting","summary":"book meeting","description":"Book a meeting on the user's own calendar for a guest (usually a lead): creates the booking, calendar event with meeting link, and sends real confirmation emails to the guest and the user. Get the exact time from get_available_slots first, and confirm the guest, meeting type, and time with the user before calling. Free.\n\nCalled over MCP as tools/call with name \"book_meeting\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"book_meeting","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/book_meetingInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#manage_signatures":{"post":{"operationId":"manage_signatures","summary":"manage signatures","description":"Manage the user's email signatures: list them, create a new one, update or delete one (by signatureId), or set one as the default for outreach. create needs name + displayName. Confirm destructive changes (delete) with the user. Free.\n\nCalled over MCP as tools/call with name \"manage_signatures\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"manage_signatures","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/manage_signaturesInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#get_deliverability":{"post":{"operationId":"get_deliverability","summary":"get deliverability","description":"Inbox/sending health: per email account (status, total sent, bounce rate, health), overall bounce/reply rates, suppressed-address counts, and LinkedIn send usage against the weekly connection-request ceiling (100 per rolling 7 days) and daily cap. Use to answer 'how's my deliverability' or to flag sending-reputation problems. Read-only, free.\n\nCalled over MCP as tools/call with name \"get_deliverability\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"get_deliverability","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/get_deliverabilityInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_agents":{"post":{"operationId":"list_agents","summary":"list agents","description":"List the user's autonomous agents (the virtual SDRs in the My Agents tab): goal, schedule, quotas, autopilot state, judge thresholds, last/next run. Pass agentId to also get that agent's recent run history (leads found/passed, drafts created/approved, blocks spent, errors) — use that to answer \"what did my agent do?\". Read-only, free.\n\nCalled over MCP as tools/call with name \"list_agents\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_agents","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_agentsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#manage_agent":{"post":{"operationId":"manage_agent","summary":"manage agent","description":"Create, update, pause, resume, delete, or immediately run one of the user's autonomous agents (virtual SDRs). create needs name + goal + brief (min 120 chars, grounded in the company profile); everything else defaults sensibly (20/week, weekdays, autopilot off, drafts land PENDING_REVIEW). Pass autopilot: true when the user asks for it — with autopilot on, drafts that pass the quality judge are approved and sent with no human review, so say that plainly when you report the config. run_now starts a run in the background (takes a few minutes; progress lands in My Agents → run history) and spends the agent's normal per-run blocks (search 12, drafting 4/lead). A clear instruction is your authorization — create/update/pause/resume/run in the same turn and report exactly what you configured; ask first only when you'd be guessing at material choices, and always confirm before delete. Free at the tool level.\n\nCalled over MCP as tools/call with name \"manage_agent\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"manage_agent","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/manage_agentInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_signals":{"post":{"operationId":"list_signals","summary":"list signals","description":"List detected buying signals (funding rounds, hiring surges, job changes, company news), newest first — both from the AI-managed company watchlist and from the market-wide news hunts (companies the user isn't tracking yet; those carry a hunt label). Each row has a signalId, type, title, summary, source URL, the company, and a linked contact when person-level. Default shows actionable signals (NEW/DRAFTING/DRAFTED). A NEW signal can be turned into outreach with draft_signal_outreach. This returns detected SIGNALS only — for the hunts use list_signal_hunts; for the company watchlist use list_signal_trackers. Free.\n\nCalled over MCP as tools/call with name \"list_signals\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_signals","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_signalsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_signal_trackers":{"post":{"operationId":"list_signal_trackers","summary":"list signal trackers","description":"List the AI-managed company watchlist for buying signals (hidden from the News page UI — the AI picks companies from the CRM and from what the news hunts surface; users add/remove via manage_signal_tracking), including companies with zero signals so far. Each row has the company name, domain, who added it (AI vs user), status (ACTIVE/PAUSED), signal count, and last/next scan times. The returned company name is the exact name manage_signal_tracking expects for pause/resume/untrack. Free.\n\nCalled over MCP as tools/call with name \"list_signal_trackers\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_signal_trackers","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_signal_trackersInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_signal_hunts":{"post":{"operationId":"list_signal_hunts","summary":"list signal hunts","description":"List the news hunts — the angles compiled from the workspace's news hunting skill (News page → Skill tab) that the AI sweeps across the whole market every day to surface buying signals at companies the user isn't tracking yet. Each row has the label, kind (ICP_EVENT / COMPETITOR / KEYWORD), the natural-language brief, literal search terms, rationale, status, signal count, and last/next sweep times. To change what gets hunted, the user edits the skill on the News page (or update the huntingSkill via the API); hunts recompile from it. Free.\n\nCalled over MCP as tools/call with name \"list_signal_hunts\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_signal_hunts","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_signal_huntsInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#draft_signal_outreach":{"post":{"operationId":"draft_signal_outreach","summary":"draft signal outreach","description":"Queue signal-grounded outreach drafting for one NEW signal (from list_signals). Works for every signal type including COMPANY_DISCOVERED. The signal is routed to the person at that company who best fits it (a security leader for a security event, finance leadership for a raise); when no saved contact fits, one company-pinned search sources the right person (one search-block charge) and adds them to contacts. A background job then drafts personalized messages that open with the signal, quality-judges them, and leaves them PENDING_REVIEW in Messages — nothing is sent (unless the user's signals-autopilot setting is on, in which case judge-passing drafts are approved to send). Charges the standard per-lead draft blocks as the job runs. Returns immediately.\n\nCalled over MCP as tools/call with name \"draft_signal_outreach\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"draft_signal_outreach","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/draft_signal_outreachInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#manage_signal_tracking":{"post":{"operationId":"manage_signal_tracking","summary":"manage signal tracking","description":"Manage the AI-managed company watchlist (hidden from the News page UI) and the News settings. Actions: track (start watching a company — needs companyName, optional domain; costs signal-tracking blocks at each weekly scan), pause / resume / untrack (needs companyName of an existing tracker), configure (update settings: autoDraft, autoTrack, discoveryEnabled (= run the news hunts), autopilot, paused — paused=true pauses the whole News layer: no scans, hunts, or block spend until resumed). IMPORTANT: autopilot=true means judge-passing signal drafts are approved and SENT without the user reviewing them — state this plainly and only enable it on a clear user instruction.\n\nCalled over MCP as tools/call with name \"manage_signal_tracking\". Has real-world side effects; confirm with the user first.","tags":["MCP tools"],"x-mcp-tool":"manage_signal_tracking","x-read-only":false,"x-side-effect":true,"security":[{"oauth2":["starlight:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/manage_signal_trackingInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/mcp#list_social_opportunities":{"post":{"operationId":"list_social_opportunities","summary":"list social opportunities","description":"List social-listening opportunities — public posts on X, Reddit, or LinkedIn that give the user a reason to reach out, from people matching the ICP, ranked by surface score (relevance + commentability). Two kinds: problem signals (complaints about tools, evaluations, asks for recommendations) and moment signals (someone just started a new role, a company milestone, a team being built) where nothing is wrong but the poster just became the buyer. Each row has the post's verbatim text and URL, the author, why it's an opening, a suggested comment the user can post themselves, and a linked contact when the poster was resolved. Hidden/low-fit posts (competitors, viral threads, off-ICP) are omitted unless includeHidden is true. Default shows actionable rows (NEW/DRAFTING/DRAFTED/ENGAGED). The feed lives on the /social page, where each row has Copy-&-open-post and Draft-outreach actions. Free.\n\nCalled over MCP as tools/call with name \"list_social_opportunities\". Read-only; free.","tags":["MCP tools"],"x-mcp-tool":"list_social_opportunities","x-read-only":true,"x-side-effect":false,"security":[{"oauth2":["starlight:read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/list_social_opportunitiesInput"}}}},"responses":{"200":{"description":"Tool result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResult"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient blocks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.1 authorization code with PKCE (S256). Public clients; register via /api/oauth/register.","flows":{"authorizationCode":{"authorizationUrl":"https://joinstarlight.com/oauth/authorize","tokenUrl":"https://joinstarlight.com/api/oauth/token","refreshUrl":"https://joinstarlight.com/api/oauth/token","scopes":{"starlight:read":"Read leads, contacts, searches, drafts, signals, bookings, metrics, and billing status.","starlight:write":"Create and change things: run searches, draft and approve outreach, edit contacts, manage sequences, agents, and bookings.","starlight:agent":"Full agent access (read + write). Default scope; equivalent to starlight:read starlight:write."}}}}},"responses":{"Error":{"description":"Structured error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"Every non-2xx response body.","required":["error","code","message"],"properties":{"error":{"type":"string","description":"Human-readable message (legacy field, same as message)."},"code":{"type":"string","description":"Stable machine identifier.","enum":["unauthorized","forbidden","no_company","user_not_found","invalid_input","not_found","insufficient_blocks","insufficient_scope","internal_error"]},"message":{"type":"string"},"hint":{"type":"string","description":"What to do about it."},"details":{"description":"Validation issues or block-balance info."},"docs":{"type":"string","format":"uri"}}},"ToolResult":{"type":"object","required":["content"],"properties":{"content":{"type":"array","items":{"type":"object","properties":{"type":{"const":"text"},"text":{"type":"string"}}}},"isError":{"type":"boolean"}}},"get_company_profileInput":{"type":"object","properties":{}},"list_searchesInput":{"type":"object","properties":{"query":{"description":"Case-insensitive text match on the search name or original query","type":"string"},"limit":{"type":"integer","minimum":1,"maximum":50}}},"search_leadsInput":{"type":"object","properties":{"query":{"type":"string","minLength":3,"description":"Natural-language description of who to find"},"maxResults":{"description":"Cap on returned leads (default 25)","type":"integer","minimum":1,"maximum":50}},"required":["query"]},"get_search_resultsInput":{"type":"object","properties":{"searchId":{"type":"string"},"minScore":{"description":"Only leads with matchScore >= this (0-100)","type":"integer","minimum":0,"maximum":100},"limit":{"type":"integer","minimum":1,"maximum":100}},"required":["searchId"]},"list_contactsInput":{"type":"object","properties":{"query":{"description":"Case-insensitive text match on name, title, or company","type":"string"},"limit":{"type":"integer","minimum":1,"maximum":100}}},"add_to_contactsInput":{"type":"object","properties":{"leadIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string"}}},"required":["leadIds"]},"evaluate_lead_fitInput":{"type":"object","properties":{"leadIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string"}},"icp":{"description":"Override ICP; defaults to the company profile's ICP","type":"string"}},"required":["leadIds"]},"draft_outreachInput":{"type":"object","properties":{"leadIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string"}},"instructions":{"type":"string","minLength":120,"maxLength":8000,"description":"Drafting brief: pitch, angle, call to action. Min 120 chars — be specific about the angle and CTA, but only with proof points grounded in get_company_profile; do not pad with invented metrics."},"sendMode":{"description":"Channel mix (default EMAIL_SEQUENCE)","type":"string","enum":["BEST_PER_CONTACT","EMAIL_SINGLE","EMAIL_SEQUENCE","LINKEDIN_CONNECTION_SINGLE","LINKEDIN_INMAIL_SINGLE","LINKEDIN_SEQUENCE","EMAIL_LINKEDIN_SEQUENCE","X_DM_SINGLE"]},"emailSteps":{"description":"Emails in the sequence (default 3)","type":"integer","minimum":2,"maximum":5},"researchEnabled":{"description":"Web research grounding (default TRUE; 2 blocks per uncached lead). Only pass false when the user explicitly declines research.","type":"boolean"},"reengage":{"description":"Set true to draft a NEW sequence for previously contacted leads whose drafts were all SENT and got no reply (stale/re-engagement). Leads with pending/approved drafts or an active scheduled sequence are still rejected.","type":"boolean"}},"required":["leadIds","instructions"]},"list_pending_draftsInput":{"type":"object","properties":{"leadId":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":50},"includeBody":{"type":"boolean"}}},"edit_draftInput":{"type":"object","properties":{"draftId":{"type":"string"},"subject":{"description":"Full replacement subject line (email only). Omit to leave unchanged.","type":"string","maxLength":300},"body":{"description":"Full replacement message body. Omit to leave unchanged.","type":"string","minLength":1,"maxLength":8000},"intent":{"description":"Why this rewrite was made / what the new message is going for (e.g. 'warm soft-touch close, no pitch'). Persisted so the quality judge grades against this intent rather than the original brief. Pass it whenever the rewrite intentionally departs from the original brief; persists across later minor edits until you provide a new one.","type":"string","maxLength":1000}},"required":["draftId"]},"repair_draftsInput":{"type":"object","properties":{"leadIds":{"description":"Only repair drafts for these leads. Omit to sweep all recent flagged drafts.","minItems":1,"maxItems":100,"type":"array","items":{"type":"string"}},"limit":{"description":"Max enrollments (leads) to repair in this call, newest first. Default 25.","type":"integer","minimum":1,"maximum":25}}},"append_sequence_stepInput":{"type":"object","properties":{"leadIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string"}},"instructions":{"type":"string","minLength":20,"maxLength":4000,"description":"Brief for the single extra email: the angle and the ask. Proof points must come from get_company_profile."}},"required":["leadIds","instructions"]},"evaluate_draft_qualityInput":{"type":"object","properties":{"draftIds":{"minItems":1,"maxItems":25,"type":"array","items":{"type":"string"}}},"required":["draftIds"]},"approve_draftsInput":{"type":"object","properties":{"draftIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string"}}},"required":["draftIds"]},"get_outreach_statusInput":{"type":"object","properties":{"sequenceId":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":25}}},"check_inboxInput":{"type":"object","properties":{"unreadOnly":{"type":"boolean"},"limit":{"type":"integer","minimum":1,"maximum":50}}},"get_metricsInput":{"type":"object","properties":{"period":{"type":"string","enum":["today","week","month"]}}},"get_billing_statusInput":{"type":"object","properties":{}},"get_contact_detailsInput":{"type":"object","properties":{"leadId":{"type":"string","description":"The lead/contact id (from list_contacts or a search)."}},"required":["leadId"]},"list_stale_leadsInput":{"type":"object","properties":{"minDaysStale":{"description":"Days since the last outgoing message to count as stale (default 14).","type":"integer","minimum":1,"maximum":365},"limit":{"description":"Max rows to return (default 25).","type":"integer","minimum":1,"maximum":100}}},"remove_contactInput":{"type":"object","properties":{"leadIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string"}}},"required":["leadIds"]},"list_scheduling_linksInput":{"type":"object","properties":{}},"update_contactInput":{"type":"object","properties":{"leadId":{"type":"string","description":"The lead/contact id to update."},"status":{"description":"Move the contact to this pipeline stage.","type":"string","enum":["NEW","CONTACTED","ENGAGED","RESPONDED","MEETING_BOOKED","CONVERTED"]},"note":{"description":"Append a note to the contact.","type":"string","minLength":1,"maxLength":5000}},"required":["leadId"]},"manage_sequenceInput":{"type":"object","properties":{"sequenceId":{"type":"string","description":"The sequence id (from get_outreach_status)."},"action":{"type":"string","enum":["pause","resume","delete"],"description":"pause: stop sending (no messages go out while paused). resume: set it back to ACTIVE so sending continues. delete: permanently remove the sequence and its enrollments."}},"required":["sequenceId","action"]},"get_inbox_messageInput":{"type":"object","properties":{"messageId":{"type":"string","description":"The inbox message id from check_inbox."}},"required":["messageId"]},"edit_inbox_replyInput":{"type":"object","properties":{"messageId":{"type":"string","description":"The inbox message id (from check_inbox, or the <current_inbox_reply> context block)."},"body":{"type":"string","minLength":1,"maxLength":8000,"description":"The full replacement reply text (plain text)."},"subject":{"description":"Replacement subject line — email replies only; omit for LinkedIn.","type":"string","maxLength":300}},"required":["messageId","body"]},"send_linkedin_replyInput":{"type":"object","properties":{"messageId":{"type":"string","description":"The LinkedIn inbox message id from check_inbox or the current_inbox_reply context."},"body":{"type":"string","minLength":1,"maxLength":8000,"description":"The reply text to send."}},"required":["messageId","body"]},"send_emailInput":{"type":"object","properties":{"leadId":{"type":"string","description":"The contact/lead id — resolve via list_contacts or get_contact_details."},"subject":{"type":"string","minLength":1,"maxLength":300,"description":"The email subject line."},"body":{"type":"string","minLength":1,"maxLength":8000,"description":"The full plain-text email body you wrote in this conversation. Do NOT add a sign-off or signature — the user's email signature is appended automatically."},"replyToThread":{"description":"Default true: if an email conversation with this contact already exists in the Inbox, send in-thread as a reply. Pass false to force a fresh thread.","type":"boolean"}},"required":["leadId","subject","body"]},"update_company_profileInput":{"type":"object","properties":{"productDescription":{"description":"What the company sells — the proof points that ground every draft.","type":"string","maxLength":8000},"idealCustomerProfile":{"description":"Who to target — the ICP used to score leads and plan searches.","type":"string","maxLength":8000},"websiteUrl":{"description":"Company website URL.","type":"string","format":"uri"},"messageLengthPreference":{"description":"Preferred outreach length.","type":"string","enum":["SHORT","MEDIUM","LONG"]},"competitors":{"description":"Direct competitor company names.","maxItems":10,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"productFactSheet":{"description":"Section-level edits to the product fact sheet. Each edit touches exactly ONE \"## \" heading; every other section is left byte-for-byte alone. There is NO whole-document write — never restate the sheet. Read it first with get_company_profile. \"Proof points\" is the fabrication whitelist: a number you add there is a number the user's reps will state to a real buyer, so only add one you actually read in a source.","maxItems":6,"type":"array","items":{"type":"object","properties":{"section":{"type":"string","minLength":1,"maxLength":80,"description":"The \"## \" heading to operate on, e.g. \"Proof points\". Matched case- and punctuation-insensitively; created at the end of the sheet if it does not exist."},"op":{"default":"append","description":"append — add lines to the end of that section, keeping what is already there. replace — overwrite that ONE section's body. remove — delete the section. Prefer append: it cannot destroy anything.","type":"string","enum":["append","replace","remove"]},"content":{"description":"Markdown body for the section — one fact per \"- \" bullet. Required for append and replace; omit for remove.","type":"string","maxLength":2000}},"required":["section"]}},"icpFactSheet":{"description":"Section-level edits to the ICP fact sheet. Same rules. \"Buyer personas\" bullets are passed to a people-search API verbatim — one exact, common job title per bullet. \"Disqualifiers\" are hard negatives that cap a lead below 50.","maxItems":6,"type":"array","items":{"type":"object","properties":{"section":{"type":"string","minLength":1,"maxLength":80,"description":"The \"## \" heading to operate on, e.g. \"Proof points\". Matched case- and punctuation-insensitively; created at the end of the sheet if it does not exist."},"op":{"default":"append","description":"append — add lines to the end of that section, keeping what is already there. replace — overwrite that ONE section's body. remove — delete the section. Prefer append: it cannot destroy anything.","type":"string","enum":["append","replace","remove"]},"content":{"description":"Markdown body for the section — one fact per \"- \" bullet. Required for append and replace; omit for remove.","type":"string","maxLength":2000}},"required":["section"]}}}},"get_connector_statusInput":{"type":"object","properties":{}},"manage_scheduling_linkInput":{"type":"object","properties":{"action":{"type":"string","enum":["create","update","delete"]},"eventTypeId":{"description":"Required for update/delete (the link's id from list_scheduling_links).","type":"string"},"title":{"type":"string","minLength":1,"maxLength":120},"slug":{"description":"URL slug (required for create).","type":"string","minLength":3,"maxLength":60,"pattern":"^[a-z0-9-]+$"},"durationMinutes":{"description":"Meeting length (required for create).","type":"integer","minimum":5,"maximum":480},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"locationType":{"type":"string","enum":["GOOGLE_MEET","ZOOM","PHONE","IN_PERSON","CUSTOM"]},"isActive":{"description":"Toggle the link on/off (update only).","type":"boolean"}},"required":["action"],"description":"Create, edit, or delete a bookable meeting type."},"list_bookingsInput":{"type":"object","properties":{"filter":{"type":"string","enum":["upcoming","past","cancelled"]},"limit":{"type":"integer","minimum":1,"maximum":100}}},"manage_bookingInput":{"type":"object","properties":{"bookingId":{"type":"string","description":"The booking id from list_bookings."},"action":{"description":"Defaults to cancel.","type":"string","enum":["cancel","reschedule"]},"newStartUtc":{"description":"Required for reschedule — an exact startUtc from get_available_slots.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reason":{"description":"Optional cancellation reason shared with the guest (cancel only).","type":"string","maxLength":1000}},"required":["bookingId"]},"get_available_slotsInput":{"type":"object","properties":{"eventTypeId":{"description":"Which meeting type (from list_scheduling_links). Defaults to the first active one.","type":"string"},"startDate":{"description":"First day to check, YYYY-MM-DD. Defaults to today.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"days":{"description":"How many days to check (default 7).","type":"integer","minimum":1,"maximum":14},"timezone":{"description":"IANA timezone for displaying times. Defaults to the user's timezone.","type":"string"}}},"book_meetingInput":{"type":"object","properties":{"eventTypeId":{"description":"Which meeting type (from list_scheduling_links / get_available_slots). Defaults to the first active one.","type":"string"},"startUtc":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$","description":"Exact slot start in UTC ISO format — use a startUtc value from get_available_slots."},"inviteeName":{"description":"The guest's full name. Optional when leadId is given (defaults to the lead's name).","type":"string","minLength":1,"maxLength":200},"inviteeEmail":{"description":"The guest's email. Optional when leadId is given (the lead's email is used).","type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"inviteePhone":{"type":"string","maxLength":50},"inviteeTimezone":{"description":"Guest's IANA timezone for their confirmation email. Defaults to the lead's known timezone, then the user's.","type":"string"},"leadId":{"description":"Link the meeting to a lead/contact by id.","type":"string"},"notes":{"type":"string","maxLength":2000}},"required":["startUtc"]},"manage_signaturesInput":{"type":"object","properties":{"action":{"type":"string","enum":["list","create","update","delete","set_default"]},"signatureId":{"description":"Required for update/delete/set_default (from action:list).","type":"string"},"name":{"description":"Internal label for the signature (required for create).","type":"string","minLength":1,"maxLength":80},"displayName":{"description":"Name shown in the signature (required for create).","type":"string","minLength":1,"maxLength":120},"role":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"companyName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"websiteUrl":{"anyOf":[{"type":"string","maxLength":400,"format":"uri"},{"type":"null"}]},"linkedinUrl":{"anyOf":[{"type":"string","maxLength":400,"format":"uri"},{"type":"null"}]},"showBookingLink":{"description":"Include the user's booking link in the signature.","type":"boolean"},"disclaimer":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":["action"]},"get_deliverabilityInput":{"type":"object","properties":{}},"list_agentsInput":{"type":"object","properties":{"agentId":{"description":"Optional: include this agent's 10 most recent runs (leads found/passed, drafts created/approved, blocks spent, errors).","type":"string"}}},"manage_agentInput":{"type":"object","properties":{"action":{"type":"string","enum":["create","update","pause","resume","delete","run_now"]},"agentId":{"description":"Required for every action except create — get it from list_agents.","type":"string"},"name":{"type":"string","minLength":1,"maxLength":80},"goal":{"description":"What the agent hunts for, e.g. \"Book demos with heads of RevOps at US fintech startups\".","type":"string","minLength":10,"maxLength":2000},"icp":{"description":"Overrides the company ICP for this agent.","anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"pitch":{"description":"Overrides the company product pitch for this agent.","anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"brief":{"description":"Drafting instructions for the writer (min 120 chars). Ground it in get_company_profile — never invent metrics or proof points.","type":"string","minLength":120,"maxLength":8000},"sendMode":{"type":"string","enum":["BEST_PER_CONTACT","EMAIL_SINGLE","EMAIL_SEQUENCE","LINKEDIN_CONNECTION_SINGLE","LINKEDIN_INMAIL_SINGLE","LINKEDIN_SEQUENCE","EMAIL_LINKEDIN_SEQUENCE","X_DM_SINGLE"]},"emailSteps":{"type":"integer","minimum":1,"maximum":5},"weeklyQuota":{"description":"New leads contacted per week (default 20).","type":"integer","minimum":1,"maximum":2000},"dailyCap":{"description":"Hard per-run ceiling (default 10).","type":"integer","minimum":1,"maximum":100},"cadence":{"type":"string","enum":["DAILY","WEEKDAYS","WEEKLY"]},"runHourUtc":{"description":"UTC hour the run fires (default 13 = 9am ET).","type":"integer","minimum":0,"maximum":23},"autopilot":{"description":"When true the agent approves and sends passing drafts with NO human review. Defaults to false on create — set it when the user asks for autopilot, and make sure your summary says drafts will send without review.","type":"boolean"},"minLeadFit":{"type":"integer","minimum":0,"maximum":100},"minDraftQuality":{"type":"integer","minimum":0,"maximum":100}},"required":["action"]},"list_signalsInput":{"type":"object","properties":{"status":{"description":"Filter by status (default: NEW + DRAFTING + DRAFTED)","type":"string","enum":["NEW","DRAFTING","DRAFTED","DISMISSED","EXPIRED"]},"limit":{"type":"integer","minimum":1,"maximum":50}}},"list_signal_trackersInput":{"type":"object","properties":{"status":{"description":"Filter by tracker status (default: all)","type":"string","enum":["ACTIVE","PAUSED"]},"limit":{"type":"integer","minimum":1,"maximum":100}}},"list_signal_huntsInput":{"type":"object","properties":{"status":{"description":"Filter by hunt status (default: all)","type":"string","enum":["ACTIVE","PAUSED"]},"limit":{"type":"integer","minimum":1,"maximum":100}}},"draft_signal_outreachInput":{"type":"object","properties":{"signalId":{"type":"string","description":"The signal to draft outreach for"}},"required":["signalId"]},"manage_signal_trackingInput":{"type":"object","properties":{"action":{"type":"string","enum":["track","pause","resume","untrack","configure"]},"companyName":{"description":"Company to track/pause/resume/untrack","type":"string"},"domain":{"description":"Company website domain (helps funding/hiring detection)","type":"string"},"autoDraft":{"type":"boolean"},"autopilot":{"type":"boolean"},"autoTrack":{"type":"boolean"},"discoveryEnabled":{"type":"boolean"},"paused":{"description":"Pause/resume the whole News layer (all scanning + spend)","type":"boolean"}},"required":["action"]},"list_social_opportunitiesInput":{"type":"object","properties":{"status":{"description":"Filter by status (default: NEW + DRAFTING + DRAFTED + ENGAGED)","type":"string","enum":["NEW","DRAFTING","DRAFTED","ENGAGED","DISMISSED","EXPIRED"]},"platform":{"type":"string","enum":["X","REDDIT","LINKEDIN"]},"limit":{"type":"integer","minimum":1,"maximum":50},"includeHidden":{"type":"boolean"}}}}}}