Skip to main content
Glama

Import or update contacts in bulk

upsert_contacts

Create-or-update up to 500 contacts in one call — the way to import a customer list from a spreadsheet, an export or another CRM. Each contact is matched against the site's existing contacts on match_on (email by default, case-insensitively): a match is UPDATED, everything else is CREATED, so re-sending the same batch is safe. Any column the CRM has no field for goes in custom_fields as a flat key/value (keys must be identifier-shaped: letters, digits, underscore) and is auto-declared as a filterable field unless you pass create_missing_fields:false. Tags MERGE with the contact's existing tags by default — pass tags_mode:"replace" only if the user actually wants the old tags gone. ALWAYS run once with dry_run:true first and show the user the created/updated counts before writing. Two deliberate limits: status (pipeline stage) is applied to NEW contacts only — an import never moves an existing contact's stage — and custom_fields always merge key-by-key rather than replacing the object.

Input Schema

NameRequiredDescriptionDefault
dry_runNo
site_idYesThe site whose CRM to write to
contactsYes
match_onNoemail
tags_modeNomerge
user_goalNoOptional: the user's goal behind this call, in one short sentence of plain words (e.g. "add a page so customers can book tables"). No names, emails or other personal details.
contact_fields_modeNooverwrite
create_missing_fieldsNo
dispatch_audience_eventsNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / user_goal
      Added value: +{
      +  "description": "Optional: the user's goal behind this call, in one short sentence of plain words (e.g. \"add a page so customers can book tables\"). No names, emails or other personal details.",
      +  "type": "string"
      +}
  2. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only tell the agent this is a non-read-only, non-destructive, non-idempotent write; the description adds the real behavioral contract: matching on `match_on` case-insensitively, UPDATED vs CREATED outcomes, custom_fields auto-declaration, tag merge-vs-replace semantics, status applying to new contacts only, and key-by-key custom_fields merging. The 're-sending the same batch is safe' claim is in mild tension with idempotentHint:false, but is defensible because merges and audience events can still differ between calls, so this is not a hard contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and scale, then layered with matching logic, tag/field merge rules, the dry-run instruction, and the two caveats. Dense but every sentence carries information an agent would otherwise have to guess; no filler or restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter bulk mutation with no output schema, the description covers the state-changing semantics thoroughly (match key, merge behavior, status limitation, dry-run workflow). It omits what dry_run and real writes return, whether audience events are dispatched by default and why they'd be enabled, and any permission/auth preconditions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 22% schema description coverage across 9 params, the description does real work: it explains match_on semantics and default, dry_run's required workflow, tags_mode, create_missing_fields, and custom_fields key shape. Gaps remain for `dispatch_audience_events` and `contact_fields_mode`, which are undocumented in both schema and description and are not self-evident from their names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific compound verb+resource ('Create-or-update up to 500 contacts in one call') plus the concrete scenario it serves: importing a customer list from a spreadsheet, an export, or another CRM. This cleanly separates it from read-oriented siblings like list_contacts and from narrower mutators like tag_contacts or define_contact_field.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit procedural guidance: 'ALWAYS run once with dry_run:true first and show the user the created/updated counts before writing,' and conditions tags_mode:"replace" on the user actually wanting old tags gone. It does not name a sibling alternative ('use tag_contacts for X'), so it falls short of a 5, but the when-to-use context is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources