# HubSpot (npm · @mindstone/mcp-server-hubspot)

HubSpot CRM: contacts, deals, tickets, line items, properties, marketing, files, workflows, threads

- Trust score: 73/100 (medium)
- Change this week: +29
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- npm · `@mindstone/mcp-server-hubspot`: 73/100 (this document), [markdown](https://verifymcp.io/servers/mindstone-mcp-server-hubspot/mindstone-mcp-server-hubspot.md), [page](https://verifymcp.io/servers/mindstone-mcp-server-hubspot/mindstone-mcp-server-hubspot)

## Channel facts

- Registry: `npm`
- Package: `@mindstone/mcp-server-hubspot`
- Version: `0.3.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 87/100
  - No malware found by supply-chain analysis.
  - Only part of the dependency tree could be resolved (99 of 103), so this covers what we could see, not the whole tree.
  - No install/post-install scripts declared.
  - Only part of the dependency tree could be resolved (99 of 103), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 84/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to mindstone/mcp-servers).
  - License check failed: the license (FSL-1.1-MIT) isn't a recognized OSI-approved license.
  - Actively maintained (last published 3 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 61/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 15047 tokens (~158/item across 95 items; 95 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 23/100
  - Stability observed for 7 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 99/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 97% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add mindstone-mcp-server-hubspot -- npx -y @mindstone/mcp-server-hubspot
```

### Codex

```bash
codex mcp add mindstone-mcp-server-hubspot -- npx -y @mindstone/mcp-server-hubspot
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mindstone-mcp-server-hubspot": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@mindstone/mcp-server-hubspot"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add mindstone-mcp-server-hubspot --command npx --arg -y --arg @mindstone/mcp-server-hubspot
```

### Hermes

```yaml
mcp_servers:
  mindstone-mcp-server-hubspot:
    command: "npx"
    args: ["-y", "@mindstone/mcp-server-hubspot"]
```

### Other

```json
{
  "mcpServers": {
    "mindstone-mcp-server-hubspot": {
      "command": "npx",
      "args": [
        "-y",
        "@mindstone/mcp-server-hubspot"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-02 (score 73, +23)

- [security regression] Provenance: pass → unverified
- [security regression] Install scripts: pass → unverified
- [security regression] Stability: 0.17 → unverified
- [security improvement] Known CVEs: unverified → partial
- [security improvement] Malware scan: unverified → pass
- [security] The attested source repository moved: mindstone/mcp-servers
- [functional regression] Capabilities: pass → unverified
- [functional regression] License: fail → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Maintenance: pass → unverified
- [functional improvement] Dependency health: unverified → partial
- [functional] Licence: FSL-1.1-MIT

### 2026-08-01 (score 50, −10)

- [security regression] Known CVEs: partial → unverified
- [functional regression] Dependency health: partial → unverified

### 2026-07-31 (score 60, +34)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 26, +1)

- [security regression] Malware scan: pass → unverified
- [functional regression] Dependency health: partial → unverified
- [functional improvement] Tool coverage: unverified → 100
- [functional] Package version: 0.3.0 → 0.3.1

### 2026-07-29 (score 25, −19)

- [functional regression] Tool coverage: 100 → unverified
- [functional improvement] Dependency health: unverified → partial
- [functional] First check of Schema quality: unverified

### 2026-07-27 (score 44)

First indexed and scored.

## MCP tools (95)

### `list_hubspot_accounts` (~180 tokens)

List all connected HubSpot accounts and their authentication status.

ALWAYS call this FIRST before any HubSpot CRM operations to:
1\. Check if any HubSpot accounts are connected
2\. Verify authentication status (valid, expired, needs re-auth)
3\. Get the email address to use for subsequent operations

If no accounts are connected, guide the user to connect one using authenticate_hubspot_account.

Example workflow:
1\. User: "Show me my HubSpot contacts"
2\. Agent: Call list_hubspot_accounts first
3\. If accounts exist and valid → proceed with search_hubspot_contacts
4\. If no accounts → tell user to connect: "You need to connect your HubSpot account first. Would you like me to start the authentication?"
5\. If auth expired → call authenticate_hubspot_account to refresh

### `authenticate_hubspot_account` (~224 tokens)

Connect a new HubSpot account or re-authenticate an existing one.

This tool initiates the OAuth flow to connect a HubSpot account:
1\. Returns an authorization URL that the user must click
2\. User signs into HubSpot and grants permissions
3\. Authentication completes automatically via callback

WHEN TO USE:
\- When list_hubspot_accounts shows no connected accounts
\- When an account shows status "expired" or "error"
\- When user explicitly asks to connect/reconnect HubSpot

WHEN NOT TO USE:
\- If list_hubspot_accounts shows a valid, active account
\- Without checking list_hubspot_accounts first (wastes user time)

After calling this tool:
1\. Present the auth_url to the user as a clickable link
2\. Tell them to click it and authorize in their browser
3\. Call complete_hubspot_auth to wait for completion
4\. Or if auto_complete is enabled, it will complete automatically

Input parameters:

- `email` (string): Optional: Email hint for the account being connected (for display purposes)

### `complete_hubspot_auth` (~132 tokens)

Wait for HubSpot OAuth authorization to complete.

Call this AFTER authenticate_hubspot_account has returned an auth_url and the user has clicked it.

This tool:
1\. Waits for the OAuth callback (up to 2 minutes)
2\. Exchanges the authorization code for access tokens
3\. Saves the account credentials
4\. Returns success with the connected email

IMPORTANT: Only call this if auto_complete was false in authenticate_hubspot_account response.
If auto_complete was true, authentication completes automatically and you don't need this tool.

Input parameters:

- `email` (string): Email address of the account being authenticated

### `remove_hubspot_account` (~98 tokens)

Disconnect a HubSpot account and delete its stored credentials.

Use this when:
\- User wants to disconnect their HubSpot account
\- User wants to switch to a different HubSpot account
\- Troubleshooting authentication issues (remove and re-add)

This permanently removes the account's access tokens. The user will need to re-authenticate to use HubSpot again.

Input parameters:

- `email` (string, required): Email address of the HubSpot account to remove

### `search_hubspot_contacts` (~296 tokens)

Search for contacts in HubSpot CRM.

USE THIS WHEN:
\- User asks "find contact [name/email]" or "look up [person]"
\- Need to find a contact before updating, associating, or viewing details
\- Preparing for a meeting and need contact info

RETURNS: Array of contacts with id, properties (email, firstname, lastname, etc.)

EXAMPLES:
1\. Find by email: filters=[{propertyName:"email", operator:"EQ", value:"john@acme.com"}]
2\. Find by name: query="John Smith"
3\. Find by company: filters=[{propertyName:"company", operator:"CONTAINS_TOKEN", value:"Acme"}]

OPERATORS: EQ, NEQ, LT, LTE, GT, GTE, CONTAINS_TOKEN (partial match), IN (list)

COMMON PROPERTIES to request: email, firstname, lastname, phone, company, jobtitle, lifecyclestage, hubspot_owner_id

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria for precise matching
- `limit` (number): Max results (default 10, max 100)
- `properties` (array): Properties to return (default: basic info)
- `query` (string): Free-text search across name/email

### `get_hubspot_contact` (~104 tokens)

Get full details for a single contact by ID.

USE THIS WHEN:
\- You already have a contact ID (from search or association)
\- Need complete contact information
\- Preparing a detailed contact profile

RETURNS: Single contact object with all requested properties

PREREQUISITE: Get contactId from search_hubspot_contacts first

Input parameters:

- `contactId` (string, required): HubSpot contact ID (numeric string)
- `properties` (array): Properties to return

### `create_hubspot_contact` (~273 tokens)

Create a new contact in HubSpot CRM.

USE THIS WHEN:
\- User says "add contact" or "create contact for [person]"
\- Logging a new lead or prospect
\- Contact doesn't exist (verify with search first!)

REQUIRED: email (strongly recommended - used for deduplication)

NOTE: The server automatically sets hs_object_source_detail_2 for source attribution.

COMMON PROPERTIES:
\- email, firstname, lastname
\- phone, mobilephone
\- company, jobtitle
\- address, city, state, zip, country
\- lifecyclestage: "lead", "marketingqualifiedlead", "salesqualifiedlead", "opportunity", "customer"
\- hubspot_owner_id: assign to a team member (RECOMMENDED — get IDs from list_hubspot_owners)

COMMON MISTAKES:
\- NOT specifying hubspot_owner_id — if omitted, the contact may be assigned to the HubSpot integration account used by your host, not the intended owner. Use list_hubspot_owners to find the correct owner ID.
\- If list_hubspot_owners returns empty (e.g., free accounts), you may proceed without hubspot_owner_id.

RETURNS: Created contact with id and properties

Input parameters:

- `properties` (object, required): Contact properties object

### `update_hubspot_contact` (~106 tokens)

Update an existing contact's properties.

USE THIS WHEN:
\- User says "update contact" or "change [field] for [contact]"
\- Need to correct or add information
\- Changing lifecycle stage or owner assignment

PREREQUISITE: Get contactId from search_hubspot_contacts first

RETURNS: Updated contact object

Input parameters:

- `contactId` (string, required): HubSpot contact ID
- `properties` (object, required): Properties to update (only include changed fields)

### `delete_hubspot_contact` (~84 tokens)

Permanently delete a contact from HubSpot.

USE THIS WHEN:
\- User explicitly asks to delete/remove a contact
\- Cleaning up duplicate or test records

WARNING: This is permanent. Associated engagements may be orphaned.

PREREQUISITE: Get contactId from search_hubspot_contacts first

Input parameters:

- `contactId` (string, required): HubSpot contact ID

### `search_hubspot_companies` (~253 tokens)

Search for companies/organizations in HubSpot CRM.

USE THIS WHEN:
\- User asks "find company [name]" or "look up [organization]"
\- Need company info for account research
\- Finding companies to associate with contacts or deals

RETURNS: Array of companies with id, properties (name, domain, industry, etc.)

EXAMPLES:
1\. Find by name: query="Acme Corp"
2\. Find by domain: filters=[{propertyName:"domain", operator:"EQ", value:"acme.com"}]
3\. Find by industry: filters=[{propertyName:"industry", operator:"EQ", value:"COMPUTER_SOFTWARE"}]

COMMON PROPERTIES to request: name, domain, industry, numberofemployees, annualrevenue, phone, city, country, hubspot_owner_id

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10, max 100)
- `properties` (array): Properties to return
- `query` (string): Free-text search by company name

### `get_hubspot_company` (~95 tokens)

Get full details for a single company by ID.

USE THIS WHEN:
\- You have a company ID (from search or association)
\- Need complete company profile for account research

PREREQUISITE: Get companyId from search_hubspot_companies or get_hubspot_associations

Input parameters:

- `companyId` (string, required): HubSpot company ID (numeric string)
- `properties` (array): Properties to return

### `create_hubspot_company` (~241 tokens)

Create a new company in HubSpot CRM.

USE THIS WHEN:
\- User says "add company" or "create account for [organization]"
\- Company doesn't exist (verify with search first!)

REQUIRED: name

COMMON PROPERTIES:
\- name (company name)
\- domain (website domain, used for deduplication)
\- industry (e.g., "COMPUTER_SOFTWARE", "FINANCIAL_SERVICES")
\- numberofemployees, annualrevenue
\- phone, address, city, state, zip, country
\- hubspot_owner_id: assign to team member (RECOMMENDED — get IDs from list_hubspot_owners)

COMMON MISTAKES:
\- NOT specifying hubspot_owner_id — if omitted, the company may be assigned to the HubSpot integration account used by your host, not the intended owner. Use list_hubspot_owners to find the correct owner ID.
\- If list_hubspot_owners returns empty (e.g., free accounts), you may proceed without hubspot_owner_id.

RETURNS: Created company with id and properties

Input parameters:

- `properties` (object, required): Company properties object

### `update_hubspot_company` (~87 tokens)

Update an existing company's properties.

USE THIS WHEN:
\- User says "update company" or "change [field] for [company]"
\- Need to correct or add company information

PREREQUISITE: Get companyId from search_hubspot_companies first

Input parameters:

- `companyId` (string, required): HubSpot company ID
- `properties` (object, required): Properties to update

### `delete_hubspot_company` (~63 tokens)

Permanently delete a company from HubSpot.

WARNING: This is permanent and may affect associated contacts and deals.

PREREQUISITE: Get companyId from search_hubspot_companies first

Input parameters:

- `companyId` (string, required): HubSpot company ID

### `search_hubspot_deals` (~305 tokens)

Search for deals/opportunities in HubSpot CRM.

USE THIS WHEN:
\- User asks "find deal [name]" or "show my deals"
\- Need to check pipeline status
\- Looking for deals by stage, amount, or owner

RETURNS: Array of deals with id, properties (dealname, amount, dealstage, etc.)

EXAMPLES:
1\. Find by name: query="Acme Enterprise"
2\. Find by stage: filters=[{propertyName:"dealstage", operator:"EQ", value:"qualifiedtobuy"}]
3\. Find deals > $10k: filters=[{propertyName:"amount", operator:"GT", value:"10000"}]
4\. Find by owner: filters=[{propertyName:"hubspot_owner_id", operator:"EQ", value:"12345"}]

NOTE: dealstage values are IDs, not names. Use list_hubspot_pipelines to get valid stage IDs.

COMMON PROPERTIES: dealname, amount, dealstage, pipeline, closedate, hubspot_owner_id, hs_deal_stage_probability

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10, max 100)
- `properties` (array): Properties to return
- `query` (string): Free-text search by deal name

### `get_hubspot_deal` (~96 tokens)

Get full details for a single deal by ID.

USE THIS WHEN:
\- You have a deal ID (from search or association)
\- Need complete deal information including custom properties

PREREQUISITE: Get dealId from search_hubspot_deals or get_hubspot_associations

Input parameters:

- `dealId` (string, required): HubSpot deal ID (numeric string)
- `properties` (array): Properties to return

### `create_hubspot_deal` (~499 tokens)

Create a new deal/opportunity in HubSpot CRM.

USE THIS WHEN:
\- User says "create deal" or "add opportunity"
\- Logging a new sales opportunity

REQUIRED: dealname, hubspot_owner_id

IMPORTANT: Use list_hubspot_pipelines first to get valid pipeline and dealstage IDs!

FALLBACK FIELDS (set by the server only if not provided):
\- hubspot_owner_id: FALLBACK ONLY — if not provided via the top-level parameter, falls back to the HubSpot integration account used by your host. This is usually the WRONG person on team accounts.
\- hs_object_source_detail_2: records that this deal was created via your MCP host

COMMON PROPERTIES (inside the properties object):
\- dealname (deal/opportunity name)
\- amount (deal value as string, e.g., "10000")
\- pipeline (pipeline ID from list_hubspot_pipelines, e.g., "default")
\- dealstage (stage ID from list_hubspot_pipelines, e.g., "qualifiedtobuy")
\- closedate (expected close date, format: "YYYY-MM-DD")

WORKFLOW:
1\. list_hubspot_pipelines to get pipeline/stage IDs
2\. list_hubspot_owners to find the correct deal owner
3\. create_hubspot_deal with valid pipeline/stage IDs AND hubspot_owner_id
4\. create_hubspot_association to link to contact/company

COMMON MISTAKES:
\- Using this tool when the user says "lead" or "create a lead" — leads are a separate HubSpot object type. Use create_hubspot_lead instead.
\- NOT specifying hubspot_owner_id — if omitted, the deal is silently assigned to the HubSpot integration account used by your host, NOT the intended deal owner. This causes incorrect assignment notifications and pipeline confusion. ALWAYS call list_hubspot_owners to find the correct owner ID.
\- Using display names instead of IDs for pipeline/dealstage — always use list_hubspot_pipelines to get valid IDs first.

RETURNS: Created deal with id and properties

Input parameters:

- `hubspot_owner_id` (string, required): Owner ID for the deal (REQUIRED — get from list_hubspot_owners). If omitted, falls back to the integration account which is usually wrong for team accounts.
- `properties` (object, required): Deal properties object

### `update_hubspot_deal` (~152 tokens)

Update an existing deal's properties.

USE THIS WHEN:
\- User says "update deal" or "move deal to [stage]"
\- Changing deal amount, stage, or close date
\- Reassigning deal to different owner

COMMON UPDATES:
\- dealstage: move to different pipeline stage (use stage ID from list_hubspot_pipelines)
\- amount: update deal value
\- closedate: update expected close date
\- hubspot_owner_id: reassign to different team member

PREREQUISITE: Get dealId from search_hubspot_deals first

Input parameters:

- `dealId` (string, required): HubSpot deal ID
- `properties` (object, required): Properties to update

### `delete_hubspot_deal` (~65 tokens)

Permanently delete a deal from HubSpot.

WARNING: This is permanent. Deal history and associations will be lost.

PREREQUISITE: Get dealId from search_hubspot_deals first

Input parameters:

- `dealId` (string, required): HubSpot deal ID

### `search_hubspot_tickets` (~90 tokens)

Search for tickets in HubSpot with filters

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10)
- `properties` (array): Properties to return
- `query` (string): Search query text

### `get_hubspot_ticket` (~40 tokens)

Get a single ticket by ID

Input parameters:

- `properties` (array): Properties to return
- `ticketId` (string, required): HubSpot ticket ID

### `create_hubspot_ticket` (~60 tokens)

Create a new ticket in HubSpot.
    
    Common properties:
    - subject (required)
    - content
    - hs_pipeline
    - hs_pipeline_stage
    - hs_ticket_priority

Input parameters:

- `properties` (object, required): Ticket properties

### `update_hubspot_ticket` (~38 tokens)

Update an existing ticket

Input parameters:

- `properties` (object, required): Properties to update
- `ticketId` (string, required): HubSpot ticket ID

### `delete_hubspot_ticket` (~30 tokens)

Delete a ticket from HubSpot

Input parameters:

- `ticketId` (string, required): HubSpot ticket ID

### `search_hubspot_leads` (~292 tokens)

Search for leads in HubSpot CRM.

NOTE: Requires Sales Hub Professional or Enterprise.

USE THIS WHEN:
\- User asks "find leads" or "show my leads"
\- Need to find leads by name or filter criteria
\- Reviewing lead pipeline or status

RETURNS: Array of leads with id, properties (hs_lead_name, etc.)

EXAMPLES:
1\. Find by name: query="John"
2\. Find by status: filters=[{propertyName:"hs_lead_status", operator:"EQ", value:"NEW"}]
3\. Find by owner: filters=[{propertyName:"hubspot_owner_id", operator:"EQ", value:"12345"}]

OPERATORS: EQ, NEQ, LT, LTE, GT, GTE, CONTAINS_TOKEN (partial match), IN (list)

COMMON PROPERTIES to request: hs_lead_name, hs_lead_status, hs_pipeline, hs_pipeline_stage, hubspot_owner_id, createdate

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria for precise matching
- `limit` (number): Max results (default 10, max 100)
- `properties` (array): Properties to return (default: basic info)
- `query` (string): Free-text search by lead name

### `get_hubspot_lead` (~118 tokens)

Get full details for a single lead by ID.

NOTE: Requires Sales Hub Professional or Enterprise.

USE THIS WHEN:
\- You already have a lead ID (from search or association)
\- Need complete lead information
\- Reviewing a specific lead's properties and status

RETURNS: Single lead object with all requested properties

PREREQUISITE: Get leadId from search_hubspot_leads first

Input parameters:

- `leadId` (string, required): HubSpot lead ID (numeric string)
- `properties` (array): Properties to return

### `create_hubspot_lead` (~294 tokens)

Create a new lead in HubSpot CRM.

NOTE: Requires Sales Hub Professional or Enterprise.

IMPORTANT: This tool creates a HubSpot Lead object (pipeline/stage tracking in Sales Hub).
DO NOT use create_hubspot_deal when the user says "lead" — deals and leads are separate HubSpot object types.

REQUIRED:
\- properties.hs_lead_name (the lead's display name)
\- contactId (leads MUST be associated with a contact at creation — HubSpot API requirement)

The contactId is used to create a LEAD_TO_PRIMARY_CONTACT association automatically.

COMMON PROPERTIES:
\- hs_lead_name (required — lead display name)
\- hs_lead_status: "NEW", "OPEN", "IN_PROGRESS", "CONNECTED", "ATTEMPTED_TO_CONTACT"
\- hubspot_owner_id: assign to a team member (get IDs from list_hubspot_owners)

WORKFLOW:
1\. search_hubspot_contacts to find/create the contact
2\. create_hubspot_lead with contactId and properties
3\. Optionally create_hubspot_association to link to a company or deal

RETURNS: Created lead with id and properties

Input parameters:

- `contactId` (string, required): HubSpot contact ID to associate with this lead (required — leads must be linked to a contact)
- `properties` (object, required): Lead properties object (hs_lead_name required)

### `update_hubspot_lead` (~135 tokens)

Update an existing lead's properties.

NOTE: Requires Sales Hub Professional or Enterprise.

USE THIS WHEN:
\- User says "update lead" or "change lead status"
\- Changing lead status, owner, or other properties

COMMON UPDATES:
\- hs_lead_status: change lead status
\- hubspot_owner_id: reassign to different team member

PREREQUISITE: Get leadId from search_hubspot_leads first

RETURNS: Updated lead object

Input parameters:

- `leadId` (string, required): HubSpot lead ID
- `properties` (object, required): Properties to update (only include changed fields)

### `delete_hubspot_lead` (~73 tokens)

Permanently delete a lead from HubSpot.

NOTE: Requires Sales Hub Professional or Enterprise.

WARNING: This is permanent. The lead record will be removed.

PREREQUISITE: Get leadId from search_hubspot_leads first

Input parameters:

- `leadId` (string, required): HubSpot lead ID

### `search_hubspot_tasks` (~77 tokens)

Search for tasks in HubSpot

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10)
- `properties` (array): Properties to return

### `get_hubspot_task` (~40 tokens)

Get a single task by ID

Input parameters:

- `properties` (array): Properties to return
- `taskId` (string, required): HubSpot task ID

### `create_hubspot_task` (~92 tokens)

Create a new task in HubSpot.
    
    Common properties:
    - hs_task_subject (required)
    - hs_task_body
    - hs_timestamp (due date in ms)
    - hs_task_status (NOT_STARTED, IN_PROGRESS, COMPLETED)
    - hs_task_priority (LOW, MEDIUM, HIGH)
    - hubspot_owner_id

Input parameters:

- `properties` (object, required): Task properties

### `update_hubspot_task` (~38 tokens)

Update an existing task

Input parameters:

- `properties` (object, required): Properties to update
- `taskId` (string, required): HubSpot task ID

### `delete_hubspot_task` (~30 tokens)

Delete a task from HubSpot

Input parameters:

- `taskId` (string, required): HubSpot task ID

### `create_hubspot_note` (~185 tokens)

Create a note in HubSpot and optionally associate it with records.

Properties:
\- hs_note_body (required) - The note content (supports HTML)
\- hs_timestamp - When the note was created (ISO8601 or Unix ms)
\- hs_attachment_ids - Semicolon-separated file IDs to attach (e.g., "123" or "123;456")
  Get file IDs from upload_hubspot_file or import_hubspot_file_from_url.

TO ATTACH FILES TO A RECORD:
1\. Upload file with upload_hubspot_file → get file id
2\. Create note with hs_attachment_ids: "<file_id>" and associations to the record
Or use the convenience tool attach_file_to_record for a one-step workflow.

Input parameters:

- `associations` (object): Associate note with records
- `properties` (object, required): Note properties (hs_note_body required)

### `create_hubspot_association` (~220 tokens)

Create an unlabeled association between two HubSpot objects (v3 API).

For labeled associations (e.g., "Primary Contact", "Contract Signatory", "Decision Maker"),
use create_hubspot_labeled_association instead.

Common association types:
\- contact_to_company
\- deal_to_contact
\- deal_to_company
\- ticket_to_contact
\- line_item_to_deal

Input parameters:

- `associationType` (string, required): Association type (e.g., contact_to_company, line_item_to_deal)
- `fromObjectId` (string, required)
- `fromObjectType` (string, required): Source object type. Common values: "contacts", "companies", "deals", "tickets", "leads", "products", "line_items", or any custom object name.
- `toObjectId` (string, required)
- `toObjectType` (string, required): Target object type. Common values: "contacts", "companies", "deals", "tickets", "leads", "products", "line_items", or any custom object name.

### `get_hubspot_associations` (~197 tokens)

Get all associations of a specific type for an object.

Useful for pivoting between object types in either direction, e.g.:
\- deal -> contacts / companies / line_items
\- line_item -> deals (resolves a line item back to its parent deal)
\- ticket -> contacts / companies
\- contact -> deals / companies

RETURNS: { results: [{ id, type }] } — array of associated record IDs.

Input parameters:

- `fromObjectId` (string, required)
- `fromObjectType` (string, required): Source object type. Common values: "contacts", "companies", "deals", "tickets", "leads", "products", "line_items", or any custom object name.
- `toObjectType` (string, required): Target object type. Common values: "contacts", "companies", "deals", "tickets", "leads", "products", "line_items", or any custom object name.

### `delete_hubspot_association` (~135 tokens)

Remove an association between two objects

Input parameters:

- `associationType` (string, required)
- `fromObjectId` (string, required)
- `fromObjectType` (string, required): Source object type. Common values: "contacts", "companies", "deals", "tickets", "leads", "products", "line_items", or any custom object name.
- `toObjectId` (string, required)
- `toObjectType` (string, required): Target object type. Common values: "contacts", "companies", "deals", "tickets", "leads", "products", "line_items", or any custom object name.

### `list_hubspot_association_labels` (~220 tokens)

List available association labels between two object types using the v4 API.

Returns all available labels (both HubSpot-defined and custom) with their typeId values.
Use the typeId from this response when calling create_hubspot_labeled_association.

Object type values: "contacts", "companies", "deals", "tickets", "products", "line_items", or custom object names.

RETURNS: Array of labels with { category, typeId, label }
\- category: "HUBSPOT_DEFINED" (built-in labels like "Primary") or "USER_DEFINED" (custom labels)
\- typeId: Numeric ID needed for create_hubspot_labeled_association
\- label: Human-readable name (e.g., "Primary Contact", "Contract Signatory")

Input parameters:

- `fromObjectType` (string, required): Source object type (e.g., "contacts", "companies", "deals")
- `toObjectType` (string, required): Target object type (e.g., "deals", "contacts", "companies")

### `create_hubspot_labeled_association` (~246 tokens)

Create a labeled association between two records using the v4 API.

Unlike create_hubspot_association (v3, unlabeled), this creates associations WITH labels
like "Primary Contact", "Contract Signatory", "Decision Maker", etc.

WORKFLOW:
1\. Call list_hubspot_association_labels to discover available labels and their typeIds
2\. Call this tool with the desired associationCategory and associationTypeId

associationCategory:
\- "HUBSPOT_DEFINED": Built-in labels (e.g., Primary Contact, typeId varies by object pair)
\- "USER_DEFINED": Custom labels created in HubSpot Settings → Objects → Associations

Input parameters:

- `associationCategory` (string, required): Label category (from list_hubspot_association_labels)
- `associationTypeId` (number, required): Label type ID (from list_hubspot_association_labels)
- `fromObjectId` (string, required): Source record ID
- `fromObjectType` (string, required): Source object type (e.g., "contacts")
- `toObjectId` (string, required): Target record ID
- `toObjectType` (string, required): Target object type (e.g., "deals")

### `list_hubspot_properties` (~120 tokens)

List all properties for a HubSpot object type.

Supports standard types (contacts, companies, deals, tickets, tasks, leads) and custom objects.
Note: For "leads", this listing endpoint works but get_hubspot_property may return SCOPE_MISSING
due to a HubSpot API scope limitation.

Input parameters:

- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")

### `get_hubspot_property` (~159 tokens)

Get a single property definition by object type and property name.

NOTE: The "leads" object type may return SCOPE_MISSING (403) because HubSpot requires
crm.schemas.leads.read scope which is not always granted during OAuth. If this happens,
use list_hubspot_properties instead (which works for leads). This is a known HubSpot API
limitation, not a bug.

Input parameters:

- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")
- `propertyName` (string, required): Internal property name (e.g., "lifecyclestage")

### `create_hubspot_property` (~221 tokens)

Create a new custom property on a HubSpot object.

VALID TYPE/FIELDTYPE COMBINATIONS:
\- string: text, textarea, phonenumber, html
\- number: number
\- date: date
\- datetime: date
\- enumeration: select, radio, checkbox, booleancheckbox
\- bool: booleancheckbox

Input parameters:

- `description` (string): Optional property description
- `fieldType` (string, required): HubSpot field type
- `groupName` (string, required): Property group internal name (use list_hubspot_property_groups to discover)
- `label` (string, required): Display label shown in HubSpot UI
- `name` (string, required): Internal property name (lowercase, no spaces, underscores allowed)
- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")
- `options` (array): Options for enumeration properties
- `type` (string, required): Property data type

### `update_hubspot_property` (~120 tokens)

Update an existing property definition. Note: type and fieldType CANNOT be changed after creation.

Input parameters:

- `description` (string): Updated description
- `label` (string): Updated display label
- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")
- `options` (array): Updated options for enumeration properties
- `propertyName` (string, required): Internal property name to update

### `delete_hubspot_property` (~88 tokens)

Archive a property from HubSpot. This ARCHIVES the property (not a hard delete).

Input parameters:

- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")
- `propertyName` (string, required): Internal property name to archive

### `list_hubspot_property_groups` (~68 tokens)

List property groups for a HubSpot object type

Input parameters:

- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")

### `create_hubspot_property_group` (~105 tokens)

Create a new property group for an object type

Input parameters:

- `displayOrder` (number): Display order for the group (optional)
- `label` (string, required): Display label for the group
- `name` (string, required): Internal group name
- `objectType` (string, required): Object type (e.g., "contacts", "companies", "deals", "tickets", "tasks", "leads", or a custom object type ID like "2-12345")

### `list_hubspot_owners` (~182 tokens)

List all HubSpot users who can own CRM records.

USE THIS WHEN:
\- Need to assign a contact, deal, or company to a team member
\- User asks "who can I assign this to?" or "show me the sales team"
\- Creating/updating records with hubspot_owner_id property

RETURNS: Array of owners with:
\- id (use this as hubspot_owner_id when creating/updating records)
\- email, firstName, lastName
\- teams[] (team memberships)

WORKFLOW EXAMPLE:
1\. User: "Assign the Acme deal to Sarah"
2\. Call list_hubspot_owners to find Sarah's owner ID
3\. Call update_hubspot_deal with hubspot_owner_id: "sarah's_id"

Input parameters:

- `limit` (number): Max results (default 100)

### `get_hubspot_owner` (~95 tokens)

Get details for a specific HubSpot owner by ID.

USE THIS WHEN:
\- You have an owner ID and need their name/email
\- Resolving hubspot_owner_id from a record to display owner name

PREREQUISITE: Get ownerId from list_hubspot_owners or from a record's hubspot_owner_id property

Input parameters:

- `ownerId` (string, required): HubSpot owner ID (numeric string)

### `list_hubspot_pipelines` (~265 tokens)

List all sales pipelines and their stages.

USE THIS WHEN (CRITICAL for deal operations):
\- BEFORE creating a deal (to get valid pipeline and dealstage IDs)
\- BEFORE updating deal stage (to get valid stage ID)
\- User asks "what are the deal stages?" or "show me the pipeline"

RETURNS: Array of pipelines, each containing:
\- pipelineId (use as "pipeline" property)
\- label (display name)
\- stages[] with:
  \- stageId (use as "dealstage" property)
  \- label (display name like "Qualified", "Proposal Sent")
  \- displayOrder (stage position)
  \- metadata.probability (win probability %)

EXAMPLE RESPONSE:
{
  "pipelineId": "default",
  "label": "Sales Pipeline",
  "stages": [
    {"stageId": "appointmentscheduled", "label": "Appointment Scheduled"},
    {"stageId": "qualifiedtobuy", "label": "Qualified to Buy"},
    {"stageId": "closedwon", "label": "Closed Won"}
  ]
}

IMPORTANT: Stage IDs are internal identifiers, NOT display names. Always use this tool first!

Input parameters:

- `objectType` (string, required): Object type (default: deals)

### `get_hubspot_pipeline` (~95 tokens)

Get details for a specific pipeline including all stages.

USE THIS WHEN:
\- You know the pipeline ID and need its stages
\- Working with a specific pipeline (not the default)

PREREQUISITE: Get pipelineId from list_hubspot_pipelines if you don't know it

Input parameters:

- `objectType` (string, required): Object type
- `pipelineId` (string, required): Pipeline ID (e.g., "default")

### `search_hubspot_calls` (~303 tokens)

Search for logged calls in HubSpot CRM.

USE THIS WHEN:
\- User asks "show recent calls" or "find calls with [contact]"
\- Need call history for meeting prep
\- Looking for specific call recordings or notes

RETURNS: Array of calls with id, properties

EXAMPLE FILTERS:
1\. Recent calls: filters=[{propertyName:"hs_timestamp", operator:"GT", value:"1704067200000"}]
2\. By owner: filters=[{propertyName:"hubspot_owner_id", operator:"EQ", value:"12345"}]
3\. Outbound only: filters=[{propertyName:"hs_call_direction", operator:"EQ", value:"OUTBOUND"}]

PROPERTIES to request:
\- hs_call_title, hs_call_body (notes/transcript)
\- hs_call_direction: "INBOUND" or "OUTBOUND"
\- hs_call_status: "COMPLETED", "BUSY", "NO_ANSWER", "FAILED", "CONNECTING", "CALLING_CRM_USER"
\- hs_call_duration (milliseconds)
\- hs_timestamp (Unix ms when call occurred)
\- hubspot_owner_id

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10, max 100)
- `properties` (array): Properties to return

### `search_hubspot_meetings` (~270 tokens)

Search for logged meetings in HubSpot CRM.

USE THIS WHEN:
\- User asks "show meetings" or "find meetings with [contact]"
\- Need meeting history for relationship context
\- Looking for past meeting notes

RETURNS: Array of meetings with id, properties

EXAMPLE FILTERS:
1\. Upcoming: filters=[{propertyName:"hs_meeting_start_time", operator:"GT", value:"1704067200000"}]
2\. Completed: filters=[{propertyName:"hs_meeting_outcome", operator:"EQ", value:"COMPLETED"}]

PROPERTIES to request:
\- hs_meeting_title, hs_meeting_body (notes/agenda)
\- hs_meeting_start_time, hs_meeting_end_time (Unix ms)
\- hs_meeting_outcome: "SCHEDULED", "COMPLETED", "RESCHEDULED", "NO_SHOW", "CANCELLED"
\- hs_meeting_location
\- hubspot_owner_id

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10, max 100)
- `properties` (array): Properties to return

### `get_hubspot_call` (~92 tokens)

Get full details for a single call by ID.

USE THIS WHEN:
\- You have a call ID and need complete details
\- Retrieving call notes or recording info

PREREQUISITE: Get callId from search_hubspot_calls or get_contact_engagements

Input parameters:

- `callId` (string, required): HubSpot call ID (numeric string)
- `properties` (array): Properties to return

### `get_hubspot_meeting` (~95 tokens)

Get full details for a single meeting by ID.

USE THIS WHEN:
\- You have a meeting ID and need complete details
\- Retrieving meeting notes or attendee info

PREREQUISITE: Get meetingId from search_hubspot_meetings or get_contact_engagements

Input parameters:

- `meetingId` (string, required): HubSpot meeting ID (numeric string)
- `properties` (array): Properties to return

### `create_hubspot_call` (~265 tokens)

Log a call in HubSpot CRM.

USE THIS WHEN:
\- User says "log a call" or "record that I called [contact]"
\- Documenting a phone conversation
\- Adding call notes after a conversation

REQUIRED: hs_timestamp (Unix timestamp in milliseconds)

COMMON PROPERTIES:
\- hs_timestamp: when call occurred (REQUIRED, Unix ms, e.g., Date.now())
\- hs_call_title: brief description
\- hs_call_body: notes, transcript, or summary
\- hs_call_direction: "INBOUND" or "OUTBOUND"
\- hs_call_status: "COMPLETED", "BUSY", "NO_ANSWER", "FAILED"
\- hs_call_duration: call length in milliseconds
\- hubspot_owner_id: who made the call

ASSOCIATIONS (link call to records):
\- contactIds: ["contact_id_1", "contact_id_2"]
\- companyIds: ["company_id"]
\- dealIds: ["deal_id"]

WORKFLOW:
1\. search_hubspot_contacts to get contact ID
2\. create_hubspot_call with associations.contactIds

RETURNS: Created call with id

Input parameters:

- `associations` (object): Link call to CRM records
- `properties` (object, required): Call properties object

### `create_hubspot_meeting` (~290 tokens)

Log a meeting in HubSpot CRM.

USE THIS WHEN:
\- User says "log a meeting" or "record meeting with [contact]"
\- Documenting a completed meeting
\- Scheduling a future meeting in CRM

REQUIRED:
\- hs_timestamp (Unix ms)
\- hs_meeting_start_time (Unix ms)
\- hs_meeting_end_time (Unix ms)

COMMON PROPERTIES:
\- hs_timestamp: when meeting was logged (Unix ms)
\- hs_meeting_start_time: meeting start (Unix ms)
\- hs_meeting_end_time: meeting end (Unix ms)
\- hs_meeting_title: meeting subject
\- hs_meeting_body: notes, agenda, or action items
\- hs_meeting_outcome: "SCHEDULED", "COMPLETED", "RESCHEDULED", "NO_SHOW", "CANCELLED"
\- hs_meeting_location: location or video link
\- hubspot_owner_id: meeting organizer

ASSOCIATIONS (link meeting to records):
\- contactIds: attendee contact IDs
\- companyIds: company IDs
\- dealIds: related deal IDs

WORKFLOW:
1\. search_hubspot_contacts to get attendee contact IDs
2\. create_hubspot_meeting with associations

RETURNS: Created meeting with id

Input parameters:

- `associations` (object): Link meeting to CRM records
- `properties` (object, required): Meeting properties object

### `get_contact_engagements` (~178 tokens)

Get all recent activity (calls, meetings) for a contact.

USE THIS WHEN:
\- User asks "what's the history with [contact]?" or "show activity for [person]"
\- Preparing for a meeting and need relationship context
\- Need a quick activity summary

RETURNS: Object with arrays for each engagement type:
{
  calls: [{id, properties}],
  meetings: [{id, properties}]
}

This is a convenience tool that fetches multiple engagement types in one call.
For more control, use search_hubspot_calls or search_hubspot_meetings directly.

PREREQUISITE: Get contactId from search_hubspot_contacts first

Input parameters:

- `contactId` (string, required): HubSpot contact ID (numeric string)
- `limit` (number): Max results per engagement type (default 5)

### `search_hubspot_products` (~246 tokens)

Search for products in your HubSpot product catalog.

USE THIS WHEN:
\- User asks about products, SKUs, or pricing
\- Looking up specific products by name or SKU
\- Finding products to add to a deal as line items

COMMON PROPERTIES:
\- name: Product name
\- hs_sku: Stock keeping unit
\- price: Unit price
\- description: Product description
\- hs_cost_of_goods_sold: Cost/COGS
\- hs_recurring_billing_period: P1M (monthly), P1Y (yearly)

SEARCH BY TEXT: Use "query" for free-text search (name, SKU)
SEARCH BY FILTER: Use "filters" for exact matches

RETURNS: Array of products with id and properties

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria (same syntax as contacts/deals)
- `limit` (number): Max results (default 10)
- `properties` (array): Properties to return
- `query` (string): Free-text search (searches name and SKU)

### `get_hubspot_product` (~74 tokens)

Get a specific product by ID.

USE THIS WHEN:
\- You have a product ID and need full details
\- Looking up product pricing or SKU details

RETURNS: Product object with all requested properties

Input parameters:

- `productId` (string, required): HubSpot product ID
- `properties` (array): Properties to return

### `create_hubspot_product` (~122 tokens)

Create a new product in the product catalog.

USE THIS WHEN:
\- Adding new products to sell
\- Setting up product catalog

REQUIRED: name
RECOMMENDED: price, hs_sku, description

EXAMPLE:
{
  "properties": {
    "name": "Enterprise License",
    "price": "10000",
    "hs_sku": "ENT-001",
    "description": "Annual enterprise license"
  }
}

RETURNS: Created product with id

Input parameters:

- `properties` (object, required): Product properties (name required)

### `update_hubspot_product` (~68 tokens)

Update an existing product's properties.

USE THIS WHEN:
\- Changing product price
\- Updating SKU or description
\- Modifying any product attribute

RETURNS: Updated product

Input parameters:

- `productId` (string, required): HubSpot product ID
- `properties` (object, required): Properties to update

### `search_hubspot_line_items` (~166 tokens)

Search for line items in HubSpot.

Line items connect products to deals for revenue tracking.
Each line item represents a product/service with quantity and price on a deal.

COMMON PROPERTIES:
\- name: Line item name (often matches product)
\- quantity: Number of units
\- price: Unit price
\- amount: Total (quantity × price)
\- hs_discount_percentage: Applied discount
\- hs_product_id: Source product ID

RETURNS: Array of line items

Input parameters:

- `after` (string): Pagination cursor from paging.next.after. Repeat the same search with this value until paging.next.after is absent.
- `filters` (array): Filter criteria
- `limit` (number): Max results (default 10)
- `properties` (array): Properties to return

### `get_hubspot_line_item` (~158 tokens)

Get a specific line item by ID.

To resolve a line item back to its parent deal in the same call, pass
\`associations: ['deals']`. The response then includes an `associations`
object with `{ deals: { results: [{ id, type }] } }`.

RETURNS: Line item object. Includes `associations` only when the
\`associations` parameter is provided.

Input parameters:

- `associations` (array): Optional associated object types to include in the response (e.g. ["deals"], ["deals", "products"]). Returns associated record IDs alongside the line item.
- `lineItemId` (string, required): HubSpot line item ID
- `properties` (array): Properties to return

### `create_hubspot_line_item` (~256 tokens)

Create a line item and optionally associate with a deal.

Line items link products to deals for revenue tracking.
This is the KEY tool for adding products to a deal.

WORKFLOW:
1\. search_hubspot_products to find product ID
2\. search_hubspot_deals to find deal ID
3\. create_hubspot_line_item with dealId association

REQUIRED PROPERTIES:
\- name: Line item name
\- quantity: Number of units (string, e.g. "1")
\- price: Unit price (string, e.g. "1000.00")

OPTIONAL:
\- hs_product_id: Link to product catalog
\- hs_discount_percentage: Discount to apply
\- dealId: Associate immediately with deal

EXAMPLE:
{
  "properties": {
    "name": "Enterprise License - Annual",
    "quantity": "2",
    "price": "10000",
    "hs_product_id": "123456"
  },
  "dealId": "789"
}

RETURNS: Created line item with id

Input parameters:

- `dealId` (string): Deal ID to associate (recommended)
- `properties` (object, required): Line item properties (name, quantity, price required)

### `list_hubspot_forms` (~129 tokens)

List all forms in HubSpot.

Forms collect leads through your website, landing pages, or embedded forms.

FORM TYPES:
\- hubspot: Standard HubSpot forms
\- captured: Non-HubSpot forms (collected via tracking)
\- flow: Pop-up forms
\- blog_comment: Blog comment forms

RETURNS: Array of forms with id, name, formType, createdAt

Input parameters:

- `after` (string): Pagination cursor
- `formTypes` (array): Filter by form type (default: all types)
- `limit` (number): Max results (default 20)

### `get_hubspot_form` (~50 tokens)

Get detailed information about a specific form.

RETURNS: Form with id, name, configuration, fieldGroups (form fields)

Input parameters:

- `formId` (string, required): HubSpot form ID or GUID

### `get_hubspot_form_submissions` (~127 tokens)

Get submissions for a specific form.

USE THIS WHEN:
\- Reviewing lead capture performance
\- Checking recent form submissions
\- Analyzing lead sources

RETURNS: Array of submissions with:
\- submittedAt: Submission timestamp
\- values: Field name/value pairs
\- pageUrl: Where form was submitted

NOTE: Uses formGuid (same as formId for most forms)

Input parameters:

- `after` (string): Pagination cursor
- `formId` (string, required): Form ID/GUID
- `limit` (number): Max submissions (default 20, max 50)

### `get_hubspot_analytics_report` (~313 tokens)

Get website traffic analytics report.

This is the ONLY reporting API available from HubSpot. HubSpot does not have a public API
for creating, listing, or managing custom reports or dashboards. For custom report needs,
users must use the HubSpot UI directly.

⚠️ REQUIRES Marketing Hub Professional or Enterprise.
Will return 403 error on free accounts.

BREAKDOWN OPTIONS:
\- totals: Overall traffic metrics
\- sessions: Session-based metrics
\- sources: Traffic by source (organic, direct, etc.)
\- geolocation: Traffic by country/region
\- utm-campaigns: By UTM campaign
\- utm-sources: By UTM source
\- utm-mediums: By UTM medium
\- pages: By page URL

TIME PERIODS:
\- totals: Aggregate for date range
\- daily: Day-by-day breakdown
\- weekly: Week-by-week
\- monthly: Month-by-month

DATE FORMAT: YYYYMMDD (e.g., "20260101")

RETURNS: {
  totals: {views, visits, leads, ...},
  breakdowns: [{breakdown: "...", metrics: {...}}, ...]
}

Input parameters:

- `breakdownBy` (string, required): How to segment the data
- `endDate` (string, required): End date YYYYMMDD
- `limit` (number): Max breakdown rows (default 100)
- `startDate` (string, required): Start date YYYYMMDD
- `timePeriod` (string, required): Time grouping

### `list_hubspot_marketing_emails` (~96 tokens)

List marketing emails in HubSpot.

RETURNS: Array of emails with:
\- id, name, subject
\- state: DRAFT, SCHEDULED, PUBLISHED, etc.
\- type: REGULAR, AB_EMAIL, BLOG_EMAIL, etc.
\- createdAt, stats (if available)

Input parameters:

- `after` (string): Pagination cursor
- `limit` (number): Max results (default 20)

### `get_hubspot_marketing_email` (~107 tokens)

Get details of a specific marketing email by ID.

USE THIS WHEN:
\- User asks "show me the follow-up email" or "what's in email X"
\- Need email content, subject, template path, or configuration

RETURNS: Full email object including:
\- id, name, subject, previewText
\- state, type, templatePath
\- content/body (if available)
\- stats summary

Input parameters:

- `emailId` (string, required): Marketing email ID

### `get_hubspot_email_statistics` (~119 tokens)

Get aggregated email performance statistics.

RETURNS: {
  aggregations: {sent, delivered, opened, clicked, bounced, unsubscribed},
  emails: [{emailId, counters: {...}}]
}

Use this to analyze email campaign performance across multiple emails.

Input parameters:

- `emailIds` (array): Specific email IDs (optional)
- `endTimestamp` (string): ISO8601 end
- `startTimestamp` (string): ISO8601 start (e.g., "2026-01-01T00:00:00Z")

### `list_hubspot_lists` (~128 tokens)

List all contact lists (segments) in HubSpot.

RETURNS: Array of lists with {listId, name, processingType, size, createdAt}

processingType values:
\- MANUAL: Static list, manually managed
\- DYNAMIC: Auto-updates based on filter criteria
\- SNAPSHOT: Point-in-time capture, does not update

Use get_hubspot_list to see a dynamic list's filter criteria.

Input parameters:

- `after` (string): Pagination cursor from previous response
- `limit` (number): Max results (default: 20, max: 100)

### `get_hubspot_list` (~110 tokens)

Get details of a specific list/segment by ID.

RETURNS: {listId, name, processingType, objectTypeId, filterBranch, size, createdAt, updatedAt}

For DYNAMIC lists, filterBranch contains the criteria that determine membership.
For MANUAL/SNAPSHOT lists, filterBranch is usually empty.

To get the contacts IN this list, use list_hubspot_list_members.

Input parameters:

- `listId` (string, required): The list ID (from list_hubspot_lists)

### `list_hubspot_list_members` (~175 tokens)

Get contact IDs that are members of a list/segment.

IMPORTANT: Returns contact IDs only, NOT full contact records.
To get contact details (email, name, etc.), use batch_read_hubspot_contacts.

WORKFLOW for exporting a segment:
1\. Call list_hubspot_list_members(listId) to get contact IDs
2\. Call batch_read_hubspot_contacts(ids, properties) to get details
3\. Repeat with pagination cursor if needed

RETURNS: {results: [{recordId, membershipTimestamp}], paging: {next: {after}}}

Input parameters:

- `after` (string): Pagination cursor from previous response
- `limit` (number): Max results per page (default: 100, max: 250)
- `listId` (string, required): The list ID to get members for

### `batch_read_hubspot_contacts` (~172 tokens)

Fetch multiple contacts by ID in a single request (up to 100).

USE THIS TO: Hydrate contact IDs from list_hubspot_list_members into full records.

WORKFLOW:
1\. list_hubspot_list_members(listId) → get recordIds
2\. batch_read_hubspot_contacts(ids, ['email', 'firstname', 'lastname']) → get details

RETURNS: {results: [{id, properties: {email, firstname, ...}, createdAt, updatedAt}]}

Common properties: email, firstname, lastname, phone, company, jobtitle, lifecyclestage

Input parameters:

- `ids` (array, required): Contact IDs to fetch (max 100)
- `properties` (array): Properties to return (e.g., ["email", "firstname", "lastname"])

### `list_hubspot_kb_articles` (~223 tokens)

List Knowledge Base articles in HubSpot via the GraphQL API (read-only).

USE THIS WHEN:
\- User asks "show me KB articles" or "what's in the knowledge base?"
\- Need to browse all KB articles with pagination
\- Looking for a specific article to retrieve with get_hubspot_kb_article

RETURNS:
\- KB articles with id, title, body, slug, URL, language, and metadata
\- Total count and pagination support via limit/offset

SCOPES REQUIRED: cms.knowledge_base.articles.read and collector.graphql_query.execute
(a 403 usually means the account's plan or the signed-in user's permissions don't include the knowledge base — reconnecting alone won't add it)

COMMON MISTAKES:
\- Expecting write operations — KB tools are read-only (no create/update/delete API exists)

Requires Service Hub Professional or Enterprise.

Input parameters:

- `limit` (number): Max articles to return (default 10)
- `offset` (number): Number of articles to skip for pagination (default 0)

### `get_hubspot_kb_article` (~233 tokens)

Get full details for a single HubSpot Knowledge Base article by ID via the GraphQL API (read-only).

USE THIS WHEN:
\- You already have an articleId and need full content/details
\- Need the complete article body, metadata, or URL

RETURNS:
\- Full KB article object with id, title, body, slug, URL, language, and metadata

WORKFLOW:
1\. Get articleId from list_hubspot_kb_articles or search_hubspot_kb_articles
2\. Call get_hubspot_kb_article for complete details

SCOPES REQUIRED: cms.knowledge_base.articles.read and collector.graphql_query.execute
(a 403 usually means the account's plan or the signed-in user's permissions don't include the knowledge base — reconnecting alone won't add it)

COMMON MISTAKES:
\- Using a knowledgeBaseId/contentGroupId instead of an articleId
\- Assuming search result snippets are full article content — use this tool for the full body

Requires Service Hub Professional or Enterprise.

Input parameters:

- `articleId` (string, required): HubSpot KB article ID

### `search_hubspot_kb_articles` (~214 tokens)

Search published HubSpot Knowledge Base content by query text via the Site Search API (read-only).

USE THIS WHEN:
\- User asks to find KB content by keyword or phrase
\- Looking up published help articles or troubleshooting docs

RETURNS:
\- Search matches with title, URL, and snippet metadata from HubSpot site search

WORKFLOW:
1\. Call search_hubspot_kb_articles with a clear query
2\. Use get_hubspot_kb_article for full article details when needed

IMPORTANT: Only finds PUBLISHED articles. This tool searches the public site index and does not
include draft or scheduled content. Use list_hubspot_kb_articles to browse all articles.

COMMON MISTAKES:
\- Expecting drafts in results — site search only indexes published content
\- Using this as the only retrieval path when you need all articles

Requires Service Hub Professional or Enterprise.

Input parameters:

- `limit` (number): Max search results to return
- `query` (string, required): Search query text

### `upload_hubspot_file` (~270 tokens)

Upload a file to HubSpot's file manager from a local file path.

USE THIS WHEN:
\- User wants to upload a document, image, or attachment to HubSpot
\- Preparing a file to attach to a CRM record (contact, deal, company, ticket)
\- Storing branding assets, proposals, contracts, etc.

RETURNS: { id, name, path, url, size, access }
\- The "id" is the file ID used to attach files to records via notes

WORKFLOW to attach a file to a record:
1\. upload_hubspot_file → get file "id"
2\. create_hubspot_note with hs_attachment_ids set to the file id, and associations to link to the record

ACCESS LEVELS:
\- PRIVATE (default): Only accessible via signed URL, not publicly visible
\- PUBLIC_NOT_INDEXABLE: Publicly accessible but search engines won't index
\- PUBLIC_INDEXABLE: Fully public and indexable by search engines

Input parameters:

- `access` (string): File visibility (default: PRIVATE)
- `filePath` (string, required): Absolute local file path to upload (e.g., "/Users/me/Documents/proposal.pdf")
- `folderPath` (string): Destination folder in HubSpot file manager (e.g., "/attachments"). Default: "/"

### `import_hubspot_file_from_url` (~283 tokens)

Import a file into HubSpot's file manager from a URL.

USE THIS WHEN:
\- User wants to import a file from the web into HubSpot
\- Adding a file from a public URL to attach to a record
\- Importing images, documents, or media from external sources

This tool handles the async import process automatically (polls until complete, up to 30s).
Returns the final file object with its ID once ready.

WORKFLOW to attach an imported file to a record:
1\. import_hubspot_file_from_url → get file { id, name, path, url, size }
2\. create_hubspot_note with hs_attachment_ids set to the file id, and associations to link to the record

ACCESS LEVELS:
\- PRIVATE (default): Only accessible via signed URL
\- PUBLIC_NOT_INDEXABLE: Publicly accessible, not indexed
\- PUBLIC_INDEXABLE: Fully public and indexable

Input parameters:

- `access` (string): File visibility (default: PRIVATE)
- `fileName` (string): Override the file name (optional, derived from URL if omitted)
- `folderPath` (string): Destination folder in HubSpot file manager (e.g., "/imports"). Default: "/"
- `url` (string, required): Public URL of the file to import (e.g., "https://example.com/doc.pdf")

### `get_hubspot_file` (~164 tokens)

Get details of a file in HubSpot's file manager by ID.

USE THIS WHEN:
\- Need to check file details (name, size, URL, access level)
\- Verifying a file exists before attaching to a record
\- Getting a viewable URL for a private file (use getSignedUrl: true)

RETURNS: { id, name, path, url, size, type, access, createdAt, updatedAt }
For private files, the url will 404. Set getSignedUrl to true to get a temporary viewable URL.

Input parameters:

- `fileId` (string, required): HubSpot file ID (from upload or import)
- `getSignedUrl` (boolean): If true, also return a signed (viewable) URL for private files

### `delete_hubspot_file` (~61 tokens)

Delete a file from HubSpot's file manager.

WARNING: This marks the file as deleted and makes its content inaccessible.
Notes that reference this file will no longer display the attachment.

Input parameters:

- `fileId` (string, required): HubSpot file ID to delete

### `attach_file_to_record` (~219 tokens)

Upload a file and attach it to a CRM record in one step.

This is a convenience tool that combines:
1\. Uploading a file to HubSpot's file manager
2\. Creating a note with the file attached
3\. Associating the note with the specified record(s)

USE THIS WHEN:
\- User says "attach this file to [contact/deal/company]"
\- Adding a document, proposal, or contract to a record
\- Uploading meeting notes or attachments to a contact

ACCEPTS EITHER:
\- filePath: Local file path to upload
\- fileUrl: Public URL to import

RETURNS: { fileId, noteId, fileName, associations }

Input parameters:

- `associations` (object, required): Records to attach the file to (at least one required)
- `filePath` (string): Local file path to upload (use this OR fileUrl)
- `fileUrl` (string): Public URL to import (use this OR filePath)
- `noteBody` (string): Optional note text to accompany the attachment

### `list_hubspot_workflows` (~271 tokens)

List all automation workflows in HubSpot (v4 BETA API).

Returns workflow metadata: id, name, type, isEnabled, timestamps.
Use get_hubspot_workflow with the flow id for full structure (actions, triggers, branches).

RELATED TOOLS:
\- get_hubspot_workflow (inspect one workflow)
\- create_hubspot_workflow (create a workflow)
\- update_hubspot_workflow (replace workflow configuration)
\- activate_hubspot_workflow / deactivate_hubspot_workflow (toggle state)
\- delete_hubspot_workflow (permanently delete)
\- enrol_in_hubspot_workflow (enrol specific records)

REQUIRES: automation scope, plus a plan that includes workflows (Operations Hub, or
Marketing/Sales Hub Professional or Enterprise). A 403 means the connection can't access
workflows — most often the account's plan or the signed-in user's permissions, less
commonly the scope isn't authorised for the app. Reconnecting alone won't add it; resolve
the underlying cause first, then reconnect HubSpot to pick up the change.

NOTE: This uses the v4 Automation API which is in BETA — response shape may change.

Input parameters:

- `limit` (number): Max workflows to return (default: 100)

### `get_hubspot_workflow` (~233 tokens)

Get full workflow structure including actions, triggers, and branches (v4 BETA API).

Returns the complete workflow graph with:
\- Enrollment criteria (triggers and conditions)
\- Actions (each with actionTypeId, fields, and connection to next action)
\- Branch logic

Useful for analyzing workflow structure and identifying potential issues.
Call list_hubspot_workflows first to discover available flow IDs.

RELATED TOOLS:
\- create_hubspot_workflow (create new workflows)
\- update_hubspot_workflow (replace workflow configuration)
\- activate_hubspot_workflow / deactivate_hubspot_workflow (toggle workflow status)
\- enrol_in_hubspot_workflow (manually enrol records)
\- delete_hubspot_workflow (permanently delete workflow)

REQUIRES: automation scope and a plan that includes workflows (see list_hubspot_workflows for what a 403 means).

NOTE: This is a BETA API — treat unknown fields cautiously as the response shape may change.

Input parameters:

- `flowId` (string, required): Workflow/flow ID (from list_hubspot_workflows)

### `create_hubspot_workflow` (~175 tokens)

Create a new HubSpot workflow.

⚠️ BETA API — this uses the v4 Automation API. Endpoint behavior may change.

WORKFLOW TYPES:
\- CONTACT_FLOW: Triggered by contact enrollment
\- COMPANY_FLOW: Triggered by company enrollment
\- DEAL_FLOW: Triggered by deal enrollment
\- TICKET_FLOW: Triggered by ticket enrollment

EXAMPLE minimal workflow:
{
  "name": "New Lead Notification",
  "type": "CONTACT_FLOW"
}

To add actions and enrollment criteria, use the fields from get_hubspot_workflow
as a reference for the expected structure.

Input parameters:

- `actions` (array): Optional workflow actions graph
- `enrollmentCriteria` (object): Optional enrollment criteria configuration
- `name` (string, required): Workflow name
- `type` (string, required): Workflow type

### `update_hubspot_workflow` (~110 tokens)

Update a workflow via PUT (full replace semantics).

IMPORTANT: This endpoint behaves like a replacement update. Include all fields you
want to preserve (name/actions/enrollmentCriteria), not just changed fields.

Use get_hubspot_workflow first, then submit the updated full structure.

Input parameters:

- `actions` (array): Workflow actions graph
- `enrollmentCriteria` (object): Enrollment criteria configuration
- `flowId` (string, required): Workflow ID to update
- `name` (string): Workflow name

### `delete_hubspot_workflow` (~66 tokens)

Permanently delete a workflow.

WARNING: This is irreversible. The workflow and its history are removed.
Set confirm=true to acknowledge permanent deletion.

Input parameters:

- `confirm` (boolean, required): Must be true to confirm permanent deletion
- `flowId` (string, required): Workflow ID to delete

### `activate_hubspot_workflow` (~34 tokens)

Activate a workflow (sets isEnabled to true).

Input parameters:

- `flowId` (string, required): Workflow ID to activate

### `deactivate_hubspot_workflow` (~35 tokens)

Deactivate a workflow (sets isEnabled to false).

Input parameters:

- `flowId` (string, required): Workflow ID to deactivate

### `enrol_in_hubspot_workflow` (~129 tokens)

Enrol specific records into a workflow.

Uses the v4 BETA enrollment endpoint. A 403 means the connection can't access workflows
(most often plan or user permissions, less commonly app authorisation) — reconnecting alone
won't fix it; resolve the cause, then reconnect. A 404 may mean your portal requires the v3
enrollment endpoint.

Input parameters:

- `flowId` (string, required): Workflow ID to enrol into
- `objectIds` (array, required): Record IDs to enrol
- `objectType` (string): Enrollment object type path segment (default: contacts)

### `list_hubspot_ticket_threads` (~305 tokens)

List conversation threads associated with a HubSpot support ticket.

Use this when you need to read the actual customer messages on a ticket — for example,
to draft a reply for an unassigned ticket. Tickets in HubSpot only expose the initial
\`subject` and `content` fields; the full back-and-forth lives on Conversations threads.

Typical workflow:
1\. search_hubspot_tickets to find candidate tickets
2\. list_hubspot_ticket_threads(ticketId) to find the thread(s) attached to a ticket
3\. list_hubspot_thread_messages(threadId) to read the message history
4\. (optional) get_hubspot_thread_message_original_content if a message is truncated

REQUIRES: `conversations.read` OAuth scope (added May 2026). On a 403: accounts
connected before then must reconnect to grant it; otherwise reconnecting won't
help — the account's plan or the signed-in user's permissions are the likely cause.

RETURNS: { results: [{ id, status, latestMessageTimestamp, ... }], paging? }

Input parameters:

- `after` (string): Pagination cursor from a previous response.paging.next.after
- `archived` (boolean): Include archived threads (default false)
- `limit` (number): Max threads to return (HubSpot default 20, max 100)
- `threadStatus` (string): Optional status filter
- `ticketId` (string, required): HubSpot ticket ID

### `list_hubspot_thread_messages` (~229 tokens)

List messages on a conversation thread, in chronological order.

Each message includes `text` and/or `richText` body, `sender`, `recipients`,
\`createdAt`, `type` (MESSAGE | COMMENT | WELCOME_MESSAGE), and `truncationStatus`.
If `truncationStatus` indicates the body was truncated, call
get_hubspot_thread_message_original_content with the same threadId/messageId to fetch
the full body.

REQUIRES: `conversations.read` OAuth scope (added May 2026). On a 403: accounts
connected before then must reconnect to grant it; otherwise reconnecting won't
help — the account's plan or the signed-in user's permissions are the likely cause.

RETURNS: { results: [...messages], paging? }

Input parameters:

- `after` (string): Pagination cursor from a previous response.paging.next.after
- `limit` (number): Max messages to return (HubSpot default 20, max 100)
- `threadId` (string, required): Conversation thread ID (from list_hubspot_ticket_threads)

### `get_hubspot_thread_message_original_content` (~163 tokens)

Fetch the full, untruncated original content of a single conversation message.

Use this only when the message returned from list_hubspot_thread_messages has a
\`truncationStatus` indicating its body was truncated. For untruncated messages, the
body is already present in list_hubspot_thread_messages and this call is unnecessary.

REQUIRES: `conversations.read` OAuth scope (added May 2026). On a 403: accounts
connected before then must reconnect to grant it; otherwise reconnecting won't
help — the account's plan or the signed-in user's permissions are the likely cause.

Input parameters:

- `messageId` (string, required): Message ID within the thread
- `threadId` (string, required): Conversation thread ID

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/mindstone-mcp-server-hubspot/mindstone-mcp-server-hubspot#diagnostics

## Score history

- 2026-08-03: 73
- 2026-08-02: 73
- 2026-08-01: 50
- 2026-07-31: 60
- 2026-07-30: 26
- 2026-07-29: 25
- 2026-07-28: 44
- 2026-07-27: 44

## Links

- npm package: https://www.npmjs.com/package/@mindstone/mcp-server-hubspot
- Socket report: https://socket.dev/npm/package/@mindstone/mcp-server-hubspot
- Repository: https://github.com/mindstone/mcp-servers
- Changelog RSS feed: https://verifymcp.io/servers/mindstone-mcp-server-hubspot/mindstone-mcp-server-hubspot/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/mindstone-mcp-server-hubspot/mindstone-mcp-server-hubspot/changelog.json
- HTML version of this page: https://verifymcp.io/servers/mindstone-mcp-server-hubspot/mindstone-mcp-server-hubspot
