CRM Config tools
The org's SHAPE rather than its records: deal stages, contact lifecycle stages, custom fields, task types, standard-field options and field layout. Export the whole shape as one document and apply it back — idempotently, with a dry run.
24 tools. Each is callable over MCP with a Bearer agx_ key that holds the required scope. The catalog is public (tools/list isn't scope-filtered); the scope below is enforced when the tool is called (tools/call) — a key without it is refused (default-deny).
get_crm_config
Export the org's ENTIRE CRM shape as one JSON document: pipelines, deal stages, contact lifecycle stages, custom fields, task types, customized standard-field options and field layouts. This is the document apply_crm_config accepts back, so export → edit → apply is a loop, and two orgs can be diffed against each other. Start here before changing any config — it tells you what the stages are actually called and what probabilities they carry. Requires config:read.
Required scope: config:read
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
include_inactive | boolean | Include retired stages/fields (default false). |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_crm_config",
"arguments": {}
}
}
get_field_layout
Get the ORG-level field layout (which fields show, in what order) for one entity + view. Per-user layouts are a personal preference and are not exposed here. Requires config:read.
Required scope: config:read
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | enum(contact, company, deal, task, product) | ✓ | |
view_type | string | detail (default) | list. |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_field_layout",
"arguments": {
"entity_type": "contact"
}
}
}
get_lifecycle_board_settings
Get the two board settings the Contacts Manage Stages panel writes alongside the stages: where the synthetic 'Unassigned' column sits (unassigned_order_index) and whether contacts matching no stage fall into the first column (unmatched_to_first). Requires config:read.
Required scope: config:read
Input
No input parameters.
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_lifecycle_board_settings",
"arguments": {}
}
}
delete_deal_stage
Delete a deal stage outright. REFUSED while deals are on it — the same rule the in-product Manage Stages panel enforces — unless you pass reassign_to naming the stage those deals move to first. Prefer retire_deal_stage unless the row must actually go. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | |
id | string | ||
reassign_to | string | Stage the deals move to. |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "delete_deal_stage",
"arguments": {
"name": "\u2026"
}
}
}
delete_lifecycle_stage
Delete a contact lifecycle stage. Refused while contacts are on it unless reassign_to names where they move. No 'retire' — see delete_deal_stage. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | |
id | string | ||
reassign_to | string |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "delete_lifecycle_stage",
"arguments": {
"name": "\u2026"
}
}
}
list_crm_pipelines
List the org's deal pipelines. READ-ONLY: deal stages are listed without a pipeline filter in-product, so a second pipeline would not partition the board. Requires config:read.
Required scope: config:read
Input
No input parameters.
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_crm_pipelines",
"arguments": {}
}
}
list_custom_fields
List custom field DEFINITIONS (name, type, options, visibility) for one entity type or all. Note describe_entity_fields is the read for querying data; this is the read for changing the shape. Requires config:read.
Required scope: config:read
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | enum(contact, company, deal, task, product) | ||
include_inactive | boolean |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_custom_fields",
"arguments": {}
}
}
list_deal_stages
List the deal pipeline's stages in board order, each with its order_index, probability, color, is_active and live deal_count — the same set the in-product Manage Stages panel shows. Retired stages are EXCLUDED unless include_inactive is true, matching the product. Requires config:read.
Required scope: config:read
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
include_inactive | boolean | Include retired stages (default false). |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_deal_stages",
"arguments": {}
}
}
list_lifecycle_stages
List the contact lifecycle stages in board order — the set the Contacts Manage Stages panel shows. Requires config:read.
Required scope: config:read
Input
No input parameters.
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_lifecycle_stages",
"arguments": {}
}
}
list_standard_field_options
List the STANDARD (built-in column) dropdown fields — lead_status, source, timezone and friends — with their effective options and whether the org has customized them. Requires config:read.
Required scope: config:read
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | string |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_standard_field_options",
"arguments": {}
}
}
list_task_types
List task types with their status lists (the Kanban columns). Requires config:read.
Required scope: config:read
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
include_inactive | boolean |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_task_types",
"arguments": {}
}
}
apply_crm_config
Make the org match a shape document (as returned by get_crm_config). Idempotent: running it twice reports every object 'unchanged'. Reconciles ONLY what the document mentions — omitting a stage never retires it, so removal stays explicit. ALWAYS call with dry_run:true first and read the change list; that is the safe way to point this at a live org. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
config | object | ✓ | Shape document: {version, deal_stages[], lifecycle_stages[], custom_fields[], task_types[]}. |
dry_run | boolean | Report the change list without writing. Do this first. |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "apply_crm_config",
"arguments": {
"config": {}
}
}
}
reorder_deal_stages
Set the deal board's stage order. order is the full list of stage names in the order you want them. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
order | array<string> | ✓ | Stage names (or ids), first to last. |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "reorder_deal_stages",
"arguments": {
"order": []
}
}
}
reorder_lifecycle_stages
Set contact lifecycle stage order. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
order | array<string> | ✓ |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "reorder_lifecycle_stages",
"arguments": {
"order": []
}
}
}
retire_custom_field
Retire a custom field (is_active=false). Values already stored on records are LEFT IN PLACE — retiring hides the field, it does not delete anyone's data. delete:true drops the definition and still keeps the stored values. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | enum(contact, company, deal, task, product) | ✓ | |
name | string | ✓ | |
delete | boolean |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "retire_custom_field",
"arguments": {
"entity_type": "contact",
"name": "\u2026"
}
}
}
retire_deal_stage
Retire a deal stage — it leaves the board and Manage Stages but the row and its deals stay put. PREFER THIS over delete_deal_stage: deals point at stages, and deleting is the only irreversible operation here. Reversible via upsert_deal_stage with is_active true. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | |
id | string |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "retire_deal_stage",
"arguments": {
"name": "\u2026"
}
}
}
retire_task_type
Retire a task type. The default task type cannot be retired — make another type the default first. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "retire_task_type",
"arguments": {
"name": "\u2026"
}
}
}
set_field_layout
Set the ORG-level field layout for one entity + view. Provide sections_order and/or field_config. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | enum(contact, company, deal, task, product) | ✓ | |
view_type | string | ||
sections_order | array<any> | ||
field_config | object |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_field_layout",
"arguments": {
"entity_type": "contact"
}
}
}
set_lifecycle_board_settings
Set either of the Contacts lifecycle board settings. Idempotent. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
unassigned_order_index | integer | ||
unmatched_to_first | boolean |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_lifecycle_board_settings",
"arguments": {}
}
}
set_standard_field_options
Replace a standard field's dropdown options. Update-only: if the org has no config row for the field this returns 404 rather than inserting a duplicate. Call list_standard_field_options first to see what's configurable. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | string | ✓ | |
name | string | ✓ | |
options | array<['string', 'object']> | ✓ |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "set_standard_field_options",
"arguments": {
"entity_type": "\u2026",
"name": "\u2026",
"options": []
}
}
}
upsert_custom_field
Create or update a custom field, addressed by entity_type + name; idempotent. New fields need type. dropdown/multiselect fields REQUIRE options — an off-list value is stored silently and never shows in the UI, so options are part of the field, not a follow-up call. name is the storage key inside the record's custom_fields JSONB and cannot be renamed (it would strand every stored value); change label instead. Changing type on an existing field is refused for the same reason. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | enum(contact, company, deal, task, product) | ✓ | |
name | string | ✓ | Storage key, e.g. partner_tier. |
label | string | What humans see. | |
type | enum(text, textarea, number, currency, date, datetime, checkbox, toggle, dropdown, multiselect, email, phone, url, file_upload, signature, rating, rich_text, tags, location, color, slider, record_link) | ||
options | array<['string', 'object']> | For dropdown/multiselect. Strings, or {value,label} objects. | |
description | string | ||
help_text | string | ||
placeholder | string | ||
is_required | boolean | ||
is_unique | boolean | ||
is_active | boolean | ||
order | integer | ||
show_in_list | boolean | ||
show_in_detail | boolean | ||
show_in_create | boolean | ||
searchable | boolean |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "upsert_custom_field",
"arguments": {
"entity_type": "contact",
"name": "\u2026"
}
}
}
upsert_deal_stage
Create or update ONE deal stage, addressed by name. Re-running with the same values reports 'unchanged'. To RENAME, pass match_name (the current name) plus the new name — the rename is cascaded to every deal's denormalized stage_name in the same transaction, which the in-product UI does NOT do. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | The stage name (the new one when renaming). |
match_name | string | Current name, when renaming. | |
id | string | Alternative to name; prefer name. | |
order_index | integer | Position in the board, 0-based. | |
probability | integer | Win probability %. Set it deliberately — inherited template values are often wrong. | |
color | string | Hex, e.g. #6B7280. | |
description | string | ||
is_active | boolean | false retires the stage; true brings a retired one back. |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "upsert_deal_stage",
"arguments": {
"name": "\u2026"
}
}
}
upsert_lifecycle_stage
Create or update ONE contact lifecycle stage by name; idempotent. Rename via match_name + new name — cascaded to contacts, which store the stage by NAME. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | |
match_name | string | Current name, when renaming. | |
id | string | ||
order_index | integer | ||
color | string | ||
description | string | ||
allowed_lead_statuses | array<string> |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "upsert_lifecycle_stage",
"arguments": {
"name": "\u2026"
}
}
}
upsert_task_type
Create or update a task type by name; idempotent. New types need statuses: a list of {name, category, color?} where category is todo|in_progress|done|cancelled. Board columns and 'is it finished?' are both derived from category, never from the status name, and at least one status must be done or nothing can ever complete. Requires config:write.
Required scope: config:write
Input
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | |
label | string | ||
description | string | ||
color | string | ||
icon | string | ||
is_active | boolean | ||
is_default | boolean | ||
order | integer | ||
statuses | array<object> |
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "upsert_task_type",
"arguments": {
"name": "\u2026"
}
}
}