← Back to all apps

HubSpot

Sales And Marketingby HubSpot
Launched Sep 11, 2026 on ChatGPT

Bring HubSpot customer context into Claude. Search and update contacts, companies, deals, tickets, campaigns, and more - without leaving Claude. Analyze campaign performance across emails, landing pages, and blog posts. Forecast pipeline, qualify leads, and update deal stages in seconds. Useful for pre-call prep, pipeline reviews, campaign attribution, and full account visibility. Permission-aware, real-time, secure.

27ChatGPT Tools
36Claude Tools
HubSpotDeveloper
Sales And MarketingCategory

Use Cases

sales-and-marketing

Available Tools

Discover HubSpot schema

discover_hubspot_schema
Full Description

Discovers HubSpot data types, pipelines, and stages.

<capabilities>

  • Searches across all HubSpot data types available to the current user
  • Returns type names that can be used as input to other tools
  • Shows read/write access status for each type based on the current user's permissions
  • Returns pipelines and their stages (including open/closed status) for a data type

</capabilities>

<usage_guidance>

  • Use this tool FIRST when you need to identify which data types exist before querying data
  • Use SEARCH_OBJECT_TYPES when you don't know the exact type name
  • Use GET_OBJECT_TYPES when you already know the type names (e.g. CONTACT, DEAL), or with an empty typeNameFilter list to retrieve all available types
  • Use GET_PIPELINES to list the pipelines and stages for a type (e.g. deal or ticket stages)
  • GET_PIPELINES stage metadata: probability (DEAL only) is the likelihood (0-1) the deal closes successfully. state (all other types) is OPEN or CLOSED, except for LEAD where the values are NEW, IN_PROGRESS, QUALIFIED, or UNQUALIFIED — QUALIFIED and UNQUALIFIED are the closed/terminal states, NEW and IN_PROGRESS are open
  • Check readAccess/writeAccess before attempting operations on a type

</usage_guidance>

<examples> <example> <user_input>How many support requests did we get last month?</user_input> <tool_call>{"query": {"_queryType": "SEARCH_OBJECT_TYPES", "searchTerms": "support requests tickets"}}</tool_call> </example>

<example> <user_input>How many products do we have?</user_input> <thoughts>"products" is ambiguous — it may be HubSpot's standard Products object or a custom object like p12345_product_models, and semantic search tends to rank the standard one first, so I won't just take the top hit. I'll review all candidates and, if more than one plausibly matches, ask the user to clarify before querying.</thoughts> <tool_call>{"query": {"_queryType": "SEARCH_OBJECT_TYPES", "searchTerms": "products"}}</tool_call> </example>

<example> <user_input>What fields are on contacts and deals?</user_input> <tool_call>{"query": {"_queryType": "GET_OBJECT_TYPES", "typeNameFilter": ["CONTACT", "DEAL"]}}</tool_call> </example>

<example> <user_input>What types of data does HubSpot have?</user_input> <tool_call>{"query": {"_queryType": "GET_OBJECT_TYPES"}}</tool_call> </example>

<example> <user_input>What are the deal pipeline stages?</user_input> <tool_call>{"query": {"_queryType": "GET_PIPELINES", "objectType": "DEAL"}}</tool_call> </example> </examples>

Parameters (1 required)
Required
queryobject

The schema query to run. Choose SEARCH_OBJECT_TYPES to discover types by natural language, or GET_OBJECT_TYPES to fetch known type names directly (or all types when typeNameFilter is empty).

Fetch

fetch
Full Description

<deprecation_notice> DEPRECATED: DO NOT USE. This tool is deprecated. Use these replacements instead:

  • Use search_properties to discover available property definitions for a CRM object type
  • Use get_crm_objects to fetch specific CRM objects by their IDs

</deprecation_notice>

Parameters (1 required)
Required
idstring

Get AEO metrics

get_aeo_metrics
Full Description

Portal-level AEO analytics: brand visibility, mentions, citations, competitor share-of-voice, and per-assistant breakdowns for a date window. Select the sections you need with include, a JSON array of section names, e.g. ["SUMMARY", "PROMPTS"] (SUMMARY, PROMPTS, CITATIONS, CITATION_ANALYSIS, COMPETITORS, ASSISTANT_BREAKDOWN, RUN_STATUS, ICPS_AND_PRODUCTS, BUSINESS_UNITS, LIMITS); defaults to {SUMMARY, RUN_STATUS}. businessUnitId is optional: omit it to use the portal's business unit automatically, or call once with include=["BUSINESS_UNITS"] first to choose one when the portal has several. CITATION_ANALYSIS additionally requires a citationUrl. Dates are ISO-8601 (YYYY-MM-DD); default to the last 30 days. Call tool_guidance (mcpToolInstructions) for the full section catalog, setup-status semantics, and field-level details.

Parameters (10 required)
Required
assistantsarray

AI assistant families to include when PROMPTS is requested. Empty = all assistants. Valid values from the AEO config tool.

businessUnitIdinteger

Business unit ID (optional). Call get_aeo_metrics with include=["BUSINESS_UNITS"] first to discover all available business unit IDs for this portal — data is keyed by the IDs returned there.

citationUrlstring

Citation URL to analyze. REQUIRED when include contains CITATION_ANALYSIS. Pass a full page URL from a manage_aeo_prompts DETAIL response's citationUrls list (CITATIONS returns domains, not URLs, so it cannot supply this value). The URL is normalized (tracking query params stripped, trailing slash / www removed, host lowercased) before matching, so pass it exactly as it appears in that citationUrls list.

endDatestring

ISO-8601 end date (YYYY-MM-DD). Optional; defaults to today. Must be on or after startDate.

filtersobject

Optional filters for the SUMMARY and PROMPTS sections: buying-journey phase, tracking status, visibility-score range, product / ICP / topic / language. Topic/group filters match ANY selected group by default; set groupFilterMode to ALL to require every selected group. Does not affect CITATIONS, COMPETITORS, or ASSISTANT_BREAKDOWN, which are always portal-wide.

includearray

Which sections to populate, as a JSON array of section names — always an array, even for a single section (e.g. ["SUMMARY", "PROMPTS"]), never a bare string. SUMMARY = portal aggregates. PROMPTS = per-prompt metrics list. CITATIONS = citation counts + top domains with ownership flags. COMPETITORS = per-brand mention counts and share-of-voice. ASSISTANT_BREAKDOWN = metrics split by AI assistant (ChatGPT, Gemini, etc.). RUN_STATUS = run freshness. ICPS_AND_PRODUCTS = the business unit's ICPs and products (ids + names/descriptions) for use as icpIds / productIds when creating prompts. BUSINESS_UNITS = available business unit IDs and names, plus the resolved BU used for this request. LIMITS = prompt usage vs capacity (promptsUsed, promptsCapacity, onCredits, managePromptsUrl). CITATION_ANALYSIS = single-URL deep dive for citationUrl (required): per-assistant citation counts, brand mentions with relationship type, content type, and citing prompts. Defaults to {SUMMARY, RUN_STATUS}.

maxPromptsinteger

Maximum number of prompts to return per page when PROMPTS is requested. Defaults to 100 and is capped at 250 to keep responses within the MCP response budget. When more prompts match than fit in one page, the PROMPTS section returns hasMore=true and a nextCursor to pass back as promptsCursor.

modelsarray

AI models to include when PROMPTS is requested. Empty = all models. Valid values from the AEO config tool.

promptsCursorinteger

Pagination cursor for the PROMPTS section. Omit (or pass 0) to start at the first page; to page through all prompts, pass the nextCursor value returned in the PROMPTS section of the previous response. Only affects the PROMPTS section.

startDatestring

ISO-8601 start date (YYYY-MM-DD). Optional; defaults to 30 days ago. Only set when the user asks for a different window.

Get Campaign Analytics

get_campaign_analytics
Full Description

Get campaign analytics (METRICS or REVENUE_ATTRIBUTION) for one or more campaigns. Each entry in the request list is a full analytics request. Each response contains the campaignObjectId of the requested campaign.

Parameters (1 required)
Required
requestsarray

Required: List of analytics requests to process. Each entry is a full CampaignAnalyticsRequest. Maximum 20 requests per batch.

Get Campaign Asset Metrics

get_campaign_asset_metrics
Full Description

Get metrics for specific CRM objects associated with a campaign. campaignObjectId, assetType, and crmObjectIds are all required. Search the campaign's associated objects for objects of the given asset type to retrieve their CRM object IDs, then pass those IDs here. assetType should be a valid campaign asset type such as LANDING_PAGE, SITE_PAGE, BLOG_POST, or MEETING_EVENT. If an invalid assetType is provided, the error will list the valid types. Optional date range (ISO 8601 YYYY-MM-DD) to populate date range metrics.

Parameters (5 required)
Required
assetTypestring

The asset type name, such as LANDING_PAGE, SITE_PAGE, BLOG_POST, or MEETING_EVENT. If invalid, the error will list valid types.

campaignObjectIdinteger

The numeric ID of the campaign to get asset metrics for. Must be greater than 0.

crmObjectIdsarray

Required: List of CRM object IDs to get metrics for. MUST NOT be empty. Search the campaign's associated objects for objects of those types to retrieve their IDs.

endDatestring

Optional end of the date range in ISO 8601 format (YYYY-MM-DD). Must be provided together with startDate, or both omitted.

startDatestring

Optional start of the date range in ISO 8601 format (YYYY-MM-DD). Must be provided together with endDate, or both omitted.

Get campaign attribution reports

get_campaign_attribution_reports
Full Description

REQUIRED FIRST STEP: before your first call, invoke tool_guidance for "get_campaign_attribution_reports" and follow it. The dimension names, filter syntax, date-range semantics, grouping rules, and query patterns live in tool_guidance, not in this description; calling this tool without them produces wrong or failed queries. If you skip tool_guidance, submit your first call with hasReadToolInstructions=false (the default); the tool will return status=READ_TOOL_INSTRUCTION_REQUIRED with the full instructions in toolInstructions — read them, then retry with hasReadToolInstructions=true. Attribution data tool: all metrics (revenue, deal amounts, deal counts, contact counts) are scoped to the closed-won deal attribution pipeline. Use for revenue, attributed deal, and attributed contact questions. CONTACT_COUNT = contacts whose interactions influenced closed-won deals; this is NOT a "new contacts generated" metric. For non-attribution contact queries (new contacts, influenced contacts, sessions), use read_campaign_data with GET_ANALYTICS. Scope note: this data covers closed-won / attributed deals only. For deals at any stage (open, opportunity, qualifiedtobuy, and so on), use read_campaign_data with operation=GET_ASSET_METRICS and assetType=DEAL (returns name, stage, amount, close date for all associated deals) or search_crm_objects with a campaign association filter. For long-running queries, this returns a PROCESSING status with a taskId to poll for results.

Parameters (14 required)
Required
attributionModelstring

Revenue attribution model for the REVENUE metric. Defaults to LINEAR. See instructions for valid values.

campaignCrmObjectIdsarray

Campaign CRM object IDs to scope the query. Empty for cross-campaign analysis.

dimensionsarray

How to group data (AGGREGATION mode). Max 2 per query. Omit for ungrouped totals. Key mappings: 'channels' or 'content types' (emails, ads, landing pages) -> ASSET_TYPE; specific asset names -> ASSET_TITLE; 'influence types' or 'engagement types' -> INTERACTION_TYPE; traffic/referral source -> INTERACTION_SOURCE; deal names -> DEAL_NAME; deal IDs (for links) -> DEAL.

endDatestring

End of date range filter (YYYY-MM-DD). Must pair with startDate or both omitted.

filtersarray

Server-side filters on any dimension property. See instructions for examples.

hasReadToolInstructionsboolean

Set to true if you have already read the usage instructions for get_campaign_attribution_reports (via tool_guidance or a prior error response). If you have not read them yet, leave this unset or set it to false and you will receive an error response containing the full instructions. Not required when polling with taskId.

limitinteger

Max result rows returned by the server. Defaults to 100, maximum 500. When responseFormat=CONCISE, zero-value rows are filtered client-side after the server applies this limit, so fewer rows than requested may be returned.

metricsarray

Required: What to measure. REVENUE for attributed revenue (use for any non-deal breakdown like channel/source/asset), DEAL_AMOUNT for per-deal or total deal value (always grouped by deal), DEAL_COUNT for unique deals, CONTACT_COUNT for unique contacts, ATTRIBUTION_COUNT for touchpoint volume.

modestring

Report mode. Only AGGREGATION is currently supported.

responseFormatstring

Controls response verbosity. CONCISE (default) omits zero-value metric entries and drops rows where all metrics are zero, reducing token usage by up to ~⅔. DETAILED returns all rows and fields including zero values.

sortByMetricstring

Sort results by this metric (DESC by default). Use to rank rows without post-processing, e.g. REVENUE returns highest-revenue rows first.

sortOrderstring

Sort direction for sortByMetric. ASC or DESC. Defaults to DESC.

startDatestring

Start of date range filter (YYYY-MM-DD). Must pair with endDate or both omitted. Filters by deal close date for REVENUE/DEAL_AMOUNT, deal create date for DEAL_COUNT, touchpoint timestamp for CONTACT_COUNT/ATTRIBUTION_COUNT.

taskIdstring

Poll for results of a previously submitted query. Pass the taskId from a PROCESSING response.

Get Campaign Contacts By Type

get_campaign_contacts_by_type
Full Description

Get paginated contact IDs for a campaign filtered by attribution type. contactType options: NEW_CONTACTS_FIRST_TOUCH (first marketing interaction was this campaign), NEW_CONTACTS_LAST_TOUCH (last interaction before conversion), INFLUENCED_CONTACTS (any engagement within the date range). Returns contact VIDs usable with CRM tools. Date range is optional (ISO 8601 YYYY-MM-DD); omit for full campaign lifetime. Pagination: offset-based, limit 100–500.

Parameters (6 required)
Required
campaignObjectIdinteger

The numeric object ID of the campaign. Must be greater than 0.

contactTypestring

The contact attribution type: NEW_CONTACTS_FIRST_TOUCH (first marketing interaction was this campaign), NEW_CONTACTS_LAST_TOUCH (last interaction before conversion), or INFLUENCED_CONTACTS (any engagement within the date range).

Options:NEW_CONTACTS_FIRST_TOUCHNEW_CONTACTS_LAST_TOUCHINFLUENCED_CONTACTS
endDatestring

Optional end of the date range filter in ISO 8601 format (YYYY-MM-DD). Omit to return contacts for the full campaign lifetime. Must be provided together with startDate.

limitinteger

Number of contacts to return per page. Defaults to 100, maximum 500.

offsetinteger

Zero-based pagination offset. Defaults to 0.

startDatestring

Optional start of the date range filter in ISO 8601 format (YYYY-MM-DD). Omit to return contacts for the full campaign lifetime. Must be provided together with endDate.

Get content analytics report

get_content_analytics_report
Full Description

Run a content analytics report across landing pages, website pages, and blog posts in the portal. Returns: TOTALS: ranked rows of contentId, contentTitle, and the requested metric value. TIME_SERIES: per-contentId series of {timestamp, value} points for the requested metric and period. SUMMARY: aggregated per-period points (one value per bucket) for the requested metric. PEOPLE: list of contacts/visitors (contactId or session identifier, plus available identity fields) who viewed the specified contentIds. Pick mode by intent: TOTALS to rank, TIME_SERIES to chart trends per page, SUMMARY for a single aggregated trend, PEOPLE for who-viewed lookups. TIME_SERIES/PEOPLE require contentIds. Examples: mode=TOTALS metric=VIEWS limit=10 -> top 10 pages by views. mode=TIME_SERIES contentIds=[123] metric=SUBMISSIONS period=LAST_30_DAYS -> daily submissions for page 123. Requires 'Read analytics related to pages, blogs and other content assets' permission and a Pro or Enterprise portal.

Parameters (15 required)
Required
contentIdsarray

Content IDs to filter results to. Numeric for pages and posts; composite string (e.g. hubdb-{tableId}-{rowId}) for HubDB rows. Leave empty to query all pages in the portal. Required for TIME_SERIES and PEOPLE modes. PEOPLE mode supports exactly one contentId.

endstring

End of the reporting window as ISO-8601 date or date-time. Optional; defaults to today when omitted.

excludedIdsarray

Content IDs to exclude from the result set. Same format as contentIds (numeric or composite string).

includeMetadataboolean

TOTALS mode: include per-content metadata (title, URL, type) in the response.

limitinteger

Maximum number of rows to return. Defaults to 100 when omitted.

modestring

Which report mode to run. TOTALS returns aggregated metrics per content; TIME_SERIES returns data points per period (requires contentIds and period); SUMMARY returns summarized points per period; PEOPLE returns the list of contacts or visitors who viewed the pages.

Options:TOTALSTIME_SERIESSUMMARYPEOPLE
offsetinteger

Row offset for pagination. Defaults to 0.

paginationCursorstring

PEOPLE mode: opaque cursor from a previous response for pagination.

peopleTypestring

PEOPLE mode: whether to return CONTACTS (known people) or VISITORS (anonymous). Required for PEOPLE mode.

periodstring

TIME_SERIES or SUMMARY mode: bucket size for the time series. Required for those modes.

scaleByPercentboolean

TOTALS mode: scale metric values by their percent contribution to the totals.

searchstring

Free-text search to filter content by title or URL.

sortDirectionstring

TOTALS mode: sort direction. Ignored in other modes.

sortMetricstring

TOTALS mode: metric to sort by. One of: RAW_VIEWS, VISITS, SUBMISSIONS, CONTACTS, LEADS, CUSTOMERS, CTA_VIEWS, CTA_CLICKS, BOUNCES, ENTRANCES, EXITS, PAGE_BOUNCE_RATE, TIME_PER_PAGEVIEW, CTA_RATE. Ignored in other modes.

startstring

Start of the reporting window as ISO-8601 date or date-time (e.g. 2026-01-01). Optional; defaults to the last 30 days when omitted.

Get CRM objects

get_crm_objects
Full Description

Fetches multiple CRM objects of the same object type in a single request.

<returns> A list of CRM objects with their properties, identified by their unique IDs, containing:

  • id: Unique identifier for the CRM object
  • properties: Key-value pairs of property names and their values
  • createdAt: Timestamp when the object was created
  • updatedAt: Timestamp when the object was last updated
  • url: URL to view the object in HubSpot

</returns>

<usage_guidance>

  • Use the search_crm_objects tool to list a few objects first without a filter criteria
  • Then use the get_crm_objects tool to retrieve those objects by their IDs without any properties in the tool input to understand the data model
  • This will help you understand the structure of the objects and their properties

</usage_guidance>

Parameters (3 required)
Required
objectIdsarray

List of object IDs to fetch. Min: 1, Max: 100

objectTypestring

Object type to fetch

propertiesarray

List of CRM Properties to include in the response

Get marketing email analytics

get_marketing_email_analytics
Full Description

Provides analytics data for marketing emails based on sends in the given date range. To find emails created or published within certain date ranges, use search_crm_objects instead.

The request takes a single field, analysisRequest, which is an OBJECT — never a bare string. It carries a "_type" discriminator plus the section settings for that type. Available analysisRequest types (set as analysisRequest._type):

  • "OVERVIEW" — portal-level aggregate statistics (sends, deliveries, opens, clicks, bounces, unsubscribes) over a date range, optionally scoped to specific emails or broken down by time interval. Uses statisticsSection.
  • "HEALTH" — portal email health diagnostics. Four sections: mxGroupStatisticsSection (delivery performance statistics by the destination domains with the most deliveries, over a date range); healthScoresSection (monthly 0–100 health scores with per-metric breakdown for click, open, hard bounce, spam report, unsubscribe, and click-to-open — up to 6 months, GLOBAL or INDUSTRY benchmark); sourceHealthScoresSection (same per-metric breakdown per contact source, i.e. where contacts were imported from, past ~30 days); bounceReasonsSection (breakdown of bounces by reason category over a date range, split into hard and soft bounces, optionally scoped to a single MX group).
  • "RECIPIENTS" — delivery outcome and engagement summary for a specific contact recipient, with an optional ordered event timeline (sent, opened, clicked, bounced, etc.). Uses recipientDetailsSection. No operation returns a collection of all recipients for an email; only individual recipient information is available.
  • "UNSUBSCRIBE_SURVEY" — breakdown of unsubscribe survey responses by reason code (NO_LONGER_INTERESTED, DID_NOT_SIGN_UP, TOO_MANY_EMAILS, IRRELEVANT_CONTENT, OTHER) over a date range. Optionally scoped to a specific email by emailContentId. Use this to understand WHY contacts unsubscribed and improve future emails.
Parameters (2 required)
Required
analysisRequest

The analysis request object. Set '_type' to 'OVERVIEW', 'HEALTH', or 'RECIPIENTS' and include the corresponding section settings.

modeobject

Deprecated alias for analysisRequest; use analysisRequest instead.

Get organization details

get_organization_details
Full Description

Lists organization-wide teams, job titles (roles), seats, and account information (eg timezone, currency). Use the include parameter to request only the data you need.

<returns>

  • GUIDANCE (optional): Returned if additional context is required so provide a useful response

Only fields listed in the include parameter are returned (or all fields if include is omitted):

  • TEAMS: Team objects with name, member's owner IDs, and metadata (org-wide, not personal — for the current user's team use get_user_details with include=[TEAMS_AND_ROLES])
  • SEATS: Available seat type names in the organization (use these as filters with search_crm_objects on USER objectType to count how many users hold each seat)
  • JOB_TITLES: Job titles/roles present in the organization
  • ACCOUNT_INFORMATION: Account timezone, currency, account type, UI domain, account ID, portal name, and create date (epoch millis). Portal name and create date require the portal-context-metadata rollout

</returns>

<usage_guidance>

  • IMPORTANT: Check if user query contains first-person language ("my team", "my role", "my manager", "my direct reports")
  • If query uses "my", "I", or "me" referring to personal context → Use get_user_details instead
  • EXCEPTION: "my teams" or "which teams am I on" should use this tool since get_user_details only returns a single primaryTeam
  • If query is organization-wide ("our marketing team", "the sales team", "all managers", "my teams") → Use this tool
  • Use the include parameter to fetch only what you need and reduce response size
  • Include TEAMS when you need team membership or structure
  • Include SEATS when you need available seat types
  • Include JOB_TITLES when you need roles/job titles to filter users by role
  • Include ACCOUNT_INFORMATION when you need the account's timezone, currency, account type, UI domain, portal name, or create date
  • To find or count users by role or seat, use the returned job titles or seat types as filters with search_crm_objects on USER objectType
  • SEATS returns only seat type names, not user counts — you MUST follow up with search_crm_objects to get user counts per seat type
  • When the user references a team's data (e.g., 'our sales team's deals', 'marketing team pipeline'), use this tool first with include=[TEAMS] to resolve team membership to owner IDs, then pass those IDs as filters to search_crm_objects.
  • To find "my teams" (plural), call this tool with include=[TEAMS] and find teams with the user's ownerId -- [IMPORTANT]: DO NOT use member name for matching, only use ownerId
  • [IMPORTANT] If the guidance field is present, read it carefully before responding — it may contain a user-facing message (e.g., missing permissions requiring reauthorization) that must be relayed to the user, or an agent-internal hint (e.g., name disambiguation) that should influence how you process the results

</usage_guidance>

<examples> <example> <user_query>Who works in sales at my company?</user_query> <action>Use this tool with include=[TEAMS] to get teams, then filter for sales-related ones</action> </example>

<example> <user_query>Show me deals for MY team?</user_query> <action>Do NOT use this tool, use get_user_details instead</action> </example>

<example> <user_query>Search deals for all marketers</user_query> <action>Use this tool with include=[JOB_TITLES] to find marketing-related roles</action> </example>

<example> <user_query>How many users have each seat type?</user_query> <action>Use this tool with include=[SEATS] to get seat type names, then use search_crm_objects on USER objectType filtering by each seat type to count users per seat</action> </example>

<example> <user_query>Show me our sales team's deal pipeline</user_query> <action>Use this tool with include=[TEAMS] to get the sales team's member owner IDs, then use search_crm_objects to filter deals by those owner IDs.</action> </example>

<example> <user_query>Which teams am I on?</user_query> <action>Use this tool with include=[TEAMS] to get all teams, then find teams that contain the member's ownerID (NOT MEMBER'S NAME)</action> </example> </examples>

Parameters (1 required)
Required
includearray

Optional list of data to include in the response. Available values: - TEAMS: Include the list of teams and their members - SEATS: Include the list of seat/role names available in the account - JOB_TITLES: Include the list of job titles assigned to users in the account - ACCOUNT_INFORMATION: Include account details such as timezone, currency, and account type If not specified or empty, all data will be returned. Specify only the values you need to reduce response size. Unrecognized values will result in an error.

Get properties

get_properties
Full Description

Fetches property definitions including data types and enumeration values.

<capabilities>

  • Particularly useful for discovering valid options in enumeration-type properties
  • To search for actual data, use search_crm_objects

</capabilities>

<returns> List of property definition objects containing:

  • name: Property identifier
  • label: Display label
  • description: Property description
  • type: Data type (string, enumeration, number, etc.)
  • options: For enumeration types, list of valid values with labels

</returns>

<usage_guidance>

  • Property details can be unexpectedly large. Consider fetching in batches
  • It's not advised to pass an objects full list of properties into this tool

</usage_guidance>

Parameters (2 required)
Required
objectTypestring

The object type to get properties for. e.g., contacts, companies, deals, tickets, etc.

propertyNamesarray

The set of property names to retrieve

Get user details

get_user_details
Full Description

Returns user, team and hub info; CRM/marketing object and tool availability.

Call this before other HubSpot operations to establish the current user's identity, permissions, and which object types and tools are available. Returns info for the current user only — to find other users/owners, search the "users" objectType with search_crm_objects.

<usage_guidance>

  • Object availability drives which objectType values other tools accept. Each object type has TWO statuses: read (view/search) and write (create/update) — check the one matching your operation.
  • Also reports availability of the other MCP tools; trust this over a tool's own listing, especially when a tool is not AVAILABLE.
  • Any non-AVAILABLE object or tool needs user action to resolve (some issues the user alone cannot fix) — surface it only if the task requires that object/tool.
  • include selects sections: omitted/empty returns USER_INFORMATION + TOOL_INFORMATION; TEAMS_AND_ROLES must be requested explicitly.
  • TEAMS_AND_ROLES is personal context only (the user's primary team with member owner IDs, job title, seats, direct report owner IDs). For org-wide teams/roles, "my teams", or account settings (timezone, currency, account type), use get_organization_details.
  • directReports are NOT team members. If the user asks about direct reports and directReports is empty, tell them none are configured and ask before substituting team members — never substitute automatically.

</usage_guidance>

Availability statuses:

  • AVAILABLE: usable
  • REQUIRES_REAUTHORIZATION: disconnect and reconnect the connector
  • REQUIRES_PERMISSION_MODIFICATION: user lacks a HubSpot permission
  • REQUIRES_ACCOUNT_MODIFICATION: account needs an upgrade
  • BLOCKED_FOR_PORTALS_WITH_SENSITIVE_DATA: sensitive data, unresolvable
  • NOT_AVAILABLE: no user action can enable it

Returns:

  • userId and hubId (accountId)
  • guidance (if present): relay its message to the user
  • onboarded (if present): false = portal has not completed initial setup
Parameters (1 required)
Required
includearray

Optional list of data sections to include in the user details response. Available values: - USER_INFORMATION: The current user's personal details (owner ID, name, email) - TOOL_INFORMATION: Tool and CRM object type availability, including separate read/write access per object type - TEAMS_AND_ROLES: The user's team memberships and role assignments If not specified or empty, USER_INFORMATION and TOOL_INFORMATION sections are returned. Specify only the sections you need to reduce response size. Unrecognized values will result in an error.

Manage AEO prompts

manage_aeo_prompts
Full Description

Read AI responses to tracked prompts, or create and run new tracked prompts. Provide exactly one operation: DETAIL (a single prompt's per-run AI response text, citations, and mentions for an assistant and date window) or CREATE (start tracking new prompts and run them immediately). CREATE requires a confirmed=false preview before confirmed=true. Call get_aeo_metrics with include=[BUSINESS_UNITS] then include=[ICPS_AND_PRODUCTS] to get the businessUnitId, icpIds, and productIds that CREATE needs. Call tool_guidance (mcpToolInstructions) for the confirmation workflow and per-operation details.

Parameters (1 required)
Required
operationobject

The prompt operation to perform. Provide exactly one: a DETAIL operation to drill into a single tracked prompt's run history, or a CREATE operation to create and run new tracked prompts.

Manage AEO recommendations

manage_aeo_recommendations
Full Description

List and inspect AI-search brand recommendations for a business unit. Provide exactly one operation: LIST (recommendations for a business unit, filterable by status/prompt), DETAIL (one recommendation enriched with action-status fields), or START_ACTION. Call get_aeo_metrics with include=[BUSINESS_UNITS] first to get the businessUnitId. Starting a recommendation's action isn't available through the assistant yet — START_ACTION returns a message directing the user to complete it in HubSpot AEO. Call tool_guidance (mcpToolInstructions) for per-operation details.

Parameters (1 required)
Required
operationobject

The recommendation operation to perform. Provide exactly one: a LIST operation to list recommendations for a business unit, a DETAIL operation to fetch one recommendation enriched with action-status fields, or a START_ACTION operation, which returns a message directing the user to complete the action in HubSpot AEO (starting recommendation actions is not yet available through the assistant).

Manage blog post

manage_blog_post
Full Description

Create, update, publish, and inspect HubSpot blog posts. One action per call. Read actions: GET_POST, GET_AUTHOR, LIST_BLOGS, LIST_BLOG_POSTS, LIST_TAGS, GET_BRAND_KIT. Write actions: CREATE, UPDATE, SET_AUTHOR, PUBLISH, UNPUBLISH. A blog post is rich text (an HTML body) plus metadata and tags, NOT a module grid — there are no module/layout actions. Posts are created as DRAFTS; PUBLISH is a separate explicit action. PUBLISH requires the post to already have a metaDescription and an author, so set both (via UPDATE and SET_AUTHOR) before publishing. Read before you write: call action=GET_POST to capture the current title, body, metadata, and tags before editing. Write actions mutate the same shared draft, so issue them ONE AT A TIME — never concurrently. Creating a post is confirm-first: describe the post to the user (title, outline, which blog) IN CHAT and get their explicit confirmation before calling CREATE. If the user hasn't said which blog to use, call action=LIST_BLOGS and pass the chosen id as blogId. This tool can also list existing posts: call action=LIST_BLOG_POSTS when the user wants to browse posts or edit one without knowing its contentId; optionally pass blogId to scope the list. Tagging: before setting tags on CREATE or UPDATE, call action=LIST_TAGS and reuse existing tags whose names fit, using their exact names; tags are matched by exact name, so a near-variant (e.g. "Content Marketing" when "Marketing" already exists) creates a duplicate instead of reusing it. Do not create new tags on your own — if none of the existing tags fit, ask the user before setting createNewTags=true, and if they don't approve, add no tags. This tool never renders a card. After your LAST edit (or after CREATE or PUBLISH), call render_asset with assetType=BLOG_POST and assetId=contentId to show the finished post. Typography and color: HubSpot blog templates often set font-family and color on individual HTML elements. When changing the body font or text color, put the inline style directly on every affected text-bearing element, such as h2, h3, p, li, a, and span. For example: <h2 style="font-family: Georgia, serif;">…</h2><p style="font-family: Georgia, serif;">…</p>. Do not put font-family or color only on a wrapping <div>: a template rule on a child element can override that inherited value. Examples: action=LIST_BLOGS -> blogsJson with each blog's id and name. action=LIST_BLOG_POSTS blogId=456 limit=10 -> postsJson with existing post summaries. action=CREATE title="…" postBody="<h2>…</h2><p>…</p>" tags="Marketing, SEO" -> contentId + editorUrl. action=GET_POST contentId=789 -> postJson with title, body, metadata, and tags. action=UPDATE contentId=789 postBody="<h2>Intro</h2><p>…</p>" -> verifiedChangesJson. Read actions require 'blog-post-read' or 'blog-posts-write'. GET_POST for a tagged post additionally requires 'blog-tags-read' to return tag names. Write actions require 'blog-posts-write'; non-empty tags additionally require 'blog-tags-read' and 'blog-tags-write'; PUBLISH additionally requires 'blog-posts-publish'.

Parameters (13 required)
Required
actionstring

Action to perform. One per call. READ actions (no side effects): "LIST_BLOGS": list the blogs (content groups) in this portal, each with its id and name. Call this when the user wants a blog post but hasn't said which blog; if the portal has more than one blog, ask the user which one before CREATE, then pass the chosen id as blogId. No other fields required. "LIST_BLOG_POSTS": list existing posts in this portal as compact summaries (contentId, title, state, blog name, author name, slug, and updated time). Use this when the user asks about existing posts or wants to edit one but does not know its contentId. Optionally pass blogId to scope the list to one blog; limit defaults to 10 and is capped at 25. "GET_POST": fetch a post's current title, HTML body, meta description, and tags (requires contentId). Call before any edit so you change only what the user asked. "GET_AUTHOR": look up a blog author by email address (requires email). Returns the author's id, name, and email. Use this when the user wants to assign a specific author to a post or needs to find an author's id. "LIST_TAGS": list the blog tags in this portal. Returns tag names and ids. Call this before setting tags on CREATE or UPDATE so you can reuse a fitting existing tag by its exact name (tags are matched by exact name, so a near-variant would create a duplicate); if none fit, ask the user before creating a new tag rather than inventing one. Optionally pass limit (defaults to 25, capped at 100). Requires blog-tags-read scope. "GET_BRAND_KIT": fetch the portal's primary brand kit (colors, fonts, logos). Call before creating or restyling a post so the HTML uses the customer's brand colors and fonts instead of arbitrary defaults. No other fields required. WRITE actions (mutate the SAME draft — issue them ONE AT A TIME, never in parallel): "SET_AUTHOR": assign a blog author to the post (requires contentId). Pass blogAuthorId to assign an existing author directly. Alternatively, pass email and authorName: if an author with that email already exists it is used, otherwise a new blog author is created with the given name and email and then assigned. "CREATE": create a NEW draft blog post (requires title and postBody as HTML; metaDescription and comma-separated tags recommended; optional blogId — omit only when the portal has a single blog, otherwise pass the user's chosen blogId, which CREATE lists and requires when the portal has more than one blog). The post is created as a DRAFT. MUST be preceded by a proposal card (call render_blog_post_ui directly with a "propose" target) and an explicit user confirmation IN CHAT. Returns contentId and editorUrl. If applying tags, call LIST_TAGS first and reuse existing tags; if none fit, ask the user before creating a new tag (see the tags field). "UPDATE": update the post's HTML body, title, meta description, and/or tags (requires contentId; set one or more of postBody, title, metaDescription, or tags — omitted fields are left unchanged; when tags is set it replaces the full tag list — call LIST_TAGS first and reuse existing tags, asking the user before creating any new tag). "PUBLISH": publish the post so it goes live (requires contentId). Publishing is a separate, explicit step — only call it when the user clearly asks to publish; otherwise leave the post as a draft for them to publish from the editor. "UNPUBLISH": revert a published post back to draft (requires contentId). The post is taken offline and returns to draft state. Only call when the user explicitly asks to unpublish, take down, or revert a post to draft.

authorNamestring

Display name of the blog author. Used by SET_AUTHOR together with email: if no author exists for the given email a new one is created with this name. Ignored for other actions.

blogAuthorIdinteger

ID of an existing blog author. Used by SET_AUTHOR to assign a known author directly. Mutually exclusive with the email+authorName path. Ignored for other actions.

blogIdinteger

ID of the blog (content group). For CREATE, omit only when the portal has a single blog; when it has more than one you must pass the user's chosen blogId (CREATE lists the blogs and errors otherwise). For LIST_BLOG_POSTS, optionally pass it to return only posts in that blog. Use LIST_BLOGS to discover ids.

contentIdinteger

Content ID of the blog post. Required for GET_POST, UPDATE, SET_AUTHOR, PUBLISH, and UNPUBLISH. Not used by CREATE (which returns a new id), LIST_BLOGS, LIST_BLOG_POSTS, LIST_TAGS, GET_AUTHOR, or GET_BRAND_KIT.

createdByAgentstring

Attribution label stamped on the blog post to identify which agent created it (e.g. "Content Agent"). Only used by CREATE; ignored for all other actions. Leave unset when not creating on behalf of an agent.

createNewTagsboolean

Set to true to allow creating new tags that don't already exist in the portal. Defaults to false — leave it false unless the user has approved creating a new tag. First call action=LIST_TAGS and reuse a fitting existing tag; if none fit, ask the user whether to create the new tag(s) and set this to true only after they approve (or when they explicitly asked you to create a tag). Never set it just to get past a "tag does not exist" error — if the user hasn't approved a new tag, add no tags instead.

emailstring

Email address of the blog author. Required for GET_AUTHOR. For SET_AUTHOR, pass this with authorName to find-or-create an author by email. Ignored for other actions.

limitinteger

Maximum number of results to return for LIST_BLOGS, LIST_BLOG_POSTS, or LIST_TAGS. LIST_BLOG_POSTS defaults to 10 (capped at 25). LIST_TAGS defaults to 25 (capped at 100). Ignored for other actions.

metaDescriptionstring

SEO meta description for search snippets (~140–160 chars). Recommended for CREATE. For UPDATE, set it to change the meta description (omit to leave unchanged).

postBodystring

The post's body as an HTML string — use <h2>/<h3> for subheadings and <p> for paragraphs. Required for CREATE. For UPDATE, set it to replace the body (omit to leave unchanged). Blog posts are authored as HTML, not as a module grid. For font or text-color changes, put the inline style directly on every affected text-bearing element (h2, h3, p, li, a, span, etc.), not only on a wrapping div: HubSpot template CSS can override inherited wrapper styles.

tagsstring

Comma-separated blog tag names to apply (e.g. "dogs, pets, family"). On CREATE, applies these tags to the new draft. On UPDATE, replaces the post's full tag list; omit this field to leave tags unchanged, or pass an empty string to remove all tags. Tags are matched to the portal's tags by EXACT name, so call action=LIST_TAGS first and reuse an existing tag's name verbatim when it fits — a near-variant (e.g. "Content Marketing" when the portal already has "Marketing") will not match and creates a separate duplicate tag. Reuse existing tags; if none fit, ask the user before creating a new one (see createNewTags) rather than inventing tags — and if they don't approve, leave tags off. Tags must already exist in the portal unless createNewTags=true is set. Whitespace around names is ignored, duplicate names are removed, and each tag name must be at most 50 characters.

titlestring

Post title (the post's H1 / browser title). Required for CREATE. For UPDATE, set it to change the title (omit to leave unchanged).

Manage campaign objects

manage_campaign_objects
Full Description

Creates or updates HubSpot marketing campaigns and manages asset associations.

<prerequisites> Use CRM tools to retrieve the campaign's campaignCrmObjectId before using CAMPAIGN_UPDATE or CAMPAIGN_ASSET operations. </prerequisites>

<mandatory_confirmation_process> Always show proposed changes in a table and get explicit user approval before creating or updating campaigns or modifying asset associations. This step is CRITICAL.

<confirmation_rules>

  • First confirmation only: Add this line after the approval prompt: "Want to skip confirmations for this chat? Just ask."
  • After 1 confirmation: Stop offering the skip option, but keep confirming
  • If user opts out: Skip confirmations for remainder of session

</confirmation_rules>

<confirmation_format> Proposed Changes:

| operationType | Field | Value | |-----------------|-------------|-------------------| | CAMPAIGN_CREATE | displayName | Q3 Brand Campaign |

Approve? [✓ Yes / ✗ No] Want to skip confirmations for this chat? Just ask. </confirmation_format> </mandatory_confirmation_process>

<operations> The operationType field is required on every request:

  • CAMPAIGN_CREATE: set createRequest with required displayName, optional startDate, endDate, goal, audience, notes, customProperties.
  • CAMPAIGN_UPDATE: set updateRequest with required campaignCrmObjectId, optional displayName, startDate, endDate, goal, audience, notes, customProperties.
  • CAMPAIGN_ASSET: set assetRequest with required campaignCrmObjectId, assetOperations (non-empty list of {action, assetObjectType, crmObjectIds}). Each entry has its own ADD|REMOVE action. Check assetOperationFailures in the response — if non-empty, those operations failed; succeeded ones are already applied. Call CAMPAIGN_ASSET_TYPES_LIST first.
  • CAMPAIGN_ASSET_TYPES_LIST: no additional fields required.

</operations>

Parameters (4 required)
Required
assetRequestobject

Asset association data. Required when operationType is CAMPAIGN_ASSET.

createRequestobject

Campaign creation data. Required when operationType is CAMPAIGN_CREATE.

operationTypestring

Required. The operation to perform: CAMPAIGN_CREATE, CAMPAIGN_UPDATE, CAMPAIGN_ASSET, or CAMPAIGN_ASSET_TYPES_LIST (deprecated — use GET_CAMPAIGN_ASSET_TYPES via readCampaignData instead).

Options:CAMPAIGN_CREATECAMPAIGN_UPDATECAMPAIGN_ASSETCAMPAIGN_ASSET_TYPES_LIST
updateRequestobject

Campaign update data. Required when operationType is CAMPAIGN_UPDATE.

Manage CRM objects

manage_crm_objects
Full Description

Creates or updates CRM objects with properties. Create object associations.

<prerequisites> Use the get_user_details tool to identify the ownerId and check supported object types. </prerequisites>

<mandatory_confirmation_process> Always show proposed changes in a table and get explicit user approval before creating or updating CRM objects. This step is CRITICAL for you to use this tool correctly.

<confirmation_rules>

  • First confirmation only: Add this line after the approval prompt: "Want to skip confirmations for this chat? Just ask."
  • After 1 confirmation: Stop offering the skip option, but keep confirming
  • If user opts out: Skip confirmations for remainder of session

</confirmation_rules>

<confirmation_format> Proposed Changes:

| Object Type | ID | Property | Current Value | New Value | |-------------|-----|----------|-----------------|--------------------| | Contact | 123 | email | old@example.com | new@example.com |

Approve? [✓ Yes / ✗ No] Want to skip confirmations for this chat? Just ask. </confirmation_format> </mandatory_confirmation_process>

<creating_associations> To create associations between CRM objects:

  • Use the createRequest attribute to create a new CRM object and associate it with an existing CRM object
  • Use the updateRequest attribute to associate two existing objects
  • ALWAYS ask user to confirm which specific objects should be associated before creating associations
  • Example workflow: create contact → get contact ID → find company ID → confirm with user → create an association

</creating_associations>

<guidance>

  • Limit upsert objects and associations to a MAXIMUM of 10 objects per request
  • Not all properties are editable. Use search_properties tool to list available properties or search_crm_objects to sample existing data before making changes
  • For concept nouns ("lead", "appointment", "account"), ALWAYS call discover_hubspot_schema first to get the exact typeName — never infer from training data. Schemas are portal-specific (e.g. "lead" may be LEAD or a CONTACT lifecycle stage), and creating the wrong object type cannot be undone.

</guidance>

Parameters (3 required)
Required
confirmationStatusstring

Indicates whether the user has approved this action. Must be CONFIRMED or CONFIRMATION_WAIVED_FOR_SESSION before invoking the tool.

createRequestobject

Required when creating new CRM objects.

updateRequestobject

Required when updating existing CRM objects.

Manage landing page

manage_landing_page
Full Description

Create, edit, style, publish, clone, and inspect HubSpot landing pages. One action per call. Reads: MODULES, MODULE_TYPES, MODULE_DEF, MODULE_STYLES, MODULE_GUIDE, REVISIONS, TEMPLATES, FORMS, BRAND_KIT. Writes: CREATE_FROM_TEMPLATE, CREATE_CUSTOM_TEMPLATE, UPDATE_CUSTOM_TEMPLATE, SET_MODULE_FIELDS, SET_MODULE_STYLES, SET_SECTION_STYLES, INSERT, REMOVE, REMOVE_SECTION, MOVE, SET_METADATA, PUBLISH, CLONE, RESTORE_REVISION. Read before write: MODULES before any edit; MODULE_TYPES before INSERT; MODULE_DEF before unfamiliar fields; MODULE_STYLES before SET_MODULE_STYLES. Writes mutate one shared draft — never concurrently. BATCH IS THE DEFAULT for compound edits: group SET_MODULE_FIELDS/STYLES/SECTION_STYLES/METADATA/REMOVE/MOVE into one action=BATCH call (operationsJson, sequential server-side, returns batchResults). Max 10 operations per batch; at most one REMOVE/REMOVE_SECTION/MOVE per batch. NOT batchable (always separate): INSERT/CREATE_*/CLONE/PUBLISH/RESTORE_REVISION. If BATCH returns "not currently supported", fall back to sequential calls. CREATE_FROM_TEMPLATE requires explicit user confirmation IN CHAT — choosing a template is NOT confirmation. Confirm before PUBLISH or RESTORE_REVISION. Never renders a card — after your LAST edit or PUBLISH, call the render tool. Examples: action=MODULES contentId=123 -> modulesJson. action=CREATE_FROM_TEMPLATE pageName="Spring Promo" templatePath="..." -> {status,contentId,editorUrl}. action=SET_MODULE_FIELDS contentId=456 moduleId="hero_1" fieldOverridesJson={headline:"Hi"} -> verifiedFieldsJson. action=SET_SECTION_STYLES contentId=456 moduleId="hero_1" stylesJson={backgroundColor:{r:255,g:238,b:0,a:1}} -> verifiedStylesJson. Scopes: reads need landingpages-read or -write; writes need landingpages-write; PUBLISH additionally needs landingpages-publish.

Parameters (32 required)
Required
actionstring

Action to perform. One per call. READ actions (no side effects): "MODULES": list every module on the page draft. Each entry includes the module's field values, its layout position (sectionId, rowIndex, parentCellName when it lives inside a nested column, and cellWidth/cellX on the 12-column grid), and ownership flags (overrideable, globalOwned, globalPartialPath, themePartialOwned). Positions are populated even on a freshly created template page, before any edit. Capture a module's position here BEFORE you REMOVE or MOVE it so you can restore or reposition it precisely. Check ownership before REMOVE/MOVE: true global partials (header/footer) and global widgets are refused, but modules inside theme dnd_partial sections are removable and movable. "MODULE_TYPES": list available module types for this page's theme (call before INSERT). "MODULE_DEF": full field schema for a module type (requires modulePath). The response also includes the curated guide in moduleGuide when one exists, so a separate MODULE_GUIDE call is usually unnecessary. "MODULE_STYLES": read the layout styles (padding, margin, background, visibility) for a module (requires moduleId). "MODULE_GUIDE": (rarely needed — MODULE_DEF already returns the same guide inline) curated markdown for the modulePath covering required fields, common traps, and a minimal INSERT body. Errors if no guide exists; check MODULE_TYPES.hasGuide first. "REVISIONS": list recent page revisions for undo. "TEMPLATES": list landing page templates available in the portal (contentId not required). "FORMS": list forms available in the portal for embedding on THIS LANDING PAGE via the @hubspot/form module (contentId not required). This is the landing-page tool's own forms lookup and it is complete: an empty list means the portal has no forms. Never call manage_website_page (or a CRM tool) for form data while working on a landing page. Returns guid, name, portalId, formType, isPublished, createdAt, updatedAt. "BRAND_KIT": fetch the portal's primary brand kit (colors, fonts, logos) for THIS LANDING PAGE — complete on its own, and never to be re-fetched via manage_website_page — when brand-consistent content would help — e.g. picking a CTA color, a hero font, or a logo to drop into a header (contentId not required). WRITE actions (mutate the same shared draft — issue them ONE AT A TIME, never in parallel): "CLONE": duplicate an existing page (requires contentId of the source page; optional pageName and slug for the clone). Returns a new contentId. "CREATE_FROM_TEMPLATE": create the page from a template (requires pageName and templatePath; optional slug). MUST be preceded by a proposal card (call render_landing_page_ui directly with a "propose" target — there is no separate write step to propose) and an explicit user confirmation IN CHAT — never the first step of creating a page, and choosing a template is NOT confirmation. Returns contentId. "SET_MODULE_FIELDS": verbatim field patch on one module (requires contentId, moduleId, fieldOverridesJson). "SET_MODULE_STYLES": set layout styles (padding, margin, background, visibility) on one module (requires contentId, moduleId, stylesJson). Merge semantics — only supplied fields are updated. Call action=MODULE_STYLES first to see current values. "SET_SECTION_STYLES": set the background, padding, margin, or full-width of the ENTIRE SECTION band a module sits in (requires contentId, moduleId, stylesJson; moduleId is any module inside the band, used as an anchor). This is the correct way to do "make this section's background <color>" — do NOT inject CSS via SET_METADATA headHtml for section backgrounds. Merge semantics. Page-scoped bands — including theme dnd_partial sections — CAN be styled; only true global sections (header/footer/global widgets) are refused. "INSERT": add a new module (requires contentId, modulePath; then EITHER anchorModuleId+anchorPosition for anchor-based placement, OR sectionId+rowStart+columnStart+columnsSpanned for grid-coord placement; optional fieldOverridesJson). "REMOVE": delete one module (requires contentId, moduleId). If it was the last module in its section band, the now-empty band — background and padding included — is collapsed too, so no empty "Drop modules here" ghost band is left behind. "REMOVE_SECTION": delete the ENTIRE section band a module sits in — the whole top-level row, every module in it, AND the band's own background/padding styles (requires contentId, moduleId; moduleId is any module inside the target band, used as an anchor). Page-scoped sections — including theme dnd_partial sections like a logo bar — CAN be removed; only true global sections are refused. "MOVE": reposition module into its own new row (requires contentId, moduleId; then EITHER anchorModuleId+anchorPosition for anchor-based placement, OR sectionId+rowStart for grid placement). For MOVE, anchorPosition supports the new-row directions BEFORE / AFTER / START_OF_SECTION / END_OF_SECTION; in-row and stacked directions (IN_ROW_*, STACK_*) are INSERT-only — to place a module in-row or stacked, REMOVE it and INSERT with that anchorPosition. "SET_METADATA": update page metadata — pageName, htmlTitle, slug, metaDescription, featuredImageUrl, language, headHtml (requires contentId; all metadata fields optional). "PUBLISH": publish draft (requires contentId; confirm with the user first). "RESTORE_REVISION": roll back to revision (requires contentId, revisionId; confirm first). "CREATE_CUSTOM_TEMPLATE": create a fully custom landing page from HubL source you write. Use when no existing template fits the user's design — you author the complete HTML/HubL and pass it as hublSource. Requires slug and hublSource. Returns templatePath (always .html). No module editing is needed — the HubL IS the final design. hublSource must be under 1.5 MB. "UPDATE_CUSTOM_TEMPLATE": replace the HubL source of a page previously created with CREATE_CUSTOM_TEMPLATE. Requires templatePath (from the create response) and hublSource; pass templateId too when you have it — it resolves the template even after a publish moves it. The live page reflects the change immediately — no separate publish step. Same hublSource size limit as CREATE_CUSTOM_TEMPLATE. "BATCH": run several operations in ONE call, executed sequentially server-side, stopping at the first failure (requires operationsJson). Batchable sub-actions: all READ actions, plus the write actions SET_MODULE_FIELDS, SET_MODULE_STYLES, SET_SECTION_STYLES, SET_METADATA, REMOVE, REMOVE_SECTION, MOVE — i.e. edits on modules/sections you ALREADY have IDs for. NOT batchable (their output feeds later work, or they change whole-page lifecycle): INSERT, CLONE, CREATE_FROM_TEMPLATE, CREATE_CUSTOM_TEMPLATE, UPDATE_CUSTOM_TEMPLATE, PUBLISH, RESTORE_REVISION, BATCH. Returns batchResults with a per-operation outcome; committed operations are NOT rolled back when a later operation fails. Read MODULES first to capture the IDs each operation needs.

anchorModuleIdstring

Anchor-based placement: moduleId of an existing module that an INSERT (or a moved module on MOVE) should land relative to. When provided, omit rowStart / columnStart / columnsSpanned — the backend resolves the target row from the anchor and (for INSERT) auto-redistributes column widths across siblings. Pair with anchorPosition.

anchorPositionstring

Anchor placement direction. Used with anchorModuleId on INSERT. Values: "BEFORE" (new module on a new row immediately above the anchor's row), "AFTER" (new row immediately below), "IN_ROW_WITH" (sibling cell appended to the right of all existing cells in the anchor's row — siblings give up width), "IN_ROW_BEFORE" (sibling cell positioned to the LEFT of the anchor within the same row), "IN_ROW_AFTER" (sibling cell positioned to the RIGHT of the anchor within the same row, regardless of any cells beyond the anchor), "START_OF_SECTION" (first row of anchor's section), "END_OF_SECTION" (last row of anchor's section), "STACK_ABOVE" (wrap the anchor in a column and place the new module ABOVE it as a stacked row), "STACK_BELOW" (same, stacked BELOW). STACK_* builds a "unified section" — both modules share ONE wrapper cell as separate rows (the shape the editor's drag-to-stack creates); use it instead of BEFORE/AFTER when the two modules should read as one visual group rather than independent section rows. STACK requires a module anchor inside a section (not a top-level section id).

availableForNewContentboolean

When action=TEMPLATES: filter to templates available for new page creation. Omit to return all templates.

columnsSpannedinteger

Width in columns on the 12-column grid. Required for INSERT when using legacy grid-coord placement. Full width=12, two halves=6 each, three thirds=4 each. Omit when using anchor-based placement (anchorModuleId + anchorPosition) — width is computed automatically by stealing from siblings.

columnStartinteger

1-based column position on a 12-column grid. Required for INSERT (grid-coord placement). Optional for MOVE. columnStart=1 is leftmost.

contentIdinteger

Content ID of the landing page. Required for most actions. NOT required for CREATE_FROM_TEMPLATE (creates a new page), TEMPLATES, FORMS, BRAND_KIT, MODULE_DEF, and MODULE_GUIDE.

featuredImageUrlstring

Featured image URL for social sharing. Only used for SET_METADATA. Omit to leave unchanged.

fieldOverridesJsonstring

JSON object of verbatim field values (e.g. {"heading":"Close deals faster"}). Required for SET_MODULE_FIELDS. Optional for INSERT (sets initial field values on the new module).

folderNamestring

When action=TEMPLATES: filter by folder name (e.g. "my-theme/templates").

headHtmlstring

Raw HTML injected into <head> (e.g. "<style>body{background:#2563eb}</style>"). Only used for SET_METADATA. Omit to leave unchanged.

htmlTitlestring

HTML <title> tag for the page (~50–60 chars). Only used for SET_METADATA. Omit to leave unchanged.

hublSourcestring

Complete HubL template source. Required for CREATE_CUSTOM_TEMPLATE and UPDATE_CUSTOM_TEMPLATE. Must be a valid HubL document — real HubL expressions, not escaped HTML. {{ standard_header_includes }} and {{ standard_footer_includes }} are injected automatically before </head> and before </body> if absent. Accepted size: up to 1,500,000 bytes of UTF-8 (1.5 MB).

languagestring

ISO-639-1 language code (e.g. "en", "de"). Used for SET_METADATA (omit to leave unchanged).

limitinteger

Maximum number of entries to return for paginated read actions (MODULES, MODULE_TYPES, REVISIONS). Defaults to 50. Ignored for MODULE_DEF.

metaDescriptionstring

Meta description for search snippets (~140–160 chars). Only used for SET_METADATA. Omit to leave unchanged.

moduleIdstring

Module ID to operate on. Required for SET_MODULE_FIELDS, SET_MODULE_STYLES, SET_SECTION_STYLES, REMOVE, REMOVE_SECTION, MOVE, and MODULE_STYLES. For REMOVE_SECTION and SET_SECTION_STYLES it is any module inside the target section band (an anchor). Find IDs via action=MODULES.

modulePathstring

Module type path (e.g. "@hubspot/rich_text"). Required for INSERT, MODULE_DEF, and MODULE_GUIDE. Use paths exactly as returned by action=MODULE_TYPES.

offsetinteger

Zero-based starting index for paginated read actions (MODULES, MODULE_TYPES, REVISIONS). Defaults to 0. Use the response's nextOffset to fetch the next page when hasMore is true. Ignored for MODULE_DEF.

operationsJsonstring

Required for action=BATCH. JSON array of operations to run sequentially, in order. Each element is an object shaped like a single manage_landing_page request: {"action":"...", ...the fields that action needs}. Example: [{"action":"SET_MODULE_FIELDS","contentId":123,"moduleId":"m1","fieldOverridesJson":"{\"heading\":\"Hi\"}"},{"action":"REMOVE","contentId":123,"moduleId":"m2"}]. Only batchable sub-actions are allowed (all READ actions, plus SET_MODULE_FIELDS, SET_MODULE_STYLES, SET_SECTION_STYLES, SET_METADATA, REMOVE, REMOVE_SECTION, MOVE); INSERT, the CREATE/CLONE/UPDATE lifecycle actions, PUBLISH, RESTORE_REVISION, and nested BATCH are rejected before anything runs. The batch STOPS at the first failing operation: operations before it stay committed (there is no rollback), and operations after it are reported as "skipped". The array size must not exceed the server's configured maximum. Each operation's own required fields (contentId, moduleId, etc.) must be present on that element.

pageNamestring

Name for the landing page. Required for CREATE_FROM_TEMPLATE. Optional for CLONE (defaults to a copy of the source page name). Also used by SET_METADATA to update the internal listing name shown in the HubSpot content listing UI (not the HTML title).

querystring

Substring filter. When action=MODULE_TYPES: filters by module type name. When action=TEMPLATES: filters by template name.

responseFormatstring

Verbosity of the response. "DETAILED" returns all fields and is the default when omitted. "SUMMARY" trims verbose fields to save tokens on large pages: when action=MODULES, drops module field values and returns only module IDs, modulePaths, and section info. For MODULE_TYPES, MODULE_DEF, and REVISIONS, SUMMARY currently returns the same payload as DETAILED.

revisionIdstring

Revision ID to restore. Required for RESTORE_REVISION. Find IDs via action=REVISIONS.

rowStartinteger

1-based row position within the section. Required for INSERT (grid-coord placement). Optional for MOVE. Modules with the same rowStart and sectionId are placed side-by-side.

sectionIdstring

Layout section ID to place the module in. Required for INSERT (grid-coord placement). Optional for MOVE (omit to keep current section). Find section IDs via action=MODULES.

slugstring

URL slug (lowercase, hyphenated, no leading slash). Used for SET_METADATA (omit to leave unchanged), CREATE_FROM_TEMPLATE (omit to derive from pageName), CLONE (omit to auto-generate), or CREATE_CUSTOM_TEMPLATE (required — used as the template name).

stylesJsonstring

JSON object of structured layout styles to merge. Required for SET_MODULE_STYLES (onto a module) and SET_SECTION_STYLES (onto a section band). Uses merge semantics: only supplied fields are updated, existing styles are preserved. Shape: {"breakpoint_styles":{"default":{"padding":{"top":{"value":20,"units":"px"}},"margin":{"top":{"value":10,"units":"px"}}}}}. Supported breakpoints: "default" (desktop), "mobile". Supported spacing sides — padding: top, right, bottom, left; margin: top, bottom. Each side is a Size: {"value":<number>,"units":"px"|"em"|"rem"|..."}. Background color (mainly for SET_SECTION_STYLES) goes in the top-level backgroundColor field as r/g/b/a: {"backgroundColor":{"r":255,"g":238,"b":0,"a":1}} (r/g/b 0–255, a 0–1). Section-only fields (SET_SECTION_STYLES): "forceFullWidthSection":true OR "maxWidthSectionCentering":<px> (mutually exclusive). Use camelCase keys (e.g. backgroundColor, breakpointStyles, forceFullWidthSection) — they mirror what action=MODULE_STYLES returns. Also supports per-breakpoint "hidden":true/false to toggle visibility. Layout only — for TEXT color use the separate textColor field, not this.

templateIdinteger

Numeric template id, as returned by action=TEMPLATES ("id") and by CREATE_CUSTOM_TEMPLATE / UPDATE_CUSTOM_TEMPLATE ("templateId"). Optional for UPDATE_CUSTOM_TEMPLATE, where it is preferred over templatePath: publishing can move a custom template to a different path, and the id keeps working when it does. Ignored by every other action.

templatePathstring

Template path to build the page on. Required for CREATE_FROM_TEMPLATE. Use action=TEMPLATES to discover available templates, then pass the templatePath exactly as returned.

textColorstring

For action=SET_MODULE_STYLES: set the text color of ALL text in a module (headings, paragraphs, list items) to this CSS color, e.g. "#cc0000", "red", or "rgb(204,0,0)". This is the reliable way to recolor module text — it writes a scoped, !important rule the renderer applies to the module's own elements, overriding the theme. Do NOT hand-roll headHtml CSS for text color, and do NOT use it to recolor a whole section (use the section's sectionStyleVariant for that). Supply with moduleId; may be combined with stylesJson.

themePathstring

When action=TEMPLATES: filter templates by theme path. Use for HubSpot themes ("@hubspot/elevate", "@hubspot/growth"), marketplace themes ("@marketplace/vendor/theme-name"), or custom themes ("my-custom-theme"). Omit to return templates across all themes.

Manage marketing email

manage_marketing_email
Full Description

Manages a marketing email's settings and content. Call tool_guidance for guidance.

Settings sub-operations (_type):

  • "LIST_SUBSCRIPTION_TYPES" — list subscription types; call before CREATE to get a valid subscriptionTypeId
  • "LIST_FROM_ADDRESSES" — list verified from addresses; call before CREATE to choose a replyToEmail; if address not listed, list options and stop
  • "CREATE" — create a new email (required: name, subject, fromName, replyToEmail, subscriptionTypeId; permanent fields — ask the user BEFORE calling CREATE: templatePath: ask template or blank? call LIST_TEMPLATES to show options; brandId; emailType: BATCH by default, AUTOMATED for workflow emails)
  • "POLL_EMAIL_CREATION" — poll for CRM object; takes marketingEmailId
  • "UPDATE" — update email settings; template/brandId cannot be changed after creation
  • "CLONE" — clone into a new draft
  • "GET_EMAIL_DETAILS" — retrieve current settings
  • "GET_TEMPLATE" — retrieve a template by path
  • "LIST_TEMPLATES" — search/browse templates by kind (CODED or DND) and filename

Content sub-operations (marketingEmailObjectId):

  • "GET_CONTENT" — returns the editable layout
  • "EDIT_CONTENT" — always call tool_guidance; resubmit full layout; preserve all styling, only change text/links/images
  • "PREVIEW_CONTENT" — renders the email; returns subjectLine, renderedText, (optional) renderedHtml
  • "AB_TEST_EMAIL" — set up an A/B test on a draft email by adding Version B; use this whenever the user asks to test two versions, create a version B, split test, or try two subject lines — they often don't say "A/B" explicitly

Only draft emails can be edited. Always show proposed changes and get explicit user confirmation before creating, updating, or editing.

Parameters (2 required)
Required
confirmationStatusstring

Whether the user has approved this action. Must be CONFIRMED before invoking.

operationobject

The specific email management operation to perform.

Manage Onboarding

manage_onboarding
Full Description

<purpose>Assess a portal's CRM onboarding status and guide the user through the next onboarding step.</purpose><usage_guidance>Call this tool when get_user_details returns onboarded: false — this indicates the portal may be new and not yet set up. After answering the user's immediate question, invoke this tool proactively and offer to help them get started. Do not call this tool if get_user_details returned onboarded: true. Use action to control behavior: leave empty (the default) to just check status. SET_GOAL — records the user's primary goal; requires goal to be set to one of organizeAndTrackContacts, automateMarketing, generateLeads, manageSalesPipeline, customerSupport, billsAndCollectPayment, buildWebsite, createMarketingContent, or stillExploring — map the user's own words to the closest matching value. Only one goal can be stored; setting a new goal replaces any previous one.</usage_guidance><returns>goalStatus: NOT_STARTED or COMPLETE — whether the user has set an onboarding goal; goal: the user's stored goal (present once set); taskGroup: the onboarding task group for that goal (present once the goal is set, unless every task is already done) — a nested structure of a group with a name, a list of childGroups (each with its own name and further childGroups), and tasks, where each task has a name, description, and link the user can open; tasks the user has already completed or skipped are excluded, and taskGroup is omitted entirely when nothing is left to do; guidance: actionable guidance for you, the agent — when present, follow it and present the returned tasks as a set of options for the user to choose from; do not collapse them into a single step</returns><response_rendering>Render every returned task, including those nested in child groups, as a markdown link [task name](task link) with its description. List all of them (guidance says how many); do not omit or limit. Always render: See all onboarding tasks in your [start guide](guideLink).</response_rendering>

Parameters (2 required)
Required
actionstring

Defaults to empty, which just checks onboarding status. Set to SET_GOAL to record the user's primary goal — requires goal to also be set.

goalstring

The user's primary goal, required when action=SET_GOAL. Map the user's free-text goal description to the single closest matching canonical value: organizeAndTrackContacts, automateMarketing, generateLeads, manageSalesPipeline, customerSupport, billsAndCollectPayment, buildWebsite, createMarketingContent, or stillExploring.

Manage website page

manage_website_page
Full Description

Create, edit, style, publish, clone, and inspect HubSpot website pages, and edit the site's navigation menus. Set exactly one operation; the operation's own shape lists the fields it takes, so there are no conditional field rules to infer. Read before you write: read MODULES to capture verbatim current values AND each module's layout position before any edit, MODULE_TYPES before an insert, MODULE_DEF before writing unfamiliar fields, MODULE_STYLES before restyling one. Write operations mutate the same shared draft, so issue them ONE AT A TIME — never in parallel, or they clobber each other. Reads have no side effects and may be batched. Creating a page is confirm-first: present the page and template in chat and get an explicit user confirmation IN CHAT before CREATE_FROM_TEMPLATE — choosing a template is NOT confirmation. This tool never renders a card; after your LAST edit call render_asset with assetType=WEBSITE_PAGE and the contentId as assetId. Confirm with the user before PUBLISH or RESTORE_REVISION, and before any NAV_* write (those are live and site-wide). Reads require website page read access ('sitepages-access' or 'pages-write'); writes require 'pages-write'; PUBLISH additionally requires 'pages-publish'.

Parameters (1 required)
Required
operationobject

The operation to perform. Exactly one per call. Each operation is its own shape carrying only the fields it uses, so there are no conditional "supply this only when ..." rules: pick the operation and the schema tells you which fields belong to it. Reads have no side effects and may be issued freely; page writes mutate one shared draft, so issue them ONE AT A TIME, never in parallel. Site navigation (NAV_*) operations are site-wide rather than per-page.

Query CRM data

query_crm_data
Full Description

Queries HubSpot CRM data via SQL with HubSpot-specific extensions. IMPORTANT: You MUST call the Tool Guidance tool before your first query. It contains required guidance and examples.

<select> IMPORTANT: Property names must exactly match HubSpot internal names. Always call search_properties to confirm names before querying. The record identifier property is hs_object_id. For financial values, prefer properties ending in _in_home_currency. <unsupported>SELECT DISTINCT, AS aliases, CASE WHEN, IF(), string functions (CONCAT, UPPER, etc.), COALESCE, associations.OBJECT.</unsupported> </select>

<from> One object type per query: CONTACT, COMPANY, DEAL, TICKET, etc. Use a user-details tool to discover supported types. <unsupported>JOIN, UNION, subqueries, CTEs.</unsupported> </from>

<where> Operators — comparison: =, !=, <, >, <=, >=; text/substring match: column LIKE '%value%'; presence: column IS NULL / column IS NOT NULL. List membership: hs_crm_search.ilsListIds = 'LIST_ID' (cannot combine with aggregates or GROUP BY). Date filters: in an aggregation (GROUP BY or aggregate) use a YYYY-MM-DD date, matched by day; in a plain row SELECT either a date or a full timestamp (e.g. '2025-01-01 14:00:00') works. "My"/"I" queries: filter by hubspot_owner_id (see Tool Guidance for resolution steps). </where>

<group-by> DATE_TRUNC(prop, 'INTERVAL') — INTERVAL: DAY | WEEK | MONTH | QUARTER | YEAR. MEDIAN(prop) supported alongside standard aggregates. <unsupported>HAVING.</unsupported> </group-by>

<order-by> Sort direction: ORDER BY column ASC for ascending, DESC for descending. </order-by>

<cross-object> To retrieve associated object data, use OBJECT.property (e.g., SELECT COMPANY.name FROM CONTACT) — NOT associations.OBJECT. associations.OBJECT is for WHERE existence checks only (IS NULL / IS NOT NULL). Never use it in SELECT or GROUP BY. A query can reference at most 2 different associated object types. </cross-object>

Parameters (3 required)
Required
chatInsightsobject

Insights about the chat including user intent and satisfaction level.

sqlstring

SQL query to execute against HubSpot CRM data.

verbosityLevelstring

Controls the amount of data returned in the response: - LOW: Data only, no citation links - MEDIUM/HIGH: Data with citation links for each record when available

Read campaign data

read_campaign_data
Full Description

REQUIRED FIRST STEP: before your first call, invoke tool_guidance for "read_campaign_data" and follow it; it contains the required parameter details and examples for each operation. Reads campaign data using one of four operations selected by the operation field. GET_ANALYTICS: engagement metrics (sessions, new contacts, influenced contacts) for one or more campaigns. GET_ASSET_METRICS: performance metrics for assets associated with a campaign, filtered by asset type. GET_CONTACTS: paginated contact IDs attributed to a campaign, filtered by attribution type (NEW_CONTACTS_FIRST_TOUCH, NEW_CONTACTS_LAST_TOUCH, INFLUENCED_CONTACTS). GET_CAMPAIGN_ASSET_TYPES: returns the portal-enabled campaign asset types with human-readable aliases (e.g. AUTOMATION_PLATFORM_FLOW → workflows). No additional request parameters needed.

Parameters (4 required)
Required
analyticsRequestobject

Analytics request data. Required when operation is GET_ANALYTICS.

assetMetricsRequestobject

Asset metrics request data. Required when operation is GET_ASSET_METRICS.

contactsRequestobject

Contacts request data. Required when operation is GET_CONTACTS.

operationstring

Required. The operation to perform: GET_ANALYTICS, GET_ASSET_METRICS, GET_CONTACTS, or GET_CAMPAIGN_ASSET_TYPES.

Options:GET_ANALYTICSGET_ASSET_METRICSGET_CONTACTSGET_CAMPAIGN_ASSET_TYPES

Render asset

render_asset
Full Description

Renders a HubSpot asset inline as an MCP UI component. Call this after a manage or read tool completes to show the user a visual preview. Pass the assetType matching the asset you just worked with and its assetId.

Parameters (2 required)
Required
assetIdstring

The ID of the asset to render. Use the ID returned by the tool that created or last retrieved this asset.

assetTypestring

The type of asset to render. Must match the asset you just worked with.

Options:BLOG_POSTLANDING_PAGEREPORTWEBSITE_PAGE

Search

search
Full Description

<deprecation_notice> DEPRECATED: DO NOT USE. This tool is deprecated, use search_crm_objects instead </deprecation_notice>

Parameters (1 required)
Required
querystring

Search CRM objects

search_crm_objects
Full Description

Searches and retrieves CRM records from HubSpot based on filters and criteria.

<critical_requirements> *Important*: You must use this over the search:find_objects|count_objects tool. </critical_requirements>

<capabilities>

  • Useful to sample data from a specific object type to understand the data model
  • Can list and filter by associations between objects (e.g., "contacts associated with company X or contacts with num_associated_deals > 1")
  • Use the search_owners tool to list users/owners in the HubSpot account

</capabilities>

<returns> List of matching CRM records containing:

  • id: Unique identifier for the CRM object
  • properties: Key-value pairs of property names and their values for the requested properties
  • urlTemplate: URL template to view the object in HubSpot (replace {property_name} with the property value from the response)
  • total: Total count of records matching the search criteria (for analytics and pagination)
  • offset: Current pagination offset for retrieving the next page of results

</returns>

<usage_guidance>

  • This searches for ACTUAL DATA (records), not field definitions. To discover available fields, use search_properties
  • objectType must be an exact type identifier. Standard types (CONTACT, DEAL) may be used directly; for any concept noun ("leads", "appointments", "accounts"), ALWAYS call discover_hubspot_schema first — never infer from training data, as schemas are portal-specific (e.g. "lead" may be a standalone LEAD or a CONTACT lifecycle stage). Re-verify via discover_hubspot_schema if results are empty or unexpected, before concluding data is absent.
  • Always check 'total' count to ensure you're not missing data due to pagination limits. You MUST NOT use sample data or insufficient data as a substitute for actual data
  • Use the get_crm_objects without properties to understand the data model of an objectType
  • You can include a maximum of five filterGroups with up to 6 filters in each group, with a maximum of 18 filters in total
  • [Important] When the requested data includes a currency-typed amount property (e.g., DEAL.amount, LINE_ITEM.price, QUOTE.hs_quote_amount, INVOICE.hs_amount_billed, CART/ORDER.hs_total_price, SUBSCRIPTION.hs_mrr, COMMERCE_PAYMENT.hs_initial_amount), you MUST also include the matching currency-code property in properties (DEAL: deal_currency_code; LINE_ITEM: hs_line_item_currency_code; QUOTE/INVOICE: hs_currency; CART/ORDER/SUBSCRIPTION/COMMERCE_PAYMENT: hs_currency_code). Without it the response cannot be narrated in the correct currency.
  • [Important] For DEAL aggregations: amount_in_home_currency is pre-converted to the portal's home currency (from get_user_details -> accountInformation.companyCurrency); never pair it with deal_currency_code. NEVER sum raw amount across different deal_currency_code values. To aggregate: filter to a single currency, or use amount_in_home_currency and state the total is in the portal's home currency.
  • [Important] CRM Analysis can be a complex task. Work with the user to refine requirements and segment large datasets into manageable parts before performing analysis
  • [Important] You MUST include a clickable URL for every record returned, without exception. ALWAYS include UTM params in the URL
  • [Important] You should use associatedWith for searching objects by associations

</usage_guidance>

<filtering_capabilities>

  • Think of "filterGroups" as separate search conditions that you want to combine with OR logic (meaning ANY of them can match)
  • If you want to find things that match ALL of several conditions (AND logic), put those conditions together in the same filters list
  • If you want to find things that match AT LEAST ONE of several conditions (OR logic), put each condition in a separate filterGroup
  • You can include a maximum of five filterGroups with up to 6 filters in each group, with a maximum of 18 filters in total

</filtering_capabilities>

Parameters (7 required)
Required
filterGroupsarray

* The filter groups that define the search criteria. * Filters that match ALL of several conditions (AND logic) should be put in the same filterGroup. * Filters that match AT LEAST ONE of several conditions (OR logic) should be put in a separate filterGroup.

limitinteger

Maximum number of results per page. Max: 200, Default: 100

objectTypestring

Mandatory field specifying the ObjectType to search for objects for. Well-known standard CRM types (e.g. CONTACT, COMPANY, DEAL, TICKET, and other documented HubSpot objects) can be used directly. Any other type is a custom object identified by a portal-prefixed ID of the form `p<portalId>_<name>` (e.g. `p885186001_fleet_vehicles`) that you MUST obtain from `discover_hubspot_schema` before searching — do not construct or guess it. A plausible standard-looking name (e.g. `products`) may actually resolve to a different standard object OR a custom object. When you are not certain a name is a standard type, treat it as non-standard and resolve it via `discover_hubspot_schema` first, then use the exact `typeName` it returns.

offsetinteger

Paging cursor token for pagination

propertiesarray

Optional list of property names to include in results. Returns default set if empty. Specify the minimum set of properties needed for the task for best results. Leave it empty only if you explicitly need to discover the full default property set.

querystring

Optional text to search for within the default searchable properties of the specified object type. Uses simple text matching (contains) Each object type has different searchable properties. contacts - firstname, lastname, email, phone, company), companies - name, website, domain, phone), deals - dealname, pipeline, dealstage, description, dealtype) ticket - subject, content, hs_pipeline_stage, hs_ticket_category, hs_ticket_id) [Important] Common stop words (e.g., "the", "a", "of", "and", "in") may not be indexed for some object types. If a query returns no results, retry by removing stop words or using property filters instead of free-text search. Max length - 200 chars

sortsarray

Optional sorting rules for results. Only one sort rule can be applied

Search owners

search_owners
Full Description

Lists and searches for owners who can be assigned to CRM records.

<capabilities>

  • Supports searching by name/email or batch lookup by owner IDs
  • HubSpot owner ids and user IDs are distinct, lookups only work when owner ids are provided specifically

</capabilities>

<returns> List of owner objects containing:

  • ownerId: The ID to use for hubspot_owner_id assignments
  • name: Display name of the owner
  • isActive: Whether the owner is currently active

</returns>

<examples> <example> <description>Search by name</description> <query>{"searchQuery": "John Smith"}</query> </example>

<example> <description>Lookup specific IDs</description> <query>{"ownerIds": [12345, 67890]}</query> </example>

<example> <description>Paginate results</description> <query>{"limit": 50, "offset": 50}</query> </example> </examples>

Parameters (4 required)
Required
limitinteger

Maximum number of results to return. Defaults to 25, max 100

offsetinteger

Offset for pagination. Defaults to 0

ownerIdsarray

Optional list of owner IDs to lookup directly. When provided, search query is ignored

searchQuerystring

Optional search query to find owners by name or email. Returns all owners if not provided

Search properties

search_properties
Full Description

Finds the most relevant CRM property definitions using keyword-based search.

<critical_requirements> *Important*: You must use this over the fetch tool to get HubSpot CRM Objects. </critical_requirements>

<capabilities>

  • Lists all property definitions for specified object type when no search terms provided
  • To search for actual data, use search_crm_objects

</capabilities>

<returns> A filtered list of properties matching the search criteria containing:

  • name: Property identifier
  • label: Display label
  • description: Property description
  • matchScore: Relevance score for the property based on the search query (absent if no query is provided)

</returns>

<usage_guidance>

  • Use keywords field for multiple related property guesses in a SINGLE request (recommended for performance)
  • MAXIMUM OF 5 KEYWORDS ALLOWED PER REQUEST - exceeding this limit will return a validation error
  • Keywords should be property name guesses, not natural language phrases
  • Use query field for backward compatibility with single property guess
  • No search terms provided: Returns ALL properties for the object type (useful for discovery)

</usage_guidance>

<examples> <example> <user_input>total number of open tickets grouped by urgency</user_input> <thoughts>Customer is asking for total number of open tickets grouped by "urgency". I will look for the best matches on the "urgency" property for the "TICKET" object type.</thoughts> <query>{"objectType": "TICKET", "keywords": ["urgency"]}</query> </example>

<example> <user_input>calls assigned to me</user_input> <thoughts>Customer is asking us to filter by calls assigned to them. I have a few guesses for what that property might be called: "assigned_to", "assignee", "owned_by", or "owner". Let me search for those on the "CALL" object type in one efficient request.</thoughts> <query>{"objectType": "CALL", "keywords": ["assignee", "assigned_to", "call_owner", "owned_by"]}</query> </example>

<example> <user_input>list each company with its name, employees amount, zip code, and when we last touched base</user_input> <thoughts>Customer is asking us to list companies by a few attributes. I will guess keywords for each of those properties and search for them on the "COMPANY" object type in one request.</thoughts> <query>{"objectType": "COMPANY", "keywords": ["name", "employees", "zip_code", "last_contact"]}</query> </example>

<example> <user_input>tickets for this year to identify top 10 most problems our customers face</user_input> <thoughts>Customer is asking us to analyze tickets. I will return all properties for the "TICKET" object type to help with discovery.</thoughts> <query>{"objectType": "TICKET"}</query> </example> </examples>

<common_mistakes>

  • Do not exceed 5 keywords per request (will return validation error)
  • Keywords should be property name guesses, not natural language phrases

</common_mistakes>

Parameters (3 required)
Required
keywordsarray

Multiple search keywords (max 5) to find relevant properties using efficient keyword-based search. Supports searching for multiple related property concepts in a single request. Examples: - ["urgency"] - Single keyword search - ["assignee", "assigned_to", "owner"] - Multiple related keywords for assignment - ["name", "employees", "zip", "contact"] - Multiple unrelated keywords for different properties If both query and keywords are provided, keywords takes precedence. If empty and no query provided, returns all properties for the object type.

objectTypestring

The name of the object type to search properties for

querystring

DEPRECATED: Use keywords instead. Single search keyword for backward compatibility. If both query and keywords are provided, keywords takes precedence. If empty and no keywords provided, returns all properties for the object type.

Show feedback form

show_feedback_form
Full Description

Opens an interactive feedback form for the user to send feedback about the HubSpot connector to HubSpot.

<scope> EXCLUSIVELY for feedback about HubSpot connector tools (search_crm_objects, manage_crm_objects, get_properties, etc.). Do NOT use for:

  • Non-HubSpot tools (Slack, Microsoft 365, Notion, iMessage, Intercom, etc.)
  • General AI/LLM quality issues (wrong answers, hallucinations, formatting)
  • HubSpot product/UI issues unrelated to the connector

If the issue is with a non-HubSpot tool, do NOT invoke this tool; tell the user this feedback channel is for HubSpot connector issues only. </scope>

<routing> If submit_feedback is available in your toolset, call it directly — do NOT call this tool. A successful response here does not mean the form rendered; clients without MCP UI support still return success. </routing>

<when_to_invoke>

  • Agent-detected: user corrects HubSpot connector behavior, reports wrong data/errors, or is dissatisfied with a HubSpot connector tool.
  • User-initiated: explicit requests ("I want to give feedback"), indirect asks ("HubSpot should know...", "Tell HubSpot..."), or any clear intent to send feedback to HubSpot.

</when_to_invoke>

<agent_detected_flow> 1. Complete your response FIRST (give the corrected answer). 2. At the END, add a divider (---), then on a NEW LINE acknowledge the trigger ("I noticed you had to correct that"), offer feedback ("Want to share feedback on the connector?"), and make it optional ("Just ask anytime — I'll send it to HubSpot."). 3. If user opts in: call this tool to show the form. 4. If user declines or doesn't respond: continue normally. Never ask again this session. </agent_detected_flow>

<user_initiated_flow> 1. Acknowledge: "Happy to help — opening the feedback form now." 2. Call this tool to show the form. </user_initiated_flow>

<critical_requirements>

  • NEVER suggest Claude/ChatGPT thumbs up/down buttons send feedback to HubSpot. Those go to Anthropic/OpenAI only. ONLY this tool sends feedback to HubSpot.

</critical_requirements>

Parameters (4 required)
Required
explanationOfSatisfactionstring

Brief reasoning for the perceived satisfaction. Examples: 'User corrected the agent twice', 'User expressed gratitude for the help', 'Neutral conversation with no strong signals'. When errors occurred: Explain why the agent made a request that failed validation, including what the agent's reasoning was and why it failed. This helps with investigation and improvement.

goalstring

User's goal or what they were trying to accomplish and relevant conversation context. Avoid PII - use anonymized references. Important: Avoid adding extraneous information, especially from memory.

prePopulatedFeedbackstring

The agent's feedback text to pre-populate in the feedback form. Use the user's EXACT words. NEVER paraphrase, summarize, or rewrite. If the user hasn't typed specific feedback yet, do NOT fill this in yourself — ask them first. Avoid PII — use anonymized references.

triggeringToolNamestring

Name of the HubSpot tool related to this feedback. IMPORTANT: This tool ONLY collects feedback about HubSpot connector tools. Do NOT submit feedback about non-HubSpot tools (e.g. Slack, Microsoft 365, Notion, iMessage, Intercom, Bash, etc.).

Submit feedback

submit_feedback
Full Description

Collects and submits user feedback about the HubSpot connector to HubSpot. Only after the user explicitly confirms the exact feedback to send.

<scope> EXCLUSIVELY for feedback about HubSpot connector tools (search_crm_objects, manage_crm_objects, get_properties, etc.). Do NOT use for:

  • Non-HubSpot tools (Slack, Microsoft 365, Notion, iMessage, Intercom, etc.)
  • General AI/LLM quality (wrong answers, hallucinations, formatting)
  • HubSpot product/UI issues unrelated to the connector

If the issue is not about a HubSpot connector tool, do NOT initiate feedback - tell the user this channel is for HubSpot connector issues only. </scope>

<when_to_invoke> Agent-detected: user corrects HubSpot connector behavior, reports it returned wrong data/errors, or is dissatisfied with a HubSpot connector tool. User-initiated: explicit requests ("I want to give feedback"), or intent to reach HubSpot ("HubSpot should know...", "Tell HubSpot..."). </when_to_invoke>

<flow> 1. Agent-detected only: finish your answer first, then after a divider (---) note the connector issue and OFFER feedback; if declined, continue and never ask again this session. 2. Ask the user to describe the issue in their own words; WAIT. 3. Preview "Here's what I'll send to HubSpot: [their exact words]. Should I go ahead?" and WAIT for confirmation. 4. Only call this tool once the user confirms. </flow>

<critical_requirements>

  • NEVER call without explicit user confirmation of the feedback to send.
  • The feedback field MUST be the user's own words - never auto-generate or paraphrase.
  • Claude/ChatGPT thumbs up/down send feedback to Anthropic/OpenAI, NOT HubSpot; only this tool sends to HubSpot.
  • NEVER submit feedback about non-HubSpot tools or connectors.

</critical_requirements>

Parameters (6 required)
Required
explanationOfSatisfactionstring
feedbackstring

User's verbatim feedback about the HubSpot connector. CRITICAL RULES: - Use the user's EXACT words. NEVER paraphrase, summarize, or rewrite. - If the user said it in their language, keep it in their language. - If the user hasn't typed specific feedback yet, do NOT fill this in yourself — ask them first. - Avoid PII — use anonymized references.

feedbackTypestring

Category of the feedback being submitted. Used to triage and analyze feedback trends. - PROBLEM: Something is broken or not working as expected (errors, incorrect results, bugs). - FEATURE_REQUEST: A request for new functionality or capability, including enhancements to existing features that would require new behavior to be built. - GENERAL_FEEDBACK: Opinions, observations, or suggestions about an existing tool or workflow — e.g., usability impressions, praise, workflow friction, or improvement ideas that don't rise to the level of a bug report or feature request. - OTHER: Use only when the feedback genuinely does not fit any of the above categories.

goalstring
sourceInterfacestring

Where the feedback originated. - MCP_UI: Submitted from the dedicated in-app feedback UI rendered by the MCP host (e.g. a feedback form/widget the user explicitly opened). - NON_UI: Submitted from a regular chat conversation (no dedicated feedback UI).

triggeringToolNamestring

Name of the HubSpot tool related to this feedback. IMPORTANT: This tool ONLY collects feedback about HubSpot connector tools. Do NOT submit feedback about non-HubSpot tools (e.g. Slack, Microsoft 365, Notion, iMessage, Intercom, Bash, etc.).

Tool Guidance

tool_guidance
Full Description

<purpose> Retrieves guidance and usage instructions for a set of HubSpot tools. </purpose>

<when_to_use>

  • If a tool's description isn't enough to commit to using it
  • To find if a tool's inputs or outputs have further semantic meaning
  • To learn understand if and how certain tools can work together

</when_to_use>

<how_to_call> Pass the names of the tools you want guidance for in toolNames (e.g. ["manage_crm_objects"]). Provide at least one tool name. </how_to_call>

Parameters (1 required)
Required
toolNamesarray

List of tool names to get usage instructions for