Skip to content

Latest commit

 

History

History
108 lines (80 loc) · 5.64 KB

File metadata and controls

108 lines (80 loc) · 5.64 KB

Model Context Protocol (MCP) Server

hubspot-cli ships with a built-in MCP server that exposes every CRM operation as a strongly-typed tool over JSON-RPC 2.0 on stdio.

See also: hubspot mcp command reference.

When to use MCP vs skills

Claude Code skills MCP server
How it works Markdown docs; Claude shells out to hubspot Typed JSON-RPC tools; client calls them directly
Setup hubspot skill-install hubspot mcp install --client …
Best for Claude Code where shell access is natural Claude Desktop, programmatic MCP clients, sandboxed agents
Arguments Free-form CLI Structured JSON matching each tool's inputSchema

You can run both in parallel — they aren't mutually exclusive.

Architecture

┌─────────────────┐   stdin (JSON-RPC frames)   ┌────────────────────────┐
│   MCP client    │ ─────────────────────────►  │  hubspot mcp serve     │
│ (Claude Desktop │                             │  (newline-delimited    │
│  or Claude Code)│ ◄───────────────────────── │   JSON-RPC 2.0 loop)   │
└─────────────────┘   stdout (JSON-RPC frames)  └───────────┬────────────┘
                                                            │ spawns
                                                            ▼
                                                  ┌──────────────────┐
                                                  │  hubspot <args>  │
                                                  │  (child process) │
                                                  └──────────────────┘

Each tools/call spawns a child hubspot process with --output json and the argv derived from the tool's arguments. The child's stdout (a {success, data, …} envelope) is wrapped in an MCP text content block and returned. isError is set when the child exits non-zero.

Self-exec keeps the MCP surface in lock-step with the CLI: every behavioural improvement in a CLI handler is instantly visible to MCP clients.

Supported methods

Method Status
initialize ✅ returns {protocolVersion: "2024-11-05", capabilities: {tools: {listChanged: false}}}
notifications/initialized ✅ silently acknowledged
tools/list ✅ returns the full catalog (60+ tools)
tools/call ✅ dispatches to the CLI via self-exec
ping ✅ returns {}
resources/*, prompts/* not implemented (server advertises only tools capability)

Authentication

The server inherits the launcher's environment. Two ways to hand it a token:

  1. Shell export. Set HUBSPOT_ACCESS_TOKEN in the shell that launches the MCP client (e.g. your desktop session).
  2. Client config env block. Both Claude Desktop and Claude Code support an env map alongside command/args.
{
  "mcpServers": {
    "hubspot": {
      "command": "hubspot",
      "args": ["mcp", "serve"],
      "env": { "HUBSPOT_ACCESS_TOKEN": "pat-na1-…" }
    }
  }
}

Multi-portal users can override per-launch: "args": ["mcp", "serve"] plus "env": { "HUBSPOT_PROFILE": "sandbox" }.

Tool design

  • Names: crm_<object>_<action>, discover_<x>, auth_<x>. Underscores only (MCP tool names must match [a-zA-Z0-9_-]+).
  • Schemas: every tool's inputSchema is strict JSON Schema with additionalProperties: false, so the client can validate before calling.
  • Properties payload: always a JSON object, never a stringified JSON blob. The server takes care of serialising it for the CLI.
  • Pagination: list/search tools accept limit (1–100) and after (cursor from the previous response's paging.next_cursor).

Error handling

The MCP tools/call result always contains at least one content block with the child process's stdout. When isError: true:

  • Parse the JSON envelope from content[0].text — it follows the standard {success: false, error: {code, message, suggestions, retry}} shape.
  • A second content block may be present with [stderr] prefix, containing any tracing output from the child.
  • _meta.exitCode echoes the CLI's exit code (see exit code reference).

Security considerations

  • The server has no authentication of its own; anyone who can talk to its stdio can call any tool. Only launch it through a trusted MCP client.
  • Destructive tools (crm_*_delete) go straight through. If your portal has records the agent should not touch, use a scoped private-app token rather than a portal-admin token.
  • Tokens are never echoed in responses — the CLI masks them — but the env block of an MCP config file is on disk; treat it with the same care as any other secrets file.

Verifying locally

printf '%s\n%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  | hubspot mcp serve \
  | tee /tmp/mcp.log \
  | jq -c '.result | keys'

You should see two lines: the initialize response keys and the tools list keys. CI runs this exact flow on every PR (mcp-smoke job) and on every release (release-sanity job).

Related