tools/call over
POST /hubspot/mcp. The connector is connected through OAuth (HubSpot login; see
Forbind HubSpot CMS).
Endpoint:
https://mcp.consile.ai/hubspot/mcp. HubSpot CMS is its own named
connector with only its own tools. Additional HubSpot portals get their own
endpoints; see Multiple portals.Write safety: guardrail model
The nine write tools split into two tiers based on reversibility:- Draft operations run freely. Creating a page, editing a blog post draft, or upserting a HubDB row all target the unpublished draft buffer. Nothing reaches the live site and the change can be discarded. No confirmation required.
- Publishing and destructive actions require
confirm: true. These are: pushing a page draft live (publish_page), publishing a blog post draft (publish_blog_post), publishing a HubDB table draft to live pages (publish_hubdb_table), and discarding a HubDB draft (reset_hubdb_draft). Withoutconfirm: true, the tool returns a dry-run preview and calls no HubSpot API.
Preview shape
When a write action requires confirmation butconfirm is omitted or false, the tool
returns this shape instead of calling HubSpot:
summary describes the change, and request shows the write that would be sent
to HubSpot. To apply, re-run the identical call with confirm: true added. The
preview is a normal successful tool result (isError is not set).
Draft-first default on create
New pages and blog posts are always created withstate: "DRAFT". The connector
enforces this regardless of what the caller sends, so nothing is accidentally published
on first create.
Tool annotations
Every tool intools/list carries MCP annotations:
openWorldHint: true marks the three tools that change the public website. Draft
writes are marked destructive because they are writes; they do not touch the live
site. Some clients ask the user to approve each call of a tool marked
destructiveHint: true; that prompt comes from the client and is separate from the
confirm guardrail.
Portal tier requirement
The OAuth scopes this connector requests (content, hubdb, business-intelligence)
require the connected HubSpot portal to be on one of:
- CMS Hub or Content Hub
- Marketing Hub Professional or Enterprise
403, which reaches the client as a generic tool error (see
Errors). The customer needs to upgrade their HubSpot subscription to use
that surface.
Authentication
HubSpot CMS uses HubSpot’s OAuth login. The customer authorizes Consile’s HubSpot app (shown in HubSpot as Consile HubSpot CMS) for one HubSpot portal from the Consile portal. Consile stores the access encrypted per customer and renews it automatically. The MCP client never sees the HubSpot token. OAuth scopes:content, hubdb, business-intelligence, oauth (the last is
auto-injected by HubSpot on every grant and is not a functional scope).
Revoking access. Disconnecting in the Consile portal (Afbryd connector /
Disconnect connector) deletes the stored access immediately; on a multi-portal
subscription it applies to portal 1. To remove the access at HubSpot as well, the
customer uninstalls the app Consile HubSpot CMS in HubSpot’s connected apps
settings. To reconnect after an uninstall or revoke, the customer disconnects and
connects again in the portal, or calls connect_account. For an extra portal, call
connect_account on that portal’s endpoint (for example /hubspot-2/mcp).
Shared parameters
Paging
List tools use cursor-based paging. Passafter from paging.next.after in the
previous response to retrieve the next page.
integer
default:"20"
Max items to return in this page (1-100).
string
Cursor from a previous response’s
paging.next.after.Page type
string
default:"site"
Which page tree:
"site" (website pages) or "landing" (landing pages).HubDB table reference
string
required
HubDB table numeric id (preferred) or unique table name.
Responses
Tools return HubSpot’s own response bodies unchanged (export_hubdb_table wraps
its export, see below). List tools return HubSpot’s
{ results, paging } envelope. The field lists below are examples, not a fixed
schema. When HubSpot answers with an empty body, the tool result is null.
Read tools: pages (4 tools)
list_pages
List website or landing pages with paging. Passarchived: true to list archived
pages instead of live ones.
string
default:"site"
integer
default:"20"
string
boolean
List archived pages instead of live ones.
{ results, paging }; page objects include fields such as id, name,
slug, state, htmlTitle, metaDescription, publishDate, archivedAt,
createdAt, updatedAt.
get_page
Retrieve a single site or landing page (the live/published version) by id.string
default:"site"
string
required
The page id.
get_page_draft
Read the unpublished draft buffer of a page to inspect pending edits before publishing.string
default:"site"
string
required
The page id.
get_page but reflects staged edits).
list_page_revisions
List prior published revisions of a page for review or rollback planning.string
default:"site"
string
required
The page id.
integer
default:"20"
string
{ results, paging }; revisions include fields such as id,
createdAt, createdBy.
Read tools: blog (4 tools)
list_blog_posts
List blog posts with paging. Passarchived: true to list archived posts.
integer
default:"20"
string
boolean
List archived posts instead of live ones.
{ results, paging }; post objects include fields such as id, name,
slug, state, contentGroupId, htmlTitle, metaDescription, publishDate,
tagIds, authorName, createdAt, updatedAt.
get_blog_post
Get a single blog post by id. Setdraft: true to read the draft buffer instead of
the live version.
string
required
The blog post id.
boolean
Read the draft buffer instead of the live version.
postBody (HTML content).
list_blog_tags
List blog tags with paging.integer
default:"20"
string
{ results, paging }; tags include fields such as id, name, slug,
createdAt, updatedAt.
list_blog_authors
List blog authors with paging. Authors are referenced by posts; this is a read-through of the author registry.integer
default:"20"
string
{ results, paging }; authors include fields such as id,
displayName, email, slug, avatar.
Read tools: HubDB (5 tools)
list_hubdb_tables
List the account’s HubDB tables with id, name, label, column metadata, row count, and publish state.integer
default:"20"
string
{ results, paging }; tables include fields such as id, name,
label, columns (array with type, name, label, options), rowCount,
publishedAt.
get_hubdb_table
Get a single HubDB table’s full definition including column schema: types, options, andforeignTableId/foreignColumnId for FOREIGN_ID columns. Call this before
writing rows to understand the expected value types.
string
required
columns array.
list_hubdb_rows
List rows of a published HubDB table with paging. Returns each row’s cell values per column. Draft rows are not included.string
required
integer
default:"20"
string
{ results, paging }; rows include id and values (map of column
name to cell value).
get_hubdb_row
Get a single published HubDB row by rowId.string
required
string
required
The row id.
id and values.
export_hubdb_table
Export a HubDB table’s data. Returns{ tableIdOrName, format, data }, where data
is the export as a text string. Use CSV (the default). EXCEL output is binary
and is not usable when returned as text.
string
required
string
default:"CSV"
Export format:
"CSV" or "EXCEL". Only "CSV" produces usable output.{ tableIdOrName, format, data } where data is the file content as a
string.
Read tools: analytics (1 tool)
get_traffic_analytics
Read traffic and page-view analytics over a date range. Optionally broken down by content, source, geolocation, or UTM campaign.Requires Marketing Hub Professional/Enterprise on the connected portal and the
business-intelligence scope.string
default:"totals"
How to break the traffic down. One of:
totals, sessions, sources,
geolocation, pages, landing-pages, utm-campaigns.string
default:"total"
Aggregation period. One of:
total, daily, weekly, monthly,
summarize/daily, summarize/weekly, summarize/monthly.string
required
Start date in
YYYYMMDD format (inclusive).string
required
End date in
YYYYMMDD format (inclusive).integer
Max breakdown rows to return (up to 1000).
Write tools (9 guardrailed)
Not supported by this connector: editing page body content (modules, widgets), setting blog tags, author or featured image, creating HubDB tables or columns, and deleting or archiving pages, posts or rows.create_page_draft
Create a new site or landing page as an unpublished draft. State is forced toDRAFT
regardless of what you pass; nothing goes live on create. publish_page only pushes
changes on an already-published page, so the first publish of a new page happens in
HubSpot.
Does not require confirmation (reversible draft operation).
string
default:"site"
string
required
Internal page name.
string
Path to the template/theme file the page uses.
string
URL slug (path) for the page.
string
SEO
<title> for the page.string
SEO meta description.
update_page_draft
Edit a page’s draft buffer (name, slug, SEO title, SEO description) without touching the live page. Publish the change later withpublish_page. Page body
content (modules, widgets) cannot be edited through this connector.
Does not require confirmation (draft buffer only, live page untouched).
string
default:"site"
string
required
The page id.
string
string
string
string
publish_page
Push a page’s unpublished draft changes live to the public website. This is a push-live of the draft: it updates an already-published page, not a first-time publish of a brand-new page. Requiresconfirm: true. Without it, returns a dry-run preview describing
exactly what would be published.
string
default:"site"
string
required
The page id.
boolean
Set
true to apply. Omit or false to receive a preview.null if
HubSpot returns an empty body); a preview if not confirmed.
create_blog_post_draft
Create a new blog post as an unpublished draft. State is forced toDRAFT. Requires
the target blog’s contentGroupId (read it from an existing post via list_blog_posts
or find it in the HubSpot UI). Publish later with publish_blog_post.
Does not require confirmation (reversible draft operation).
string
required
The blog (content group) id this post belongs to.
string
required
Post title / internal name.
string
URL slug for the post.
string
Post body HTML.
string
SEO
<title>.string
SEO meta description.
update_blog_post_draft
Edit a blog post’s draft buffer (title, slug, body, SEO) without touching the live post. Publish later withpublish_blog_post.
Does not require confirmation (draft buffer only, live post untouched).
string
required
The blog post id.
string
string
string
Post body HTML.
string
string
publish_blog_post
Push a blog post’s draft changes live to the public site. Requiresconfirm: true. Without it, returns a dry-run preview.
string
required
The blog post id.
boolean
Set
true to apply. Omit or false to receive a preview.null if
HubSpot returns an empty body); a preview if not confirmed.
upsert_hubdb_row_draft
Create a new row (omitrowId) or update an existing one (pass rowId) in a
HubDB table’s draft. Changes are staged and invisible on live pages until
publish_hubdb_table is called.
Call get_hubdb_table first to inspect column types. Cell values must match each
column’s type (for example: FOREIGN_ID columns expect arrays, select columns expect
option objects, date columns expect epoch milliseconds).
There is no tool for reading a table’s draft rows: list_hubdb_rows and
get_hubdb_row read the published table, so a row written here is not visible to
them until publish_hubdb_table has run. The publish_hubdb_table preview names
the table but does not list the pending row changes, so check the draft in HubSpot
before confirming.
Does not require confirmation (staged in draft, nothing live until publish).
string
required
string
Existing row id to update. Omit to create a new row.
object
required
Map of
columnName to cell value, typed per the column schema.publish_hubdb_table
Publish a HubDB table’s draft (schema and rows) so the changes appear on live pages. Any prior HubDB row write is invisible until this is called. Requiresconfirm: true. Without it, returns a dry-run preview.
string
required
boolean
Set
true to apply. Omit or false to receive a preview.null if
HubSpot returns an empty body); a preview if not confirmed.
reset_hubdb_draft
Discard all unpublished draft changes on a HubDB table, reverting the draft to the current live/published version. Destructive: all staged row and schema edits are lost. Requiresconfirm: true. Without it, returns a dry-run preview.
string
required
boolean
Set
true to apply. Omit or false to receive a preview.null if
HubSpot returns an empty body); a preview if not confirmed.
Code examples
Tool names are namespaced
hubspot__<tool> in Claude/ChatGPT (the AI invokes
these automatically). The bare names (e.g. list_pages) are used here for
readability.Errors
If the stored HubSpot access has expired or been revoked (for example because the HubSpot app was uninstalled),tools/call returns a result with isError: true
and one of these messages:
HubSpot access token has expired; reconnect requiredHubSpot rejected the access token (401); reconnect required
tools/call returns a result with isError: true
and the text Tool invocation failed. The usual causes are:
- the connected portal’s plan does not include the surface (CMS/Content Hub or Marketing Hub Professional/Enterprise; traffic analytics needs Marketing Hub Professional/Enterprise),
- an argument that does not match the schema (for example a date not in
YYYYMMDD).
tools/list, but every call returns a message asking them to have
an administrator assign them under Team in the portal. See
Errors & limits.
HubSpot limits public apps to about 110 requests per 10 seconds per connected
HubSpot account. A call that exceeds HubSpot’s rate limit can fail with
Tool invocation failed.; wait a few seconds and try again.
Multiple portals
This connector is multi-instance. A customer can add more HubSpot portals in the Consile portal (Tilføj portal / Add portal, administrators only). Portal 1 is served athttps://mcp.consile.ai/hubspot/mcp with tools named hubspot__<tool>.
Portal N (N ≥ 2) is served at https://mcp.consile.ai/hubspot-N/mcp with tools named
hubspot-N__<tool> and the server name Consile · HubSpot CMS #N. Each portal is
connected and authorized separately. One user seat covers every portal of the
connector.
After an extra portal is removed, the endpoint URL of a remaining portal can change.
Check the connector configuration in your MCP clients after a removal.
Every endpoint’s tools/list also includes the unprefixed system tool
connect_account, which takes no arguments and returns a link (valid for 10 minutes)
for connecting, or reconnecting, the HubSpot account behind that endpoint.