Request for Guidance on Hierarchical Property Mapping in HubSpot MCP Integration

Hi all,

Hope you are doing well. I’m new to this platform so if apologizing if I’ve chosen incorrect topic and tags.

I’m Neel, an AI Engineer. We have integrated the HubSpot MCP server into our chatbot so users can fetch data directly from HubSpot.

I’m reaching out for guidance on an issue we’ve encountered while fetching deal information with filters.

A user requested a list of opportunities in a specific stage within a specific pipeline, along with the collaborator. To support this, the agent first called the search_properties tool with object_type = DEAL and properties such as pipeline and stage. The tool returned a standard flattened response.


The response
{
	"result": [
		{
			"type": "enumeration",
			"options": [5 items],
			"name": "pipeline",
			"label": "Pipeline",
			"description": "The pipeline the deal is in. This determines which stages are options for the deal."
		},
		{
			"type": "enumeration",
			"options": [50 items],
			"name": "hubspot_owner_id",
			"label": "Deal owner",
			"description": "User the deal is assigned to. Assign additional users to a deal record by creating a custom user property."
		},
		{
			"type": "enumeration",
			"options": [49 items],
			"name": "dealstage",
			"label": "Deal Stage",
			"description": "The stage of the deal. Deal stages allow you to categorize and track the progress of the deals that you are working on."
		}
	],
	"propertiesNotFound": [
	  "deal_collaborator_owner_ids"
	]
}

each item is a object of value and label, where the value is an unique ID, whereas the label is what is shown to the user in the app.


The challenge is that this response does not preserve the hierarchical relationship between pipelines and their corresponding stages. As a result, the agent can identify pipeline values, deal stage values, and owner values, but it cannot reliably determine which stage belongs to which pipeline when stage names overlap across pipelines.

For example:

  • P1:j1 → S1:i1, S2:i2, S3:i3, S4:i4
  • P2:j2 → S5:i5, S2:i6, S3:i7, S4:i8

Here:

  • P represents pipelines
  • S represents stages
  • j and i represent the corresponding IDs/values

In this case, both pipelines contain stages with the same names, but the underlying IDs are different.

If the user asks for deals in Pipeline P2 at Stage S2, the agent retrieves the available pipeline and stage values through search_properties, then calls search_crm_object with the selected IDs. However, because the property response is flattened and does not retain the parent-child mapping, the agent may incorrectly pair values, such as:

  • P1:j1 with S2:i6
  • P2:j2 with S2:i2

These are invalid combinations, so search_crm_object correctly returns null.

The expected valid combinations would be:

  • P1:j1 with S2:i2
  • P2:j2 with S2:i6

Because of this ambiguity, users are unable to retrieve the correct filtered deal data whenever multiple pipelines contain stage names that overlap. The workflow only succeeds when stage names are unique across pipelines.

Based on my understanding of agent behavior and LLM reasoning, the root cause appears to be the loss of hierarchical context in the tool response.

Could anyone please suggest the best way to handle this scenario?

I also want to understand why the MCP tools return JSON response instead of more structured, custom objects as list of string. Kind of __repr__ for the objects in code, which shows all the relevant attributes and their values. I know that JSON is the convention the industry follows for MCP serve, but I’m curious to know if there’s a specific reason for this choice, as we can return the structured __repr__ kind of object for each deal(in this case) as list of strings tied to response key in the json payload.

I’d really appreciate any guidance, recommendations, or best practices you can share.

Thank you for your time.

Hi @TurabitDev , welcome to the HubSpot Community!

This is a well-reasoned analysis, and you’ve correctly identified the root cause — the fix lives in your retrieval strategy, not in anything you can change about the tool’s response shape.

On the pipeline/stage ambiguity

search_properties is designed as a flat property-metadata lookup — it returns property names, labels, and descriptions, but it isn’t a hierarchical enumeration endpoint. For deal stage and pipeline enumeration values specifically, get_properties is the better fit, as it returns full property definitions including data types and enumeration values. You can find more detail in the Integrate with the remote HubSpot MCP server docs.

The hierarchy you’re looking for does exist in HubSpot’s data model — dealstage is an enumeration property whose option values are scoped per-pipeline via the Pipelines API, where each pipeline object contains a nested stages array with each stage’s ID and label tied to its parent pipeline. That context just isn’t what search_properties surfaces.

Practical fix for your agent: rather than relying on search_properties’s flattened output, have your agent call get_properties for dealstage (or query the Pipelines API directly) to retrieve the full enumeration structured per-pipeline. Then resolve the pipeline → stage ID mapping in your own code before calling search_crm_objects. That makes the ID pairing deterministic logic rather than LLM inference over a flat list, which removes the ambiguity entirely.

On JSON vs. custom __repr__-style output

The docs focus on what each tool returns rather than the design reasoning behind response formats — for that level of detail, the Developer Feedback form is your best bet to raise this to the Dev team :slight_smile:

Hope that helps unblock you — let us know how it goes!

Cassie, Community Manager