Now talk to Hivekind in Claude or ChatGPT. Your priority accounts, GTM context, right where you work.

Data quality

domain.data_quality.v2

Search the exact account/contact and inspect current values before changes. Employment verification has preview/start/status steps. Read duplicates, preview the exact merge and review survivor/field effects before execute. Deletes, moves and owner reassignment require exact scope authorization; reconcile uncertain writes rather than repeat under another ID.

Delete an account

accounts.delete.v2

Use when: Permanently remove an account that should not be in the workspace at all — a bad import, a test record, a company entered twice under different domains that is not worth merging. Call it first with dry_run true (the default) and show the user what would go; call again with dry_run false only after they confirm.

Avoid when: Do not use this to stop working an account — archive it with accounts.archive.v2, which is reversible. Do not use it for a duplicate of another account — accounts.merge.execute.v2 keeps the history. It refuses while a contact on the account is in a running or paused HiveLoop, or while a Channel Partner record is built on it; the result says which, so tell the user what to stop first rather than retrying.

Effects: Irreversible. Deletes the account with ALL its contacts, their HiveLoop history, messages, drafts and notes, its landing pages and ICP scores, and cancels its signal monitors. dry_run true (the default) previews the counts and writes nothing.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.delete.v2",
      "arguments": {
        "account_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    },
    "account_id": {
      "description": "Exact account UUID returned by a Hivekind search, list, get, preview, or resource call.",
      "format": "uuid",
      "title": "Account Id",
      "type": "string"
    },
    "dry_run": {
      "default": true,
      "description": "True (the default) reports what would be deleted and writes nothing. Show that to the user, then call again with false.",
      "title": "Dry Run",
      "type": "boolean"
    }
  },
  "required": [
    "account_id"
  ],
  "title": "McpMcpAccountsDeleteInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "DeletionBlockerV1": {
      "additionalProperties": false,
      "properties": {
        "code": {
          "description": "live_hiveloop or channel_partner.",
          "maxLength": 64,
          "minLength": 1,
          "title": "Code",
          "type": "string"
        },
        "message": {
          "maxLength": 1000,
          "minLength": 1,
          "title": "Message",
          "type": "string"
        },
        "loops": {
          "default": [],
          "description": "Names of the running or paused HiveLoops holding the record.",
          "items": {
            "type": "string"
          },
          "maxItems": 50,
          "title": "Loops",
          "type": "array"
        }
      },
      "required": [
        "code",
        "message"
      ],
      "title": "DeletionBlockerV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "entity_type": {
      "enum": [
        "account",
        "contact"
      ],
      "title": "Entity Type",
      "type": "string"
    },
    "entity_id": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Entity Id",
      "type": "string"
    },
    "name": {
      "anyOf": [
        {
          "maxLength": 255,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "dry_run": {
      "title": "Dry Run",
      "type": "boolean"
    },
    "deleted": {
      "default": false,
      "title": "Deleted",
      "type": "boolean"
    },
    "can_delete": {
      "title": "Can Delete",
      "type": "boolean"
    },
    "blockers": {
      "default": [],
      "items": {
        "$ref": "#/$defs/DeletionBlockerV1"
      },
      "maxItems": 8,
      "title": "Blockers",
      "type": "array"
    },
    "will_delete": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "Counts of what goes with the record: loop_activations, messages, drafts, notes, and for an account also contacts, signal_monitors and campaign_memberships.",
      "title": "Will Delete",
      "type": "object"
    }
  },
  "required": [
    "entity_type",
    "entity_id",
    "dry_run",
    "can_delete"
  ],
  "title": "AccountsDeleteResultV2",
  "type": "object"
}

Dismiss a duplicate suggestion

accounts.duplicates.dismiss.v2

Use when: You confirmed an exact suggested group contains different companies and want it excluded from future duplicate results.

Avoid when: You intend to combine account data; preview a merge instead.

Effects: Writes a reversible suppression decision; account records are unchanged.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.duplicates.dismiss.v2",
      "arguments": {
        "account_ids": [
          "00000000-0000-4000-8000-000000000001",
          "00000000-0000-4000-8000-000000000001"
        ]
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    },
    "account_ids": {
      "description": "The accounts that are NOT duplicates of each other.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 10,
      "minItems": 2,
      "title": "Account Ids",
      "type": "array"
    }
  },
  "required": [
    "account_ids"
  ],
  "title": "McpMcpAccountsDuplicatesDismissInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "additionalProperties": false,
  "properties": {
    "dismissed": {
      "default": [],
      "items": {
        "type": "string"
      },
      "maxItems": 10,
      "title": "Dismissed",
      "type": "array"
    },
    "pairs": {
      "default": 0,
      "minimum": 0,
      "title": "Pairs",
      "type": "integer"
    }
  },
  "title": "AccountsDuplicatesDismissResultV2",
  "type": "object"
}

Search duplicate account candidates

accounts.duplicates.search.v2

Use when: You need deterministic groups of existing accounts that may represent the same company before data cleanup.

Avoid when: You are searching accounts by business criteria; use accounts.search.v2.

Effects: Returns bounded candidate groups with stable account IDs. Read only.

Cost: No gateway credit charge; reads saved workspace data without starting paid provider work. Gateway rate code: none; downstream billing may apply.

Access: accounts:read. Approval: operation authorization. Reads do not need an operation UUID.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.duplicates.search.v2",
      "arguments": {},
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "limit": {
      "default": 50,
      "description": "Maximum number of records to return in this page.",
      "maximum": 200,
      "minimum": 1,
      "title": "Limit",
      "type": "integer"
    }
  },
  "title": "McpAccountsDuplicatesSearchInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "AccountCampaignMembershipV1": {
      "additionalProperties": false,
      "description": "One campaign an account belongs to (HIVE-1388).",
      "properties": {
        "campaign_id": {
          "format": "uuid",
          "title": "Campaign Id",
          "type": "string"
        },
        "name": {
          "maxLength": 255,
          "title": "Name",
          "type": "string"
        },
        "status": {
          "description": "The campaign's status: \"active\", \"draft\", \"paused\", or \"archived\" once it has been archived, whatever it was before.",
          "maxLength": 64,
          "title": "Status",
          "type": "string"
        },
        "added_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the account joined the campaign (UTC).",
          "title": "Added At"
        }
      },
      "required": [
        "campaign_id",
        "name",
        "status"
      ],
      "title": "AccountCampaignMembershipV1",
      "type": "object"
    },
    "AccountSummaryV1": {
      "additionalProperties": false,
      "properties": {
        "account_id": {
          "format": "uuid",
          "title": "Account Id",
          "type": "string"
        },
        "name": {
          "maxLength": 255,
          "minLength": 1,
          "title": "Name",
          "type": "string"
        },
        "domain": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Domain"
        },
        "industry": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Industry"
        },
        "region": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Region"
        },
        "employee_count": {
          "anyOf": [
            {
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Employee Count"
        },
        "owner_id": {
          "anyOf": [
            {
              "format": "uuid",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Owner Id"
        },
        "account_type": {
          "anyOf": [
            {
              "maxLength": 64,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Account Type"
        },
        "icp_score": {
          "anyOf": [
            {
              "maximum": 100,
              "minimum": 0,
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Icp Score"
        },
        "icp_grade": {
          "anyOf": [
            {
              "maxLength": 32,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Icp Grade"
        },
        "updated_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the account record last changed (UTC).",
          "title": "Updated At"
        },
        "icp_disqualified": {
          "default": false,
          "description": "True when a rubric disqualifier matched this account. A disqualifier pins the account to the rubric's lowest tier no matter how well it scored, so a high icp_score beside a low icp_grade is expected here, not a data error.",
          "title": "Icp Disqualified",
          "type": "boolean"
        },
        "icp_disqualification_reason": {
          "anyOf": [
            {
              "maxLength": 500,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Which disqualifier matched and why. Null unless icp_disqualified is true.",
          "title": "Icp Disqualification Reason"
        },
        "network_strength": {
          "default": 0,
          "description": "Connection strength from distinct usable LinkedIn workspace members and Channel Partner organizations, capped at three.",
          "maximum": 3,
          "minimum": 0,
          "title": "Network Strength",
          "type": "integer"
        },
        "independent_source_count": {
          "default": 0,
          "description": "Uncapped number of distinct usable network sources.",
          "minimum": 0,
          "title": "Independent Source Count",
          "type": "integer"
        },
        "linkedin_member_count": {
          "default": 0,
          "description": "Distinct consented workspace LinkedIn members with a usable route.",
          "minimum": 0,
          "title": "Linkedin Member Count",
          "type": "integer"
        },
        "partner_count": {
          "default": 0,
          "description": "Distinct active Channel Partner organizations with confirmed usable routes.",
          "minimum": 0,
          "title": "Partner Count",
          "type": "integer"
        },
        "partner_names": {
          "default": [],
          "description": "Names of active Channel Partners providing usable routes.",
          "items": {
            "type": "string"
          },
          "maxItems": 20,
          "title": "Partner Names",
          "type": "array"
        },
        "tags": {
          "default": [],
          "description": "Account tags on this account (free-form workspace labels).",
          "items": {
            "type": "string"
          },
          "maxItems": 50,
          "title": "Tags",
          "type": "array"
        },
        "web_url": {
          "anyOf": [
            {
              "maxLength": 2048,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Browser link to this account in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
          "title": "Web Url"
        },
        "campaigns": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/AccountCampaignMembershipV1"
              },
              "maxItems": 50,
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Every campaign this account belongs to, archived ones included, newest membership first. An empty list means it is in none; null means this tool did not look.",
          "title": "Campaigns"
        }
      },
      "required": [
        "account_id",
        "name"
      ],
      "title": "AccountSummaryV1",
      "type": "object"
    },
    "DuplicateAccountGroupV1": {
      "additionalProperties": false,
      "description": "Accounts that look like the same company, most complete first.",
      "properties": {
        "reasons": {
          "default": [],
          "items": {
            "type": "string"
          },
          "maxItems": 8,
          "title": "Reasons",
          "type": "array"
        },
        "accounts": {
          "default": [],
          "items": {
            "$ref": "#/$defs/AccountSummaryV1"
          },
          "maxItems": 10,
          "title": "Accounts",
          "type": "array"
        }
      },
      "title": "DuplicateAccountGroupV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "groups": {
      "default": [],
      "items": {
        "$ref": "#/$defs/DuplicateAccountGroupV1"
      },
      "maxItems": 200,
      "title": "Groups",
      "type": "array"
    },
    "total_groups": {
      "default": 0,
      "minimum": 0,
      "title": "Total Groups",
      "type": "integer"
    }
  },
  "title": "AccountsDuplicatesSearchResultV2",
  "type": "object"
}

Match a company list against accounts

accounts.match.v2

Use when: You have a list of companies (domains, URLs, or names, e.g. from a CRM export, spreadsheet, or roster) and need to know which are already accounts in Hivekind and which are not, in one call. Takes up to 200 entries per call; split a longer list into batches of 200.

Avoid when: You are searching by business criteria such as industry, owner, or ICP grade; use accounts.search.v2. You need duplicates already inside Hivekind; use accounts.duplicates.search.v2.

Effects: Returns every distinct input as matched (with the account), ambiguous (several candidate accounts), or unmatched. Domains are normalized before comparison; names match whole and case-insensitively. Read only.

Cost: No gateway credit charge; reads saved workspace data without starting paid provider work. Gateway rate code: none; downstream billing may apply.

Access: accounts:read. Approval: operation authorization. Reads do not need an operation UUID.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.match.v2",
      "arguments": {
        "items": [
          "Example items"
        ]
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "items": {
      "description": "Companies to look up, one per entry: a domain, a website URL, or a company name. Domains and URLs are normalized (scheme, www., path and port dropped, lowercased) and matched against account domains; anything else, or a domain with no match, is matched against the account name, whole and case-insensitively. Blank entries are ignored and repeats are answered once.",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "minItems": 1,
      "title": "Items",
      "type": "array"
    },
    "include_archived": {
      "default": true,
      "description": "Also match archived accounts, reported with account_status \"archived\". Leave on when checking a list before an import: an archived account is still in Hivekind, and reporting it as missing invites a duplicate.",
      "title": "Include Archived",
      "type": "boolean"
    }
  },
  "required": [
    "items"
  ],
  "title": "McpAccountsMatchInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "AccountMatchAmbiguousV2": {
      "additionalProperties": false,
      "description": "One input that resolves to more than one account; the caller picks.",
      "properties": {
        "input": {
          "maxLength": 500,
          "title": "Input",
          "type": "string"
        },
        "matched_on": {
          "enum": [
            "domain",
            "name"
          ],
          "title": "Matched On",
          "type": "string"
        },
        "candidates": {
          "items": {
            "$ref": "#/$defs/AccountMatchRowV2"
          },
          "maxItems": 25,
          "minItems": 2,
          "title": "Candidates",
          "type": "array"
        }
      },
      "required": [
        "input",
        "matched_on",
        "candidates"
      ],
      "title": "AccountMatchAmbiguousV2",
      "type": "object"
    },
    "AccountMatchRowV2": {
      "additionalProperties": false,
      "properties": {
        "account_id": {
          "format": "uuid",
          "title": "Account Id",
          "type": "string"
        },
        "name": {
          "maxLength": 255,
          "title": "Name",
          "type": "string"
        },
        "domain": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Domain"
        },
        "account_type": {
          "anyOf": [
            {
              "maxLength": 64,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Account Type"
        },
        "account_status": {
          "enum": [
            "active",
            "archived"
          ],
          "title": "Account Status",
          "type": "string"
        },
        "owner_id": {
          "anyOf": [
            {
              "format": "uuid",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Owner Id"
        },
        "owner_name": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Owner Name"
        },
        "icp_grade": {
          "anyOf": [
            {
              "maxLength": 32,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Icp Grade"
        },
        "icp_score": {
          "anyOf": [
            {
              "maximum": 100,
              "minimum": 0,
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Icp Score"
        }
      },
      "required": [
        "account_id",
        "name",
        "account_status"
      ],
      "title": "AccountMatchRowV2",
      "type": "object"
    },
    "AccountMatchV2": {
      "additionalProperties": false,
      "properties": {
        "input": {
          "maxLength": 500,
          "title": "Input",
          "type": "string"
        },
        "matched_on": {
          "enum": [
            "domain",
            "name"
          ],
          "title": "Matched On",
          "type": "string"
        },
        "account": {
          "$ref": "#/$defs/AccountMatchRowV2"
        }
      },
      "required": [
        "input",
        "matched_on",
        "account"
      ],
      "title": "AccountMatchV2",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "matched": {
      "default": [],
      "items": {
        "$ref": "#/$defs/AccountMatchV2"
      },
      "maxItems": 200,
      "title": "Matched",
      "type": "array"
    },
    "ambiguous": {
      "default": [],
      "items": {
        "$ref": "#/$defs/AccountMatchAmbiguousV2"
      },
      "maxItems": 200,
      "title": "Ambiguous",
      "type": "array"
    },
    "unmatched": {
      "default": [],
      "description": "Inputs with no account in the workspace, verbatim.",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "title": "Unmatched",
      "type": "array"
    },
    "input_count": {
      "maximum": 200,
      "minimum": 0,
      "title": "Input Count",
      "type": "integer"
    },
    "distinct_count": {
      "maximum": 200,
      "minimum": 0,
      "title": "Distinct Count",
      "type": "integer"
    }
  },
  "required": [
    "input_count",
    "distinct_count"
  ],
  "title": "AccountsMatchResultV2",
  "type": "object"
}

Execute an irreversible account merge

accounts.merge.execute.v2

Use when: You explicitly approved the exact survivor/absorbed pair after reviewing accounts.merge.preview.v2.

Avoid when: You have not previewed the pair, are uncertain they are duplicates, or only want to suppress the suggestion.

Effects: Moves related rows, fills survivor blanks, and permanently DELETES the absorbed account. Irreversible.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.merge.execute.v2",
      "arguments": {
        "absorbed_account_id": "00000000-0000-4000-8000-000000000002",
        "winner_account_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "winner_account_id": {
      "description": "The account that would survive.",
      "format": "uuid",
      "title": "Winner Account Id",
      "type": "string"
    },
    "absorbed_account_id": {
      "description": "The account that would be absorbed and deleted by execute.",
      "format": "uuid",
      "title": "Absorbed Account Id",
      "type": "string"
    },
    "field_overrides": {
      "additionalProperties": {
        "enum": [
          "winner",
          "loser"
        ],
        "type": "string"
      },
      "description": "Which record's value wins, for a column BOTH accounts have filled — for example {\"account_type\": \"loser\"}. A column left out keeps the survivor's value. Columns the survivor left blank are taken from the absorbed account either way, so this only settles real conflicts.",
      "title": "Field Overrides",
      "type": "object"
    },
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    }
  },
  "required": [
    "winner_account_id",
    "absorbed_account_id"
  ],
  "title": "McpMcpAccountsMergeExecuteInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "MergedAccountBriefV1": {
      "additionalProperties": false,
      "description": "Enough of an account to say which row survived and which was absorbed.",
      "properties": {
        "account_id": {
          "maxLength": 64,
          "minLength": 1,
          "title": "Account Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "domain": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Domain"
        },
        "account_status": {
          "anyOf": [
            {
              "maxLength": 32,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Account Status"
        },
        "web_url": {
          "anyOf": [
            {
              "maxLength": 2048,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Browser link to this account (null for an absorbed account once the merge ran) in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
          "title": "Web Url"
        }
      },
      "required": [
        "account_id"
      ],
      "title": "MergedAccountBriefV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "winner": {
      "$ref": "#/$defs/MergedAccountBriefV1"
    },
    "loser": {
      "$ref": "#/$defs/MergedAccountBriefV1"
    },
    "rows_moved": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "Child rows repointed onto the winner, by table.",
      "title": "Rows Moved",
      "type": "object"
    },
    "rows_dropped": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "Loser rows dropped because the winner already held the equivalent row.",
      "title": "Rows Dropped",
      "type": "object"
    },
    "fields_filled": {
      "default": [],
      "description": "Winner columns that were blank and were taken from the loser.",
      "items": {
        "type": "string"
      },
      "maxItems": 32,
      "title": "Fields Filled",
      "type": "array"
    },
    "fields_overridden": {
      "default": [],
      "description": "Winner columns that held a value and were replaced by the loser's, because field_overrides asked for it.",
      "items": {
        "type": "string"
      },
      "maxItems": 32,
      "title": "Fields Overridden",
      "type": "array"
    },
    "dry_run": {
      "default": false,
      "title": "Dry Run",
      "type": "boolean"
    },
    "warnings": {
      "default": [],
      "items": {
        "type": "string"
      },
      "maxItems": 32,
      "title": "Warnings",
      "type": "array"
    }
  },
  "required": [
    "winner",
    "loser"
  ],
  "title": "AccountsMergeResultV2",
  "type": "object"
}

Preview an account merge

accounts.merge.preview.v2

Use when: You selected an exact survivor and absorbed account from duplicate evidence and need to see every row and field that would move.

Avoid when: You want to apply the merge, or the accounts are not confirmed duplicates.

Effects: Forces dry-run mode. Nothing is written or deleted.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: accounts:read. Approval: operation authorization. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.merge.preview.v2",
      "arguments": {
        "absorbed_account_id": "00000000-0000-4000-8000-000000000002",
        "winner_account_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "winner_account_id": {
      "description": "The account that would survive.",
      "format": "uuid",
      "title": "Winner Account Id",
      "type": "string"
    },
    "absorbed_account_id": {
      "description": "The account that would be absorbed and deleted by execute.",
      "format": "uuid",
      "title": "Absorbed Account Id",
      "type": "string"
    },
    "field_overrides": {
      "additionalProperties": {
        "enum": [
          "winner",
          "loser"
        ],
        "type": "string"
      },
      "description": "Which record's value wins, for a column BOTH accounts have filled — for example {\"account_type\": \"loser\"}. A column left out keeps the survivor's value. Columns the survivor left blank are taken from the absorbed account either way, so this only settles real conflicts.",
      "title": "Field Overrides",
      "type": "object"
    }
  },
  "required": [
    "winner_account_id",
    "absorbed_account_id"
  ],
  "title": "McpAccountsMergePreviewInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "MergedAccountBriefV1": {
      "additionalProperties": false,
      "description": "Enough of an account to say which row survived and which was absorbed.",
      "properties": {
        "account_id": {
          "maxLength": 64,
          "minLength": 1,
          "title": "Account Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "domain": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Domain"
        },
        "account_status": {
          "anyOf": [
            {
              "maxLength": 32,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Account Status"
        },
        "web_url": {
          "anyOf": [
            {
              "maxLength": 2048,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Browser link to this account (null for an absorbed account once the merge ran) in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
          "title": "Web Url"
        }
      },
      "required": [
        "account_id"
      ],
      "title": "MergedAccountBriefV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "winner": {
      "$ref": "#/$defs/MergedAccountBriefV1"
    },
    "loser": {
      "$ref": "#/$defs/MergedAccountBriefV1"
    },
    "rows_moved": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "Child rows repointed onto the winner, by table.",
      "title": "Rows Moved",
      "type": "object"
    },
    "rows_dropped": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "Loser rows dropped because the winner already held the equivalent row.",
      "title": "Rows Dropped",
      "type": "object"
    },
    "fields_filled": {
      "default": [],
      "description": "Winner columns that were blank and were taken from the loser.",
      "items": {
        "type": "string"
      },
      "maxItems": 32,
      "title": "Fields Filled",
      "type": "array"
    },
    "fields_overridden": {
      "default": [],
      "description": "Winner columns that held a value and were replaced by the loser's, because field_overrides asked for it.",
      "items": {
        "type": "string"
      },
      "maxItems": 32,
      "title": "Fields Overridden",
      "type": "array"
    },
    "dry_run": {
      "default": false,
      "title": "Dry Run",
      "type": "boolean"
    },
    "warnings": {
      "default": [],
      "items": {
        "type": "string"
      },
      "maxItems": 32,
      "title": "Warnings",
      "type": "array"
    }
  },
  "required": [
    "winner",
    "loser"
  ],
  "title": "AccountsMergeResultV2",
  "type": "object"
}

Assign an account owner

accounts.owner.set.v2

Use when: Give accounts an owner, or move them to a different one. Do this for accounts that arrived without one: an account nobody owns is skipped by every rule-based grading run, so it can never be re-scored again.

Avoid when: Do not use this to change what an account is graded against in general — grading follows the owner's own pinned rubric, so this moves the account to that person's rubric as a side effect.

Effects: Re-grades each account in the background against the new owner's rubric, which spends scoring credits. An owner with no rubric pinned has the account's score cleared instead.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.owner.set.v2",
      "arguments": {
        "account_ids": [
          "00000000-0000-4000-8000-000000000001"
        ],
        "owner_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "account_ids": {
      "description": "Exact account UUIDs returned by a Hivekind search, list, get, preview, or resource call.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 100,
      "minItems": 1,
      "title": "Account Ids",
      "type": "array"
    },
    "owner_id": {
      "description": "The workspace member to own these accounts. Grading follows the owner's own pinned rubric, so choose someone assigned to the rubric these accounts should be graded against -- an owner with no rubric has their score cleared instead.",
      "format": "uuid",
      "title": "Owner Id",
      "type": "string"
    },
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    }
  },
  "required": [
    "account_ids",
    "owner_id"
  ],
  "title": "McpMcpAccountsOwnerSetInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "AccountOwnerAssignmentV2": {
      "additionalProperties": false,
      "description": "What became of one account in the batch.",
      "properties": {
        "account_id": {
          "format": "uuid",
          "title": "Account Id",
          "type": "string"
        },
        "name": {
          "default": "",
          "maxLength": 255,
          "title": "Name",
          "type": "string"
        },
        "assigned": {
          "default": false,
          "title": "Assigned",
          "type": "boolean"
        },
        "reason": {
          "default": "",
          "maxLength": 500,
          "title": "Reason",
          "type": "string"
        }
      },
      "required": [
        "account_id"
      ],
      "title": "AccountOwnerAssignmentV2",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "owner_id": {
      "format": "uuid",
      "title": "Owner Id",
      "type": "string"
    },
    "assigned_count": {
      "default": 0,
      "minimum": 0,
      "title": "Assigned Count",
      "type": "integer"
    },
    "failed_count": {
      "default": 0,
      "minimum": 0,
      "title": "Failed Count",
      "type": "integer"
    },
    "accounts": {
      "default": [],
      "items": {
        "$ref": "#/$defs/AccountOwnerAssignmentV2"
      },
      "maxItems": 100,
      "title": "Accounts",
      "type": "array"
    }
  },
  "required": [
    "owner_id"
  ],
  "title": "AccountsOwnerSetResultV2",
  "type": "object"
}

Edit account fields

accounts.update.v2

Use when: Correct or fill in an account's details — name, domain, industry, region, type, subtype, tier or owner — on one account or on many at once. Pass dry_run true first to see exactly which accounts would change, what each change sets off, and what it would cost; use clear_fields to empty a field, since leaving a field out means 'keep it'.

Avoid when: Do not use this to archive an account — that is accounts.archive.v2 — or to delete one, which is accounts.delete.v2. Do not use it to combine two records for the same company — that is accounts.merge.execute.v2. Changing an account's type to Competitor, Self or Partner pins its ICP grade, so do not reach for it as a way to adjust a score.

Effects: Changing the owner re-scores each account in the background against the new owner's pinned rubric, which spends scoring credits; an owner with no rubric has the account's score cleared instead. Contacts, HiveLoops and drafts are NOT reassigned — only the account's owner moves. Changing account_type to Competitor pins the grade to F, Self and Partner pin it to "-", and each of those keeps a matching Context Library entry in step. Accounts that are archived, outside the workspace, unchanged, or whose new domain is already taken are skipped with a reason rather than failing the call.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "accounts.update.v2",
      "arguments": {
        "account_ids": [
          "00000000-0000-4000-8000-000000000001"
        ],
        "updates": {
          "industry": "Software"
        }
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "$defs": {
    "AccountFieldUpdatesV1": {
      "additionalProperties": false,
      "description": "New values for the fields being changed. Omitted means \"leave alone\".",
      "properties": {
        "name": {
          "anyOf": [
            {
              "maxLength": 255,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Company name.",
          "title": "Name"
        },
        "domain": {
          "anyOf": [
            {
              "maxLength": 255,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary company domain. Normalised on the way in, so a full URL is accepted. Only settable on one account per call, because the workspace allows one account per domain.",
          "title": "Domain"
        },
        "industry": {
          "anyOf": [
            {
              "maxLength": 255,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Industry"
        },
        "region": {
          "anyOf": [
            {
              "maxLength": 255,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Region"
        },
        "account_type": {
          "anyOf": [
            {
              "maxLength": 64,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Prospect, Client, Prior Client, Partner, Competitor or Self. Competitor pins the ICP grade to F, Self and Partner pin it to \"-\", and each of the four keeps a matching Context Library entry in step.",
          "title": "Account Type"
        },
        "account_subtype": {
          "anyOf": [
            {
              "maxLength": 64,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Account Subtype"
        },
        "account_tier": {
          "anyOf": [
            {
              "pattern": "^[A-Da-d]$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A, B, C or D.",
          "title": "Account Tier"
        },
        "partner_type": {
          "anyOf": [
            {
              "maxLength": 64,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Partner Type"
        },
        "user_id": {
          "anyOf": [
            {
              "format": "uuid",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "New owner. Changing it re-scores the account against that person's pinned rubric, which spends credits; an owner with no rubric has the account's score cleared instead.",
          "title": "User Id"
        }
      },
      "title": "AccountFieldUpdatesV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    },
    "account_ids": {
      "description": "Accounts to apply the same change to.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 500,
      "minItems": 1,
      "title": "Account Ids",
      "type": "array"
    },
    "updates": {
      "$ref": "#/$defs/AccountFieldUpdatesV1",
      "description": "Fields to set. Leave a field out to keep its value."
    },
    "clear_fields": {
      "default": [],
      "description": "Fields to set back to empty: user_id, account_tier, account_subtype, partner_type, industry, region. Leaving a field out of updates keeps it; only this clears it.",
      "items": {
        "type": "string"
      },
      "maxItems": 6,
      "title": "Clear Fields",
      "type": "array"
    },
    "dry_run": {
      "default": false,
      "description": "True previews the per-account change and what it would cost, and writes nothing. Preview first whenever the change moves owners — each re-scored account spends credits.",
      "title": "Dry Run",
      "type": "boolean"
    }
  },
  "required": [
    "account_ids"
  ],
  "title": "McpMcpAccountsUpdateInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "AccountUpdateOutcomeV1": {
      "additionalProperties": false,
      "description": "What one account in the batch did, or would do.",
      "properties": {
        "account_id": {
          "maxLength": 64,
          "minLength": 1,
          "title": "Account Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "web_url": {
          "anyOf": [
            {
              "maxLength": 2048,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Browser link to this account in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
          "title": "Web Url"
        },
        "updated": {
          "default": false,
          "title": "Updated",
          "type": "boolean"
        },
        "changed_fields": {
          "default": [],
          "description": "Fields that actually differed; unchanged values are not rewritten.",
          "items": {
            "type": "string"
          },
          "maxItems": 16,
          "title": "Changed Fields",
          "type": "array"
        },
        "reason": {
          "anyOf": [
            {
              "maxLength": 64,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Why this account was left alone. One of: not_found (outside the workspace), archived, domain_taken (another account already holds that domain), no_change, update_failed. Null when it was updated.",
          "title": "Reason"
        },
        "consequences": {
          "default": [],
          "description": "What this change sets off elsewhere — re-scores, cleared grades, Library entries. Repeat these to the user rather than paraphrasing.",
          "items": {
            "type": "string"
          },
          "maxItems": 8,
          "title": "Consequences",
          "type": "array"
        }
      },
      "required": [
        "account_id"
      ],
      "title": "AccountUpdateOutcomeV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "results": {
      "default": [],
      "items": {
        "$ref": "#/$defs/AccountUpdateOutcomeV1"
      },
      "maxItems": 500,
      "title": "Results",
      "type": "array"
    },
    "updated": {
      "default": 0,
      "minimum": 0,
      "title": "Updated",
      "type": "integer"
    },
    "skipped": {
      "default": 0,
      "description": "Accounts left alone; each one's reason is on its outcome.",
      "minimum": 0,
      "title": "Skipped",
      "type": "integer"
    },
    "dry_run": {
      "default": false,
      "title": "Dry Run",
      "type": "boolean"
    },
    "accounts_to_rescore": {
      "default": 0,
      "description": "Accounts whose owner change fires a metered ICP re-score.",
      "minimum": 0,
      "title": "Accounts To Rescore",
      "type": "integer"
    },
    "estimated_credits": {
      "default": "0",
      "description": "Credits those re-scores are expected to cost, from the workspace rate card. Decimal as a string.",
      "maxLength": 32,
      "title": "Estimated Credits",
      "type": "string"
    }
  },
  "title": "AccountsUpdateResultV2",
  "type": "object"
}

Delete a contact

contacts.delete.v2

Use when: Permanently remove a contact that should not be in the workspace — a wrong person, a bad import, a test record. Call it first with dry_run true (the default) and show the user what would go; call again with dry_run false only after they confirm.

Avoid when: It refuses while the contact is in a running or paused HiveLoop; the result names the loop, so tell the user to remove them from it first rather than retrying.

Effects: Irreversible. Deletes the contact with its HiveLoop history, messages, drafts and notes. dry_run true (the default) previews the counts and writes nothing.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "contacts.delete.v2",
      "arguments": {
        "contact_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    },
    "contact_id": {
      "description": "Exact contact UUID returned by a Hivekind search, list, get, preview, or resource call.",
      "format": "uuid",
      "title": "Contact Id",
      "type": "string"
    },
    "dry_run": {
      "default": true,
      "description": "True (the default) reports what would be deleted and writes nothing. Show that to the user, then call again with false.",
      "title": "Dry Run",
      "type": "boolean"
    }
  },
  "required": [
    "contact_id"
  ],
  "title": "McpMcpContactsDeleteInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "DeletionBlockerV1": {
      "additionalProperties": false,
      "properties": {
        "code": {
          "description": "live_hiveloop or channel_partner.",
          "maxLength": 64,
          "minLength": 1,
          "title": "Code",
          "type": "string"
        },
        "message": {
          "maxLength": 1000,
          "minLength": 1,
          "title": "Message",
          "type": "string"
        },
        "loops": {
          "default": [],
          "description": "Names of the running or paused HiveLoops holding the record.",
          "items": {
            "type": "string"
          },
          "maxItems": 50,
          "title": "Loops",
          "type": "array"
        }
      },
      "required": [
        "code",
        "message"
      ],
      "title": "DeletionBlockerV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "entity_type": {
      "enum": [
        "account",
        "contact"
      ],
      "title": "Entity Type",
      "type": "string"
    },
    "entity_id": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Entity Id",
      "type": "string"
    },
    "name": {
      "anyOf": [
        {
          "maxLength": 255,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "dry_run": {
      "title": "Dry Run",
      "type": "boolean"
    },
    "deleted": {
      "default": false,
      "title": "Deleted",
      "type": "boolean"
    },
    "can_delete": {
      "title": "Can Delete",
      "type": "boolean"
    },
    "blockers": {
      "default": [],
      "items": {
        "$ref": "#/$defs/DeletionBlockerV1"
      },
      "maxItems": 8,
      "title": "Blockers",
      "type": "array"
    },
    "will_delete": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "Counts of what goes with the record: loop_activations, messages, drafts, notes, and for an account also contacts, signal_monitors and campaign_memberships.",
      "title": "Will Delete",
      "type": "object"
    }
  },
  "required": [
    "entity_type",
    "entity_id",
    "dry_run",
    "can_delete"
  ],
  "title": "ContactsDeleteResultV2",
  "type": "object"
}

Preview employment verification

contacts.employment.preview.v2

Use when: You resolved exact contact or account IDs and need the billable lookup count before checking employment.

Avoid when: You want to run verification or start outreach.

Effects: No lookups, contact changes, activation changes, or charges.

Cost: Free. Reports the estimated verification charge. Gateway rate code: none; downstream billing may apply.

Access: accounts:read. Approval: operation authorization. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "contacts.employment.preview.v2",
      "arguments": {
        "contact_ids": [
          "00000000-0000-4000-8000-000000000001"
        ]
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "contact_ids": {
      "default": [],
      "description": "Check exactly these contacts. Resolve the request to a concrete set first — contacts.search.v2, or the contacts on an account — then pass them here.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 1000,
      "title": "Contact Ids",
      "type": "array"
    },
    "account_ids": {
      "default": [],
      "description": "Check every contact at these accounts. Expanded server-side, so the batch cap applies to the contacts this resolves to, not to the number of accounts named.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 200,
      "title": "Account Ids",
      "type": "array"
    }
  },
  "title": "McpContactsEmploymentPreviewInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "additionalProperties": false,
  "properties": {
    "requested_contacts": {
      "minimum": 0,
      "title": "Requested Contacts",
      "type": "integer"
    },
    "would_check": {
      "description": "Contacts a lookup would actually be made for — the billable count.",
      "minimum": 0,
      "title": "Would Check",
      "type": "integer"
    },
    "already_fresh": {
      "description": "Checked within the last 90 days; free and skipped.",
      "minimum": 0,
      "title": "Already Fresh",
      "type": "integer"
    },
    "no_email": {
      "description": "No email address, so never eligible for a lookup.",
      "minimum": 0,
      "title": "No Email",
      "type": "integer"
    },
    "not_found": {
      "description": "Named contact ids that do not exist in this workspace. Only meaningful when contact_ids was given.",
      "minimum": 0,
      "title": "Not Found",
      "type": "integer"
    },
    "credits_per_contact": {
      "minimum": 0,
      "title": "Credits Per Contact",
      "type": "number"
    },
    "estimated_credits": {
      "minimum": 0,
      "title": "Estimated Credits",
      "type": "number"
    },
    "max_batch": {
      "minimum": 1,
      "title": "Max Batch",
      "type": "integer"
    }
  },
  "required": [
    "requested_contacts",
    "would_check",
    "already_fresh",
    "no_email",
    "not_found",
    "credits_per_contact",
    "estimated_credits",
    "max_batch"
  ],
  "title": "ContactsEmploymentPreviewResultV2",
  "type": "object"
}

Start employment verification

contacts.employment.start.v2

Use when: You approved the exact contact/account scope returned by contacts.employment.preview.v2 and need current-employer checks.

Avoid when: You want to send outreach, or have not previewed the billable scope.

Effects: Queues verification; confirmed departures pause activations, cancel unsent drafts, and enqueue employer refresh. It never sends outreach.

Cost: One credit per fresh lookup completed; cached, missing-email, and failed lookups are free. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "contacts.employment.start.v2",
      "arguments": {
        "contact_ids": [
          "00000000-0000-4000-8000-000000000001"
        ]
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "contact_ids": {
      "default": [],
      "description": "Check exactly these contacts. Resolve the request to a concrete set first — contacts.search.v2, or the contacts on an account — then pass them here.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 1000,
      "title": "Contact Ids",
      "type": "array"
    },
    "account_ids": {
      "default": [],
      "description": "Check every contact at these accounts. Expanded server-side, so the batch cap applies to the contacts this resolves to, not to the number of accounts named.",
      "items": {
        "format": "uuid",
        "type": "string"
      },
      "maxItems": 200,
      "title": "Account Ids",
      "type": "array"
    },
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    }
  },
  "title": "McpMcpContactsEmploymentStartInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "additionalProperties": false,
  "properties": {
    "run_id": {
      "format": "uuid",
      "title": "Run Id",
      "type": "string"
    },
    "job_id": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Job Id",
      "type": "string"
    },
    "requested_contacts": {
      "minimum": 0,
      "title": "Requested Contacts",
      "type": "integer"
    },
    "would_check": {
      "minimum": 0,
      "title": "Would Check",
      "type": "integer"
    }
  },
  "required": [
    "run_id",
    "job_id",
    "requested_contacts",
    "would_check"
  ],
  "title": "ContactsEmploymentStartResultV2",
  "type": "object"
}

Get employment verification status

contacts.employment.status.get.v2

Use when: You have a verification run_id and need progress, departures, and updated-employer evidence.

Avoid when: You need status for an import, discovery, or grading job.

Effects: Returns a bounded status result. Read only.

Cost: No gateway credit charge; reads saved workspace data without starting paid provider work. Gateway rate code: none; downstream billing may apply.

Access: accounts:read. Approval: operation authorization. Reads do not need an operation UUID.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "contacts.employment.status.get.v2",
      "arguments": {
        "run_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "run_id": {
      "description": "Exact run UUID returned by a Hivekind search, list, get, preview, or resource call.",
      "format": "uuid",
      "title": "Run Id",
      "type": "string"
    }
  },
  "required": [
    "run_id"
  ],
  "title": "McpContactsEmploymentStatusInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "$defs": {
    "DepartedContactV1": {
      "additionalProperties": false,
      "properties": {
        "contact_id": {
          "anyOf": [
            {
              "format": "uuid",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Contact Id"
        },
        "contact_name": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Contact Name"
        },
        "contact_email": {
          "anyOf": [
            {
              "maxLength": 320,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Contact Email"
        },
        "reason": {
          "anyOf": [
            {
              "maxLength": 64,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Reason"
        },
        "current_company": {
          "anyOf": [
            {
              "maxLength": 255,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where Exa says they work now, when it could tell.",
          "title": "Current Company"
        }
      },
      "title": "DepartedContactV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "run_id": {
      "format": "uuid",
      "title": "Run Id",
      "type": "string"
    },
    "status": {
      "enum": [
        "pending",
        "running",
        "succeeded",
        "failed"
      ],
      "title": "Status",
      "type": "string"
    },
    "requested_count": {
      "minimum": 0,
      "title": "Requested Count",
      "type": "integer"
    },
    "processed_count": {
      "minimum": 0,
      "title": "Processed Count",
      "type": "integer"
    },
    "passing_count": {
      "minimum": 0,
      "title": "Passing Count",
      "type": "integer"
    },
    "blocked_count": {
      "minimum": 0,
      "title": "Blocked Count",
      "type": "integer"
    },
    "unverified_count": {
      "description": "Contacts whose lookup never completed, so nothing was confirmed either way. These are NOT billed and are re-checked next time.",
      "minimum": 0,
      "title": "Unverified Count",
      "type": "integer"
    },
    "blocked_contacts": {
      "default": [],
      "items": {
        "$ref": "#/$defs/DepartedContactV1"
      },
      "maxItems": 200,
      "title": "Blocked Contacts",
      "type": "array"
    },
    "error_message": {
      "anyOf": [
        {
          "maxLength": 1000,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Error Message"
    },
    "started_at": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Started At"
    },
    "completed_at": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Completed At"
    }
  },
  "required": [
    "run_id",
    "status",
    "requested_count",
    "processed_count",
    "passing_count",
    "blocked_count",
    "unverified_count"
  ],
  "title": "ContactsEmploymentStatusResultV2",
  "type": "object"
}

Move a contact to another account

contacts.move.v2

Use when: Re-file a contact that sits under the wrong company — a bad import, an old employer, a duplicate account that is not being merged. Resolve the contact_id and the target account_id first, and name both to the user before moving.

Avoid when: Do not use this to merge two accounts — that is accounts.merge.execute.v2, which moves every contact. Do not use it to edit the person's fields — that is contacts.update.v2. It refuses when the target already has the same person (same email or LinkedIn profile), when the target is archived, or while the contact is in a running or paused HiveLoop; the error says which, so tell the user rather than retrying.

Effects: Changes only the contact's account. Messages, HiveLoop history, signals and LinkedIn relationship status stay with the contact; its own notes move to the new account's feed. No ICP re-score and no owner change. The move is recorded in the contact's move history with who made it. Reversible by moving it back.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "contacts.move.v2",
      "arguments": {
        "contact_id": "00000000-0000-4000-8000-000000000001",
        "target_account_id": "00000000-0000-4000-8000-000000000001"
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "additionalProperties": false,
  "properties": {
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    },
    "contact_id": {
      "description": "Exact contact_id; resolve it with contacts.search.v2 first.",
      "format": "uuid",
      "title": "Contact Id",
      "type": "string"
    },
    "target_account_id": {
      "description": "Exact account_id of the account to move the contact to; resolve it with accounts.search.v2 first.",
      "format": "uuid",
      "title": "Target Account Id",
      "type": "string"
    },
    "reason": {
      "anyOf": [
        {
          "maxLength": 500,
          "minLength": 1,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Why the contact is being moved; kept in the contact's move history.",
      "title": "Reason"
    }
  },
  "required": [
    "contact_id",
    "target_account_id"
  ],
  "title": "McpMcpPublicContactsMoveInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "additionalProperties": false,
  "description": "V2 result for contacts.move.v2; preserves the established validators.",
  "properties": {
    "contact_id": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Contact Id",
      "type": "string"
    },
    "name": {
      "anyOf": [
        {
          "maxLength": 255,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "moved": {
      "description": "False when the contact was already on that account; nothing changed.",
      "title": "Moved",
      "type": "boolean"
    },
    "from_account_id": {
      "anyOf": [
        {
          "maxLength": 64,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "From Account Id"
    },
    "from_account_name": {
      "anyOf": [
        {
          "maxLength": 255,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "From Account Name"
    },
    "to_account_id": {
      "maxLength": 64,
      "minLength": 1,
      "title": "To Account Id",
      "type": "string"
    },
    "to_account_name": {
      "anyOf": [
        {
          "maxLength": 255,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "To Account Name"
    },
    "notes_moved": {
      "default": 0,
      "description": "The contact's own notes, now shown on the new account's feed.",
      "minimum": 0,
      "title": "Notes Moved",
      "type": "integer"
    },
    "web_url": {
      "anyOf": [
        {
          "maxLength": 2048,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Browser link to this contact in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
      "title": "Web Url"
    },
    "to_account_web_url": {
      "anyOf": [
        {
          "maxLength": 2048,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Browser link to this account the contact now belongs to in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
      "title": "To Account Web Url"
    }
  },
  "required": [
    "contact_id",
    "moved",
    "to_account_id"
  ],
  "title": "PublicContactsMoveResultV2",
  "type": "object"
}

Edit contact fields

contacts.update.v2

Use when: Correct or fill in a contact's first or last name, title, email, phone or LinkedIn URL. Leave a field out to keep it; list it in clear_fields to empty it.

Avoid when: Do not use this to change a buyer role — that comes from buyer-role classification (accounts.classify_buyers.v2). Do not use it to move a contact to a different company. Do not use it to verify whether someone still works somewhere — that is the employment tools.

Effects: Writes only the fields passed. An email already held by another contact in the workspace is refused.

Cost: No gateway rate is configured. Check the Core workflow preview/quote for downstream charges and final settlement. Gateway rate code: none; downstream billing may apply.

Access: actions:execute. Approval: exact_scope_single_action. A stable operation UUID is required.

Keep the same operation and operation_id when retrying identical work. Reconcile an uncertain result before new work; never replay an old V1 write under a new V2 ID.

Check status, execution_state, error_code, output and evidence/resource references. Queued work is not complete: poll jobs.status.get.v2 in domain.workspace.v2. For read-back verification require read_back_verified=true where returned; reconcile failures without creating another object.

Invocation example using fictional fixtures
{
  "tool": "domain.data_quality.v2",
  "arguments": {
    "params": {
      "action": "invoke",
      "operation": "contacts.update.v2",
      "arguments": {
        "contact_id": "00000000-0000-4000-8000-000000000001",
        "updates": {
          "first_name": "Example"
        }
      },
      "operation_id": "00000000-0000-4000-8000-000000000003"
    }
  },
  "notice": "Fictional fixture IDs and example text. Resolve real IDs, use returned preview tokens and approve exact side effects before execution. Input validation is not proof of provider readiness or a successful business outcome."
}
Input schema: fields, defaults and constraints
{
  "$defs": {
    "ContactFieldUpdatesV1": {
      "additionalProperties": false,
      "description": "New values for the fields being changed. Omitted means \"leave alone\".",
      "properties": {
        "first_name": {
          "anyOf": [
            {
              "maxLength": 120,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "First Name"
        },
        "last_name": {
          "anyOf": [
            {
              "maxLength": 120,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Last Name"
        },
        "title": {
          "anyOf": [
            {
              "maxLength": 255,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Title"
        },
        "email": {
          "anyOf": [
            {
              "maxLength": 320,
              "minLength": 3,
              "pattern": "^[^@\\s]+@[^@\\s]+$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Must not already belong to another contact in the workspace.",
          "title": "Email"
        },
        "phone": {
          "anyOf": [
            {
              "maxLength": 64,
              "minLength": 3,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Phone"
        },
        "linkedin_url": {
          "anyOf": [
            {
              "maxLength": 512,
              "minLength": 10,
              "pattern": "^https?://([a-z]{2,3}\\.)?linkedin\\.com/",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The person's linkedin.com/in/... profile URL.",
          "title": "Linkedin Url"
        }
      },
      "title": "ContactFieldUpdatesV1",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "properties": {
    "action_proposal_id": {
      "anyOf": [
        {
          "format": "uuid",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional. Hivekind fills this from the MCP consent grant.",
      "title": "Action Proposal Id"
    },
    "contact_id": {
      "description": "Exact contact UUID returned by a Hivekind search, list, get, preview, or resource call.",
      "format": "uuid",
      "title": "Contact Id",
      "type": "string"
    },
    "updates": {
      "$ref": "#/$defs/ContactFieldUpdatesV1",
      "description": "Fields to set. Leave a field out to keep its value."
    },
    "clear_fields": {
      "default": [],
      "description": "Fields to set back to empty. Leaving a field out of updates keeps it; only this clears it.",
      "items": {
        "enum": [
          "title",
          "email",
          "phone",
          "linkedin_url"
        ],
        "type": "string"
      },
      "maxItems": 4,
      "title": "Clear Fields",
      "type": "array"
    }
  },
  "required": [
    "contact_id"
  ],
  "title": "McpMcpContactsUpdateInputV2",
  "type": "object"
}
Output schema inside the result envelope
{
  "additionalProperties": false,
  "properties": {
    "contact_id": {
      "maxLength": 64,
      "minLength": 1,
      "title": "Contact Id",
      "type": "string"
    },
    "account_id": {
      "anyOf": [
        {
          "maxLength": 64,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Account Id"
    },
    "name": {
      "anyOf": [
        {
          "maxLength": 255,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "changed_fields": {
      "default": [],
      "items": {
        "type": "string"
      },
      "maxItems": 16,
      "title": "Changed Fields",
      "type": "array"
    },
    "web_url": {
      "anyOf": [
        {
          "maxLength": 2048,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Browser link to this contact in the Hivekind app. Use it verbatim whenever you link the record for a person, including inside note bodies; never build a link by hand or use a hivekind:// URI, which is an MCP resource handle, not a page. Null when the server has no app URL configured.",
      "title": "Web Url"
    }
  },
  "required": [
    "contact_id"
  ],
  "title": "ContactsUpdateResultV2",
  "type": "object"
}