{"ok":true,"protocol":"mcp","protocolNote":"Model Context Protocol server, Streamable HTTP transport. This JSON is a plain-HTTP view of the same catalog an MCP client receives from tools/list.","transport":"streamable-http","service":"scaliq-mcp","name":"scaliq","version":"1.0.0","description":"LinkedIn outreach automation (campaigns, leads, search, messaging) for a single ScaliQ workspace, exposed 1:1 over the ScaliQ Public API.","instructions":"ScaliQ MCP — LinkedIn outreach automation for the authenticated ScaliQ workspace.\nEvery tool maps 1:1 to the ScaliQ Public API (/public/v1). This server holds no data of its own.\n\nAuth: the user supplies an API key (sk_live_… / sk_test_…) as an X-API-Key header in their MCP\nclient config. Discovery works without it; any tools/call without it fails. If a call reports a\nmissing key, tell the user to add it in their MCP client config — do not ask them to paste it in chat.\n\nGetting oriented: list_accounts returns accountId values plus each account's usage and daily caps\nfor today; list_campaigns returns campaignId values plus per-campaign stats. Most other tools need\none of those ids, so call these first rather than guessing. List endpoints paginate: follow\nnextCursor while it is non-null.\n\nCost and risk: only add_lead spends a ScaliQ credit (1 per successful insert); everything else is 0.\nsearch_linkedin and lookup_profile are free but consume the connected LinkedIn account's daily\nquota, so page deliberately instead of looping. send_message sends a real, irreversible LinkedIn DM\n— always confirm recipient and exact wording with the user first, and check the account's remaining\nsend allowance from list_accounts.\n\nScope: call only the tools listed here. This server exposes no product, pricing, or documentation\ntools, and cannot reach data outside the key holder's own workspace. Do not invent endpoints.","auth":{"type":"api_key","header":"X-API-Key","alternative":"Authorization: Bearer sk_live_…","requiredForDiscovery":false,"requiredForToolCalls":true,"obtainKeyAt":"https://app.scaliq.ai/api-mcp","note":"Keys are per-workspace. Discovery (this document, initialize, tools/list) needs no key; every tools/call does. Users add the key to their MCP client config, never in chat."},"howToConnect":{"url":"https://mcp.scaliq.ai","mcpEndpoint":"POST https://mcp.scaliq.ai/","alias":"POST https://mcp.scaliq.ai/mcp","requiredHeaders":{"Accept":"application/json, text/event-stream","Content-Type":"application/json","X-API-Key":"sk_live_YOUR_KEY"},"exampleClientConfig":{"mcpServers":{"scaliq":{"url":"https://mcp.scaliq.ai","headers":{"X-API-Key":"sk_live_YOUR_KEY"}}}},"note":"A plain browser GET returns this document. MCP clients must send Accept: text/event-stream to reach the transport."},"credits":{"add_lead":1,"everythingElse":0,"note":"search_linkedin and lookup_profile cost 0 credits but consume the connected LinkedIn account daily quota."},"limits":{"note":"Per-account LinkedIn caps and usage for the current UTC day are returned by list_accounts under `today`. Rate limits are enforced by the REST API and surface as HTTP 429."},"publicApiBaseUrl":"https://api.scaliq.ai/public/v1","toolCount":11,"tools":[{"name":"get_credits","title":"Get credits","description":"GET /credits — remaining ScaliQ credits and plan id. Free (0 credits).","inputSchema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_accounts","title":"List LinkedIn accounts","description":"GET /accounts — paginated list of connected accounts (id, status, active, hasSalesNavigator) plus today's per-account usage and caps in `today` (connectionRequestsSent/Accepted, messagesSent, and their limits; UTC-day reset). Check usage against the limits before sending. Follow `nextCursor` when it is not null.","inputSchema":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100},"cursor":{"type":"string"}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_campaigns","title":"List campaigns","description":"GET /campaigns — paginated campaign list. Each item includes `stats` (connectionRequestsSent/Accepted, acceptanceRate, messagesSent, repliesReceived, replyRate), so campaign performance needs no per-campaign fetch. Rates are percentages and are null when the denominator is 0.","inputSchema":{"type":"object","properties":{"status":{"type":"string","description":"Optional campaign status filter"},"limit":{"type":"integer","minimum":1,"maximum":100},"cursor":{"type":"string"}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"get_campaign","title":"Get campaign","description":"GET /campaigns/:campaignId — one campaign with its stats. Free (0 credits).","inputSchema":{"type":"object","properties":{"campaignId":{"type":"string","minLength":1}},"required":["campaignId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"list_leads","title":"List leads","description":"GET /campaigns/:campaignId/leads — at most one of tag, replied, needsReply. Each lead carries name parts, location, and contact details (companyLinkedin, website, email); `fullName` falls back to firstName + lastName. Contact fields are null unless the lead was imported or enriched with them.","inputSchema":{"type":"object","properties":{"campaignId":{"type":"string","minLength":1},"tag":{"type":"string"},"replied":{"type":"boolean"},"needsReply":{"type":"boolean"},"limit":{"type":"integer","minimum":1,"maximum":100},"cursor":{"type":"string"}},"required":["campaignId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"get_lead","title":"Get lead","description":"GET /campaigns/:campaignId/leads/:leadId — the list-lead fields plus `headline` and `workExperience` (array of company/position/location/description/start/end, newest first, max 10). Use this rather than list_leads when you need a lead's role history.","inputSchema":{"type":"object","properties":{"campaignId":{"type":"string","minLength":1},"leadId":{"type":"string","minLength":1}},"required":["campaignId","leadId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"add_lead","title":"Add lead","description":"POST /campaigns/:campaignId/leads — insert by LinkedIn URL (1 credit on create). Optional profile fields.","inputSchema":{"type":"object","properties":{"campaignId":{"type":"string","minLength":1},"linkedinUrl":{"type":"string","minLength":8,"maxLength":500},"fullName":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"jobTitle":{"type":"string"},"companyName":{"type":"string"},"email":{"type":"string"},"location":{"type":"string"},"headline":{"type":"string"},"personalization":{"type":"string"},"idempotencyKey":{"type":"string","minLength":1,"maxLength":128,"description":"Optional Idempotency-Key header value (dedupe retries)."}},"required":["campaignId","linkedinUrl"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"update_lead","title":"Update lead","description":"PATCH /campaigns/:campaignId/leads/:leadId — set tag and/or excluded. Free (0 credits).","inputSchema":{"type":"object","properties":{"campaignId":{"type":"string","minLength":1},"leadId":{"type":"string","minLength":1},"tag":{"type":["string","null"]},"excluded":{"type":"boolean"}},"required":["campaignId","leadId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"}},{"name":"send_message","title":"Send LinkedIn message","description":"POST /inbox/messages — sends a REAL LinkedIn DM to an existing campaign lead (text only), immediately and irreversibly. There is no unsend. Confirm the recipient and the exact text with the user before calling. Free (0 credits) but it spends the account's daily send allowance — check `today` from list_accounts first.","inputSchema":{"type":"object","properties":{"campaignId":{"type":"string","minLength":1},"leadId":{"type":"string","minLength":1},"text":{"type":"string","minLength":1,"maxLength":8000},"accountId":{"type":"string"},"idempotencyKey":{"type":"string","minLength":1,"maxLength":128,"description":"Optional Idempotency-Key header value (dedupe retries)."}},"required":["campaignId","leadId","text"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":true},"execution":{"taskSupport":"forbidden"}},{"name":"lookup_profile","title":"Lookup LinkedIn profile","description":"POST /linkedin/profiles/lookup — clean profile DTO (does not add a lead). Accepts messy /in/…?miniProfileUrn=… URLs (tracking params stripped). Returns firstName/lastName, website, companyLinkedin, and current jobTitle/companyName. Pass depth:\"full\" for about + experience[] (role history with dates/descriptions). Free (0 credits) but each call spends the connected account's LinkedIn lookup quota (~80–150/day) — do not loop over large lists.","inputSchema":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"linkedinUrl":{"type":"string","minLength":8,"maxLength":500},"depth":{"type":"string","enum":["basic","full"]}},"required":["accountId","linkedinUrl"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"execution":{"taskSupport":"forbidden"}},{"name":"search_linkedin","title":"Search LinkedIn","description":"POST /linkedin/search — one sync page (classic or sales_nav). Provide exactly one of query or url. jobTitle/companyName are only set when LinkedIn returns a structured current role — otherwise they are null and headline stays the free-text line. Use lookup_profile (depth full) for reliable title/company/experience. Free (0 credits) but each page spends the account's LinkedIn search quota — page deliberately, do not burst.","inputSchema":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"type":{"type":"string","enum":["classic","sales_nav"]},"query":{"type":"string","description":"Natural-language query. Mutually exclusive with url."},"url":{"type":"string","description":"LinkedIn / Sales Navigator search URL. Mutually exclusive with query."},"limit":{"type":"integer","minimum":1,"maximum":100},"cursor":{"type":["string","null"]}},"required":["accountId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"execution":{"taskSupport":"forbidden"}}],"endpoints":{"discovery":"/","wellKnown":"/.well-known/mcp.json","llmsTxt":"/llms.txt","health":"/health","mcp":"/ (alias /mcp)"},"documentation":"https://docs.scaliq.ai"}