Announcing CIMD support for MCP Client registration
Learn more

HubSpot MCP server: setup, MCP connectors and per-user access

Diagram: Claude Code, Cursor and Codex reach HubSpot's MCP server with an MCP connector's client ID, while a product's agent reaches it per user through Scalekit
Nityashree Yadunath
Product Marketing Manager

The HubSpot MCP server is HubSpot's official remote MCP server at https://mcp.hubspot.com. It acts as the HubSpot user who signs in through OAuth 2.1 with PKCE, and it respects that user's permissions, so an agent can only read and change records the user can already reach. HubSpot made it generally available to all HubSpot accounts on April 13, 2026.

HubSpot's own AI connectors for Claude, ChatGPT, Gemini and Microsoft Copilot run on this server. Clients such as Claude Code, Cursor and Codex can also connect through an MCP connector you create in HubSpot. A product whose agent works in many customers' HubSpot accounts needs one more layer, because each user's tokens have to be stored, refreshed and revoked, which is the per-user side of MCP integrations.

TL;DR

  • HubSpot runs two MCP servers. The remote server at https://mcp.hubspot.com reads and writes CRM records, activities, content and campaigns. The developer MCP server runs locally through the HubSpot CLI and helps you build HubSpot apps and CMS assets.
  • The remote server has no dynamic client registration. Outside HubSpot's own AI connectors, you create an MCP connector under Development > MCP Connectors and give its client ID and secret to your client, with a redirect URL that matches it exactly.
  • Your own product's agent can use the same server per user. Scalekit AgentKit's hubspotmcp connection runs each user's sign-in, stores and refreshes their tokens, and serves HubSpot's tools from one MCP server URL with a short-lived session token per run.

What the HubSpot MCP server can read and write

HubSpot's MCP server documentation lists what an agent can reach:

  • Read. CRM records including contacts, companies, deals, tickets, leads, users, custom objects and segments; calls, emails, meetings, notes and tasks; blog posts, landing pages, site pages, campaigns and marketing events; content analytics; conversations from help desk and the conversations inbox; marketing email drafts and analytics. Revenue objects such as quotes, invoices, orders and subscriptions are in beta.
  • Create and edit. CRM records and custom object records, activities, landing pages, website pages and blog posts (including publishing), campaigns, marketing email drafts, pipelines, custom properties and static segments.

Tool availability depends on the account's subscription, the user's permissions and the account's configuration, so HubSpot recommends running get_user_details first: it returns the user, the account and read and write access per object. A few limits are worth knowing before you design around the server:

  • If an account has Sensitive Data turned on, activities and conversations are blocked through the MCP server. The restriction does not apply to HubSpot's standard CRM APIs.
  • The server is built on the CRM search API, which has no vector search. search_crm_objects takes up to five filter groups of six filters each and returns at most 200 results per page.
  • query_crm_data runs SQL with HubSpot extensions but does not support joins, subqueries or association traversal.
  • The AEO tools need Marketing Hub Professional or Enterprise, quotes need Revenue Hub Professional or Enterprise, and manage_website_page, manage_blog_post and render_asset are only available in Claude, ChatGPT and Gemini.

How it authenticates

A request without a token gets a 401 whose WWW-Authenticate header points to the server's protected resource metadata. That metadata names https://mcp.hubspot.com itself as the authorization server, which supports the authorization code grant with S256 PKCE and authenticates clients with a client secret in the request body. It publishes no registration endpoint, so a client cannot register itself. That is why HubSpot's setup starts with creating an MCP connector.

You don't define scopes on an MCP connector. HubSpot derives them from the tools the server has when a user installs the connector and from the permissions that user grants. When HubSpot adds tools that need new scopes, users who installed earlier have to reinstall to grant them; HubSpot's changelog notes that an existing app may show a REQUIRES_REAUTHORIZATION status for newly added object types.

Remote server or developer MCP server

Server
Runs on
Signs in with
Use it for
Remote HubSpot MCP server
HubSpot's infrastructure at https://mcp.hubspot.com
Each user's HubSpot sign-in (OAuth 2.1 with PKCE) through HubSpot's AI connectors or your MCP connector
Reading and writing CRM records, activities, content and campaigns as that user
Developer MCP server
Your machine, started by the HubSpot CLI
Your HubSpot CLI account, authorized with a personal access key
Building HubSpot apps, CMS templates, modules and serverless functions from your editor

Create an MCP connector

MCP connectors were called MCP Auth Apps when HubSpot introduced them, and some guides still use that name. To create one:

  1. In HubSpot, open Development and choose MCP Connectors in the left sidebar.
  2. Click Create MCP connector and enter a name, an optional description and icon, and one or more redirect URLs. The first redirect URL is the default.
  3. Open the connector's details page and copy the client ID and client secret.

Each client sends its own redirect URL during sign-in, and it has to match one on the connector exactly:

Client
Redirect URL to add to the MCP connector
Where the client ID and secret go
Claude Code
http://localhost:8080/callback, with the port you pass to --callback-port
--client-id and --client-secret flags
Cursor desktop
http://localhost:8787/callback
auth.CLIENT_ID and auth.CLIENT_SECRET in mcp.json
Cursor web and Cursor Agents
https://www.cursor.com/agents/mcp/oauth/callback
The same mcp.json entry
Codex
The exact URL that codex mcp add prints
--oauth-client-id and --oauth-client-secret flags
MCP Inspector
http://localhost:6274/oauth/callback/debug
The Inspector's OAuth settings
Scalekit AgentKit
The redirect URI shown on your hubspotmcp connection
The connection's client ID and client secret fields

During sign-in, the user selects which HubSpot account to connect and grants the connector's permissions. To test the connector first, run the MCP Inspector with the Streamable HTTP transport, the URL https://mcp.hubspot.com/ and your client ID and secret, then call get_user_details.

Add the HubSpot MCP server to Claude Code

If you use Claude with a paid plan, the quickest route is HubSpot's connector for Claude. In Claude, go to Settings, choose Customize, click Browse and search for HubSpot, then sign in and choose what the connector can access. A Super Admin, or a user with App Marketplace permissions, enables it in HubSpot first. Claude Code shows connectors you added in claude.ai when you log in to Claude Code with your claude.ai account.

To add the server under your own MCP connector, register http://localhost:8080/callback on the connector and pass its credentials. The --client-secret flag prompts for the secret with masked input, and Claude Code keeps it in your system keychain on macOS or a credentials file elsewhere:

claude mcp add --transport http \ --client-id YOUR_CLIENT_ID --client-secret --callback-port 8080 \ hubspot https://mcp.hubspot.com

Then run /mcp in Claude Code and finish the sign-in in your browser. claude mcp get hubspot shows whether the client ID, secret and callback port are configured. If you add https://mcp.hubspot.com without --client-id, sign-in fails with an error saying the auth server does not support dynamic client registration.

Add it to Cursor

Cursor reads static OAuth credentials from the auth object of a server entry. Put this in ~/.cursor/mcp.json for every project or .cursor/mcp.json for one, with the client ID and secret in environment variables:

{ "mcpServers": { "hubspot": { "url": "https://mcp.hubspot.com", "auth": { "CLIENT_ID": "${env:HUBSPOT_MCP_CLIENT_ID}", "CLIENT_SECRET": "${env:HUBSPOT_MCP_CLIENT_SECRET}" } } } }

Register http://localhost:8787/callback on the connector for the desktop app, and https://www.cursor.com/agents/mcp/oauth/callback as well if anyone signs in from the web or Cursor Agents. Then connect the server from Cursor's MCP settings.

Add it to Codex

Codex appends a server-specific ID to its OAuth callback for HubSpot, and it fills in the listener port at sign-in time unless you fix it. Set a fixed port and callback at the top of ~/.codex/config.toml first, so the redirect URL stays stable:

mcp_oauth_callback_port = 8765 mcp_oauth_callback_url = "http://127.0.0.1:8765/callback"

Then add the server with your connector's credentials:

codex mcp add hubspot --url https://mcp.hubspot.com \ --oauth-client-id "$HUBSPOT_MCP_CLIENT_ID" \ --oauth-client-secret "$HUBSPOT_MCP_CLIENT_SECRET"

Codex prints a line starting with OAuth callback URL, followed by the full URL, in the form http://127.0.0.1:8765/callback/<id>. Add that exact URL to the connector's redirect URLs before you sign in, then run codex mcp login hubspot. Codex stores the secret in config.toml, so keep that file private and out of version control. To have Codex ask before any tool the server does not mark read-only, add default_tools_approval_mode to the [mcp_servers.hubspot] table that codex mcp add wrote:

[mcp_servers.hubspot] url = "https://mcp.hubspot.com" default_tools_approval_mode = "writes"

Set up the developer MCP server

The developer MCP server became generally available on February 19, 2026. It needs HubSpot CLI 8.2.0 or later, and hs mcp setup adds it to Claude Code, Codex, Cursor, Gemini CLI, VS Code or Windsurf as a server named HubSpotDev:

npm install -g @hubspot/cli hs --version hs mcp setup

Setup asks whether to use standalone mode, which runs the server through npx @hubspot/cli instead of a global install and suits machines where global npm installs are restricted. Its tools search and fetch HubSpot's developer docs, create, validate, upload and deploy projects, read build logs and create CMS templates, modules and serverless functions. It authenticates through your HubSpot CLI account with a personal access key. Older tutorials point to the @hubspot/mcp-server npm package, a beta that ran with a private app access token; its last release, 0.4.0, dates from June 2025.

Official, self-hosted or managed: which to use

Option
Runs on
Credential
Better fit when
HubSpot's remote MCP server
HubSpot's infrastructure
Each user's own HubSpot sign-in, through HubSpot's AI connectors or your MCP connector
People work in Claude, ChatGPT, Gemini, Copilot, Claude Code, Cursor or Codex against their own HubSpot account
Self-hosted community server
Your machine, over stdio
A private app access token in an environment variable
One developer needs REST endpoints the hosted tools don't cover, in an account where they are a Super Admin
Managed per-user server
The vendor's infrastructure
Each end user's HubSpot OAuth tokens, stored and refreshed by the vendor
Your product's agent works in many customers' HubSpot accounts

HubSpot's remote server is the right default for anyone working in their own AI client. HubSpot's AI connectors page makes the case directly under the heading "Write-back without the wrapper": agents get read and write access without a custom development layer, permissions come from HubSpot, and every write is attributed in the audit log. New tools arrive without changes on your side.

Community servers wrap the REST API instead. shinzo-labs/hubspot-mcp is MIT-licensed, runs through npx @shinzolabs/hubspot-mcp with a HUBSPOT_ACCESS_TOKEN environment variable, and lists OAuth as a planned enhancement. Its README also says it collects anonymous telemetry, with an opt-out. HubSpot now files private apps under Legacy apps, and creating one requires a Super Admin. A private app token works for the app across the account with the scopes you chose, so it suits one developer's tooling better than a team of users. HubSpot's Agent CLI, in beta, is HubSpot's own terminal tool for bulk updates and CRM clean-up, with a dry-run mode that previews every change.

HubSpot MCP vs API compares the two surfaces for agents in more detail. In short, interactive assistants fit the MCP server, while background jobs and work the MCP tools don't cover fit the REST API, and a product with many users needs per-user credentials on either path.

Connect your own agent for many HubSpot accounts

HubSpot built MCP connectors for ecosystem partners as well as customers, and each user picks the HubSpot account to connect during sign-in. That makes the remote server usable from a product that serves many companies. This differs from HubSpot's REST OAuth in one important way. The MCP server limits every action to what the signed-in user can see and edit. A REST OAuth access token reflects the app's scopes, so HubSpot's OAuth guide notes that a user who can only view their own contacts, but authorizes the contacts read scope, produces a token that can view every contact in the account.

Built by hand against the MCP server, per-user access looks like this:

  1. Create one MCP connector with your product's redirect URL.
  2. Send each user through the authorization code flow with PKCE, and exchange the code with your client secret.
  3. Store each user's access and refresh tokens encrypted, keyed by your user ID.
  4. Refresh with the refresh token when the access token expires. If the refresh token has expired or been invalidated, the user has to sign in again.
  5. Track reinstall prompts when HubSpot adds tools that need new scopes.
  6. Delete the tokens when the user disconnects.

Per-user OAuth for MCP integrations covers this design and its failure modes in more depth.

With Scalekit AgentKit

AgentKit is an MCP gateway that runs each user's OAuth flow, stores their tokens encrypted with AES-256-GCM under a key per environment, refreshes them and calls tools as that user. It has two HubSpot connections:

Connection
What it calls
Better fit when
hubspotmcp
HubSpot's remote MCP server, with 28 tools: 20 read, 5 write and 3 destructive
You want HubSpot's own tools, its confirmation step on writes, and access limited to each user's HubSpot permissions
hubspot
HubSpot's REST APIs, with 457 tools: 198 read, 179 write and 80 destructive
You need batch creates, upserts and archives, batch associations, or endpoints the MCP server doesn't expose

For the HubSpot MCP connector, Scalekit's own OAuth credentials are available, so you can start without creating an MCP connector. To show your own app on HubSpot's consent screen, create an MCP connector, add the redirect URI from your Scalekit connection to it, and paste the connector's client ID and secret into the connection. Every connection has its own MCP server, at your environment URL followed by /mcp/v3/connections/ and the connection name, so there is nothing else to create.

Once per user: send an authorization link.

import os from scalekit import ScalekitClient actions = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ).actions CONNECTION = "hubspotmcp" # the name of your HubSpot MCP connection user_id = "user_123" # your app's stable ID for this user link = actions.get_authorization_link( connection_name=CONNECTION, identifier=user_id ) print("Send the user this link:", link.link)

Before each run: mint a session token. This one is read-only and lasts 30 minutes.

from datetime import timedelta session = actions.mcp.create_session_token( connection_name=CONNECTION, identifier=user_id, expiry=timedelta(minutes=30), access_level="READ_ONLY", ) env_url = os.environ["SCALEKIT_ENVIRONMENT_URL"] server_url = f"{env_url}/mcp/v3/connections/{CONNECTION}"

During the run: connect any MCP client with the server URL and the session token as a bearer header. With the Python MCP SDK (version 2):

import asyncio import httpx2 from mcp import Client from mcp.client.streamable_http import streamable_http_client async def run(): headers = {"Authorization": f"Bearer {session.token}"} async with httpx2.AsyncClient(headers=headers, timeout=60) as http: transport = streamable_http_client(server_url, http_client=http) async with Client(transport) as mcp: tools = await mcp.list_tools() print([tool.name for tool in tools.tools]) result = await mcp.call_tool( "hubspotmcp_get_user_details", {} ) print(result.is_error, result.content) asyncio.run(run())

Scalekit checks the token, finds that user's HubSpot account and calls HubSpot's server with it, so your agent never receives the user's HubSpot tokens. How session tokens behave:

  • A token is bound to one user and one server. Sent to any other server URL, it returns 401.
  • It lasts one hour by default, and you can set anything from 60 seconds to 24 hours.
  • It is short-lived by design and is not refreshed. Mint a new one per run or per chat session. A new token does not revoke earlier ones.
  • With access_level="READ_ONLY", the run sees only tools annotated read-only, so hubspotmcp_manage_crm_objects and the other write tools are left out and refused if called.

When an agent needs a few tools from several apps, a Virtual MCP server lets you choose them and share one URL across users in the same way. To revoke one user, delete their connected account; their next call fails until they authorize again, and other users keep working:

actions.delete_connected_account( connection_name=CONNECTION, identifier=user_id )

For a framework walkthrough on the hubspot connection, see building a LangChain agent for multiple HubSpot users.

Security notes

  • Start with read access. Most CRM questions only need search and reads. Use read-only session tokens until a workflow needs writes, and give write runs their own token.
  • Pass write approval through. HubSpot's write tools ask for explicit user confirmation before a create or update. On manage_crm_objects that confirmation is a confirmationStatus argument, either CONFIRMED or CONFIRMATION_WAIVED_FOR_SESSION, which the agent fills in. In your own product, show the proposed change to the user and set that value only after they approve.
  • Require approval in clients. Records, notes and emails in a CRM contain text written by other people, so a hidden instruction should not be able to change a deal without a person approving it. Cursor asks before every MCP tool call by default. In Codex, default_tools_approval_mode = "writes" prompts for tools not marked read-only. In Claude Code, an ask rule for mcp__hubspot__manage_* makes HubSpot's write tools wait for you on a server you added as hubspot, as in the settings example below.
  • Plan for Sensitive Data accounts. In accounts with Sensitive Data turned on, activities and conversations are not available through the MCP server, so an agent that summarises calls or emails needs the REST API there.
  • Keep secrets out of config you share. Use environment variables in Cursor, and keep Codex's config.toml private, since it holds the client secret.
  • Know how to revoke. Users can disconnect the connector in their HubSpot settings. With Scalekit, deleting a connected account removes one user's access without touching anyone else's.

The Claude Code ask rule goes in your settings.json, or you can add it from /permissions:

{ "permissions": { "ask": ["mcp__hubspot__manage_*"] } }

FAQs

Is the HubSpot MCP server free?

HubSpot made the remote server generally available to all HubSpot accounts. HubSpot says its connector for Claude is free to install and works on all HubSpot tiers, including Free, with a paid Claude plan. Some tools need specific subscriptions, such as Marketing Hub Professional or Enterprise for AEO tools and Revenue Hub Professional or Enterprise for quotes.

Is the HubSpot MCP server still in beta?

No. The remote server moved out of beta on April 13, 2026, and the developer MCP server became generally available on February 19, 2026. Revenue objects such as quotes, invoices and subscriptions are still in beta on the remote server.

Does the HubSpot MCP server support custom objects?

Yes. HubSpot lists custom objects among the CRM records the server can read, and custom object records among those it can create and edit. Run get_user_details to see which objects your account and user can access.

Why does Claude Code say HubSpot does not support dynamic client registration?

HubSpot's authorization server does not let clients register themselves, so you need an MCP connector's client ID and secret. Create the connector under Development > MCP Connectors with the redirect URL http://localhost:8080/callback, then add the server with --client-id, --client-secret and --callback-port 8080.

What is the difference between the HubSpot MCP server and the developer MCP server?

The remote HubSpot MCP server at mcp.hubspot.com reads and writes an account's CRM data as the signed-in user. The developer MCP server runs locally through the HubSpot CLI and helps you build HubSpot apps, CMS assets and serverless functions.

Can my SaaS product use the HubSpot MCP server for its customers?

Yes. HubSpot built MCP connectors for ecosystem partners as well as customers, and each user picks the HubSpot account to connect during sign-in. Your product then has to store, refresh and revoke each user's tokens, which Scalekit's hubspotmcp connection does for you.

Details checked October 2026.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.