headlo-mcp
Officialheadlo-mcp
MCP server for Headlo — gives Claude Desktop and Claude Code access to your Headlo collections, records, pages, and components.
Use it as a standalone server, or install as a library to add your own tools and intercept built-in ones.
Quickstart
Claude Desktop
Edit claude_desktop_config.json (Mac: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):
{
"mcpServers": {
"headlo": {
"command": "npx",
"args": ["headlo-mcp"],
"env": {
"HEADLO_API_TOKEN": "hl_pat_your_token_here"
}
}
}
}Restart Claude Desktop. You should see the Headlo tools available.
Claude Code
claude mcp add headlo -e HEADLO_API_TOKEN=hl_pat_your_token_here -- npx headlo-mcpRemote MCP (no install)
If you don't need to extend the server, point Claude directly at the Headlo API:
claude mcp add headlo https://api.headlo.com/v1/mcp --header "Authorization: Bearer hl_pat_your_token_here"Extending the server
Install as a library to add your own tools or intercept built-in ones:
npm install headlo-mcp @modelcontextprotocol/sdkAdd custom tools
import { createHeadloServer } from 'headlo-mcp'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'
const server = createHeadloServer()
// your own tool alongside the built-ins
server.tool('my_crm_lookup', 'Look up a contact in my CRM', { email: z.string() }, async ({ email }) => {
const contact = await myCRM.find(email)
return { content: [{ type: 'text', text: JSON.stringify(contact) }] }
})
await server.connect(new StdioServerTransport())Intercept built-in tool calls
Pass a wrap map to run code before or after any built-in tool:
import { createHeadloServer } from 'headlo-mcp'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
const server = createHeadloServer({
wrap: {
// validate before creating a record, sync to CRM after
create_record: async (args, next) => {
await mySchema.validate(args)
const result = await next(args)
await myCRM.push(result)
return result
},
// log every CAP session to your analytics
cap_capture_expert: async (args, next) => {
const result = await next(args)
await myAnalytics.track(args.cap_id, result)
return result
},
}
})
await server.connect(new StdioServerTransport())next(args) calls the original Headlo handler. You can modify args before passing them, or modify the result before returning it.
Environment variables
Variable | Required | Description |
| Yes | Your Headlo API token ( |
| No | API base URL (default: |
| No | Anon key for public tool calls |
Built-in tools
Context
Tool | Description |
| List all sites and workspaces — call this first |
Collections
Tool | Description |
| List all collections in a workspace |
| Create a new collection with a schema |
| Update a collection label or schema |
Records
Tool | Description |
| List records in a collection (includes drafts) |
| Get a single record by ID |
| Create a new record |
| Update a record (partial — only provided fields change) |
| Delete a record |
Pages
Tool | Description |
| List all pages for a site |
| Create a new page |
| Update a page title, layout, or status |
Modules
Tool | Description |
| List all modules on a page |
| Add a module to a page slot |
| Update a module's record, options, or template |
| Remove a module from a page |
Public
Tool | Description |
| List modules on a page (anon auth) |
| Get a single module (anon auth) |
CAP (Context Accumulation Protocol)
CAP is Headlo's expert intake system — structured question flows backed by pre-researched knowledge that produce better AI answers than generic prompts.
Tool | Description |
| Create a new CAP with intake questions and knowledge probes for a question on the Ask network |
| Run a CAP as a live multi-turn intake session — call with empty message to start, pass answers in subsequent calls |
| Conversationally edit an existing CAP — add/remove questions, edit options |
Running a CAP session (multi-turn):
// Turn 1 — load the CAP (empty message)
const t1 = await cap_capture_expert({ cap_id: 'abc123def456', message: '' })
// → { response: "Question 1 of 3: ...", session_state: {...}, complete: false }
// Turn 2 — answer the first question, pass session_state back
const t2 = await cap_capture_expert({ cap_id: 'abc123def456', message: 'Downtown', session_state: t1.session_state })
// → { response: "Question 2 of 3: ...", session_state: {...}, complete: false }
// Turn 3 — final answer
const t3 = await cap_capture_expert({ cap_id: 'abc123def456', message: 'Coffee shops', session_state: t2.session_state })
// → { response: "...", complete: true, answer: "..." }Intercepting CAP calls with middleware:
const server = createHeadloServer({
wrap: {
cap_capture_expert: async (args, next) => {
const result = await next(args)
// log every completed session to your analytics
if (result.complete) await myAnalytics.track(args.cap_id, result)
return result
},
}
})Onboarding
Tool | Description |
| Create a new agency/workspace |
| Create a new site |
| Save logo and brand color |
| Get current onboarding step |
License
Elastic License 2.0 — © Headlo
Source available. Free for internal use. Production self-hosting requires a commercial license.
Built by Headlo.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/headlohq/headlo-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server