Headlessly
MCP

MCP Reference

Complete reference for the three MCP tools -- search, fetch, do.

{
  "mcpServers": {
    "headlessly": {
      "url": "https://crm.headless.ly/mcp",
      "headers": { "Authorization": "Bearer hly_sk_..." }
    }
  }
}

headless.ly exposes exactly three MCP tools: search, fetch, and do. They cover all 35 entity types, all CRUD operations, all custom verbs, across all 52 composable systems. No tool selection problem, no token bloat, no routing confusion.

Why Three Tools

Every SaaS MCP integration ships dozens or hundreds of tools. An agent connecting to a CRM gets search_contacts, get_contact, create_contact, update_contact, delete_contact -- times every entity type. The combinatorial explosion lands in the tool namespace, forcing the model to read thousands of tokens of tool definitions before it can act.

headless.ly pushes the combinatorics into the argument space instead. Three tool definitions total ~480 tokens. A conventional 200-tool server burns ~40,000 tokens on definitions alone.

The three primitives map to the three things agents do with data:

ToolPurposeWhen to Use
searchFind entities matching filters"Show me all leads from this week"
fetchGet a specific entity, schema, metric, or business status"Get contact details" or "What's our MRR?"
doExecute TypeScript in a secure sandboxAny mutation, multi-step logic, aggregation

Connection Setup

Point any MCP-compatible client at your tenant's endpoint:

{
  "mcpServers": {
    "headlessly": {
      "url": "https://headless.ly/mcp",
      "headers": {
        "Authorization": "Bearer hly_sk_your_api_key"
      }
    }
  }
}

Or use the CLI to start a local MCP bridge:

npx @headlessly/cli mcp --context crm
npx @headlessly/cli mcp --context billing
npx @headlessly/cli mcp --context healthcare

The --context flag sets the default system scope without changing the available tools.

Subdomain Scoping

Every *.headless.ly subdomain resolves to the same Cloudflare Worker. The subdomain determines the default context for search results and schema discovery, but all three tools can always reach any entity in the graph.

crm.headless.ly/mcp           # CRM context -- Organization, Contact, Deal prominent
billing.headless.ly/mcp       # Billing context -- Product, Subscription, Invoice prominent
healthcare.headless.ly/mcp    # Healthcare industry context
build.headless.ly/mcp         # Build journey -- Projects, Issues, Content prominent

Paths provide secondary dimensions. crm.headless.ly/healthcare and healthcare.headless.ly/crm resolve to the same composed context.

Authentication Levels

Access is progressive. An unauthenticated agent can explore. An authenticated agent can act.

LevelAuthTools AvailableCapability
L0Nonesearch, fetchRead-only exploration of public schemas and demo data
L1Session tokensearch, fetch, doSandboxed read/write within session scope
L2API key (hly_sk_...)search, fetch, doFull tenant access, production mutations
L3Admin key (hly_admin_...)search, fetch, doCross-tenant, schema modification, bulk operations

L0 is designed for agent discovery. An agent connecting without credentials can fetch schemas, search demo data, and understand the system before requesting elevated access.

Progressive Capability

At L0, do calls return a structured error with an upgrade path:

{
  "error": "authentication_required",
  "message": "The do tool requires L1+ authentication.",
  "upgrade": "https://headless.ly/~your-tenant/settings/api-keys"
}

At L1 (session tokens), the sandbox runs in a restricted mode: 30-second timeout, 128MB memory, 100 entity operations per call, read-only access to other tenants' data.

At L2 (API keys), limits increase: 60-second timeout, 256MB memory, 1000 entity operations per call.

Rate Limits

Auth LevelRequests per MinuteBurstEntity Operations per Call
L03010N/A (read-only)
L110030100
L21,0001001,000
L3UnlimitedUnlimited10,000

Rate limit headers are included on every response:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1706745600

When a rate limit is exceeded, the server returns HTTP 429 with a Retry-After header.

Tool Summary

Find entities across the graph with MongoDB-style filters, sorting, and pagination. Returns a list of matching entities.

headless.ly/mcp#search
{ "type": "Deal", "filter": { "value": { "$gte": 50000 } }, "sort": "-value", "limit": 10 }

fetch

Get a single entity by ID, a schema definition, a named metric, or the full business status snapshot.

headless.ly/mcp#fetch
{ "type": "Contact", "id": "contact_fX9bL5nRd", "include": ["deals", "organization"] }

do

Execute arbitrary TypeScript in a secure Cloudflare container sandbox. The $ context provides access to all 35 entities and their verbs.

headless.ly/mcp#do
const leads = await $.Contact.find({ stage: 'Lead' })
for (const lead of leads) {
  await $.Contact.qualify(lead.$id)
}
return { qualified: leads.length }

On this page