---
title: "describe"
description: "Schema discovery for OnePageCRM entities — field types, required fields, writable flags, and examples."
canonical_url: https://developer.onepagecrm.com/mcp/tools/describe/
source: Markdown mirror of https://developer.onepagecrm.com/mcp/tools/describe/
---

`describe` is the schema introspection tool. AI agents call it first to
learn which entities exist, which fields each entity has, and which
fields they're allowed to write — without that, the agent would be
guessing at field names.

## Signature

```json
{
  "type": "object",
  "properties": {
    "entity": {
      "description": "Entity name or array of names. Omit for a summary of all entities.",
      "oneOf": [
        { "type": "string" },
        { "type": "array", "items": { "type": "string" } }
      ]
    }
  }
}
```

All arguments are optional.

## What it returns

| Input                       | Output                                                                   |
| --------------------------- | ------------------------------------------------------------------------ |
| `describe()`                | A summary of every entity (names, one-line descriptions).                |
| `describe("contacts")`      | Full schema for `contacts`: every field with its type and traits (filterable, sortable, writable, …), the `required_for_create` rule, and a `create_example`. |
| `describe(["contacts","deals"])` | Full schema for both, returned as a map keyed by entity name.       |

The writable flags here are the same ones `create` and `update`
enforce, so a field marked `writable: true` is one the agent can
actually set.

## Entities

`contacts`, `companies`, `deals`, `actions`, `notes`, `calls`,
`meetings`. Custom fields are included on the entities they're defined
for.

## Example

```json
{
  "entity": "contacts"
}
```

Truncated response:

```jsonc
{
  "name": "contacts",
  "description": "CRM contacts — people and their company, contact details, and metadata.",
  "fields": {
    "first_name": { "type": "string", "writable": true, "max_length": 50, "filterable": true, "sortable": true },
    "status":     { "type": "string_virtual", "writable": false, "description": "Output only — resolved from status_id." },
    "status_id":  { "type": "string", "writable": true, "groupable": true },
    "emails":     { "type": "embedded_array", "writable": true, "valid_types": ["work", "home", "other"] },
    "created_at": { "type": "time", "writable": false }
  },
  "required_for_create": { "one_of": ["last_name", "company"] },
  "create_example": {
    "first_name": "Alice",
    "last_name": "Smith",
    "company": "Acme",
    "emails": [{ "type": "work", "address": "alice@acme.com" }]
  }
}
```

Two things worth noting from that shape: `required_for_create` is a
top-level rule, not a per-field flag — here it means a contact needs at
least a `last_name` **or** a `company`. And display fields like `status`
are `*_virtual` and output-only; you write the underlying id
(`status_id`) instead.

## Errors

- **Unknown entity** — `describe("foo")` returns an error response naming
  the valid entities. The tool never raises silently.

## Scope

`mcp`. `describe` returns schema, not records, so it's available on
every authorized MCP session.
