Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Connect AI agents to the HubSpot MCP server

Vendor MCP
Open markdown

The HubSpot MCP connector routes your AI agent's tool calls to HubSpot's own MCP server through Scalekit. Each user signs in to HubSpot once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 28 tools.

Tools
28
What they doRead · write · destructive
20 · 5 · 320 read5 write3 destructive
Users sign in with
OAuth app
Scalekit's or your own

Setup

  1. Install the SDK

    Terminal window
    npm install @scalekit-sdk/node dotenv
  2. Set your credentials

    Add your Scalekit credentials to your .env file. Find values in app.scalekit.com > Developers > API Credentials.

    .env
    SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
    SCALEKIT_CLIENT_ID=<your-client-id>
    SCALEKIT_CLIENT_SECRET=<your-client-secret>
  3. Create the HubSpot MCP connection

    In AgentKit > Connections, create a HubSpot MCP connection. The name you give it is the connection_name your code passes. See Configure connections.

    Scalekit credentials are available for HubSpot, so you don't need to register an OAuth app. To show your own app on the consent screen, use your own credentials instead.

    Use your own OAuth app

    Register your Scalekit environment with the HubSpot MCP connector so Scalekit handles the OAuth flow and token lifecycle for your users. HubSpot MCP uses a dedicated MCP Auth App — not a Legacy App or a standard Public App.

    1. Copy the redirect URI from Scalekit

      • In Scalekit dashboard, go to AgentKit > Connections > Create Connection.
      • Search for HubSpot MCP and click Create.
      • Copy the Redirect URI from the connection details panel. It looks like:
        https://<YOUR_ENV>.scalekit.cloud/sso/v1/oauth/conn_<ID>/callback
    2. Create an MCP auth app in HubSpot

      • Log in to developers.hubspot.com and open your developer account.
      • In the left sidebar, click MCP Auth Apps (marked Beta). Do not use Legacy Apps or Projects.

      HubSpot developer portal showing the MCP Auth Apps section in the left sidebar

      • Click Create MCP auth app (top right).
      • Enter an App name, for example Agent Auth, and complete any required fields.
      • Click Create.
    3. Add the redirect URI and configure scopes

      • Inside your new MCP auth app, navigate to the Auth or OAuth settings section.

      • Under Redirect URLs, paste the Scalekit redirect URI you copied in step 1 and save.

      • Under Scopes, add the scopes your agent needs. Start with:

        crm.objects.contacts.read
        crm.objects.contacts.write
        crm.objects.companies.read
        crm.objects.deals.read

        Add additional scopes based on the tools your agent will use (for example, content scopes for landing pages and campaigns).

    4. Copy your app credentials

      • In your MCP auth app settings, find the App ID (visible in the app list as a number, for example 43664586).
      • Locate your Client ID and Client Secret under the OAuth settings.
    5. Add credentials in Scalekit

      • In Scalekit dashboard, go to AgentKit > Connections and open the HubSpot MCP connection you created.
      • Enter:
        • Client ID — from your MCP auth app
        • Client Secret — from your MCP auth app
        • Permissions — the scope strings you configured in step 3 (for example, crm.objects.contacts.read crm.objects.deals.read)
      • Click Save.
  4. Authorize a user and make your first call

    quickstart.mts
    import { ScalekitClient } from '@scalekit-sdk/node'
    import 'dotenv/config'
    import { createInterface } from 'node:readline/promises'
    const scalekit = new ScalekitClient(
    process.env.SCALEKIT_ENVIRONMENT_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET,
    )
    const actions = scalekit.actions
    const connector = 'hubspotmcp'
    const identifier = 'user_123'
    // Generate an authorization link for the user
    const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
    console.log('Authorize HubSpot MCP:', link)
    const rl = createInterface({ input: process.stdin, output: process.stdout })
    await rl.question('Press Enter after authorizing...')
    rl.close()
    // Make your first call
    const result = await actions.executeTool({
    connector,
    identifier,
    toolName: 'hubspotmcp_get_aeo_metrics',
    toolInput: {},
    })
    console.log(result)
    Terminal window
    npx tsx quickstart.mts

    Each user signs in once. See Authorize a user for the full flow and statuses.

Tools

Pass the exact name to execute_tool
Try in PlaygroundRequest a tool
  • hubspotmcp_discover_hubspot_schemaSearches HubSpot schema to discover available data types or look up known types directly.Read-only

    Discover Hubspot Schema

    Searches HubSpot schema to discover available data types or look up known types directly. Use SEARCH_OBJECT_TYPES when you don't know the exact type name, or 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. Check readAccess/writeAccess before attempting operations on a type.

    Inputs

    querystringrequired
    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).
  • hubspotmcp_get_aeo_metricsPortal-level AEO analytics: brand visibility, mentions, citations, competitor share-of-voice, and per-assistant breakdowns for a date window.Read-only

    Get Aeo Metrics

    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.

    Inputs

    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.
    compareToPreviousPeriodboolean
    Set to true to also return how the SUMMARY metrics changed versus the immediately preceding period of equal length — answering "is my AI-search visibility going up or down?". Populates summary.comparison with the prior period's values and the deltas. Adds one extra aggregation, so only set it when the user asks about a trend, change, or improvement. Only affects SUMMARY.
    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.
    promptSortBystring
    Field the PROMPTS section is sorted by. CREATED_AT (default) = prompt creation time. VISIBILITY_SCORE = visibility score. CITATION_COUNT = number of citations. Sorting by VISIBILITY_SCORE or CITATION_COUNT relies on visibility metrics and is not supported on very large portals; narrow the result set with filters first if that happens (on such portals both PROMPTS and SUMMARY are then omitted with an explanatory status).one of CREATED_ATVISIBILITY_SCORECITATION_COUNT
    promptSortOrderstring
    Direction for promptSortBy. DESC (default) = highest/newest first (e.g. most-cited or highest-visibility first); ASC = lowest/oldest first (e.g. use with VISIBILITY_SCORE to surface the worst-performing prompts). Only affects the PROMPTS section.one of ASCDESC
    startDatestring
    ISO-8601 start date (YYYY-MM-DD). Optional; defaults to 30 days ago. Only set when the user asks for a different window.
  • hubspotmcp_get_campaign_analyticsRetrieve engagement analytics (sessions, new contacts, influenced contacts) for one or more HubSpot campaigns.Read-only

    Get Campaign Analytics

    Retrieve engagement analytics (sessions, new contacts, influenced contacts) for one or more HubSpot campaigns.

    Inputs

    requestsarray
    Required: List of analytics requests to process. Each entry is a full CampaignAnalyticsRequest. Maximum 20 requests per batch.
  • hubspotmcp_get_campaign_asset_metricsRetrieve performance metrics for assets (emails, landing pages, CTAs) associated with a campaign.Read-only

    Get Campaign Asset Metrics

    Retrieve performance metrics for assets (emails, landing pages, CTAs) associated with a campaign.

    Inputs

    assetTypestringrequired
    The asset type name, such as LANDING_PAGE, SITE_PAGE, BLOG_POST, or MEETING_EVENT. If invalid, the error will list valid types.
    campaignCrmObjectIdintegerrequired
    The numeric ID of the campaign to get asset metrics for. Must be greater than 0.
    crmObjectIdsarray
    Optional list of CRM object IDs to scope metrics to specific assets. When omitted or empty, metrics are returned for all assets of the given assetType associated with the campaign.
    endDatestring
    End of the date range in YYYY-MM-DD format.
    startDatestring
    Start of the date range in YYYY-MM-DD format.
  • hubspotmcp_get_campaign_attribution_reportsREQUIRED FIRST STEP: before your first call, invoke tool_guidance for "get_campaign_attribution_reports" and follow it.Read-only

    Get Campaign Attribution Reports

    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. 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. For non-attribution contact queries (new contacts, influenced contacts, sessions), use read_campaign_data with GET_ANALYTICS. For deals at any stage, use read_campaign_data with operation=GET_ASSET_METRICS and assetType=DEAL, 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.

    Inputs

    attributionModelstring
    Revenue attribution model for the REVENUE metric. Defaults to LINEAR. See instructions for valid values.one of LINEARFIRST_INTERACTIONLAST_INTERACTIONFULL_PATHU_SHAPEDW_SHAPEDTIME_DECAYJ_SHAPEDINVERSE_J_SHAPED
    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 once you have read the instructions for get_campaign_attribution_reports — either via tool_guidance (preferred) or from a READ_TOOL_INSTRUCTION_REQUIRED response. IMPORTANT: after calling tool_guidance for this tool, your very next call to get_campaign_attribution_reports MUST include hasReadToolInstructions=true. Omitting it (default false) triggers an inline READ_TOOL_INSTRUCTION_REQUIRED response instead of executing the query; do not omit it once you have already read the instructions from tool_guidance. 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.one of AGGREGATIONSEARCH
    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.one of CONCISEDETAILED
    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.one of ASCDESC
    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.
  • hubspotmcp_get_campaign_contacts_by_typeRetrieve paginated contact IDs for a campaign filtered by attribution type (NEW_CONTACTS, INFLUENCED_CONTACTS, or ALL_CONTACTS).Read-only

    Get Campaign Contacts By Type

    Retrieve paginated contact IDs for a campaign filtered by attribution type (NEW_CONTACTS, INFLUENCED_CONTACTS, or ALL_CONTACTS).

    Inputs

    campaignCrmObjectIdintegerrequired
    The numeric object ID of the campaign. Must be greater than 0.
    contactTypestringrequired
    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).one of NEW_CONTACTS_FIRST_TOUCHNEW_CONTACTS_LAST_TOUCHINFLUENCED_CONTACTS
    endDatestring
    End of the date range in YYYY-MM-DD format.
    limitinteger
    Maximum number of results to return per page.
    offsetinteger
    Pagination offset — number of records to skip before returning results.
    startDatestring
    Start of the date range in YYYY-MM-DD format.
  • hubspotmcp_get_content_analytics_reportRun a content analytics report across HubSpot landing pages, website pages, and blog posts for a given date range.Read-only

    Get Content Analytics Report

    Run a content analytics report across HubSpot landing pages, website pages, and blog posts for a given date range.

    Inputs

    modestringrequired
    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.one of TOTALSTIME_SERIESSUMMARYPEOPLE
    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.
    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.one of CONTACTSVISITORS
    periodstring
    TIME_SERIES or SUMMARY mode: bucket size for the time series. Required for those modes.one of DAILYWEEKLYMONTHLYQUARTERLYYEARLY
    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.one of ASCDESC
    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.one of RAW_VIEWSVISITSSUBMISSIONSCONTACTSLEADSCUSTOMERSCTA_VIEWSCTA_CLICKSBOUNCESENTRANCESEXITSPAGE_BOUNCE_RATETIME_PER_PAGEVIEWCTA_RATE
    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.
  • hubspotmcp_get_crm_objectsFetch multiple CRM objects of the same type in a single request by their IDs.Read-only

    Get Crm Objects

    Fetch multiple CRM objects of the same type in a single request by their IDs.

    Inputs

    objectTypestringrequired
    The HubSpot CRM object type to operate on (e.g. contacts, companies, deals).
    objectIdsarray
    List of object IDs to fetch. Min: 1, Max: 100
    propertiesarray
    List of property names to include in results.