Skip to main content
Glama
mcp-creatio

mcp-creatio

by CRACKISH

Read records

read
Read-only

Query records from a single Creatio entity with filters, selected columns, sorting, paging, and total counts to retrieve exact CRM data for reports or workflows.

Instructions

Query records of one entity: filter, pick columns, sort, page, count. Find the entity first if unsure (dataforge-similar-tables, global-search, list-entities) and check its columns with describe-entity. select also takes related columns by path (Account.Name); a lookup column (Account) returns { value, displayValue }. filters take a column, a lookup id (OwnerId = a GUID) or a related column (Account.Name). top defaults to 50; page with skip + a stable orderBy; count: true adds the total of all matches ({ total, value }) to any page — top: 1 with orderBy gives the total and the first row in one call, top: 0 the total alone. Response: an array of rows; a missing value is null (text may be ""); a date/time is in the user's Creatio time zone with its offset ("2026-11-10T15:00:00+02:00"), a Date column "YYYY-MM-DD". An unknown entity or column fails as "unknown_column:Emial (Contact). Did you mean: Email?" — retry with the suggestion. Example: { entity: "Opportunity", select: ["Title", "Amount", "Stage"], filters: { all: [{ field: "OwnerId", op: "eq", value: "" }] }, orderBy: "Amount desc", top: 10 }. Date filter values follow the same zone ("2026-11-01" = the user's midnight). More patterns: get-guide: query-guide; dates: get-guide: datetime-guide.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "entity": "<entity>"
    },
    "name": "read"
  }
}

Input Schema

NameRequiredDescriptionDefault
topNoMax rows (default 50, max 1000). With `count: true`, `top: 0` returns only the total.
skipNoRows to skip, for paging (page 3 of 25 → skip: 50, top: 25). Use a stable orderBy.
countNoAlso return the total number of matching rows (ignoring top/skip): the response becomes { total, value }.
entityYesEntity (object schema) name, e.g. "Contact", "Account", "Opportunity", "Activity".
selectNoColumns to return. Recommended: keeps the response small.
filtersNoStructured filter: { all: [...], any: [...] } of { field, op, value } or { field, in: [...] }. Examples: { all: [{ field: "Account.Name", op: "eq", value: "Acme" }] }; { all: [{ field: "OwnerId", op: "eq", value: "<contactId>" }, { field: "Amount", op: "gt", value: 1000 }] }; { any: [{ field: "Stage.Name", op: "eq", value: "Presentation" }, { field: "Stage.Name", op: "eq", value: "Negotiation" }] }.
orderByNoSort order: "CreatedOn desc", "Name asc, Amount desc".

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed11 schema fields changedv0.8.0
    • changedInput schema / properties / count / description
      Previous value: -"When true, also return the TOTAL number of matching records ($count=true), ignoring top/skip. The response shape becomes { total, value } instead of a bare array.\nšŸ’” For a COUNT-ONLY question (\"how many opportunities does X have\"), set count:true AND top:0 — you get { total: N, value: [] } in one request instead of fetching rows. Filter the same way as a normal read (e.g. lookups via ContactId → auto Contact/Id)."New value: +"Also return the total number of matching rows (ignoring top/skip): the response becomes { total, value }."
    • changedInput schema / properties / entity / description
      Previous value: -"Creatio OData entity set to query (e.g., Contact, Account, Activity). Tip: call \"list-entities\" first, then \"describe-entity\" to confirm fields before reading."New value: +"Entity (object schema) name, e.g. \"Contact\", \"Account\", \"Opportunity\", \"Activity\"."
    • changedInput schema / properties / filters / description
      Previous value: -"Structured filters (alternative to raw $filter). Handles OData syntax, GUID formatting, and lookup navigation automatically.\n\nšŸ”— FILTERING BY A LOOKUP (related record) — use NAVIGATION, not the scalar FK:\n- By name (best): Contact/Name eq 'Andrew Baker', Type/Name eq 'Employee'\n- By id: Contact/Id eq <guid>  (GUID, no quotes)\n- āŒ Do NOT filter the scalar `ContactId`/`OwnerId`/`AccountId` directly — Creatio OData 500s with \"Column by path XxxId not found in schema\".\n- The primary key `Id eq <guid>` DOES work as-is (it is a real column, not a lookup).\n(With this structured parameter you can pass either form — a `XxxId` field with a GUID value is auto-rewritten to `Xxx/Id`.)\n\nExamples:\n- Lookup by name: { all:[{ field:'Contact/Name', op:'eq', value:'Andrew Baker' }] } (RECOMMENDED)\n- Lookup by id: { all:[{ field:'ContactId', op:'eq', value:'60733efc-f36b-1410-a883-16d83cab0980' }] }  // becomes Contact/Id eq <guid>\n- Multiple AND: { all:[{ field:'IsActive', op:'eq', value:true }, { field:'Name', op:'contains', value:'John' }] }\n- Multiple OR: { any:[{ field:'Stage/Name', op:'eq', value:'Presentation' }, { field:'Stage/Name', op:'eq', value:'Negotiation' }] }"New value: +"Structured filter: { all: [...], any: [...] } of { field, op, value } or { field, in: [...] }. Examples: { all: [{ field: \"Account.Name\", op: \"eq\", value: \"Acme\" }] }; { all: [{ field: \"OwnerId\", op: \"eq\", value: \"<contactId>\" }, { field: \"Amount\", op: \"gt\", value: 1000 }] }; { any: [{ field: \"Stage.Name\", op: \"eq\", value: \"Presentation\" }, { field: \"Stage.Name\", op: \"eq\", value: \"Negotiation\" }] }."
    • changedInput schema / properties / filters / properties / all / description
      Previous value: -"All conditions (AND). Example: [{ field:\"Stage/Name\", op:\"eq\", value:\"Presentation\" }]"New value: +"Conditions that must ALL hold (AND)."
    • changedInput schema / properties / filters / properties / all / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "field": {
      -        "description": "Field to filter on. To filter by a linked record, use navigation: by name `Contact/Name` / `Type/Name`, or by id `Contact/Id`. A scalar lookup FK (`ContactId`, `OwnerId`, `AccountId`) with a GUID value is auto-rewritten to `<Lookup>/Id`. The primary key is `Id`.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "op": {
      -        "description": "Comparison operators: eq, ne, gt, ge, lt, le, contains, startswith, endswith.",
      -        "enum": [
      -          "eq",
      -          "ne",
      -          "gt",
      -          "ge",
      -          "lt",
      -          "le",
      -          "contains",
      -          "startswith",
      -          "endswith"
      -        ],
      -        "type": "string"
      -      },
      -      "value": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "number"
      -          },
      -          {
      -            "type": "boolean"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Value to compare with. GUIDs are emitted unquoted for Id/lookup paths; other strings are quoted/escaped automatically."
      -      }
      -    },
      -    "required": [
      -      "field",
      -      "op",
      -      "value"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "field": {
      -        "description": "Field to filter on. To filter by a linked record, use navigation: by name `Contact/Name` / `Type/Name`, or by id `Contact/Id`. A scalar lookup FK (`ContactId`, `OwnerId`, `AccountId`) with a GUID value is auto-rewritten to `<Lookup>/Id`. The primary key is `Id`.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "in": {
      -        "description": "Set of values (expanded to an OR group). Lookup FK GUIDs are auto-navigated.",
      -        "items": {
      -          "anyOf": [
      -            {
      -              "type": "string"
      -            },
      -            {
      -              "type": "number"
      -            },
      -            {
      -              "type": "boolean"
      -            }
      -          ]
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "field",
      -      "in"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "field": {
      +        "description": "A column (`Name`), a lookup by id (`AccountId` compared with a GUID) or a related column by path (`Account.Name`). The primary key is `Id`.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "op": {
      +        "description": "eq, ne, gt, ge, lt, le; contains / startswith / endswith for text (case-insensitive).",
      +        "enum": [
      +          "eq",
      +          "ne",
      +          "gt",
      +          "ge",
      +          "lt",
      +          "le",
      +          "contains",
      +          "startswith",
      +          "endswith"
      +        ],
      +        "type": "string"
      +      },
      +      "value": {
      +        "description": "Value to compare with: text, number, boolean, a GUID for ids, or null with eq / ne for \"is empty\" / \"is not empty\". Quoting and escaping are handled for you.",
      +        "type": [
      +          "string",
      +          "number",
      +          "boolean",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "field",
      +      "op",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "field": {
      +        "description": "A column (`Name`), a lookup by id (`AccountId` compared with a GUID) or a related column by path (`Account.Name`). The primary key is `Id`.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "in": {
      +        "description": "Matches any of these values (one value type per list).",
      +        "items": {
      +          "type": [
      +            "string",
      +            "number",
      +            "boolean"
      +          ]
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "field",
      +      "in"
      +    ],
      +    "type": "object"
      +  }
      +]
    • changedInput schema / properties / filters / properties / any / description
      Previous value: -"Any condition (OR). Example: [{ field:\"Type/Name\", op:\"eq\", value:\"Employee\" }, { field:\"Type/Name\", op:\"eq\", value:\"Manager\" }]"New value: +"Conditions of which at least ONE must hold (OR); combined with `all` by AND."
    • changedInput schema / properties / filters / properties / any / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "field": {
      -        "description": "Field to filter on. To filter by a linked record, use navigation: by name `Contact/Name` / `Type/Name`, or by id `Contact/Id`. A scalar lookup FK (`ContactId`, `OwnerId`, `AccountId`) with a GUID value is auto-rewritten to `<Lookup>/Id`. The primary key is `Id`.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "op": {
      -        "description": "Comparison operators: eq, ne, gt, ge, lt, le, contains, startswith, endswith.",
      -        "enum": [
      -          "eq",
      -          "ne",
      -          "gt",
      -          "ge",
      -          "lt",
      -          "le",
      -          "contains",
      -          "startswith",
      -          "endswith"
      -        ],
      -        "type": "string"
      -      },
      -      "value": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "number"
      -          },
      -          {
      -            "type": "boolean"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Value to compare with. GUIDs are emitted unquoted for Id/lookup paths; other strings are quoted/escaped automatically."
      -      }
      -    },
      -    "required": [
      -      "field",
      -      "op",
      -      "value"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "field": {
      -        "description": "Field to filter on. To filter by a linked record, use navigation: by name `Contact/Name` / `Type/Name`, or by id `Contact/Id`. A scalar lookup FK (`ContactId`, `OwnerId`, `AccountId`) with a GUID value is auto-rewritten to `<Lookup>/Id`. The primary key is `Id`.",
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "in": {
      -        "description": "Set of values (expanded to an OR group). Lookup FK GUIDs are auto-navigated.",
      -        "items": {
      -          "anyOf": [
      -            {
      -              "type": "string"
      -            },
      -            {
      -              "type": "number"
      -            },
      -            {
      -              "type": "boolean"
      -            }
      -          ]
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "field",
      -      "in"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "field": {
      +        "description": "A column (`Name`), a lookup by id (`AccountId` compared with a GUID) or a related column by path (`Account.Name`). The primary key is `Id`.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "op": {
      +        "description": "eq, ne, gt, ge, lt, le; contains / startswith / endswith for text (case-insensitive).",
      +        "enum": [
      +          "eq",
      +          "ne",
      +          "gt",
      +          "ge",
      +          "lt",
      +          "le",
      +          "contains",
      +          "startswith",
      +          "endswith"
      +        ],
      +        "type": "string"
      +      },
      +      "value": {
      +        "description": "Value to compare with: text, number, boolean, a GUID for ids, or null with eq / ne for \"is empty\" / \"is not empty\". Quoting and escaping are handled for you.",
      +        "type": [
      +          "string",
      +          "number",
      +          "boolean",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "field",
      +      "op",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "field": {
      +        "description": "A column (`Name`), a lookup by id (`AccountId` compared with a GUID) or a related column by path (`Account.Name`). The primary key is `Id`.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "in": {
      +        "description": "Matches any of these values (one value type per list).",
      +        "items": {
      +          "type": [
      +            "string",
      +            "number",
      +            "boolean"
      +          ]
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "field",
      +      "in"
      +    ],
      +    "type": "object"
      +  }
      +]
    • changedInput schema / properties / orderBy / description
      Previous value: -"OData $orderby clause for sorting results.\n\nSyntax: \"FieldName asc\" or \"FieldName desc\"\nMultiple fields: \"Field1 asc, Field2 desc\"\n\nāœ… EXAMPLES:\n- orderBy: \"Name asc\" - sort by name ascending\n- orderBy: \"CreatedOn desc\" - newest first\n- orderBy: \"Amount desc\" - highest amount first\n- orderBy: \"Name asc, Amount desc\" - sort by multiple fields\n\nāš ļø NOTE: You can only sort by direct properties of the entity.\nSorting by navigation properties (like Account/Name) is NOT supported in Creatio OData."New value: +"Sort order: \"CreatedOn desc\", \"Name asc, Amount desc\"."
    • changedInput schema / properties / select / description
      Previous value: -"Fields to return from the main entity. Strongly recommended for performance.\n\nāš ļø IMPORTANT: $select works ONLY for direct properties of the entity!\n- āœ… CORRECT: select=['Id','Name','AccountId','Email']\n- āŒ WRONG: select=['Account/Name'] - navigation paths NOT supported\n\nāš ļø CRITICAL: When using $filter with $select:\n- ALWAYS include filtered fields in $select array\n- Example: filter by AccountId → select=['Id','AccountId',...]\n- Creatio returns error \"Column by path X not found\" if field filtered but not selected\n- This does NOT apply to expanded entities - those are separate\n\nšŸ’” TO GET RELATED DATA: Use expand parameter (RECOMMENDED)!\n- expand=['Account'] loads full Account object automatically\n- No need to include expanded fields in select\n- Much better than making separate requests\n\nUse 'describe-entity' to discover available field names."New value: +"Columns to return. Recommended: keeps the response small."
    • changedInput schema / properties / skip / description
      Previous value: -"Offset pagination ($skip): skip this many matching rows before returning. Combine with top to page, e.g. page 3 of 25 → skip:50, top:25. Pair with a stable orderBy so pages do not overlap."New value: +"Rows to skip, for paging (page 3 of 25 → skip: 50, top: 25). Use a stable orderBy."
    • changedInput schema / properties / top / description
      Previous value: -"Max rows to return ($top). Defaults to 50 when omitted (so results are never unbounded); raise it or paginate with skip for more. Use top:0 with count:true for a count-only query. Suggest 25–200."New value: +"Max rows (default 50, max 1000). With `count: true`, `top: 0` returns only the total."
  2. First observedv0.6.5

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare readOnlyHint=true and openWorldHint=false and the description is fully consistent with that. Beyond the annotations it discloses pagination defaults (top=50, max implied by schema), the count response shape ({ total, value }), null vs empty-string semantics, Creatio time-zone date formatting with offset, and the exact unknown_column error format plus retry guidance — substantial behavioral context an agent cannot get elsewhere.

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

Conciseness4/5

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

Dense but front-loaded: the core verb and capability list come first, then the workflow prerequisite, then parameter semantics, then response format, ending with an example and guide references. A few clauses (top default 50, date-zone note repeated for filters) duplicate the schema, keeping it just short of a 5.

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

Completeness5/5

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

For a 7-parameter tool with nested filter objects and no output schema, the description covers invocation workflow, parameter nuances, response shape, value formatting, error recovery, and a concrete example. Nothing an agent needs to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning the schema does not: `select` accepts related columns by path (Account.Name), a lookup column returns { value, displayValue }, and filters accept a lookup id or a related path. The paging recipe (skip + stable orderBy) and the top:1 / top:0 count tricks further clarify intended usage, though some of this repeats the schema.

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

Purpose5/5

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

Opens with a specific verb and resource plus the full capability set: 'Query records of one entity: filter, pick columns, sort, page, count.' That is clearly distinguishable from the write-side siblings (create/update/delete) and from describe-entity/list-entities.

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

Usage Guidelines5/5

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

Gives explicit prerequisites and alternatives: find the entity first with dataforge-similar-tables, global-search, or list-entities, then verify columns with describe-entity. It also routes to get-guide: query-guide and datetime-guide for further patterns, which is a genuine when-to-use forward reference.

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