MCP · Tool
query
Read CRM data through OQL — filter, sort, select fields, and aggregate across contacts, deals, actions, notes, calls, and meetings.
Last updated Jul 17, 2026
query is the primary read tool. It accepts a JSON query object
that the OnePageCRM Query Language (OQL) understands
and runs it. Everything OQL can
express — filters, ordering, field projection, aggregates, date
helpers — is available here.
Signature
{
"type": "object",
"properties": {
"query": {
"type": "object",
"properties": {
"select": { "description": "Field array, [\"*\"], or aggregates." },
"from": { "type": "string", "description": "Entity name." },
"where": { "type": "object", "description": "Filter conditions (AND'd)." },
"order_by": { "type": "array", "description": "Sort order." },
"group_by": { "type": "array", "description": "Group fields (max 3)." },
"having": { "type": "object", "description": "Post-aggregation filter (requires group_by)." },
"distinct": { "type": "boolean", "description": "Unique combinations of the selected fields." },
"limit": { "type": "integer" }
}
}
},
"required": ["query"]
}
The query argument is a JSON OQL query — the same
shape shown throughout the OQL docs.
Entities you can query
contacts, companies, deals, actions, notes, calls,
meetings. See OQL Entities for the fields
each one exposes.
Examples
Today’s open actions:
{
"query": {
"from": "actions",
"select": ["*"],
"where": { "date": "TODAY()", "completed": false },
"limit": 50
}
}
Won deals this quarter, by owner:
{
"query": {
"from": "deals",
"select": ["count()", { "sum": ["amount"] }],
"where": { "status": "won", "close_date": "THIS_QUARTER()" },
"group_by": ["owner_id"],
"order_by": [{ "sum_amount": "desc" }]
}
}
A specific contact by email:
{
"query": {
"from": "contacts",
"select": ["id", "first_name", "last_name", "emails"],
"where": { "emails.address": "jane.doe@acmesolar.example" }
}
}
For more patterns, see OQL Recipes.
Response shape
{
"rows": [ /* one object per result row */ ],
"row_count": 17
}
When a result set is clipped to the response cap, a "truncated": true
flag is added — it is omitted otherwise. If you see it, ask for a
tighter filter or a smaller select.
Operators and functions
OQL supports =, !=, <, >, <=, >=, in, between, like,
{"is": null}, and {"is not": null}. Date helpers (TODAY(),
THIS_QUARTER(), LAST_QUARTER(), DAYS_AGO(n), …) and the aggregate
functions count(), sum, avg, min, max, median, and
percentile are available, each with an optional distinct modifier.
Grouped results can be filtered after aggregation with having, and
distinct: true returns unique combinations of the selected fields.
The authoritative references are:
Errors
- Schema errors — unknown entity or unknown field on the entity.
- Syntax errors — malformed
whereclauses, unsupported operators. - Execution errors — limit exceeded, type mismatch, etc.
Each error comes back as a structured response (not an exception) so the agent can correct itself and retry on the next turn.
Scope
crm.readonly is sufficient. crm also works (write scope includes
read).
Results are always filtered to records the authenticated user can
see — query doesn’t bypass per-user permissions, even when the
account has multiple users.