Contacts
3 tools- search_contacts readFree-text search across name, email, and company.
- get_contact readFetch one contact's full profile by ID.
- create_contact writeCreate a new contact record.
An MCP server that turns HubSpot contacts, deals, and support tickets into tools Claude can call directly — search, create, update, and one cross-object account brief. Built the way a client engineer ships a customer integration: authenticated, tested, and honest about its limits.
Teams that want Claude working against their own business systems need someone to build the bridge. This server is that bridge for HubSpot. It speaks the Model Context Protocol to Claude, and translates each tool call into a real, authenticated HubSpot API request.
Nothing here is simulated. Ask Claude to find a contact, move a deal to a new stage, open a support ticket, or summarize an account, and the change happens in the CRM — with the same auth, error handling, and association logic a production integration needs.
Every call is mediated, validated, and authenticated by the server, which is the only component that ever holds a credential.
The private-app token carries only contacts, deals, and tickets scopes, and lives in an environment variable — never hard-coded or logged.
Every tool input is validated with Zod before a request is built, so malformed calls fail fast with a clear message.
A HubSpot auth or API error round-trips as a tool-level error Claude can read and react to, rather than crashing the server.
The reason to put an MCP server in front of a CRM instead of just using its UI: contact, deals, and tickets fetched concurrently and returned as one readable brief Claude can reason over.
Illustrative output built from this project's own test fixtures.
The short version. The full HubSpot walkthrough covers accounts, scopes, and troubleshooting.
npm install npm run build
As a super admin: Development → Legacy apps → Create legacy app → Private, with read and write scopes for contacts, deals, and tickets. Step-by-step guide →
App → Auth tab → Show token. Pass it as HUBSPOT_ACCESS_TOKEN in your MCP config (next step) or export it in your shell.
Add this to your Claude Desktop or Claude Code MCP config:
{
"mcpServers": {
"hubspot-crm": {
"command": "node",
"args": ["/absolute/path/to/dist/index.js"],
"env": { "HUBSPOT_ACCESS_TOKEN": "your-token" }
}
}
}Run npm run inspector to open the official MCP Inspector and call each tool directly — no Claude client required.
Every tool's business logic is a standalone exported function, separate from its MCP
registration, so it can be unit-tested without spinning up a protocol transport. All 26 tests
run against a mocked fetch — CI never needs a live HubSpot credential.
The server was also verified end-to-end with a real MCP client over stdio, including a genuine HubSpot authentication error round-tripping cleanly back through the protocol as a tool-level error instead of a crash.