Skip to main content
HubSpot The HubSpot connector exposes a HubSpot portal through the HubSpot REST API to Agent Factory agents (through MCP) and to Builder automations (through the Hubspot.op: App instructions) — covering the CRM (contacts, companies, deals, tickets, engagements, associations, pipelines, properties, owners, lists) and the Marketing layer (forms, marketing emails, workflows, files). The ~120 HubSpot operations are grouped into 18 entity tools, each driven by an action argument. The MCP server runs in the tenant app-instance context: it resolves the installing workspace’s own credentials and authorizes the calling agent against that workspace’s allowlist. Authentication supports several modes:
  • Per-user OAuth2 — central client (oauthCentral, recommended) — one HubSpot OAuth application is registered once by the platform maintainer; every end user signs in with their own HubSpot portal. Nothing to register per workspace: each one just installs the app and clicks Connect.
  • Per-user OAuth2 — tenant client (oauth) — paste your own HubSpot OAuth client ID/secret in the connector config app. Each user signs in with their own account against your client (authorization-code + PKCE flow).
  • Private App token (accessToken) — a caller-managed HubSpot Private App access token (PAT), used as-is with no exchange. Best for service-account / non-interactive automations where a single identity is preferable.

CRM Records

Contacts, companies, deals and tickets with list/search/get/create/update/archive plus batch and merge operations

Engagements & Marketing

Notes, tasks, calls, emails, meetings; pipelines, properties, owners, lists; forms, marketing emails, workflows and files

Per-user auth

Per-user OAuth (central or tenant client) resolved server-side, or a caller-managed Private App token

Who is this for?

This connector is used by three different roles. Jump to the section that matches yours — each one is self-contained.

Agent builder

You build agents in Agent Factory and want them to use HubSpot. → Agent builder tab.

Platform admin

You run the platform and set up the shared HubSpot OAuth client once for everyone. → Platform admin setup accordion below.

Workspace builder

You write Builder automations (DSUL) that call HubSpot operations directly. → Workspace builder tab.

Prerequisites

  • A HubSpot account with access to the portal you want to expose.
  • For the OAuth modes — a HubSpot OAuth application. HubSpot’s Developer Platform 2025.2 retired the legacy Public Apps UI: the OAuth app is now declared as code in a HubSpot project and deployed via the HubSpot CLI (from a free HubSpot developer account at developers.hubspot.com, separate from any CRM account). The platform maintainer registers one app for the central mode; a workspace can also register its own for the tenant mode. Copy the Client ID and Client Secret from the deployed app’s Auth tab.
  • For the Private App token mode — a Private App access token created at HubSpot Settings → Integrations → Private Apps (https://app.hubspot.com/private-apps/<portal-id>), with the scopes covering the operations you intend to call.
  • OAuth scopes — the connector requests the free-tier essentials by default (oauth, crm.objects.contacts.*, crm.objects.companies.*, crm.objects.deals.*, crm.objects.owners.read, tickets). Paid-tier features (lists, content, automation, forms, files) require their own scopes and a matching HubSpot subscription; every requested scope must be declared in the deployed app’s requiredScopes / optionalScopes.
  • Base URL: https://api.hubapi.com (single host).
Goal: two one-time tasks — (1) configure the shared central OAuth client so every workspace lets its users sign in with their own HubSpot portal, and (2) optionally expose HubSpot as a reusable capability in AI Governance so agent builders can pick it without pasting endpoint URLs. Throughout, <api-url> is your environment’s API URL (https://api.studio.prisme.ai/v2 on production).

1. Configure the connector

1

Register the OAuth application at HubSpot

Create a free HubSpot developer account, install the CLI (npm install -g @hubspot/cli@latest), then deploy the OAuth app project. The hubspot workspace ships ready-to-deploy projects under workspaces/hubspot/project/ (one per environment); each app-hsmeta.json declares the redirect URI, required and optional scopes. Set the single Authorized redirect URI to the core workspace callback:
<api-url>/workspaces/slug:hubspot/webhooks/oauthCallback
(e.g. https://api.studio.prisme.ai/v2/workspaces/slug:hubspot/webhooks/oauthCallback on production). Deploy with hs project upload && hs project deploy, allowlist the portals (numeric Hub IDs) that may install the app, then copy the Client ID and Client Secret from the app’s Auth tab (the secret is shown only once).
2

Enter the credentials through the configuration app

Open the central hubspot workspace and launch its Configuration app<studio>/apps/hubspot (e.g. https://studio.prisme.ai/apps/hubspot). Loaded from the core workspace, the app shows the maintainer view (org owner / editor / admin only); paste the Client ID and Client Secret there and Save — the app stores them in the core workspace’s secrets for you. Do not edit Studio’s raw Secrets by hand. These credentials stay in the hubspot workspace and are never exposed to tenants or end users; token exchange is proxied through the core centralTokenExchange webhook so the client secret never leaves the core workspace.
3

Tell workspaces to use the central client

Each consuming workspace selects auth mode oauthCentral in the connector configuration app (no client id/secret to enter on their side). Their users then just click Connect.
4

(Optional) Publish to the Capabilities catalog

From that same maintainer view, the Add to catalog button publishes HubSpot to the org-wide Capabilities catalog in one click (org owner / admin only; it stays disabled until the central client is saved). Once published, every agent builder in the org can enable HubSpot from the catalog without pasting an endpoint — see Option A in the Agent builder tab.

2. Declare the capability in AI Governance

As an alternative to (or in addition to) the catalog button, you can declare HubSpot as a named capability in AI Governance. Agent builders then enable that capability on their agents instead of pasting a raw MCP endpoint.
1

Open AI Governance > Capabilities

Create (or edit) the HubSpot capability.
2

Point it at the MCP endpoint

Set the capability’s MCP server URL to the connector’s MCP Endpoint, and set its Scope to:
context_id,agent_id,user_id
The agent_id in the scope is what lets the connector identify and authorize the calling agent.
3

Make it available to agent builders

Once created, the capability appears in the capability picker for agent builders in your organization, who enable it on their agents. Access to the catalog follows your organization’s existing roles; there is no per-capability role grant.
4

Smoke-test

From an agent that has the capability, in a workspace configured for oauthCentral, trigger any tool (e.g. contacts with action: "list"). The user is prompted to connect once (HubSpot sign-in, pick a portal); subsequent calls reuse the stored token transparently and refresh it automatically.
Declaring the capability makes the connector available; it does not by itself authorize a specific agent. This connector follows the tenant-context model — which agents may actually call it is gated per-workspace by the authorized-agents allowlist in the configuration app (see the Workspace builder tab). There is also no OAuth auth-config JSON to attach in Governance: connect / status / disconnect are handled by the connector’s own webhooks, wired automatically.
HubSpot scope handling has a strict OAuth-URL contract: the connector lists required scopes in scope= and optional scopes in optional_scope=, and every requested scope must already be declared in the HubSpot app’s requiredScopes or optionalScopes. Putting an optional-tier scope (Marketing Hub Pro+, CMS Hub, etc.) into scope= triggers a “domain mismatch” rejection. The shipped app-hsmeta.json keeps requiredScopes to the free-tier essentials; paid-tier scopes sit in optionalScopes. To add a scope, edit app-hsmeta.json for each environment and re-run hs project upload && hs project deploy.

Agent builder

Goal: let an agent you build in Agent Factory use HubSpot through MCP tools.
Before an agent can call the connector, a Workspace builder must have installed and configured the HubSpot app in a workspace (see the Workspace builder tab), and — for the central OAuth mode — a Platform admin must have provisioned the shared OAuth client (see the Platform admin setup accordion above).
This connector runs in the tenant app-instance context: your agent is authorized two ways at once — it is identified by the agent_id that Agent Factory injects through the capability Scope, and that agent must appear in the connector’s authorized-agents allowlist (managed in the configuration app). The HubSpot access token itself is resolved server-side from the configured auth mode.There are two ways to wire it up. Pick based on how much isolation you need.

Option A — Enable the shared capability from the catalog

The fastest path: a Platform admin has already published a HubSpot capability to the Capabilities catalog (see the Platform admin setup accordion above — the Add to catalog button, or §2), so you just pick it from the catalog.
1

Open your agent in Agent Factory

Open the agent you want to extend and go to its capabilities / tools.
2

Add the HubSpot capability

Browse the capability catalog, select HubSpot, and enable it. The MCP endpoint URL and the Scope (context_id,agent_id,user_id) are already wired by the admin — nothing to paste, and the shared instance accepts every agent, so there is no allowlist step on your side.
3

Connect a HubSpot account

On the first tool call, an unconnected user is prompted to sign in — Agent Factory surfaces a connect_url to HubSpot’s authorization page, where the user picks the portal to authorize (from the allowlisted set) and reviews the requested scopes. After sign-in the per-user token is stored and reused on subsequent calls.
Convenient, but your agent runs against a shared, platform-managed instance: its HubSpot credentials are owned by someone else and the instance accepts every agent that is granted the capability. Prefer Option B for anything beyond quick experiments.
For production agents, install the connector in your own workspace and point the agent at that workspace’s MCP endpoint.
Prefer this mode for security. Because the MCP runs in your app-instance context, the HubSpot credentials, the per-user OAuth tokens and the authorized-agents allowlist are all scoped to your workspace — not shared platform-wide. You decide exactly which agents may call it and which HubSpot account / auth mode backs them, and a misconfiguration elsewhere can never expose your data. The shared catalog capability (Option A) is a broad surface many agents can reach; your own workspace is an isolated, least-privilege boundary.
1

Install and configure the connector in your workspace

Follow the Workspace builder tab: install HubSpot in your workspace, open its Configuration app, choose the auth mode and connect a HubSpot account (or paste a Private App token).
2

Allowlist your agent

In that workspace’s config app, open Authorized agents and tick your agent (the Install capability button does this for you), or enable Allow all agents.
3

Add the MCP capability to your agent

In your agent, add a capability pointing at your workspace’s MCP Endpoint URL, and set its Scope to:
context_id,agent_id,user_id
The agent_id is what lets the connector identify and authorize your agent — without it, every call is rejected with an explicit “agent could not be identified” message. This Scope is separate from the HubSpot OAuth scopes.
4

Connect a HubSpot account

On the first tool call, the user is prompted to sign in (or uses Connect in the config app). The per-user token is stored and reused; refresh is automatic.

Brief the agent in its system prompt

Whichever option you pick, wiring the capability is not enough — the agent must know the connector exists and when to reach for it. Add a short paragraph to the agent’s system prompt. Copy-pasteable starter:
You have access to the HubSpot MCP server. Use it whenever the user asks about CRM data — contacts, companies, deals, tickets, engagements, pipelines or marketing assets (forms, emails, workflows). Each tool is an entity that takes an `action` argument. Always prefer `action: search` over `action: list` for filtered lookups. For batch work, use the `batch*` actions instead of looping individual calls. Always confirm with the user before destructive actions (archive, delete, batchArchive, unenrollContact, removeMembers).
Refine the trigger keywords (resource names, business domains, typical user phrasings) so the agent reliably picks up the right intent in your context.
Legacy AI Knowledge agents (no native MCP picker): add the connector under Advanced > Tools > MCP and paste the MCP Endpoint URL. The agent still has to be allowlisted in the config app and its identity propagated so the connector can read its agent_id.
Restricting to read-only (least privilege). HubSpot tools cover both reads and writes (create/update contacts, companies, deals). The requested OAuth scopes are the grant. To allow only read access, set the Scopes field in the configuration app to the read-only set, dropping every *.write scope, e.g.:
oauth crm.objects.contacts.read crm.objects.companies.read crm.objects.deals.read crm.objects.owners.read tickets
With central OAuth (oauthCentral) you do not create your own HubSpot app — keep oauthCentral and enter the read scopes; your tenant scope overrides the platform default (the central app must list these read scopes). Write calls are then rejected by HubSpot with 403. The scope is set at the workspace level (a workspace editor can widen it again).

Available Tools

The MCP server exposes 18 entity-level tools, each with an action argument to select the operation. Every tool accepts an outputFormat parameter (see Output Formats).

contacts / companies / deals

These three CRM tools share the same set of actions.
ActionDescription
listList records with pagination and property selection
getRetrieve a single record by id (or by idProperty)
createCreate a record with properties and optional associations
updateUpdate a record by id
archiveArchive (soft-delete) a record
searchFull-text and structured search with filter groups, sorts and a query shortcut
mergeMerge two records into one (primaryObjectIdobjectIdToMerge)
batchReadRead up to 100 records at once
batchCreateCreate up to 100 records in one call
batchUpdateUpdate up to 100 records in one call
batchArchiveArchive up to 100 records in one call

tickets

Same actions as the CRM trio above, minus merge.

associations

ActionDescription
listList associations from a record to a target object type
createCreate an association between two records
archiveRemove an association between two records

notes / tasks / calls / engagementEmails / meetings

All five engagement tools share the same actions.
ActionDescription
listList engagements
getRetrieve a single engagement
createCreate an engagement, optionally with associations to CRM records
updateUpdate an engagement
archiveArchive an engagement

pipelines

ActionDescription
listList pipelines for an object type
getRetrieve a pipeline
createCreate a pipeline
updateUpdate a pipeline
archiveArchive a pipeline
listStagesList the stages of a pipeline
getStageRetrieve a stage
createStageAdd a stage to a pipeline
updateStageUpdate a stage
archiveStageArchive a stage

properties

ActionDescription
listList properties for an object type
getRetrieve a property
createCreate a property
updateUpdate a property
archiveArchive a property
listGroupsList property groups for an object type
createGroupCreate a property group
updateGroupUpdate a property group
archiveGroupArchive a property group

owners

ActionDescription
listList owners (optionally filter by email)
getRetrieve an owner by id

lists

ActionDescription
createCreate a list
getRetrieve a list (optionally with filters)
updateRename a list
deleteDelete a list
searchSearch lists by name and processing type
addMembersAdd records to a static list
removeMembersRemove records from a static list
getMembershipsList the members of a list

forms

ActionDescription
listList marketing forms
getRetrieve a form
createCreate a form
updateUpdate a form
archiveArchive a form
submitSubmit values to a form on behalf of a visitor

marketingEmails

ActionDescription
listList marketing emails
getRetrieve a marketing email
createCreate a marketing email
updateUpdate a marketing email
archiveArchive a marketing email
sendTransactionalSend a transactional single-send email to a recipient

workflows

ActionDescription
listList workflows
getRetrieve a workflow
enrollContactEnroll a contact in a workflow by email
unenrollContactUnenroll a contact from a workflow by email

files

ActionDescription
listList files
getRetrieve file metadata
getSignedUrlCreate a signed URL to download a file
archiveArchive a file
importFromUrlImport a file from a public URL
listFoldersList folders
createFolderCreate a folder
archiveFolderArchive a folder

Output Formats

Every tool accepts an outputFormat parameter that controls the MCP response shape:
  • verbose (default) — human-readable text for LLM consumption
  • structured — machine-readable JSON in structuredContent
  • both — both text and structured content

Tool Details

{
  "name": "contacts",
  "arguments": {
    "action": "search",
    "filterGroups": [
      {
        "filters": [
          { "propertyName": "email", "operator": "EQ", "value": "alice@acme.com" }
        ]
      }
    ],
    "properties": ["email", "firstname", "lastname", "lifecyclestage"],
    "limit": 1
  }
}
ParameterRequiredDescription
actionYesMust be search
filterGroupsNoArray of { filters: [{ propertyName, operator, value }] }. Filters inside a group are AND’d; groups are OR’d
sortsNoArray of { propertyName, direction }
queryNoFree-text query alternative to filterGroups
propertiesNoProperties to include in the response
limitNoPage size (max 100)
afterNoCursor from a previous response (paging.next.after)

deals (action: create)

{
  "name": "deals",
  "arguments": {
    "action": "create",
    "properties": {
      "dealname": "Acme — annual contract",
      "amount": "120000",
      "dealstage": "appointmentscheduled",
      "pipeline": "default",
      "closedate": "2026-09-30"
    },
    "associations": [
      {
        "to": { "id": "11223344" },
        "types": [
          { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 5 }
        ]
      }
    ]
  }
}
ParameterRequiredDescription
actionYesMust be create
propertiesYesMap of HubSpot deal properties
associationsNoOptional list of association targets ({ to.id, types: [{ associationCategory, associationTypeId }] })

lists (action: addMembers)

{
  "name": "lists",
  "arguments": {
    "action": "addMembers",
    "listId": "12345"
  }
}
ParameterRequiredDescription
actionYesMust be addMembers
listIdYesTarget list ID (only valid for static / MANUAL lists)

marketingEmails (action: sendTransactional)

{
  "name": "marketingEmails",
  "arguments": {
    "action": "sendTransactional",
    "emailId": "67890",
    "message": {
      "to": "alice@acme.com",
      "from": "noreply@acme.com"
    },
    "contactProperties": { "firstname": "Alice" },
    "customProperties": { "orderId": "ORD-12345" }
  }
}
ParameterRequiredDescription
actionYesMust be sendTransactional
emailIdYesThe single-send email template ID
messageYes{ to, from, cc, bcc, replyTo, sendId }
contactPropertiesNoProperties to set on the contact for personalization
customPropertiesNoCustom merge tags resolved inside the email body

workflows (action: enrollContact)

{
  "name": "workflows",
  "arguments": {
    "action": "enrollContact",
    "workflowId": "98765",
    "email": "alice@acme.com"
  }
}
ParameterRequiredDescription
actionYesMust be enrollContact
workflowIdYesTarget workflow
emailYesEmail of the contact to enroll

Error Handling

HTTP StatusMeaningTypical Cause
400Bad RequestInvalid property value, malformed filterGroups, missing required field
401UnauthorizedMissing / invalid PAT or OAuth token, revoked refresh token
403ForbiddenThe token lacks the required scope, or the portal does not have the feature enabled (Marketing Hub Pro+, etc.)
404Not FoundRecord / list / workflow / form does not exist (or was archived)
409ConflictUnique-property collision (e.g. a contact with the same email already exists)
429Rate LimitedPer-portal quota exceeded — back off using the X-HubSpot-RateLimit-Secondly-Remaining headers
500 / 502 / 503Server ErrorTransient HubSpot API error — retry with exponential backoff

Common Issues

“This agent is not authorized to use this connector” — The calling agent is not in the allowlist. Open the configuration app → Authorized agents → tick this agent (id is shown in the error) or enable Allow all agents, and Save. The Install capability button does this for you. “The calling agent could not be identified” — The MCP capability Scope does not declare agent_id, so Agent Factory never injects the agent identity. Set the Scope to context_id,agent_id,user_id on the capability (this is separate from the HubSpot OAuth scopes), then allow the agent in the config app. “HubSpot is not connected for this user” — No per-user OAuth token is stored for the caller. Open the configuration app (OAuth mode) and click Connect, or use the agent’s connect flow. “HubSpot token refresh failed … must reconnect” — The stored refresh token was rejected by HubSpot (revoked, or expired after ~6 months idle). The connection is dropped automatically; the user must reconnect from the config app. “HubSpot OAuth is not configured” — Neither a tenant OAuth client nor the central platform client is available. Set the OAuth client ID/secret in the config app (tenant mode), or ask the platform maintainer to provision the central OAuth client from the core workspace’s config app. invalid_scope / “domain mismatch” during the OAuth dance — The OAuth URL requests a scope the deployed HubSpot app does not declare. Every requested scope must appear in requiredScopes or optionalScopes of app-hsmeta.json; re-run hs project upload && hs project deploy after editing. OBJECT_ALREADY_EXISTS on contact create — A contact with the same email already exists. Either update the existing contact (use email as idProperty) or query first with search. Lists API: cannot add members to a dynamic list — Only static / MANUAL lists accept addMembers and removeMembers. Dynamic lists are driven by their filter criteria. No token revocation — HubSpot exposes no RFC 7009 revocation endpoint, so disconnecting deletes the platform-stored tokens rather than revoking them at HubSpot — refresh tokens may stay valid until they naturally expire (typically 6 months idle).

External Resources

HubSpot Developer Docs

Official HubSpot REST API reference

HubSpot OAuth scopes

Required vs optional scopes, scope-tier matrix, scope group reference

Tool Agents

Learn how Agent Factory agents consume MCP tools in Prisme.ai.