HubSpot MCP Operator
Allows building HubSpot automation end-to-end, including creating and managing workflows (enrollment criteria, actions, goal criteria), managing dynamic lists with filter validation, and performing CRM object searches and updates, with writes verified by reading back state.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@HubSpot MCP OperatorCreate a workflow named 'Welcome' that enrolls new contacts."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
HubSpot MCP Operator (demo)
A Model Context Protocol server that lets an AI agent author HubSpot automation end-to-end — build a workflow, set who gets enrolled, wire up the steps, define the conversion goal, and segment contacts into lists — entirely through tool calls, with every mutation verified by reading state back.
About this repo. This is a sanitized, standalone reconstruction of an internal tool I built and ran in production against a live HubSpot portal. All organization-specific data — real object IDs, list/workflow IDs, customer segments, credentials — has been removed. It targets only HubSpot's standard objects and ships with an
.env.exampleyou point at your own test portal. It builds, boots, and registers all 24 tools (verified); running the write tools requires your own HubSpot private-app token.
Why this exists
HubSpot's UI is the normal way to build a marketing workflow. But "build a workflow" is exactly the kind of multi-step, schema-heavy task an agent should be able to do — if it has tools that are safe to hand to a model.
The hard part isn't calling the API. It's making the tools trustworthy enough to act autonomously:
A
200 OKfrom HubSpot does not mean the thing you intended actually happened. The flows API will accept a malformed filter and silently store it as "always false." A list filter can be saved and quietly match zero records.A model that fuzzy-matches "the onboarding workflow" and mutates the wrong flow is a disaster.
The v4 flows API is read-modify-write: to change one field you must PUT the entire flow back, minus the fields the API rejects on write.
This server is built around those realities.
Related MCP server: HubSpot MCP Server
Design principles
1. Every tool returns the same envelope — and writes verify themselves.
{
"ok": true,
"operation": "workflows.set_enrollment_criteria",
"data": { /* request echo + the re-fetched object */ },
"audit": {
"attempted": true,
"verified": true, // ← we re-read the object and confirmed the change
"targetType": "workflow",
"targetId": "1234567890",
"targetName": "Trial → Activation Nurture"
}
}audit.verified is the contract. A write tool performs the mutation, then re-fetches the object and checks the change is actually present before claiming success. create reads the new record back; delete re-lists to confirm the object is gone; lists.members.add re-reads each record's memberships. An agent can branch on audit.verified instead of trusting a status code.
2. Mutations require an unambiguous target. Workflow write tools resolve their target by ID or by exact (case-insensitive) name only. No partial match ever selects a flow to mutate — if the name isn't unique, the tool returns the candidate list and refuses to act.
3. Read-modify-write is encapsulated. sanitizeWorkflowForUpdate / sanitizeWorkflowForCreate strip the server-managed fields (id, revisionId, timestamps) that HubSpot rejects on write, so a single field change round-trips the whole flow safely. Callers just say "set these actions" or "set this enrollment criteria."
4. Failure modes are distinguished. "You sent a bad request" and "this portal can't do this via the API" are different signals to an agent. workflows.add_go_to_workflow_step detects the unsupported-step failure and flags unsupported_via_api: true rather than returning a generic error.
5. Raw filter branches pass straight through. Workflow enrollment, workflow goals, and list filters all share HubSpot's nested AND/OR filterBranch shape. The tools don't invent a DSL on top — they pass the raw branch through, so the full expressiveness of HubSpot filters is available. (See the gotcha below for how to validate one.)
Tool surface (24 tools)
Workflows (automation/v4/flows)
Tool | What it does |
| List / find by ID, exact name, or partial query |
| Full flow detail |
| Create an empty, disabled flow shell |
| Set who is enrolled (raw |
| Replace the action graph; auto-derives |
| Set the conversion goal ( |
| Lifecycle, by ID or exact name |
| Copy criteria + steps into a new disabled flow |
| Append a cross-workflow jump (flags |
Lists (crm/v3/lists)
Tool | What it does |
| Find lists; |
| Create a DYNAMIC (or MANUAL/SNAPSHOT) list with a raw |
| Replace an existing dynamic list's filters in place (full replace) |
| Lifecycle (delete is a verified soft-delete) |
| Manual membership, verified per record |
CRM (crm/v3/objects)
Tool | What it does |
| Query / by-ID / structured |
| One record with optional properties + associations |
| Patch a record, verified by readback |
| Associated records of another object type |
A worked example: an agent builds a nurture from one prompt
"Enroll trial contacts who haven't activated into a 3-step nurture, and mark them converted when they activate."
crm.search { objectType: "contacts", count: true, → total: 4,812 (sizing the audience)
filterGroups: [{ filters: [
{ propertyName: "lifecyclestage", operator: "EQ", value: "trial" },
{ propertyName: "activated", operator: "NEQ", value: "true" } ] }] }
workflows.create_manual { name: "Trial → Activation Nurture" } → id 1234567890, verified
workflows.set_enrollment_criteria { workflowId: "1234567890", ... } → verified
workflows.set_actions { workflowId: "1234567890", actions: [email, delay, email, delay, email] } → verified
workflows.set_goal_criteria { workflowId: "1234567890", → verified
goalFilterBranch: { activated EQ "true" } }
workflows.set_enabled { workflowId: "1234567890", isEnabled: true } → verifiedEach step returns audit.verified: true only after the change is re-read from HubSpot. If set_enrollment_criteria had stored an "always false" branch, the agent could catch it before turning the flow on.
The filter-validation gotcha (the most useful thing I learned)
HubSpot will accept and store an invalid filterBranch with a 200, then silently treat it as always false — the workflow enrolls no one and gives no error. You cannot trust the write echo.
The reliable validation is to create a throwaway dynamic list with the same branch: a list returns precise per-filter validation errors and a real member count. Confirm the count is sane, then apply the branch to the workflow and delete the probe list. lists.create + lists.get + lists.delete exist partly to make this loop cheap.
Setup
npm install
cp .env.example .env # then paste your HubSpot private-app token
npm run build # compiles src/ -> dist/
npm start # runs the MCP server over stdioRegister it with any MCP client (e.g. Claude Desktop / Claude Code):
{
"mcpServers": {
"hubspot-operator": {
"command": "node",
"args": ["/absolute/path/to/hubspot-mcp-operator-demo/dist/server.js"]
}
}
}⚠️ The write tools mutate real HubSpot objects. Point this at a test/sandbox portal, and scope the private-app token to only what you need.
Layout
src/
server.ts MCP bootstrap — registers all 24 tools, one envelope renderer
hubspot.ts the single fetch choke point + typed HubSpotApiError
config.ts .env loading + requireEnv
types.ts ToolEnvelope / ToolAudit — the shared contract
utils.ts envelopes, exact-match targeting, read-modify-write sanitizers
workflows.ts the 11 flow tools (the centerpiece)
lists.ts the 9 list tools, incl. per-record membership verification
crm.ts the 4 CRM tools, incl. count-mode searchTech
TypeScript (strict, NodeNext ESM) · @modelcontextprotocol/server · zod for tool input schemas · HubSpot REST v3/v4. No build step beyond tsc.
License
MIT — see LICENSE.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
CRM + visual automation builder AI agents can drive via MCP: contacts, tags, maps, email/SMS flows.
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Marketing MCP: content, SEO, outbound, LinkedIn, ads. Agents provision a sandbox with one POST.
Human-in-the-loop review and approval for AI agents. Audit trail, approval policies, native MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI clients to seamlessly take HubSpot actions and interact with HubSpot data, allowing users to create/update CRM records, manage associations, and gain insights through natural language.2220MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with HubSpot CRM for managing contacts, companies, deals, and sending emails through natural language commands.275MIT
- AlicenseAqualityBmaintenanceEnables interaction with HubSpot CRM through MCP, providing tools to manage contacts, companies, deals, and search/associations via natural language.18275MIT
- AlicenseAqualityBmaintenanceEnables AI agents to safely operate HubSpot CRM contacts, deals, and pipelines via MCP, with caching, idempotency, audit trails, and robust error handling.15MIT
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/holmjames/hubspot-mcp-operator-demo'
If you have feedback or need assistance with the MCP directory API, please join our Discord server