Building a Better HubSpot Integration with MCP, Test Accounts, and App Cards
When people think “HubSpot integration,” they usually picture a few API calls, some brittle webhooks, and a staging portal that never quite behaves like production. That used to be me, too. But with HubSpot’s new developer stack – local MCP server, configurable test accounts, and React-based app cards – you can build and test integrations

When people think “HubSpot integration,” they usually picture a few API calls, some brittle webhooks, and a staging portal that never quite behaves like production.
That used to be me, too.
But with HubSpot’s new developer stack – local MCP server, configurable test accounts, and React-based app cards – you can build and test integrations like a real product team instead of a collection of scripts taped together.
In this article, I’ll walk through how I’m using these tools to build a deep HubSpot integration for a WordPress-based SaaS (SampleHQ), and how you can steal the same workflow for your own app.
We’ll cover:
- Using the HubSpot MCP server in your IDE to “pair program” with your CRM
- Spinning up realistic test accounts with different subscription tiers
- Importing real-ish test data via CSV and JSON configs
- Building React app cards so your app lives inside HubSpot, not just around it
- Wiring all of this into a backend (in my case: a multi-tenant WordPress plugin)
1. The Problem: CRM Integrations Are Usually Held Together with Duct Tape
A typical integration story looks like this:
- One sandbox account for everyone
- Half-documented workflows, “do not touch” properties, and mystery webhooks
- Manual clicking to set up test data whenever you want to check one scenario
- Debugging against production because staging never matches reality
If your app needs to:
- Create custom objects,
- Sync sample/transaction data,
- Read revenue and attribution,
- And expose UI inside HubSpot…
…that kind of chaos stops being “annoying” and starts being dangerous.
The new HubSpot dev tools solve three big problems:
- Context – the MCP server gives your AI assistant real knowledge of HubSpot’s CLI, project structure, and docs.
- Isolation – configurable test accounts let you spin up portals that simulate different subscription tiers and hubs.
- Embedded UX – app cards let you place your app’s logic directly on contact records (or other objects), instead of forcing reps to live in two tabs.
Let’s wire those pieces together.
2. Set Up the HubSpot MCP Server in Your IDE
First step: give your AI assistant actual access to HubSpot’s developer context, instead of treating it like just another chatbot.
HubSpot ships a developer MCP server that runs locally and talks to your IDE / AI client. Once installed, it can:
- Walk you through HubSpot CLI commands
- Create and validate projects
- Add app features & CMS assets
- Upload/deploy projects
- Even analyze app usage and churn risk
Prerequisites
- You’ve joined the developer MCP server public beta
- You’re on HubSpot CLI
7.6.0or higher (hs --version) - You’re using a supported client (Cursor, Claude Code, VS Code, Windsurf, etc.)
Install / update the CLI:
npm install -g @hubspot/cli@latest
Run MCP setup
In your terminal:
hs mcp setup
You’ll be prompted to select which client to connect (e.g., Cursor, Claude Code, VS Code). Once you pick your client and finish setup, restart the client so it can see the new MCP server.
Now your AI assistant can answer questions like:
- “Create a new HubSpot project with an app card and webhook handling.”
- “Validate my project and show me what’s wrong before I deploy.”
- “Help me add a React theme to this project.”
- “Upload this project to my dev account.”
Instead of copy-pasting from docs, you’re effectively pair programming with the HubSpot platform itself.
3. Use Configurable Test Accounts Instead of Torturing One Sandbox
Next, you need somewhere safe (and realistic) to test all this.
HubSpot’s configurable test accounts let you spin up developer portals that simulate specific subscription mixes and tiers – Starter, Professional, Enterprise, per hub. You can create them either via the CLI or in the UI.
Requirement: your project must be on platform version 2025.2+ and CLI 7.6.0+.
Option A: Create a test account from scratch (CLI)
hs test-account create
Then choose:
- Create test account from scratch
- Enter a name & description
- Select which hubs and tiers (Marketing, Sales, Service, Ops, Content, etc.)
HubSpot creates the account and prints the Hub ID. You can then:
- Open it in the browser
- Authenticate it with the CLI
- Use it for local development and app installation
Option B: Create from a config file (recommended for teams & CI)
For repeatable setups, generate a JSON config:
hs test-account create-config
The prompts are similar (name, description, subscriptions), but this time HubSpot writes a JSON file like:
{
"accountName": "AllHubsProfessional",
"description": "Professional test account",
"marketingLevel": "PROFESSIONAL",
"opsLevel": "PROFESSIONAL",
"serviceLevel": "PROFESSIONAL",
"salesLevel": "PROFESSIONAL",
"contentLevel": "PROFESSIONAL"
}
Now you can create accounts on demand:
hs test-account create --config-path ./test-portal-config.json
This is perfect when you want:
- One config for Starter
- One for Professional
- One for Enterprise
…and you want your CI/CD pipeline to spin up portals automatically during integration tests.
4. Import Realistic Test Data into Your Portal
An empty CRM isn’t very useful for testing.
HubSpot lets you seed test accounts with CRM data using the CLI and the CRM imports API behind the scenes.
The pattern:
- One or more CSV files with the actual data (contacts, companies, etc.)
- One JSON configuration file that tells HubSpot how to map columns to properties
Example JSON for importing contacts and companies:
{
"name": "Test account data import (contact and company)",
"importOperations": {
"0-1": "CREATE",
"0-2": "CREATE"
},
"files": [
{
"fileName": "contact-data.csv",
"fileFormat": "CSV",
"fileImportPage": {
"hasHeader": true,
"columnMappings": [
{
"columnObjectTypeId": "0-1",
"columnName": "First Name",
"propertyName": "firstname"
},
{
"columnObjectTypeId": "0-1",
"columnName": "Email",
"propertyName": "email",
"columnType": "HUBSPOT_ALTERNATE_ID"
}
]
}
},
{
"fileName": "company-data.csv",
"fileFormat": "CSV",
"fileImportPage": {
"hasHeader": true,
"columnMappings": [
{
"columnObjectTypeId": "0-2",
"columnName": "Company domain name",
"propertyName": "domain",
"columnType": "HUBSPOT_ALTERNATE_ID"
}
]
}
}
]
}
Place the JSON and CSV files in the same directory, then run:
hs test-account import-data
The CLI will ask:
- Which test account to use
- Which JSON file to use
Then it fires the CRM imports API and gives you a link to the imports dashboard so you can monitor progress and errors.
For something like SampleHQ, this is where I’ll import:
- Example contacts (buyers, engineers, account managers)
- Companies (manufacturing plants, brands)
- Optional: deals that represent awarded business
That way, when the app card loads, it has real-looking data to work with.
5. Build a HubSpot App Card That Talks to Your App
Now the fun part: having your app actually show up inside HubSpot.
On the latest developer platform (2025.2), you can build React-based app cards that live on object records (like contacts). Perfect for showing:
- Recent sample orders
- Which SKUs were requested
- Links back into your own app
- Attribution / influence info
Step 1 – Add a card to your HubSpot project
From your project directory:
hs project add
When prompted for a component, select Card.
HubSpot scaffolds:
myProject
└── src/
└── app/
└── cards/
├── NewCard-hsmeta.json
├── NewCard.jsx
└── package.json
NewCard-hsmeta.json– configuration (placement, object type, etc.)NewCard.jsx– your React UIpackage.json– dependencies used for bundling
Step 2 – Install deps & upload the project
Install card dependencies:
hs project install-deps
Then upload:
hs project upload
# or, for a specific account:
hs project upload --account YOUR_TEST_HUB_ID
You can open the project in the browser with:
hs project open
From there, install the app into your test account via the Distribution tab → Install now.
Step 3 – Add the card to the contact record UI
In your HubSpot test account:
- Go to CRM → Contacts
- Open any contact
- At the top of the middle column, click Customize → Default view
- Click the + where you want your card
- In the right sidebar, open Card library → Card types → App
- Add your new app card, then Save and exit
Now your boilerplate card appears on contact records.
Step 4 – Start local development
To get instant reloads during development:
hs project dev
- Select the test account to use
- The CLI starts the local dev server
- Refresh a contact record with your card added
You’ll see a “Developing locally” tag on the card. Any changes to .jsx / .tsx files will live-reload into that card.
This is where your integration becomes tangible:
- The card can call your backend via an authenticated API
- It can display SampleHQ sample orders linked to that contact
- It can trigger actions like “Link this contact’s deals to sample orders” or “Open this sample order in the app”
6. Where the WordPress Plugin Fits In
In my case, the backend is a multi-tenant WordPress plugin (samplehq-core) that:
- Stores CRM connections in custom tables per tenant
- Links WordPress sample orders to HubSpot deals
- Reads revenue from HubSpot in read-only mode for attribution
- Exposes REST endpoints for things like:
GET /samplehq/v1/picker/candidatesPOST /samplehq/v1/picker/link- Webhook receivers for HubSpot events
The app card becomes the front door for HubSpot users:
- When you open a contact, the card loads from your HubSpot project
- The card calls your WordPress plugin via the REST API
- The plugin looks up:
- All SampleHQ orders linked to that contact
- Any deals linked to those orders
- Attribution snapshots, SKUs, etc.
- The card renders that in a compact React UI
On the WordPress side, everything is multi-tenant-safe and CRM-agnostic; HubSpot is just one of the registered CRM clients. But from the HubSpot user’s point of view, it feels like a native card.
7. Automate It with GitHub Actions and Test Accounts
The last step is to stop treating this as a “thing you click by hand” and start treating it like a proper pipeline.
Because test accounts are configurable and scriptable, you can:
- Spin up test portals with
hs test-account create --config-path … - Import data with
hs test-account import-data - Deploy your project to them with
hs project upload
Add GitHub Actions on top and you get a loop like:
- CI job creates a test account from a config file
- It imports a canned dataset (contacts, companies, demo deals)
- It deploys the latest build of your HubSpot project
- It runs E2E tests against your app card + backend APIs
- It tears down or reuses the test account as needed
For apps that also live in a separate backend (like a WordPress multisite), you can:
- Spin up a short-lived WordPress environment (e.g., with Docker or your cloud platform)
- Run plugin migrations
- Point your HubSpot project’s app card at that environment
- Run integration scenarios end-to-end
No more “it works in my portal” debugging.
8. Putting It All Together
If you’re building a serious HubSpot integration today, the stack I’d recommend looks like this:
- Local HubSpot MCP server in your IDE
- Use it as your always-on assistant for CLI commands, project scaffolding, and validation.
- Configurable test accounts per scenario
- One config per pricing tier / hub combination.
- Spin them up via CLI or GitHub Actions as part of your test pipeline.
- Data imports via
hs test-account import-data- Seed accounts with realistic contacts, companies, and deals for your domain.
- React app cards on key objects (contacts, companies, deals)
- Treat them as the UX layer between HubSpot users and your backend.
- A clean backend integration layer (WordPress plugin, Laravel app, whatever you’re using)
- Handle OAuth, webhooks, multi-tenant storage, and attribution.
- Keep deals read-only if your use case is about attribution, not pipeline management.
Once you wire these pieces together, “HubSpot integration” stops being a spaghetti of webhooks and ad-hoc scripts, and starts feeling like a product surface you can ship features into.
Bojan