HubSpot
HubSpot MCP for Faster Ops and AI Automation
How we wired HubSpot into Cursor with MCP — service keys, pipelines, and AI agents that can read and write CRM data without leaving the IDE.
Most CRM work is still copy-paste: open HubSpot, find a deal, rename a stage, check a pipeline, paste an ID into .env. That loop is slow — and it breaks the moment your AI coding agent cannot see the CRM.
We fixed that at ScaleMorph by connecting HubSpot to Cursor through MCP (Model Context Protocol). The agent can query pipelines, inspect scopes, and help wire website → CRM without us tab-hopping for every ID. This post is what we learned setting it up on HubSpot Free.
What MCP changes
MCP is a standard way for AI tools to call external systems with structured tools — not scraped UI, not “paste this curl yourself.”
With HubSpot MCP connected:
- You ask in natural language: “List deal pipelines and stages.”
- The agent calls HubSpot APIs through the MCP server.
- You stay in the IDE where the website and env files already live.
That is the ops win: CRM context next to the code that creates leads.
Two HubSpot MCP flavors (pick the right one)
| Server | Best for | Auth |
|---|---|---|
Local @hubspot/mcp-server |
CRM read/write from Cursor with a service key | PRIVATE_APP_ACCESS_TOKEN |
Remote mcp.hubspot.com |
OAuth connector apps | MCP connector + PKCE |
HubSpot Developer MCP (hs mcp) |
Building HubSpot apps / CMS | CLI / projects |
For a software house running a custom Next.js site → HubSpot Free, the local server + service key is the practical path. HubSpot is sunsetting new legacy private apps; service keys are the replacement for system-to-system tokens.
We skipped the remote OAuth connector for day one — Cursor’s OAuth redirect has been unreliable with HubSpot’s HTTPS-only callback rules. Local stdio MCP avoids that.
Setup that actually connects in Cursor
1. Create a HubSpot service key
In HubSpot: Development → Legacy apps → Create service key.
Minimum scopes for lead capture + pipeline hygiene:
- Contacts: read + write
- Deals: read + write
- Deals schema write (
crm.schemas.deals.write) if the agent should rename pipeline stages
Copy the key once. Store it in .env as HUBSPOT_ACCESS_TOKEN (never commit it).
2. Point Cursor at a real Node binary
A common failure: Cursor’s bundled npx crashes with:
ENOENT: .../Cursor.app/Contents/Resources/app/resources/lib
Fix: install @hubspot/mcp-server locally and launch it with your nvm Node 22 path — not bare npx.
Example project config (.cursor/mcp.json, gitignored):
{
"mcpServers": {
"hubspot": {
"command": "/path/to/.nvm/versions/node/v22.x.x/bin/node",
"args": [
"/path/to/project/.cursor/hubspot-mcp/node_modules/@hubspot/mcp-server/dist/index.js"
],
"env": {
"PRIVATE_APP_ACCESS_TOKEN": "pat-..."
}
}
}
}
Restart Cursor → Settings → Tools & MCP → enable hubspot until it shows connected.
3. Prove the link
Ask the agent to list deal pipelines. You should see labels and stage IDs without opening HubSpot. Those IDs go straight into env:
HUBSPOT_PIPELINE_ID=default
HUBSPOT_STAGE_NEW_ID=appointmentscheduled
Faster ops: what we used it for
Pipeline naming without the UI slog.
Default HubSpot stages (“Appointment Scheduled”, “Qualified To Buy”) do not match how a consultancy sells. With schema write scope, we renamed the default pipeline to Website inbound and stages to:
New lead → Qualified → Discovery booked → Proposal → Won / Lost
(IDs stay stable when you only rename labels — important for the website API.)
Env wiring while coding.
The next engineering card is form submit → create contact + deal in New lead. Having pipeline and stage IDs verified from the same chat session removes a whole class of “wrong stage ID in production” bugs.
Scope debugging.
When a rename failed, the API returned MISSING_SCOPES with crm.schemas.deals.write. That feedback loop is faster than guessing which checkbox HubSpot wants.
AI automation without losing judgment
MCP does not mean “let the model run the company.” Treat it like a junior ops operator with a checklist:
| Allow | Require a human |
|---|---|
| List pipelines, contacts, deals | Mass deletes |
| Rename stages you already designed | Changing closed-won logic |
| Draft a test contact for a form QA | Live customer outreach |
Pull IDs into .env |
Spending / marketing blasts |
Writes should be explicit (“rename these stages”) not ambient. Good MCP servers already warn on data modification — keep that habit even if the tool does not.
Where this fits a lead-engine cycle
Our sequence for scalemorph.com:
- Choose CRM + public
contact@fallback - Authenticate email (SPF / DKIM / DMARC)
- Connect HubSpot MCP so ops and code share one source of truth
- Build contact form API → HubSpot +
/thanks - Only then: campaigns, enrichment, paid traffic
MCP accelerates step 3–4. It does not replace a clear pipeline or a company inbox.
Practical checklist
- Service key with contacts + deals (+ schemas write if automating pipeline edits)
- Token in local
.env/ MCP env — never in git - Cursor MCP uses absolute Node path (avoid broken Cursor
npx) - Green “connected” status under Tools & MCP
- Pipeline labels match how sales actually works
- Website form writes to the New lead stage ID you verified via MCP
Closing
HubSpot MCP is not a magic CRM. It is a short cable between the place you sell (HubSpot) and the place you build (Cursor). For a small software house, that cable means fewer tabs, fewer wrong IDs, and an AI agent that can help with ops without inventing a second system of record.
If you are wiring a marketing site into HubSpot and want the capture path production-ready, talk to ScaleMorph.



