PandaDoc lets you create, send, and track documents for signature directly from your Claude conversation. Ask Claude to prepare an NDA from your existing templates, send a proposal to a client, check which contracts are still waiting to be signed, or pull the complete audit trail for any document. Connect your PandaDoc account to manage your entire document workflow without leaving the conversation.
When the user names a document, template, or contact, resolve the name to an id with `documents_list`, `documents_search`, `templates_list`, or `contacts_list` instead of asking the user for an id.
A recipient with no `role` is added as CC. In a markdown document, a recipient is a signer only when `role_fields` maps a field to their role; an unmapped role is dropped and the recipient is added as CC.
Protocol
Pass100/10016 / 16 pts
Connection, authentication, and protocol compatibility.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description85/100
Audit trail for one document: who viewed or signed it and when, from which IP address. Use it for disputes and compliance checks. Returns only the first page of entries.
The description explains the capability, when to use it, and what to expect.
Inputs47/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Resolve an email address to the contact it belongs to. Use it to get the `contact_id` that `recipients_add_cc` needs, or the `new_contact_id` that `recipients_reassign` needs. For someone already on the document, skip this lookup: `documents_details_get` returns `contact_id` on each recipient alongside the recipient's own `id`. The match is on the full email address and nothing else: there is no search by name, by company, or by part of an address. When the user names a person without an email, ask for the email rather than guessing one. Returns no contact when the workspace address book holds none for that address; use `contacts_create` to add one.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
email
Full email address of the contact, e.g. '[email protected]'. Matched exactly.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Create a contact in the workspace address book from an email address, and return it with its `id`, the contact id that `recipients_add_cc` and `recipients_reassign` take. The contact stays in the workspace address book after this call, so confirm the address with the user before calling. `contacts_list` resolves an address the workspace already knows; call this only when it returns no contact.
The description explains the capability, when to use it, and what to expect.
Inputs63/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
email
Full email address of the contact to create, e.g. '[email protected]'.
Clear enough to supply this argument.
first_name
First name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
last_name
Last name.
Explain the meaning of this value, not just its name.
company
Company.
Explain the meaning of this value, not just its name.
job_title
Job title.
Explain the meaning of this value, not just its name.
phone
Phone number.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description86/100
Full-text search with status/date filters.
Examples: 'NDA in completed docs' · 'modified 2026-01-01–2026-03-31' · 'sent docs Q1 2026'
For natural-language queries, prefer ``ai_search`` if available. If the user refers to a document by name and an ID is needed for a downstream operation, use this tool to resolve the name to an ID first. Do not ask the user for a document ID before attempting this lookup.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
query
Full-text search string (matches document content and metadata).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
page
Page number (1-based). Omit to use API default (1).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
count
Page size. Omit for the default of 30. Maximum 100.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
status
Restrict hits to documents with these statuses (omit to ignore status). Valid values: Draft, Sent, Completed, Uploaded, Error, Viewed, Waiting for Approval, Approved, Rejected, Waiting for Payment, Paid, Expired, Declined, External Review, Scheduled. Example: ["Sent", "Completed"].
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
date_filter_column
Which document timestamp the date window applies to. If you set any date filter, set **all three** of ``date_filter_column``, ``from_date``, and ``to_date``. Allowed values: ``date_created``, ``date_expiration``, ``last_modified``, ``signature_date``, ``effective_date``.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
from_date
Inclusive window start (ISO-8601), e.g. ``2026-03-01T00:00:00Z``. Use together with ``date_filter_column`` and ``to_date``.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
to_date
Inclusive window end (ISO-8601), e.g. ``2026-03-31T23:59:59Z``. Use together with ``date_filter_column`` and ``from_date``.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
# Create document
Create a new PandaDoc document. Pass a single `request` object and set its `source` to choose how the document is created:
- `source: "template"` — from an existing template. Required: `template_uuid`. Also accepts `name`, `recipients`, `fields`, `tokens`, `tags`, `images`, `pricing_tables`, `tables`, `texts`, `folder_uuid`, `owner`, `detect_title_variables`, `content_placeholders`.
- `source: "markdown"` — from markdown content. Required: `name`, `document_markdown`. Also accepts `recipients` (individual recipients only; groups are not supported), `role_fields`, `folder_uuid`.
- `source: "file"` — from a downloadable PDF or DOCX. Required: `name` and exactly one of `url` or `file_uuid`. Also accepts `recipients`, `parse_form_fields`, `fields`, `tokens`, `tags`, `folder_uuid`, `owner`.
The schema is polymorphic on `source`: each source accepts **only** its own parameters. Passing a parameter that belongs to another source is rejected by validation, so you never need to guess which fields are ignored.
Not for editing an existing document — use `documents_update` for that.
## Asynchronous creation
Document creation is asynchronous for every `source` (template, markdown, and file).
A successful tool response means creation was accepted, not that the document is ready. The document starts in `Uploaded` and becomes `Draft` once it is ready.
After calling this tool:
1. Poll `documents_status_get` until it reports `Draft`, or until it returns an error.
2. If `Draft`, the document is ready to edit, send, or fetch details/content.
3. If `documents_status_get` returns an error, creation failed (invalid file, markdown conversion failure, validation errors, etc.). Report `error.detail` and do not call details/content/edit/send on it. This is terminal — `error.retryable` is `false`, so stop polling.
4. While status is still `Uploaded`, do not assume success and do not call tools that require a ready document.
A failed creation is reported for roughly 8 hours. After that a status lookup reports the document as not found — treat that as the same terminal failure, not a reason to resume polling.
## Template
Create a document populated from an existing PandaDoc template. Requires `template_uuid`. Recipients are optional — omit them to use template defaults or to add them later. If the template isn't known yet, call `templates_list` first, then `templates_details_get` to discover its roles, fields, and variables. Optionally set fields, tokens, pricing tables, recipients, and other template data.
## File
Create a document from a PDF or DOCX using exactly one file reference:
- `url` — a directly downloadable URL with no authentication or HTML interstitial.
- `file_uuid` — the reference returned by the `files_request_upload_url` tool. First upload the file bytes to its `presigned_url` with an HTTP PUT, then call this tool with the returned `file_uuid`. The uploaded file is checked for ownership, allowed type, size, and malware before document creation.
Presigned S3/GCS/Azure URLs or direct CDN links work best for `url`. Google Drive and Dropbox share links do not work because they return HTML instead of the file.
To parse fillable PDF form fields, set `parse_form_fields: true` and provide `fields` mapping **every** form field name to a recipient role — omitting any causes failure.
## Markdown
Create a new document in PandaDoc from markdown when there is only text representing the document content.
Document content must be generated according to the guidelines below.
The response includes a `document_url` field with a direct URL to open the created document in PandaDoc.
### Markdown guidelines
You can use standard CommonMark and GitHub-Flavored Markdown (tables, strikethrough, etc), plus the following custom extensions:
#### Custom Syntax Extensions
##### 1. Variables
Variables are placeholder values that the document creator fills in PandaDoc before sending to recipients.
Prioritize variables over fields for any value that the sender controls or pre-fills, even if it may be visible to recipients.
**Syntax:** `[VariableName]` or `[Variable.Name]` or `[Multi.Part.Variable]`
- Can include underscores, numbers, and multiple dot-separated parts
**Use variables for values controlled by the document creator:**
- Document metadata: `[Effective.Date]`, `[Agreement.Number]`, `[Contract.Value]`
- Company/sender information: `[Company.Name]`, `[Company.Address]`
- Pre-calculated values: `[Invoice.Total]`, `[Discount.Amount]`
- Recipient information already known: `[Recipient.CompanyName]`, `[Recipient.FirstName]`
**Key principle:** If the sender controls the value, use a variable.
##### 2. Fields
Fields are interactive form elements that recipients fill in or interact with during the signing process.
Recipients see these as input boxes, checkboxes, or signature areas.
> **Making a recipient a Signer — three things must line up.** A recipient becomes a Signer only when a field is assigned to their role. To assign one, all three of these must agree:
>
> 1. Give the field an `id` in `document_markdown` — e.g. `[[signature id="Signer_Sig"]]`.
> 2. Add a recipient whose `role` matches — e.g. `{ "email": "[email protected]", "role": "Signer" }`.
> 3. Map the role to that id in `role_fields` — e.g. `[{ "role": "Signer", "field_ids": ["Signer_Sig"] }]`.
>
> A bare `[[signature]]` with no `id`, or a recipient that no `role_fields` entry references, is added as **CC** and cannot sign. Always set an `id` on signature/date fields the recipient must complete and reference it from `role_fields`.
**Use fields for values controlled by the recipient:**
- Recipient signatures: `[[signature id="Signer_Sig"]]` (see the Signer callout above — a signature with no `id` and no `role_fields` mapping leaves the recipient as CC)
- Recipient personal data they must enter: `[[text]]`, `[[email]]`, `[[phone]]`, `[[date]]`
- Recipient choices/consents: `[[checkbox]]`
- Information only the recipient knows or decides
**Key principle:** If the recipient controls the value, use a field.
Fields can be prefilled with default values, but are typically left empty for the recipient to fill.
**Syntax:** `[[field_type attributes]]`
**Field Types:**
- `text` - Text input field
- `email` - Email input field
- `phone` - Phone number input field (**`format` is required** — see below)
- `number` - Number input field
- `date` - Date input field
- `checkbox` - Checkbox field
- `signature` - Digital signature field
- `dropdown` - Dropdown selection field (**`option` is required** — see below)
**Attributes (HTML-style):**
- `required="true"` - Makes field required
- `placeholder="text"` - Placeholder text
- `checked="true"` - Pre-checked (checkbox only)
- `value="timestamp"` - For date fields, use UNIX timestamp with millisecond precision (e.g., value="1718406000000"). For other fields, use plain text (e.g., value="John Doe").
- `format="US"` or `format="international"` - **Required for `phone` fields.** Must be exactly `"US"` or `"international"`. There is no default — omitting it causes a validation error.
- `date_format="yyyy/MM/dd"` - Date format in ICU notation (e.g., `"dd/MM/yyyy"`, `"MM-dd-yyyy"`). Defaults to `"yyyy/MM/dd"` if omitted.
- `option="Text"` - **Required for `dropdown` fields.** Repeatable — add one per option (e.g., `option="Yes" option="No"`). To assign a stable UUID to an option, use `option="uuid:Text"` format.
- `id="Client_Text1"` - Specify an external ID that describes who should fill this field and what it represents (e.g., `id="Client_Signature"`, `id="Landlord_FullName"`, `id="Buyer_Email"`). Use the pattern `<RecipientRole>_<FieldPurpose>` so the field can later be assigned to the correct recipient. Multiple fields MAY share the same ID (they'll be synced — when one is filled, all are filled with the same value), but they MUST have the same type and attributes. **This is also the only value `role_fields[].field_ids` may reference** (see below) — a field with no `id="..."` cannot be pre-assigned to a role.
**Assigning fields to roles via `role_fields`:** to pre-assign a field to a recipient's role at creation time, give the field an `id="..."` in `document_markdown`, then reference that exact same string in `role_fields[].field_ids`. A `field_ids` value that does not match any `id="..."` in `document_markdown` is rejected — never invent a `role_fields` value without first setting the matching `id="..."` on the field:
```text
document_markdown: "Signed: [[signature id=\"Signer_Sig\"]]"
role_fields: [{"role": "Signer", "field_ids": ["Signer_Sig"]}]
```
**Examples:**
- `[[text placeholder="Enter name"]]`
- `[[email required="true" placeholder="Email address"]]`
- `[[phone format="US"]]`
- `[[phone format="international"]]`
- `[[number]]`
- `[[date required="true" value="1718406000000"]]`
- `[[date date_format="dd/MM/yyyy"]]`
- `[[checkbox checked="true"]]`
- `[[dropdown option="Yes" option="No"]]`
- `[[dropdown option="Yes" option="No" value="Yes" placeholder="Choose..."]]`
**Important:** Fields with the same ID must have the same type and attributes. For example, you cannot have `[[text id="Field1"]]` and `[[email id="Field1"]]` in the same document as well as `[[text id="Field2" placeholder="Full Legal Name" ]]` and `[[text id="Field2"]]` because they have different attributes.
**Dropdown constraints:**
- At least one `option` attribute is required.
- Option texts must be unique within the dropdown.
- If `value` is set, it must match one of the defined option texts exactly; otherwise a validation error occurs.
##### 3. Standalone Checkboxes
Checkboxes use GFM syntax but can appear anywhere, not just in lists:
- `[ ]` - Unchecked
- `[x]` - Checked
- Can be used inline, standalone, or in task lists
##### 4. Page Breaks
**Syntax:** `---` (three hyphens) creates a page break.
**IMPORTANT:** Page breaks should be rare and intentional. Most documents don't need page breaks.
Only use `---` when content **must** be on separate pages for a specific reason:
- Legal/structural requirement
- Document structure demands it
**Do NOT use `---`:**
- Between sections (use headings: `## Section Title`)
- As visual decoration (use blank lines)
- Simply because there's a section transition
##### 5. Pricing Tables
A pricing table is a table of line items followed by a list of totals, wrapped in
HTML comment markers that the reader never sees. Use one whenever the document
quotes prices: quotes, proposals, order forms, invoices. **Without the markers it is
an ordinary table** — the numbers come back as plain text, with no currency, no
quantities and no recalculation.
**Syntax:**
```markdown
<!-- pandadoc:pricing-table name="Services" -->
| Name | Description | Price | QTY | Tax | Subtotal |
|------------|-------------|-------------|-----|------|-------------|
| Consulting | Senior rate | 2000.24 USD | 3 | 23 % | 6000.72 USD |
* Subtotal: 6000.72 USD
* Discount: -10 %
* Total: 5400.65 USD
<!-- pandadoc:end-pricing-table -->
```
**Columns** are matched by name:
- `Name` — **required**, on every row. Text, may be formatted.
- `Price` — **required**, on every row. An amount, e.g. `2000.24 USD`.
- `Description` — text, may be formatted
- `SKU` — text
- `Cost` — an amount
- `QTY` — a number. Added for you (as 1) if the column is left out.
- `Tax` — a percentage (`23 %`) or an amount (`50.00 USD`)
- `Discount` — a percentage (`-10 %`) or an amount (`-50.00 USD`), written negative
- `Subtotal` — an amount. Added for you if the column is left out.
An empty `Name` or `Price` cell is an error, and a column not in this list is kept
as text under the name you wrote. `Tax` and `Discount` may each be a percentage or
money, but a single column has to agree with itself: one mixing `-10 %` and
`-5.00 USD` is an error.
**Footer totals** go in a list directly under the table as `Name: value`. Only
`Subtotal`, `Discount`, `Tax`, `Total` and `Total QTY` are accepted; any other total
is an error.
**The name** builds the document's tokens: a table named `Services` with a `Total`
gives you `[Services.Total]` to use in any paragraph. Two tables may not share a
name; an unnamed table takes the next free `Pricing Table N`.
**The end marker** may be left out for a single table, which then reads as the table
after the marker plus the totals after that. It is **required** for a table in
sections, and it stops an unrelated table further down being swallowed into the
prices.
**Sections and optional items** — a heading above a table titles that group of line
items, and every section must describe the same columns. A checkbox before the name
offers the item rather than including it; no box means it is simply part of the
quote. `[optional]` on a section heading lets the reader drop the whole section,
`[choose one]` limits it to a single ticked row:
```markdown
<!-- pandadoc:pricing-table -->
### Setup
| Name | Price |
|---------|------------|
| Install | 500.00 USD |
### Add-ons [optional]
| Name | Price |
|-----------------------|------------|
| [ ] Extended warranty | 200.00 USD |
| [x] Support plan | 100.00 USD |
* Total: 600.00 USD
<!-- pandadoc:end-pricing-table -->
```
**Currency** comes from the amounts themselves, which must all agree on one. A
currency code (`2000.24 USD`) always names it; a symbol only when it belongs to a
single currency — `zł` is Poland's alone, but `$` is shared by many and names none.
**Not supported in a Markdown pricing table:** photos, tiered ("buy 10+") prices,
per-item editable quantities, column width, lock and colour, and the CRM datasource.
Those are set in the PandaDoc editor.
##### 6. Money Formatting
By default amounts are read the Anglo way — `.` splits decimals, `,` groups
thousands, and the currency code follows the number (`1,234.56 USD`). If the
document writes money any other way, say so in YAML front matter at the very top of
the file:
```markdown
---
pandadoc:
money:
display_as: symbol
position: before
separate_with_space: true
precision: 2
decimal_delimiter: comma
thousand_delimiter: space
---
```
With that block, `zł 2 000,24` reads as two thousand. All six settings are required
when the block is present:
- `display_as` — `no_code`, `symbol`, `code`, `code_and_symbol`
- `position` — `before`, `after`
- `separate_with_space` — `true`, `false`
- `precision` — a number of decimal places, e.g. `2`
- `decimal_delimiter` — `dot`, `comma`, `space`, `quote`, `no_delimiter`
- `thousand_delimiter` — same values as `decimal_delimiter`
These say **how** money is written, not which currency it is. Quantities and
percentages carry no currency but are written the same way, so a document splitting
decimals with a comma writes `1,5` and `7,25 %`. Digits that are not grouped in
threes are an error rather than a guess, so write amounts consistently with the
settings you declared.
**Note:** front matter opens with `---`, which is also the page break. The block is
only read as front matter at the very top of the file naming `pandadoc`; a `---`
anywhere else stays a page break.
### Limitations (Features NOT Supported)
**Do NOT include:**
- Raw HTML, including `<br>`, `<u>`, and `<div>`
- Blockquotes inside lists
- Images inside links inline with text (e.g., `[](link)`)
- Merged table cells
**Field syntax rules:**
- Field types must be lowercase and match the closed set exactly (`text`, `email`, `phone`, `number`, `date`, `checkbox`, `signature`, `dropdown`). Capitalized or otherwise altered forms are not recognized.
- The only valid syntax is `[[field_type attributes]]`. Forms like `[[Signature|Signer]]`, `[[signature:sig_a]]`, `[[s:Owner1]]`, and `[[signature_1]]` are not recognized — use `[[signature id="Signer_Signature"]]` instead.
- Fields sharing the same `id` must have the same field type — a mismatched type is rejected. `signature` fields cannot share an `id` with any other field, including another `signature` field.
- Every value passed in `role_fields.field_ids` must match the `id` attribute of a field present in `document_markdown`.
The description explains the capability, when to use it, and what to expect.
Inputs26/100
70 of 202 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
request › oneOf › 0 › source
Not provided
Missing description. Explain what this value means and how to supply it.
request › oneOf › 0 › template_uuid
UUID of the template to create the document from.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
request › oneOf › 0 › name
Document name. Defaults to the template title when omitted.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Field ids to assign to this role. Each value must exactly match an id="..." attribute you set on a [[...]] field in document_markdown (see the tool description's Fields section) — not a name you invent. A field with no id="..." attribute cannot be referenced here.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
request › oneOf › 1 › folder_uuid
UUID of the folder (folder_uuid, NOT folder_id).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
request › oneOf › 2 › source
Not provided
Missing description. Explain what this value means and how to supply it.
request › oneOf › 2 › name
Name for the new document.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
request › oneOf › 2 › url
Publicly accessible URL to a PDF or DOCX file. Do not set this when using `file_uuid`. Must return the raw file on HTTP GET without auth (presigned S3/GCS/Azure URLs or direct CDN links work). Google Drive and Dropbox share links do not work — they return HTML, not the file.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
request › oneOf › 2 › file_uuid
Reference returned by the `files_request_upload_url` tool after the upload completes. Do not set this when using `url`.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Missing description. Explain what this value means and how to supply it.
request › oneOf › 2 › parse_form_fields
Parse fillable PDF form fields. Requires `fields` mapping EVERY form field name to a recipient role — omitting any causes failure. Ask the user for the complete list of field names before enabling this.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description69/100
Update a document. Document must be in Draft status. You can update text blocks, fields, and other document properties. After creating a new document, wait for it to reach Draft status before updating.
The description explains the capability, when to use it, and what to expect.
Inputs22/100
21 of 87 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
document_id
Document ID
Explain the meaning of this value, not just its name.
name
Document name
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
url
Document URL
Explain the meaning of this value, not just its name.
recipients › anyOf › 0 › items › anyOf › 0 › id
Not provided
Missing description. Explain what this value means and how to supply it.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description78/100
Manually change a document's status. Only these transitions are allowed: Completed, Paid, Expired, or Declined. Status changes are restricted based on the current document status. Other statuses (such as Sent, Viewed, Approved) are set automatically by the system and cannot be set with this tool.
Explain mutations, irreversible effects, or prerequisites that matter before calling this tool.
Inputs69/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
Send a document to its recipients. The document must be in Draft status. After sending, the status changes to Sent and recipients receive a notification. Use skip_unfilled_variables to send even when some variables are empty. Pass selected_approvers only if documents_details_get shows an `approval_execution`; if absent, send without it. Always confirm with the user before sending.
The description explains the capability, when to use it, and what to expect.
Inputs41/100
8 of 16 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
document_id
Document ID
Explain the meaning of this value, not just its name.
message
A message that will be sent by email with a link to the document to sign.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
subject
Value that will be used as the email subject.
Explain what happens when this optional value is omitted.
silent
If true, disables email notifications for document recipients and the sender. Also disables scheduled reminders. Does not affect 'Approve document' email notification.
Clear enough to supply this argument.
sender › anyOf › 0 › email
Not provided
Missing description. Explain what this value means and how to supply it.
sender › anyOf › 0 › membership_id
Not provided
Missing description. Explain what this value means and how to supply it.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Retrieve only the overall document status (e.g. Draft, Sent, Completed, Expired); returns just id and status. Some statuses are set automatically by the system: Sent (when the document is sent), Viewed (when a recipient opens it), Approved/Rejected (via approval workflows). Does not return recipients, fields or any other document content. For recipients (names, emails, roles, per-recipient signing progress) use documents_details_get. Right after creating a document it may still be processing — if so, wait briefly and check again before acting.
The description explains the capability, when to use it, and what to expect.
Inputs50/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Retrieve a document's full structure by document_id. Use this to see who the recipients are (names, emails, roles, signing progress), and to read fields, variables, tokens, tags, pricing/grand total, linked objects, name, status, dates, version, reference number, creator and template. Also use it to inspect a document before acting on it. Recipients carry `recipient_type` (signer, CC, approver) and, when the person is a workspace contact, the `contact_id` the contact tools take. Does not return extracted metadata — use `documents_metadata_batch_get` for that; for the overall status only, use `documents_status_get`.
The description explains the capability, when to use it, and what to expect.
Inputs50/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description88/100
Returns a summary for the specified document. Supports three granularity levels: detailed, short, or headline. If not ready, returns `{retry_after: N}` where N is seconds to wait before retrying.
The description explains the capability, when to use it, and what to expect.
Inputs63/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
summary_type
Summary granularity to return. Must be one of: 'detailed', 'short', or 'headline'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description83/100
Returns the textual content of a document in plaintext or markdown format. If the content is not ready, returns `{retry_after: N}` where N is seconds to wait before retrying.
The description explains the capability, when to use it, and what to expect.
Inputs59/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
content_format
Content format to return. Must be one of: 'plaintext' or 'markdown'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "DocumentContentToolStructuredContent",
"required": [
"format",
"body"
],
"properties": {
"body": {
"type": "string",
"title": "Body",
"description": "Document body as plaintext or markdown (see ``format``)."
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Etag",
"default": null,
"description": "Opaque version identifier for the returned content."
},
"format": {
"enum": [
"plaintext",
"markdown"
],
"type": "string",
"title": "DocumentContentFormat",
"description": "Document content format types."
}
},
"description": "MCP payload for ``documents_content_get``.\n\nUses ``body`` instead of ``content`` so JSON Schema validation does not mix up\nthis string with MCP ``CallToolResult.content`` (an array of content blocks).",
"additionalProperties": false
},
{
"type": "object",
"title": "NotReadyResponse",
"required": [
"retry_after"
],
"properties": {
"retry_after": {
"type": "integer",
"title": "Retry After",
"description": "Seconds the client should wait before retrying the request."
}
},
"description": "Not-ready hint: the requested resource is still being generated.\n\nReturned when the requested resource is not available yet and\nthe client should retry after the indicated number of seconds."
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Document content on success, or a not-ready hint (`retry_after` seconds) when the content is still being generated. Other failures surface as a standard tool error."
}
},
"description": "Document content on success, or a not-ready hint (`retry_after` seconds) when the content is still being generated. Other failures surface as a standard tool error. The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
}
Original tool metadata
{
"name": "documents_content_get",
"title": "Get document content",
"description": "Returns the textual content of a document in plaintext or markdown format. If the content is not ready, returns `{retry_after: N}` where N is seconds to wait before retrying.",
"inputSchema": {
"type": "object",
"required": [
"document_id",
"content_format"
],
"properties": {
"document_id": {
"type": "string",
"description": "Document ID"
},
"content_format": {
"enum": [
"plaintext",
"markdown"
],
"type": "string",
"description": "Content format to return. Must be one of: 'plaintext' or 'markdown'."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "DocumentContentToolStructuredContent",
"required": [
"format",
"body"
],
"properties": {
"body": {
"type": "string",
"title": "Body",
"description": "Document body as plaintext or markdown (see ``format``)."
},
"etag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Etag",
"default": null,
"description": "Opaque version identifier for the returned content."
},
"format": {
"enum": [
"plaintext",
"markdown"
],
"type": "string",
"title": "DocumentContentFormat",
"description": "Document content format types."
}
},
"description": "MCP payload for ``documents_content_get``.\n\nUses ``body`` instead of ``content`` so JSON Schema validation does not mix up\nthis string with MCP ``CallToolResult.content`` (an array of content blocks).",
"additionalProperties": false
},
{
"type": "object",
"title": "NotReadyResponse",
"required": [
"retry_after"
],
"properties": {
"retry_after": {
"type": "integer",
"title": "Retry After",
"description": "Seconds the client should wait before retrying the request."
}
},
"description": "Not-ready hint: the requested resource is still being generated.\n\nReturned when the requested resource is not available yet and\nthe client should retry after the indicated number of seconds."
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Document content on success, or a not-ready hint (`retry_after` seconds) when the content is still being generated. Other failures surface as a standard tool error."
}
},
"description": "Document content on success, or a not-ready hint (`retry_after` seconds) when the content is still being generated. Other failures surface as a standard tool error. The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Use to read the business terms extracted from documents — counterparty, contract value, dates, renewal terms — without fetching and re-reading their full text. Handles 1-40 documents per call, so pass a one-element `document_ids` for a single one. Narrow the response with `field_keys` when only certain terms matter. Extraction generally runs once a document is completed, so a document still being worked on may have nothing to return yet. Each document reports its own outcome, so one failure does not lose the rest: `ok` carries that document's fields, `extraction_pending` should be retried after `retry_after` seconds, `extraction_not_started` means the document is not completed yet, `extraction_failed` is terminal (contact support), `not_found` and `access_denied` mean the document cannot be read, and `internal_error` is safe to retry for that document alone.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
document_ids
1-40 document IDs to fetch metadata for. Duplicates are rejected by the server.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
field_keys
Optional case-sensitive filter on metadata field `key` (the human-readable field name returned as `results[].ai_metadata.results[].key`, e.g. `Contract value`). Unknown keys are silently ignored. When omitted, every populated field is returned per document.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "AgentBatchAIMetadataResponse",
"required": [
"count"
],
"properties": {
"count": {
"type": "integer",
"title": "Count",
"minimum": 0,
"description": "Number of entries in `results`. Equal to the number of documents requested."
},
"results": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"title": "AgentBatchAIMetadataResultOk",
"required": [
"document_id",
"ai_metadata",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "ok",
"title": "Status",
"default": "ok",
"description": "Discriminator for the success branch."
},
"ai_metadata": {
"type": "object",
"title": "AgentAIMetadataResponse",
"required": [
"count"
],
"properties": {
"count": {
"type": "integer",
"title": "Count",
"minimum": 0,
"description": "Total number of metadata fields available for the document across all pages."
},
"results": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"title": "AgentAICurrencyMetadataField",
"required": [
"key",
"field_type"
],
"properties": {
"key": {
"type": "string",
"title": "Key",
"description": "Field name, e.g. `Counterparty name`. This is the value to pass in `field_keys` to request this field again."
},
"value": {
"anyOf": [
{
"type": "object",
"title": "AIMetadataValue",
"required": [
"value",
"acceptance_status"
],
"properties": {
"value": {
"type": "string",
"title": "Value",
"description": "Extracted or entered value, serialised as a string. Interpretation depends on the parent field's ``field_type``."
},
"acceptance_status": {
"type": "string",
"title": "Acceptance Status",
"description": "Acceptance state of this value. Public spec values are ``pending`` and ``accepted``"
}
},
"description": "Extracted value for a metadata field on a document."
},
{
"type": "null"
}
],
"default": null,
"description": "Extracted value for this field on the document. Omitted when no value has been extracted."
},
"field_type": {
"type": "string",
"const": "currency",
"title": "Field Type"
},
"currency_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Currency Code",
"default": null,
"description": "Currency that `value` is denominated in, e.g. `USD`. Omitted when the workspace default currency applies."
}
},
"description": "A monetary field, whose `value` is an amount with no currency symbol.",
"additionalProperties": false
},
{
"type": "object",
"title": "AgentAIDurationMetadataField",
"required": [
"key",
"field_type"
],
"properties": {
"key": {
"type": "string",
"title": "Key",
"description": "Field name, e.g. `Counterparty name`. This is the value to pass in `field_keys` to request this field again."
},
"value": {
"anyOf": [
{
"type": "object",
"title": "AIMetadataValue",
"required": [
"value",
"acceptance_status"
],
"properties": {
"value": {
"type": "string",
"title": "Value",
"description": "Extracted or entered value, serialised as a string. Interpretation depends on the parent field's ``field_type``."
},
"acceptance_status": {
"type": "string",
"title": "Acceptance Status",
"description": "Acceptance state of this value. Public spec values are ``pending`` and ``accepted``"
}
},
"description": "Extracted value for a metadata field on a document."
},
{
"type": "null"
}
],
"default": null,
"description": "Extracted value for this field on the document. Omitted when no value has been extracted."
},
"period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Period",
"default": null,
"description": "Unit that `value` is counted in, e.g. `months`. Omitted when upstream did not record one."
},
"field_type": {
"type": "string",
"const": "duration",
"title": "Field Type"
}
},
"description": "A length-of-time field, whose `value` is a magnitude with no unit.",
"additionalProperties": false
},
{
"type": "object",
"title": "AgentAIMetadataField",
"required": [
"key",
"field_type"
],
"properties": {
"key": {
"type": "string",
"title": "Key",
"description": "Field name, e.g. `Counterparty name`. This is the value to pass in `field_keys` to request this field again."
},
"value": {
"anyOf": [
{
"type": "object",
"title": "AIMetadataValue",
"required": [
"value",
"acceptance_status"
],
"properties": {
"value": {
"type": "string",
"title": "Value",
"description": "Extracted or entered value, serialised as a string. Interpretation depends on the parent field's ``field_type``."
},
"acceptance_status": {
"type": "string",
"title": "Acceptance Status",
"description": "Acceptance state of this value. Public spec values are ``pending`` and ``accepted``"
}
},
"description": "Extracted value for a metadata field on a document."
},
{
"type": "null"
}
],
"default": null,
"description": "Extracted value for this field on the document. Omitted when no value has been extracted."
},
"field_type": {
"type": "string",
"title": "Field Type",
"description": "Data type of the field. Values usually include `single_line`, `multi_line`, `date`, `number`, `dropdown`, `checkbox`, `url`, `percent`, `signature_info`."
}
},
"description": "One metadata field on a document, with its extracted value.\n\nCarries the value plus only the configuration needed to read that value\ncorrectly. Field-definition internals are not returned — selectable option\nlists, placeholder text and selection-mode flags describe how the field is\nfilled in, which nothing here can do.",
"additionalProperties": false
}
]
},
"title": "Results",
"description": "Metadata fields populated for the document."
}
},
"description": "Metadata fields populated for this document.",
"additionalProperties": false
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Per-document entry carrying that document's populated metadata.",
"additionalProperties": false
},
{
"type": "object",
"title": "BatchAIMetadataResultExtractionPending",
"required": [
"document_id",
"retry_after",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "extraction_pending",
"title": "Status",
"default": "extraction_pending",
"description": "Discriminator for the in-progress branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation of the current state."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
},
"retry_after": {
"type": "integer",
"title": "Retry After",
"minimum": 1,
"description": "Seconds the client should wait before retrying this document."
}
},
"description": "Extraction is still in progress for this document."
},
{
"type": "object",
"title": "BatchAIMetadataResultExtractionFailed",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "extraction_failed",
"title": "Status",
"default": "extraction_failed",
"description": "Discriminator for the terminal-failure branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation. Retrying will not help — contact support."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Terminal extraction failure for this document."
},
{
"type": "object",
"title": "BatchAIMetadataResultExtractionNotStarted",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "extraction_not_started",
"title": "Status",
"default": "extraction_not_started",
"description": "Discriminator for the not-started branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation, typically because the document is not yet completed."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Extraction has not been triggered for this document yet."
},
{
"type": "object",
"title": "BatchAIMetadataResultNotFound",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "not_found",
"title": "Status",
"default": "not_found",
"description": "Discriminator for the missing-document branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "The document does not exist or has been deleted."
},
{
"type": "object",
"title": "BatchAIMetadataResultAccessDenied",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "access_denied",
"title": "Status",
"default": "access_denied",
"description": "Discriminator for the per-document permission-denied branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Caller is authenticated but cannot access this specific document."
},
{
"type": "object",
"title": "BatchAIMetadataResultInternalError",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "internal_error",
"title": "Status",
"default": "internal_error",
"description": "Discriminator for the per-document internal-error branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Isolated server-side failure for this single document.\n\nThe request as a whole succeeded; retrying the affected document\n(alone or in a smaller batch) is safe."
}
]
},
"title": "Results",
"description": "Per-document outcomes, in the same order as the requested documents. Each entry's shape is selected by its `status`."
}
},
"description": "Per-document metadata outcomes for a batch of documents.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Batch metadata for up to 40 documents in a single call. Returns `{count, results[]}` where each entry is keyed by `document_id` and discriminated by `status`: `ok` carries the populated metadata; `extraction_pending` carries `retry_after` seconds; `extraction_failed` is terminal (contact support); `extraction_not_started` typically means the document is not yet completed; `not_found` and `access_denied` are per-document gating outcomes; `internal_error` is an isolated per-document failure that is safe to retry on its own. Whole-request failures (validation, auth, rate limit, …) surface as a standard tool error."
}
},
"description": "Batch metadata for up to 40 documents in a single call. Returns `{count, results[]}` where each entry is keyed by `document_id` and discriminated by `status`: `ok` carries the populated metadata; `extraction_pending` carries `retry_after` seconds; `extraction_failed` is terminal (contact support); `extraction_not_started` typically means the document is not yet completed; `not_found` and `access_denied` are per-document gating outcomes; `internal_error` is an isolated per-document failure that is safe to retry on its own. Whole-request failures (validation, auth, rate limit, …) surface as a standard tool error. The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
}
Original tool metadata
{
"name": "documents_metadata_batch_get",
"title": "Batch get document metadata",
"description": "Use to read the business terms extracted from documents — counterparty, contract value, dates, renewal terms — without fetching and re-reading their full text. Handles 1-40 documents per call, so pass a one-element `document_ids` for a single one. Narrow the response with `field_keys` when only certain terms matter. Extraction generally runs once a document is completed, so a document still being worked on may have nothing to return yet. Each document reports its own outcome, so one failure does not lose the rest: `ok` carries that document's fields, `extraction_pending` should be retried after `retry_after` seconds, `extraction_not_started` means the document is not completed yet, `extraction_failed` is terminal (contact support), `not_found` and `access_denied` mean the document cannot be read, and `internal_error` is safe to retry for that document alone.",
"inputSchema": {
"type": "object",
"required": [
"document_ids"
],
"properties": {
"field_keys": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 150,
"minItems": 1
},
{
"type": "null"
}
],
"default": null,
"description": "Optional case-sensitive filter on metadata field `key` (the human-readable field name returned as `results[].ai_metadata.results[].key`, e.g. `Contract value`). Unknown keys are silently ignored. When omitted, every populated field is returned per document."
},
"document_ids": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 40,
"minItems": 1,
"description": "1-40 document IDs to fetch metadata for. Duplicates are rejected by the server."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "AgentBatchAIMetadataResponse",
"required": [
"count"
],
"properties": {
"count": {
"type": "integer",
"title": "Count",
"minimum": 0,
"description": "Number of entries in `results`. Equal to the number of documents requested."
},
"results": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"title": "AgentBatchAIMetadataResultOk",
"required": [
"document_id",
"ai_metadata",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "ok",
"title": "Status",
"default": "ok",
"description": "Discriminator for the success branch."
},
"ai_metadata": {
"type": "object",
"title": "AgentAIMetadataResponse",
"required": [
"count"
],
"properties": {
"count": {
"type": "integer",
"title": "Count",
"minimum": 0,
"description": "Total number of metadata fields available for the document across all pages."
},
"results": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"title": "AgentAICurrencyMetadataField",
"required": [
"key",
"field_type"
],
"properties": {
"key": {
"type": "string",
"title": "Key",
"description": "Field name, e.g. `Counterparty name`. This is the value to pass in `field_keys` to request this field again."
},
"value": {
"anyOf": [
{
"type": "object",
"title": "AIMetadataValue",
"required": [
"value",
"acceptance_status"
],
"properties": {
"value": {
"type": "string",
"title": "Value",
"description": "Extracted or entered value, serialised as a string. Interpretation depends on the parent field's ``field_type``."
},
"acceptance_status": {
"type": "string",
"title": "Acceptance Status",
"description": "Acceptance state of this value. Public spec values are ``pending`` and ``accepted``"
}
},
"description": "Extracted value for a metadata field on a document."
},
{
"type": "null"
}
],
"default": null,
"description": "Extracted value for this field on the document. Omitted when no value has been extracted."
},
"field_type": {
"type": "string",
"const": "currency",
"title": "Field Type"
},
"currency_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Currency Code",
"default": null,
"description": "Currency that `value` is denominated in, e.g. `USD`. Omitted when the workspace default currency applies."
}
},
"description": "A monetary field, whose `value` is an amount with no currency symbol.",
"additionalProperties": false
},
{
"type": "object",
"title": "AgentAIDurationMetadataField",
"required": [
"key",
"field_type"
],
"properties": {
"key": {
"type": "string",
"title": "Key",
"description": "Field name, e.g. `Counterparty name`. This is the value to pass in `field_keys` to request this field again."
},
"value": {
"anyOf": [
{
"type": "object",
"title": "AIMetadataValue",
"required": [
"value",
"acceptance_status"
],
"properties": {
"value": {
"type": "string",
"title": "Value",
"description": "Extracted or entered value, serialised as a string. Interpretation depends on the parent field's ``field_type``."
},
"acceptance_status": {
"type": "string",
"title": "Acceptance Status",
"description": "Acceptance state of this value. Public spec values are ``pending`` and ``accepted``"
}
},
"description": "Extracted value for a metadata field on a document."
},
{
"type": "null"
}
],
"default": null,
"description": "Extracted value for this field on the document. Omitted when no value has been extracted."
},
"period": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Period",
"default": null,
"description": "Unit that `value` is counted in, e.g. `months`. Omitted when upstream did not record one."
},
"field_type": {
"type": "string",
"const": "duration",
"title": "Field Type"
}
},
"description": "A length-of-time field, whose `value` is a magnitude with no unit.",
"additionalProperties": false
},
{
"type": "object",
"title": "AgentAIMetadataField",
"required": [
"key",
"field_type"
],
"properties": {
"key": {
"type": "string",
"title": "Key",
"description": "Field name, e.g. `Counterparty name`. This is the value to pass in `field_keys` to request this field again."
},
"value": {
"anyOf": [
{
"type": "object",
"title": "AIMetadataValue",
"required": [
"value",
"acceptance_status"
],
"properties": {
"value": {
"type": "string",
"title": "Value",
"description": "Extracted or entered value, serialised as a string. Interpretation depends on the parent field's ``field_type``."
},
"acceptance_status": {
"type": "string",
"title": "Acceptance Status",
"description": "Acceptance state of this value. Public spec values are ``pending`` and ``accepted``"
}
},
"description": "Extracted value for a metadata field on a document."
},
{
"type": "null"
}
],
"default": null,
"description": "Extracted value for this field on the document. Omitted when no value has been extracted."
},
"field_type": {
"type": "string",
"title": "Field Type",
"description": "Data type of the field. Values usually include `single_line`, `multi_line`, `date`, `number`, `dropdown`, `checkbox`, `url`, `percent`, `signature_info`."
}
},
"description": "One metadata field on a document, with its extracted value.\n\nCarries the value plus only the configuration needed to read that value\ncorrectly. Field-definition internals are not returned — selectable option\nlists, placeholder text and selection-mode flags describe how the field is\nfilled in, which nothing here can do.",
"additionalProperties": false
}
]
},
"title": "Results",
"description": "Metadata fields populated for the document."
}
},
"description": "Metadata fields populated for this document.",
"additionalProperties": false
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Per-document entry carrying that document's populated metadata.",
"additionalProperties": false
},
{
"type": "object",
"title": "BatchAIMetadataResultExtractionPending",
"required": [
"document_id",
"retry_after",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "extraction_pending",
"title": "Status",
"default": "extraction_pending",
"description": "Discriminator for the in-progress branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation of the current state."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
},
"retry_after": {
"type": "integer",
"title": "Retry After",
"minimum": 1,
"description": "Seconds the client should wait before retrying this document."
}
},
"description": "Extraction is still in progress for this document."
},
{
"type": "object",
"title": "BatchAIMetadataResultExtractionFailed",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "extraction_failed",
"title": "Status",
"default": "extraction_failed",
"description": "Discriminator for the terminal-failure branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation. Retrying will not help — contact support."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Terminal extraction failure for this document."
},
{
"type": "object",
"title": "BatchAIMetadataResultExtractionNotStarted",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "extraction_not_started",
"title": "Status",
"default": "extraction_not_started",
"description": "Discriminator for the not-started branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation, typically because the document is not yet completed."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Extraction has not been triggered for this document yet."
},
{
"type": "object",
"title": "BatchAIMetadataResultNotFound",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "not_found",
"title": "Status",
"default": "not_found",
"description": "Discriminator for the missing-document branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "The document does not exist or has been deleted."
},
{
"type": "object",
"title": "BatchAIMetadataResultAccessDenied",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "access_denied",
"title": "Status",
"default": "access_denied",
"description": "Discriminator for the per-document permission-denied branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Caller is authenticated but cannot access this specific document."
},
{
"type": "object",
"title": "BatchAIMetadataResultInternalError",
"required": [
"document_id",
"description",
"status"
],
"properties": {
"status": {
"type": "string",
"const": "internal_error",
"title": "Status",
"default": "internal_error",
"description": "Discriminator for the per-document internal-error branch."
},
"description": {
"type": "string",
"title": "Description",
"description": "Human-readable explanation."
},
"document_id": {
"type": "string",
"title": "Document Id",
"description": "The document this result corresponds to."
}
},
"description": "Isolated server-side failure for this single document.\n\nThe request as a whole succeeded; retrying the affected document\n(alone or in a smaller batch) is safe."
}
]
},
"title": "Results",
"description": "Per-document outcomes, in the same order as the requested documents. Each entry's shape is selected by its `status`."
}
},
"description": "Per-document metadata outcomes for a batch of documents.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Batch metadata for up to 40 documents in a single call. Returns `{count, results[]}` where each entry is keyed by `document_id` and discriminated by `status`: `ok` carries the populated metadata; `extraction_pending` carries `retry_after` seconds; `extraction_failed` is terminal (contact support); `extraction_not_started` typically means the document is not yet completed; `not_found` and `access_denied` are per-document gating outcomes; `internal_error` is an isolated per-document failure that is safe to retry on its own. Whole-request failures (validation, auth, rate limit, …) surface as a standard tool error."
}
},
"description": "Batch metadata for up to 40 documents in a single call. Returns `{count, results[]}` where each entry is keyed by `document_id` and discriminated by `status`: `ok` carries the populated metadata; `extraction_pending` carries `retry_after` seconds; `extraction_failed` is terminal (contact support); `extraction_not_started` typically means the document is not yet completed; `not_found` and `access_denied` are per-document gating outcomes; `internal_error` is an isolated per-document failure that is safe to retry on its own. Whole-request failures (validation, auth, rate limit, …) surface as a standard tool error. The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
Assign, reassign, or unassign document fields to recipients. The document must be in draft status. Provide a list of field-to-recipient mappings. Set recipient_id to null to unassign a field. Use get document details to obtain field UUIDs (fields[].uuid) and recipient IDs (recipients[].id). Once a field is assigned, that recipient becomes a signer for it. If it's unclear which recipient a field belongs to, ask the user before assigning.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Explain the meaning of this value, not just its name.
document_id
Document ID
Explain the meaning of this value, not just its name.
assignments › items › field_id
UUID of the document field to assign. Obtain from document details (fields[].uuid).
Clear enough to supply this argument.
assignments › items › recipient_id
UUID of the recipient to assign the field to. Obtain from document details (recipients[].id). Set to null to unassign the field from its current recipient.
{
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "DocumentFieldsAssignmentStructuredContent",
"required": [
"assigned",
"document_id"
],
"properties": {
"assigned": {
"type": "boolean",
"const": true,
"title": "Assigned"
},
"document_id": {
"type": "string",
"title": "Document Id"
}
},
"description": "``documents_fields_assign`` — confirmation after field assignment update.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
}
Original tool metadata
{
"name": "documents_fields_assign",
"title": "Assign document fields to recipients",
"description": "Assign, reassign, or unassign document fields to recipients. The document must be in draft status. Provide a list of field-to-recipient mappings. Set recipient_id to null to unassign a field. Use get document details to obtain field UUIDs (fields[].uuid) and recipient IDs (recipients[].id). Once a field is assigned, that recipient becomes a signer for it. If it's unclear which recipient a field belongs to, ask the user before assigning.",
"inputSchema": {
"type": "object",
"required": [
"document_id",
"assignments"
],
"properties": {
"assignments": {
"type": "array",
"items": {
"type": "object",
"required": [
"field_id",
"recipient_id"
],
"properties": {
"field_id": {
"type": "string",
"description": "UUID of the document field to assign. Obtain from document details (fields[].uuid)."
},
"recipient_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "UUID of the recipient to assign the field to. Obtain from document details (recipients[].id). Set to null to unassign the field from its current recipient."
}
}
},
"minItems": 1,
"description": "List of field-to-recipient assignments. Each item maps a field UUID to a recipient UUID (or null to unassign)."
},
"document_id": {
"type": "string",
"description": "Document ID"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "DocumentFieldsAssignmentStructuredContent",
"required": [
"assigned",
"document_id"
],
"properties": {
"assigned": {
"type": "boolean",
"const": true,
"title": "Assigned"
},
"document_id": {
"type": "string",
"title": "Document Id"
}
},
"description": "``documents_fields_assign`` — confirmation after field assignment update.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description84/100
Associate a document with a CRM object such as a HubSpot deal, so the document appears in that CRM record. Works on a document in any status. `provider` and `entity_type` identify the CRM object. Common pairs: `hubspot` with `deal`; `salesforce-oauth2` (or `salesforce-oauth2-sandbox`) with `opportunity`, `lead`, `account`, or `contact`; `pipedrive` with `deal`, `organization`, or `person`; `ms-dynamics` with `opportunity`, `lead`, `contact`, `quote`, or `competitor`. `entity_id` is the object's id in that CRM (for HubSpot, the deal id). The CRM integration must be connected in the workspace. A document can be linked to several CRM objects with separate calls.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
document_id
Document UUID
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
provider
CRM provider, e.g. 'hubspot'.
Clear enough to supply this argument.
entity_type
CRM object type, e.g. 'deal'.
Clear enough to supply this argument.
entity_id
CRM object id, e.g. the HubSpot deal id.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description86/100
Update one recipient's details (email, name, phone, company, address, redirect) in place. Signers can be edited in Draft, Waiting Approval, Approved, Rejected, Sent, or Viewed status. A signer's email cannot be changed after they have signed. CC recipients can be edited in any status except Expired or Declined. Get recipient_id from document details first. To change an email to one that belongs to another contact, resolve the new email with `contacts_list`, then call `recipients_reassign` with the returned contact id as `new_contact_id`.
The description explains the capability, when to use it, and what to expect.
Inputs74/100
13 of 17 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
document_id
Document UUID
Clear enough to supply this argument.
recipient_id
Recipient UUID from document details.
Clear enough to supply this argument.
email
New email address.
Clear enough to supply this argument.
first_name
First name.
Clear enough to supply this argument.
last_name
Last name.
Clear enough to supply this argument.
phone
Phone number.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
company
Company name.
Clear enough to supply this argument.
title
Job title.
Clear enough to supply this argument.
state
State or region.
Clear enough to supply this argument.
street_address
Street address.
Clear enough to supply this argument.
city
City.
Clear enough to supply this argument.
postal_code
Postal / ZIP code.
Clear enough to supply this argument.
country
Country.
Clear enough to supply this argument.
delivery_methods › anyOf › 0 › email
Not provided
Missing description. Explain what this value means and how to supply it.
delivery_methods › anyOf › 0 › sms
Not provided
Missing description. Explain what this value means and how to supply it.
redirect › anyOf › 0 › is_enabled
Not provided
Missing description. Explain what this value means and how to supply it.
redirect › anyOf › 0 › url
Not provided
Missing description. Explain what this value means and how to supply it.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
Add a CC (non-signing) recipient to a document. Requires an existing contact ID, which is not the same as a recipient id. For someone already on the document, take `contact_id` from that recipient in `documents_details_get`. Otherwise resolve their email with `contacts_list`; when it finds no contact, `contacts_create` can add one after the user confirms the address. Cannot add to Expired or Declined documents. Adding a contact that is already a CC recipient is silently ignored. This tool only adds CC recipients; signers must be set via `documents_create` or `documents_update`.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
document_id
Document UUID
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
contact_id
Contact UUID to add as CC.
Clear enough to supply this argument.
kind
'contact' or 'contact_group'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "RecipientAddStructuredContent",
"required": [
"added",
"document_id"
],
"properties": {
"added": {
"type": "boolean",
"const": true,
"title": "Added"
},
"document_id": {
"type": "string",
"title": "Document Id"
},
"recipient_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Recipient Id",
"default": null
}
},
"description": "``recipients_add_cc`` — result after adding a CC recipient.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
}
Original tool metadata
{
"name": "recipients_add_cc",
"title": "Add CC recipient to document",
"description": "Add a CC (non-signing) recipient to a document. Requires an existing contact ID, which is not the same as a recipient id. For someone already on the document, take `contact_id` from that recipient in `documents_details_get`. Otherwise resolve their email with `contacts_list`; when it finds no contact, `contacts_create` can add one after the user confirms the address. Cannot add to Expired or Declined documents. Adding a contact that is already a CC recipient is silently ignored. This tool only adds CC recipients; signers must be set via `documents_create` or `documents_update`.",
"inputSchema": {
"type": "object",
"required": [
"document_id",
"contact_id"
],
"properties": {
"kind": {
"enum": [
"contact",
"contact_group"
],
"type": "string",
"default": "contact",
"description": "'contact' or 'contact_group'."
},
"contact_id": {
"type": "string",
"description": "Contact UUID to add as CC."
},
"document_id": {
"type": "string",
"description": "Document UUID"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "RecipientAddStructuredContent",
"required": [
"added",
"document_id"
],
"properties": {
"added": {
"type": "boolean",
"const": true,
"title": "Added"
},
"document_id": {
"type": "string",
"title": "Document Id"
},
"recipient_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Recipient Id",
"default": null
}
},
"description": "``recipients_add_cc`` — result after adding a CC recipient.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
Replace a signer with another contact. `recipient_id` is the signer being replaced, from the recipient's `id` in document details. `new_contact_id` is the replacement's contact ID, never a recipient id: take it from that recipient's `contact_id` in document details when they are already on the document, and otherwise resolve their email with `contacts_list`; when it finds no contact, `contacts_create` can add one after the user confirms the address. Transfers all assigned fields to the new signer. The original signer is removed. Cannot reassign already-signed recipients. To just fix a signer's email/name, use `recipients_edit`.
The description explains the capability, when to use it, and what to expect.
Inputs69/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
document_id
Document UUID
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
recipient_id
Recipient UUID of the signer to replace.
Clear enough to supply this argument.
new_contact_id
Contact UUID of the new signer.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
kind
'contact' or 'contact_group'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "RecipientReassignStructuredContent",
"required": [
"reassigned",
"document_id"
],
"properties": {
"reassigned": {
"type": "boolean",
"const": true,
"title": "Reassigned"
},
"document_id": {
"type": "string",
"title": "Document Id"
},
"new_recipient_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "New Recipient Id",
"default": null
}
},
"description": "``recipients_reassign`` — result after reassigning a signer.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
}
Original tool metadata
{
"name": "recipients_reassign",
"title": "Reassign signer (change signer)",
"description": "Replace a signer with another contact. `recipient_id` is the signer being replaced, from the recipient's `id` in document details. `new_contact_id` is the replacement's contact ID, never a recipient id: take it from that recipient's `contact_id` in document details when they are already on the document, and otherwise resolve their email with `contacts_list`; when it finds no contact, `contacts_create` can add one after the user confirms the address. Transfers all assigned fields to the new signer. The original signer is removed. Cannot reassign already-signed recipients. To just fix a signer's email/name, use `recipients_edit`.",
"inputSchema": {
"type": "object",
"required": [
"document_id",
"recipient_id",
"new_contact_id"
],
"properties": {
"kind": {
"enum": [
"contact",
"contact_group"
],
"type": "string",
"default": "contact",
"description": "'contact' or 'contact_group'."
},
"document_id": {
"type": "string",
"description": "Document UUID"
},
"recipient_id": {
"type": "string",
"description": "Recipient UUID of the signer to replace."
},
"new_contact_id": {
"type": "string",
"description": "Contact UUID of the new signer."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "RecipientReassignStructuredContent",
"required": [
"reassigned",
"document_id"
],
"properties": {
"reassigned": {
"type": "boolean",
"const": true,
"title": "Reassigned"
},
"document_id": {
"type": "string",
"title": "Document Id"
},
"new_recipient_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "New Recipient Id",
"default": null
}
},
"description": "``recipients_reassign`` — result after reassigning a signer.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Discover, browse, or pick a template by name, tag, or folder (e.g. 'what templates do we have?', 'find the NDA template'). If the user refers to a template by name and an ID is needed for a downstream operation, use this tool to resolve the name to an ID first. Do not ask the user for a template ID before attempting this lookup. Returns a paginated list of templates. Pass a returned `id` as `templates_details_get`'s `template_id` to inspect roles/fields/variables, or as `documents_create`'s `template_uuid` to generate a document. Not for searching documents (use `documents_list`) or creating one.
The description explains the capability, when to use it, and what to expect.
Inputs69/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
count
Specify how many templates to return.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
deleted
Returns only the deleted templates.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
fields
Additional fields to include in the response.
Explain the meaning of this value, not just its name.
folder_uuid
UUID of the folder where the templates are stored.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
template_id
Specify template ID.
Explain the meaning of this value, not just its name.
page
Specify which page of the dataset to return.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
q
Search query. Filter by template name.
Clear enough to supply this argument.
shared
Returns only the shared templates.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
tag
Search tag. Filter by template tag.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description88/100
Inspect a template's schema — roles, fields, variables, pricing tables, content placeholders, tags, metadata — usually to prepare a `documents_create` call (e.g. 'what roles does the Sales Contract template expect?'). Typical flow: `templates_list` -> this tool -> `documents_create`. Not for listing templates or fetching a regular document.
The description explains the capability, when to use it, and what to expect.
Inputs50/100
Explain the meaning of this value, not just its name.
template_id
Template ID
Explain the meaning of this value, not just its name.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Update an existing template's CUSTOM variables (tokens) and/or its signer roles. Provide `tokens` to upsert variables by name, and/or `roles` to replace the full list of roles. Inspect current roles and variables with `templates_details_get` first. At least one of `tokens` or `roles` must be provided. This tool does not rename a template or edit its content/pages. A newly created template needs a few seconds to finish processing before it can be updated; if an update fails immediately after creation, wait briefly and retry. This returns only a confirmation, not the updated template — to read the UUIDs of any newly created roles, call `templates_details_get` afterwards.
The description explains the capability, when to use it, and what to expect.
Inputs79/100
Explain the meaning of this value, not just its name.
template_id
Template ID
Explain the meaning of this value, not just its name.
tokens › anyOf › 0 › items › name
Variable name, e.g. 'Favorite.Pet'.
Clear enough to supply this argument.
tokens › anyOf › 0 › items › value
Value to set for the variable.
Explain the meaning of this value, not just its name.
roles › anyOf › 0 › items › id
UUID of an existing role to update (from `templates_details_get` roles[].id). Omit to add a new role.
Clear enough to supply this argument.
roles › anyOf › 0 › items › name
Role name, e.g. 'Client' or 'Signer'. Must be unique within the template.
Clear enough to supply this argument.
roles › anyOf › 0 › items › signing_order
Signing order for the role. Set it on every role as a contiguous sequence starting from 1 (duplicates allowed for parallel signing groups, e.g. 1, 1, 2), or omit it on every role for fully parallel signing — do not mix ordered and unordered roles.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "UpdateTemplateStructuredContent",
"required": [
"updated",
"template_id"
],
"properties": {
"updated": {
"type": "boolean",
"const": true,
"title": "Updated"
},
"template_id": {
"type": "string",
"title": "Template Id"
}
},
"description": "``templates_update`` — confirmation payload after a template update.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
}
Original tool metadata
{
"name": "templates_update",
"title": "Update template",
"description": "Update an existing template's CUSTOM variables (tokens) and/or its signer roles. Provide `tokens` to upsert variables by name, and/or `roles` to replace the full list of roles. Inspect current roles and variables with `templates_details_get` first. At least one of `tokens` or `roles` must be provided. This tool does not rename a template or edit its content/pages. A newly created template needs a few seconds to finish processing before it can be updated; if an update fails immediately after creation, wait briefly and retry. This returns only a confirmation, not the updated template — to read the UUIDs of any newly created roles, call `templates_details_get` afterwards.",
"inputSchema": {
"type": "object",
"required": [
"template_id"
],
"properties": {
"roles": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "UUID of an existing role to update (from `templates_details_get` roles[].id). Omit to add a new role."
},
"name": {
"type": "string",
"description": "Role name, e.g. 'Client' or 'Signer'. Must be unique within the template."
},
"signing_order": {
"anyOf": [
{
"type": "integer",
"minimum": 1
},
{
"type": "null"
}
],
"default": null,
"description": "Signing order for the role. Set it on every role as a contiguous sequence starting from 1 (duplicates allowed for parallel signing groups, e.g. 1, 1, 2), or omit it on every role for fully parallel signing — do not mix ordered and unordered roles."
}
},
"description": "``templates_update`` — one signer role in the replacement roles list.",
"additionalProperties": false
}
},
{
"type": "null"
}
],
"default": null,
"description": "Replace the full set of template roles in one request: items with an `id` update that role, items without an `id` are created, and existing roles omitted from the list are deleted. Passing an empty list removes every role. This can delete signer roles, so confirm with the user before you replace or remove roles."
},
"tokens": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"value"
],
"properties": {
"name": {
"type": "string",
"description": "Variable name, e.g. 'Favorite.Pet'."
},
"value": {
"type": "string",
"description": "Value to set for the variable."
}
},
"description": "``templates_update`` — one CUSTOM variable to upsert.",
"additionalProperties": false
},
"minItems": 1
},
{
"type": "null"
}
],
"default": null,
"description": "CUSTOM variables to upsert, as a list of {name, value} pairs. Must be non-empty when provided. The template's predefined variables are read-only; attempts to change them are ignored."
},
"template_id": {
"type": "string",
"description": "Template ID"
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"content": {
"type": "array",
"title": "MCP content (e.g. TextContent blocks)"
},
"isError": {
"type": "boolean"
},
"structuredContent": {
"type": "object",
"anyOf": [
{
"type": "object",
"title": "UpdateTemplateStructuredContent",
"required": [
"updated",
"template_id"
],
"properties": {
"updated": {
"type": "boolean",
"const": true,
"title": "Updated"
},
"template_id": {
"type": "string",
"title": "Template Id"
}
},
"description": "``templates_update`` — confirmation payload after a template update.",
"additionalProperties": false
},
{
"type": "object",
"title": "McpToolErrorStructuredContent",
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"title": "McpToolErrorBody",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"title": "Code",
"description": "Stable error code (e.g. ``UPSTREAM_PANDADOC_API_ERROR``, ``PANDADOC_API_RESPONSE_INVALID``, ``TOOL_INPUT_VALIDATION_ERROR``)."
},
"detail": {
"title": "Detail",
"default": null
},
"message": {
"type": "string",
"title": "Message"
},
"retryable": {
"type": "boolean",
"title": "Retryable",
"default": false
},
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null
},
"http_status": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Http Status",
"default": null,
"description": "HTTP status from the PandaDoc request when the failure was a response (4xx/5xx). Omitted for transport/validation-only failures."
}
},
"description": "Machine-readable error information when the tool result has ``isError: true``.",
"additionalProperties": false
}
},
"description": "Standard ``structuredContent`` when ``isError: true`` (``error`` key).",
"additionalProperties": false
}
],
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`)."
}
},
"description": "Successful `structuredContent` for this tool, or a standard error object under the `error` key (when the tool result has `isError: true`). The full `tools/call` result is an object with `content` (MCP), optional `isError` / `meta`, and optional `structuredContent` (the success|error oneOf).",
"additionalProperties": true
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
Create a copy of an existing template within the same workspace. Optionally provide a `name` for the copy; when omitted or empty, a name is auto-generated from the source template. Returns the new template's id and name, plus the source template id.
Describe the returned information so the agent knows whether it will answer the request.
Inputs63/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
template_id
ID of the template to duplicate
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
name
Custom name for the copy; when omitted or empty, a name is auto-generated from the source template.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Delete a template by ID. The template is moved to the deleted state and no longer appears in normal listings (it can still be found by listing with the deleted filter). Confirm with the user before deleting.
The description explains the capability, when to use it, and what to expect.
Inputs50/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
template_id
Template ID to delete
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Send a reminder to recipients of a document that is out for signature, so the ones who have not completed their part are prompted again. The document must be in Sent or Viewed status. Reminders reach real people by email and/or SMS, so confirm with the user which recipients to remind before calling. Take recipient ids from the document's details; recipients left out of the call are not reminded. To word the email yourself, pass subject and message at the top level of the call — they apply to every recipient in it. This call can succeed as a call and still deliver nothing: it always answers with one entry per requested recipient, carrying a status for both email and SMS. Report a reminder as sent only where that status is `sent`. Where a method you requested has any other status, name the recipient, the method and the reason from `detail`, and do not call the request successful. A method you did not request always reports `error` with "delivery method is not selected" — that is expected, not a failure, and must not be mentioned to the user.
Describe the returned information so the agent knows whether it will answer the request.
Inputs75/100
6 of 8 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
document_id
Id of the document whose recipients should be reminded.
Clear enough to supply this argument.
reminders › items › recipient_id
Id of the recipient to remind, from the document's details.
Clear enough to supply this argument.
reminders › items › email
Send this recipient's reminder by email.
Clear enough to supply this argument.
reminders › items › sms
Also send it by SMS. Requires SMS delivery to be enabled for this recipient, and a valid phone number on them.
Clear enough to supply this argument.
reminders › items › if › email
Not provided
Missing description. Explain what this value means and how to supply it.
reminders › items › then › sms
Not provided
Missing description. Explain what this value means and how to supply it.
subject
Subject line for the reminder email, applied to every recipient in this call. Set this when the user dictates a subject ("subject ASAP"). Ignored by SMS; the account default is used when omitted.
Clear enough to supply this argument.
message
Body of the reminder email, in Markdown, applied to every recipient in this call. Set this when the user dictates the wording ("text SIGN IT"). Ignored by SMS; the account default is used when omitted.
{
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "array",
"items": {
"type": "object",
"required": [
"recipient_id",
"email",
"sms"
],
"properties": {
"sms": {
"type": "object",
"required": [
"status"
],
"properties": {
"detail": {
"type": [
"string",
"null"
],
"description": "Why the reminder was not sent, for `error` attempts — for example the recipient already completed their part, signing order has not reached them yet, that delivery method is not enabled for them, or they were already reminded within the last 24 hours. Relay this reason to the user in your own words; do not drop it."
},
"status": {
"enum": [
"sent",
"error",
"scheduled"
],
"type": "string",
"description": "`sent` when the reminder went out, `error` when it did not and `detail` says why. Only `sent` means the recipient was actually reminded. A method that was not requested always reports `error`; judge a delivery only for the methods you asked for."
},
"sent_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the reminder was sent, for `sent` attempts."
}
},
"description": "Outcome of one delivery method for one recipient."
},
"email": {
"type": "object",
"required": [
"status"
],
"properties": {
"detail": {
"type": [
"string",
"null"
],
"description": "Why the reminder was not sent, for `error` attempts — for example the recipient already completed their part, signing order has not reached them yet, that delivery method is not enabled for them, or they were already reminded within the last 24 hours. Relay this reason to the user in your own words; do not drop it."
},
"status": {
"enum": [
"sent",
"error",
"scheduled"
],
"type": "string",
"description": "`sent` when the reminder went out, `error` when it did not and `detail` says why. Only `sent` means the recipient was actually reminded. A method that was not requested always reports `error`; judge a delivery only for the methods you asked for."
},
"sent_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the reminder was sent, for `sent` attempts."
}
},
"description": "Outcome of one delivery method for one recipient."
},
"recipient_id": {
"type": "string"
}
}
},
"minItems": 1,
"description": "One entry per recipient the reminder was requested for, including recipients that turned out not to be on the document."
}
}
}
Original tool metadata
{
"name": "documents_reminder_send",
"title": "Send document reminder",
"description": "Send a reminder to recipients of a document that is out for signature, so the ones who have not completed their part are prompted again. The document must be in Sent or Viewed status. Reminders reach real people by email and/or SMS, so confirm with the user which recipients to remind before calling. Take recipient ids from the document's details; recipients left out of the call are not reminded. To word the email yourself, pass subject and message at the top level of the call — they apply to every recipient in it. This call can succeed as a call and still deliver nothing: it always answers with one entry per requested recipient, carrying a status for both email and SMS. Report a reminder as sent only where that status is `sent`. Where a method you requested has any other status, name the recipient, the method and the reason from `detail`, and do not call the request successful. A method you did not request always reports `error` with \"delivery method is not selected\" — that is expected, not a failure, and must not be mentioned to the user.\n",
"inputSchema": {
"type": "object",
"required": [
"document_id",
"reminders"
],
"properties": {
"message": {
"type": [
"string",
"null"
],
"default": null,
"maxLength": 5000,
"description": "Body of the reminder email, in Markdown, applied to every recipient in this call. Set this when the user dictates the wording (\"text SIGN IT\"). Ignored by SMS; the account default is used when omitted."
},
"subject": {
"type": [
"string",
"null"
],
"default": null,
"maxLength": 512,
"description": "Subject line for the reminder email, applied to every recipient in this call. Set this when the user dictates a subject (\"subject ASAP\"). Ignored by SMS; the account default is used when omitted."
},
"reminders": {
"type": "array",
"items": {
"if": {
"required": [
"email"
],
"properties": {
"email": {
"const": false
}
}
},
"then": {
"required": [
"sms"
],
"properties": {
"sms": {
"const": true
}
}
},
"type": "object",
"required": [
"recipient_id"
],
"properties": {
"sms": {
"type": "boolean",
"default": false,
"description": "Also send it by SMS. Requires SMS delivery to be enabled for this recipient, and a valid phone number on them."
},
"email": {
"type": "boolean",
"default": true,
"description": "Send this recipient's reminder by email."
},
"recipient_id": {
"type": "string",
"maxLength": 22,
"description": "Id of the recipient to remind, from the document's details."
}
},
"additionalProperties": false
},
"maxItems": 110,
"minItems": 1,
"description": "The recipients to remind, one entry each."
},
"document_id": {
"type": "string",
"maxLength": 22,
"description": "Id of the document whose recipients should be reminded."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"result"
],
"properties": {
"result": {
"type": "array",
"items": {
"type": "object",
"required": [
"recipient_id",
"email",
"sms"
],
"properties": {
"sms": {
"type": "object",
"required": [
"status"
],
"properties": {
"detail": {
"type": [
"string",
"null"
],
"description": "Why the reminder was not sent, for `error` attempts — for example the recipient already completed their part, signing order has not reached them yet, that delivery method is not enabled for them, or they were already reminded within the last 24 hours. Relay this reason to the user in your own words; do not drop it."
},
"status": {
"enum": [
"sent",
"error",
"scheduled"
],
"type": "string",
"description": "`sent` when the reminder went out, `error` when it did not and `detail` says why. Only `sent` means the recipient was actually reminded. A method that was not requested always reports `error`; judge a delivery only for the methods you asked for."
},
"sent_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the reminder was sent, for `sent` attempts."
}
},
"description": "Outcome of one delivery method for one recipient."
},
"email": {
"type": "object",
"required": [
"status"
],
"properties": {
"detail": {
"type": [
"string",
"null"
],
"description": "Why the reminder was not sent, for `error` attempts — for example the recipient already completed their part, signing order has not reached them yet, that delivery method is not enabled for them, or they were already reminded within the last 24 hours. Relay this reason to the user in your own words; do not drop it."
},
"status": {
"enum": [
"sent",
"error",
"scheduled"
],
"type": "string",
"description": "`sent` when the reminder went out, `error` when it did not and `detail` says why. Only `sent` means the recipient was actually reminded. A method that was not requested always reports `error`; judge a delivery only for the methods you asked for."
},
"sent_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the reminder was sent, for `sent` attempts."
}
},
"description": "Outcome of one delivery method for one recipient."
},
"recipient_id": {
"type": "string"
}
}
},
"minItems": 1,
"description": "One entry per recipient the reminder was requested for, including recipients that turned out not to be on the document."
}
}
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Search the current workspace's contacts by first name, last name, or company. This tool does not search by email address; use contacts_list for an email address instead. Results can contain several contacts with the same name, so confirm which contact the user means before making a change. To add a returned contact as a CC, pass its id to recipients_add_cc as contact_id. To replace a signer with a returned contact, pass its id to recipients_reassign as new_contact_id.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
query
First name, last name, company, or a combination to search for.
Clear enough to supply this argument.
page
One-based page number.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
page_size
Maximum number of contacts to return on this page.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Search the workspace's product catalog by free text across item name, SKU, description and category name, with optional filters. Use this to identify an existing catalog item before quoting its price or adding it as a line item. A query with no matches returns an empty list — treat that as "nothing found," not an invitation to guess a price or an item yourself.
`pricing_model` and `billing_type` are independent — read both. `pricing_model` says whether `price` is a flat unit amount ("fixed") or depends on quantity tiers ("volume_based" — get tier detail from `catalog_item_get`, and never present its `price` as a flat unit price). `billing_type` says whether that amount is charged once ("one_time"), per `billing_period` ("recurring"), or has no defined billing cadence ("unspecified"). A "volume_based" item can also be "recurring".
Call `catalog_item_get` once a specific item has been identified — for example by an exact SKU, an unambiguous search result, or the user picking one of the candidates — when full tier or bundle detail is needed.
If no single result is clearly the one the user meant, list the candidates rather than choosing silently. Include `sku` and, when available, `price` with `billing_period` when applicable. For a "volume_based" candidate, say it's volume-priced instead of quoting `price` as a flat amount.
The description explains the capability, when to use it, and what to expect.
Inputs54/100
5 of 7 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
query
Free-text search matched against item name, SKU, description and category name, ranked name > SKU > description.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
billing_types
Restrict results to these billing types.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
types
Restrict results to these item types. "bundle" items are search-only here: they are supported only in Quote builder blocks, not classic pricing tables.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
page
Not provided
Missing description. Explain what this value means and how to supply it.
per_page
Not provided
Missing description. Explain what this value means and how to supply it.
order_by
Sort field, optionally prefixed with "-" for descending (e.g. "-price").
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
exclude_uuids
Item UUIDs to omit from results — use this when building a multi-line quote so an item already added isn't matched again.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"items",
"has_more_items",
"total"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"uuid",
"name",
"sku",
"pricing_model",
"currency",
"billing_type"
],
"properties": {
"sku": {
"type": "string"
},
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"price": {
"type": [
"number",
"null"
],
"description": "Price amount when available. Interpret only together with `pricing_model`, `billing_type`, and `billing_period`."
},
"currency": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
],
"description": "Plain-text, single-line summary (HTML stripped)."
},
"billing_type": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string",
"description": "\"one_time\" or \"recurring\" (per `billing_period`); \"unspecified\" means no billing cadence is defined."
},
"pricing_model": {
"enum": [
"fixed",
"volume_based"
],
"type": "string",
"description": "Whether `price` is a flat unit amount (\"fixed\") or depends on quantity tiers (\"volume_based\" — do not quote `price` as a flat unit price; get tier detail from `catalog_item_get`). Independent of `billing_type` — a \"volume_based\" item can also be \"recurring\"."
},
"billing_period": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Set when `billing_type` is \"recurring\"; otherwise null."
}
},
"additionalProperties": false
}
},
"total": {
"type": "integer",
"description": "Total number of items matching the query, across all pages."
},
"has_more_items": {
"type": "boolean",
"description": "Whether another page of results is available."
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "catalog_items_search",
"title": "Search product catalog items",
"description": "Search the workspace's product catalog by free text across item name, SKU, description and category name, with optional filters. Use this to identify an existing catalog item before quoting its price or adding it as a line item. A query with no matches returns an empty list — treat that as \"nothing found,\" not an invitation to guess a price or an item yourself.\n`pricing_model` and `billing_type` are independent — read both. `pricing_model` says whether `price` is a flat unit amount (\"fixed\") or depends on quantity tiers (\"volume_based\" — get tier detail from `catalog_item_get`, and never present its `price` as a flat unit price). `billing_type` says whether that amount is charged once (\"one_time\"), per `billing_period` (\"recurring\"), or has no defined billing cadence (\"unspecified\"). A \"volume_based\" item can also be \"recurring\".\nCall `catalog_item_get` once a specific item has been identified — for example by an exact SKU, an unambiguous search result, or the user picking one of the candidates — when full tier or bundle detail is needed.\nIf no single result is clearly the one the user meant, list the candidates rather than choosing silently. Include `sku` and, when available, `price` with `billing_period` when applicable. For a \"volume_based\" candidate, say it's volume-priced instead of quoting `price` as a flat amount.",
"inputSchema": {
"type": "object",
"properties": {
"page": {
"type": "integer",
"default": 1,
"minimum": 1
},
"query": {
"type": [
"string",
"null"
],
"default": null,
"description": "Free-text search matched against item name, SKU, description and category name, ranked name > SKU > description."
},
"types": {
"type": [
"array",
"null"
],
"items": {
"enum": [
"regular",
"bundle",
"custom"
],
"type": "string"
},
"default": null,
"description": "Restrict results to these item types. \"bundle\" items are search-only here: they are supported only in Quote builder blocks, not classic pricing tables."
},
"order_by": {
"anyOf": [
{
"enum": [
"sku",
"-sku",
"title",
"-title",
"price",
"-price",
"date_modified",
"-date_modified"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Sort field, optionally prefixed with \"-\" for descending (e.g. \"-price\")."
},
"per_page": {
"type": "integer",
"default": 10,
"minimum": 1
},
"billing_types": {
"type": [
"array",
"null"
],
"items": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string"
},
"default": null,
"description": "Restrict results to these billing types."
},
"exclude_uuids": {
"type": [
"array",
"null"
],
"items": {
"type": "string",
"format": "uuid"
},
"default": null,
"description": "Item UUIDs to omit from results — use this when building a multi-line quote so an item already added isn't matched again."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"items",
"has_more_items",
"total"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"uuid",
"name",
"sku",
"pricing_model",
"currency",
"billing_type"
],
"properties": {
"sku": {
"type": "string"
},
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"price": {
"type": [
"number",
"null"
],
"description": "Price amount when available. Interpret only together with `pricing_model`, `billing_type`, and `billing_period`."
},
"currency": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
],
"description": "Plain-text, single-line summary (HTML stripped)."
},
"billing_type": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string",
"description": "\"one_time\" or \"recurring\" (per `billing_period`); \"unspecified\" means no billing cadence is defined."
},
"pricing_model": {
"enum": [
"fixed",
"volume_based"
],
"type": "string",
"description": "Whether `price` is a flat unit amount (\"fixed\") or depends on quantity tiers (\"volume_based\" — do not quote `price` as a flat unit price; get tier detail from `catalog_item_get`). Independent of `billing_type` — a \"volume_based\" item can also be \"recurring\"."
},
"billing_period": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Set when `billing_type` is \"recurring\"; otherwise null."
}
},
"additionalProperties": false
}
},
"total": {
"type": "integer",
"description": "Total number of items matching the query, across all pages."
},
"has_more_items": {
"type": "boolean",
"description": "Whether another page of results is available."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Get full detail for a specific catalog item by UUID — use once an item has been identified (for example via `catalog_items_search`) and its complete pricing, custom fields, or bundle composition are needed.
Each pricing block (`default_pricing`, and each variant's `pricing` entries) reports `tiers` when the item is priced by quantity — in that case `price` alone is not the amount to quote, use the tiers instead. `billing_period` is set only when `billing_type` is "recurring"; otherwise ignore it.
`variants` lists the item's purchasable configurations (usually one), each with its own SKU, status, and custom fields (up to 200). `bundle_items`, when present, lists what the bundle contains — each entry is either a reference to another catalog item (with its own `pricing`) or a one-off custom line (flat `price`/`currency`, no catalog reference). Customer-facing bundle customization rules are not included here.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
Input documentation gives an agent enough context to populate the arguments.
uuid
UUID of the catalog item, from a `catalog_items_search` result.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Permanently delete a single catalog item by UUID. This cannot be undone — there is no soft delete and no restore, and this includes its pricing, custom fields, and bundle composition. Documents already sent that reference this item are unaffected (their line values were copied at send time).
Before calling this, use `catalog_items_search` or `catalog_item_get` to resolve the UUID to the item's name and SKU, if present, and explicitly ask the user to confirm deleting that specific item by name. Do not call this from an earlier request to find, view, or modify the item alone — only after the user has explicitly agreed to the deletion in this exchange. Call this once per item; there is no bulk delete.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
uuid
UUID of the catalog item to delete.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"uuid",
"name"
],
"properties": {
"sku": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string",
"description": "Name of the item that was deleted, for confirming back to the user."
},
"uuid": {
"type": "string",
"format": "uuid"
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "catalog_item_delete",
"title": "Delete catalog item",
"description": "Permanently delete a single catalog item by UUID. This cannot be undone — there is no soft delete and no restore, and this includes its pricing, custom fields, and bundle composition. Documents already sent that reference this item are unaffected (their line values were copied at send time).\nBefore calling this, use `catalog_items_search` or `catalog_item_get` to resolve the UUID to the item's name and SKU, if present, and explicitly ask the user to confirm deleting that specific item by name. Do not call this from an earlier request to find, view, or modify the item alone — only after the user has explicitly agreed to the deletion in this exchange. Call this once per item; there is no bulk delete.",
"inputSchema": {
"type": "object",
"required": [
"uuid"
],
"properties": {
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of the catalog item to delete."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"uuid",
"name"
],
"properties": {
"sku": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string",
"description": "Name of the item that was deleted, for confirming back to the user."
},
"uuid": {
"type": "string",
"format": "uuid"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Create a new item in the workspace's product catalog. This is a write operation — always call `catalog_items_search` first to check for an existing item with a similar name or SKU, and warn about close matches instead of silently creating what may be a duplicate.
Before calling this, show the user exactly what will be created (title, price, SKU, and bundle contents if any) and explicitly ask them to confirm. Do not call this from an earlier request to search, price, or discuss an item alone — only after the user has explicitly agreed to create it in this exchange.
For flat pricing, set `price_configuration.price` and leave `pricing_model` as "fixed". For quantity-tiered pricing, set `pricing_model` to "volume_based" and provide `tiers` instead — never invent a flat price for a volume-priced item. Set `billing_type` to "recurring" only when the item is charged on a repeating cycle, and always pair it with `billing_cycle`.
Set `type` to "bundle" to create a bundle instead of a regular item. `bundle_items` is required when `type` is "bundle" (up to 300 lines) and must be omitted otherwise. Each line is either a reference to an existing regular catalog item (`kind: "catalog_item"`, with its `uuid` — resolve this via `catalog_items_search`/`catalog_item_get` first; this fails with a clear error if the uuid doesn't resolve to an existing regular item) or a one-off custom line not backed by any catalog item (`kind: "custom"`, with its own `title`/`price`/`currency`). The bundle's own `price_configuration` is always a flat price or tiers you set directly, exactly like a regular item — it is never derived automatically from the bundle's contents, regardless of what those contents cost or how they're billed.
This tool's response never includes bundle composition, even for a bundle — call `catalog_item_get` on the returned `uuid` afterward if you need to confirm what was actually created.
If the workspace's plan doesn't include Product Catalog, or the caller's role can't edit the catalog, this fails with a human-readable error rather than creating anything — never invent a price or silently retry as a different user.
The description explains the capability, when to use it, and what to expect.
Inputs29/100
9 of 26 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
type
Not provided
Missing description. Explain what this value means and how to supply it.
title
Item name, shown to customers.
Clear enough to supply this argument.
sku
Optional SKU. When omitted, one is generated automatically.
Clear enough to supply this argument.
description
Not provided
Missing description. Explain what this value means and how to supply it.
category_id
Not provided
Missing description. Explain what this value means and how to supply it.
custom_fields › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
custom_fields › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › pricing_model
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › price
Flat unit price. Required when `pricing_model` is "fixed"; must be omitted when "volume_based" — use `tiers` instead.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
price_configuration › tiers › items › min_qty
Minimum quantity this tier's price applies from.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
price_configuration › tiers › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › currency
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › cost
Internal cost basis, for margin awareness only.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
price_configuration › billing_type
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › billing_cycle
Required when `billing_type` is "recurring"; must be omitted otherwise.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
bundle_items › items › quantity
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › optional
Whether this line can be removed from the bundle.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
bundle_items › items › selected
Whether this line is included by default.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
bundle_items › items › item › oneOf › 0 › kind
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › item › oneOf › 0 › uuid
UUID of an existing regular catalog item to include.
Clear enough to supply this argument.
bundle_items › items › item › oneOf › 1 › kind
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › item › oneOf › 1 › title
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › item › oneOf › 1 › sku
Not provided
Missing description. Explain what this value means and how to supply it.
{
"name": "catalog_item_create",
"title": "Create a product catalog item",
"description": "Create a new item in the workspace's product catalog. This is a write operation — always call `catalog_items_search` first to check for an existing item with a similar name or SKU, and warn about close matches instead of silently creating what may be a duplicate.\nBefore calling this, show the user exactly what will be created (title, price, SKU, and bundle contents if any) and explicitly ask them to confirm. Do not call this from an earlier request to search, price, or discuss an item alone — only after the user has explicitly agreed to create it in this exchange.\nFor flat pricing, set `price_configuration.price` and leave `pricing_model` as \"fixed\". For quantity-tiered pricing, set `pricing_model` to \"volume_based\" and provide `tiers` instead — never invent a flat price for a volume-priced item. Set `billing_type` to \"recurring\" only when the item is charged on a repeating cycle, and always pair it with `billing_cycle`.\nSet `type` to \"bundle\" to create a bundle instead of a regular item. `bundle_items` is required when `type` is \"bundle\" (up to 300 lines) and must be omitted otherwise. Each line is either a reference to an existing regular catalog item (`kind: \"catalog_item\"`, with its `uuid` — resolve this via `catalog_items_search`/`catalog_item_get` first; this fails with a clear error if the uuid doesn't resolve to an existing regular item) or a one-off custom line not backed by any catalog item (`kind: \"custom\"`, with its own `title`/`price`/`currency`). The bundle's own `price_configuration` is always a flat price or tiers you set directly, exactly like a regular item — it is never derived automatically from the bundle's contents, regardless of what those contents cost or how they're billed.\nThis tool's response never includes bundle composition, even for a bundle — call `catalog_item_get` on the returned `uuid` afterward if you need to confirm what was actually created.\nIf the workspace's plan doesn't include Product Catalog, or the caller's role can't edit the catalog, this fails with a human-readable error rather than creating anything — never invent a price or silently retry as a different user.",
"inputSchema": {
"type": "object",
"required": [
"title",
"price_configuration"
],
"properties": {
"sku": {
"type": [
"string",
"null"
],
"default": null,
"description": "Optional SKU. When omitted, one is generated automatically."
},
"type": {
"enum": [
"regular",
"bundle"
],
"type": "string",
"default": "regular"
},
"title": {
"type": "string",
"description": "Item name, shown to customers."
},
"category_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"default": null
},
"description": {
"type": [
"string",
"null"
],
"default": null,
"maxLength": 500
},
"bundle_items": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"item"
],
"properties": {
"item": {
"oneOf": [
{
"type": "object",
"required": [
"kind",
"uuid"
],
"properties": {
"kind": {
"type": "string",
"const": "catalog_item"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of an existing regular catalog item to include."
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"kind",
"title",
"price",
"currency"
],
"properties": {
"sku": {
"type": [
"string",
"null"
],
"default": null
},
"kind": {
"type": "string",
"const": "custom"
},
"price": {
"type": "number"
},
"title": {
"type": "string"
},
"currency": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
],
"default": null,
"maxLength": 500
}
},
"additionalProperties": false
}
]
},
"optional": {
"type": "boolean",
"default": false,
"description": "Whether this line can be removed from the bundle."
},
"quantity": {
"type": "integer",
"default": 1,
"minimum": 1
},
"selected": {
"type": "boolean",
"default": true,
"description": "Whether this line is included by default."
}
},
"additionalProperties": false
},
"default": null,
"maxItems": 300,
"description": "Required when `type` is \"bundle\"; must be omitted when \"regular\"."
},
"custom_fields": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"value": {}
},
"additionalProperties": false
},
"default": null
},
"price_configuration": {
"type": "object",
"required": [
"pricing_model",
"currency"
],
"properties": {
"cost": {
"type": [
"number",
"null"
],
"default": null,
"description": "Internal cost basis, for margin awareness only."
},
"price": {
"type": [
"number",
"null"
],
"default": null,
"description": "Flat unit price. Required when `pricing_model` is \"fixed\"; must be omitted when \"volume_based\" — use `tiers` instead."
},
"tiers": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "number"
},
"min_qty": {
"type": "integer",
"minimum": 1,
"description": "Minimum quantity this tier's price applies from."
}
}
},
"default": null,
"description": "Quantity price tiers. Required when `pricing_model` is \"volume_based\"; not allowed otherwise."
},
"currency": {
"type": "string"
},
"billing_type": {
"enum": [
"one_time",
"recurring"
],
"type": "string",
"default": "one_time"
},
"billing_cycle": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Required when `billing_type` is \"recurring\"; must be omitted otherwise."
},
"pricing_model": {
"enum": [
"fixed",
"volume_based"
],
"type": "string",
"default": "fixed"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"uuid",
"name",
"sku",
"pricing_model",
"currency",
"billing_type"
],
"properties": {
"sku": {
"type": "string"
},
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"price": {
"type": [
"number",
"null"
]
},
"currency": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
],
"description": "Plain-text, single-line summary (HTML stripped)."
},
"billing_type": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string"
},
"pricing_model": {
"enum": [
"fixed",
"volume_based"
],
"type": "string"
},
"billing_period": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Set when `billing_type` is \"recurring\"; otherwise null."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Update fields on an existing catalog item by UUID. This is a write operation — call `catalog_item_get` first, show the user a before → after comparison of what will change (price especially), and explicitly ask them to confirm this specific change. Do not call this from an earlier request that only found or viewed the item — only after the user has explicitly agreed to this exact change in this exchange.
Every field is optional — set only the ones that should change. A field that is left out, or explicitly set to `null`, is left untouched — `null` is not a way to clear a field's current value except where a field's own description says otherwise. `custom_fields`, when set to an array, replaces the item's entire custom fields list (not a merge) — send an empty array to clear it.
Only `type=regular` and `type=bundle` items can be updated through this tool; calling it on a "custom" item fails with a clear error rather than changing anything. Bundles cannot be created here — use `catalog_item_create` with `type: "bundle"` for that.
`bundle_items`, when set, replaces the bundle's entire composition (not a merge) and can only be set on an item that is already a bundle — setting it on a regular item fails with a clear error rather than converting it, and it cannot be an empty list (there is no way to clear a bundle's composition through this tool). Each line is either a reference to an existing regular catalog item (`kind: "catalog_item"`, with its `uuid` — this fails with a clear error if the uuid doesn't resolve to an existing regular item, rather than silently dropping the line) or a one-off custom line (`kind: "custom"`, with its own `title`/`price`/`currency`) — see `catalog_item_create`'s `bundle_items` for the full shape. Leave `bundle_items` out entirely to leave a bundle's composition unchanged; this tool never changes an item's `type`. This fails if the bundle has customer-facing configuration (selection groups and/or rules) that reference its current lines by id, since replacing the composition risks breaking those references.
For flat pricing, set `price_configuration.price`. For quantity-tiered pricing, set `price_configuration.tiers` instead — never invent a flat price for a volume-priced item. Set `billing_type` to "recurring" only when the item is charged on a repeating cycle, and always pair it with `billing_cycle`.
`price_configuration`'s sub-fields follow the same "leave it out to leave it unchanged" rule as the top-level fields — changing only `price` means sending `price_configuration: {"price": ...}` with nothing else in it. Never include `pricing_model`, `billing_type`, `billing_cycle`, or `currency` unless you intend to change that specific thing, and never guess a value for one of them from context — check `catalog_item_get`'s response for the current value first if you're unsure. Including one of these with the wrong value silently changes it alongside the field you meant to update.
For multiple items ("raise these 5 prices"), summarize the full change set for every item and get one explicit confirmation covering all of them before calling this tool repeatedly — cap this at roughly 20 items per run. For larger bulk repricing, point the user at catalog CSV export/import instead.
If the workspace's plan doesn't include Product Catalog, or the caller's role can't edit the catalog, this fails with a human-readable error rather than changing anything — never invent a result or silently retry as a different user.
The description explains the capability, when to use it, and what to expect.
Inputs44/100
12 of 26 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
uuid
UUID of the catalog item to update, from a `catalog_items_search` or `catalog_item_get` result.
Clear enough to supply this argument.
title
Item name, shown to customers.
Clear enough to supply this argument.
sku
Not provided
Missing description. Explain what this value means and how to supply it.
description
Not provided
Missing description. Explain what this value means and how to supply it.
category_id
Set to a category UUID to move the item there. Leave null (or omit) to leave the category unchanged — this specific tool cannot remove an item from its category (that requires a separate categorization capability, not exposed here yet).
Clear enough to supply this argument.
custom_fields › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
custom_fields › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › pricing_model
Omit or leave null to leave the pricing model unchanged.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
price_configuration › price
Flat unit price. Omit or leave null when the item is priced by `tiers` instead.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
price_configuration › tiers › items › min_qty
Minimum quantity this tier's price applies from.
Clear enough to supply this argument.
price_configuration › tiers › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
price_configuration › currency
Omit or leave null to leave the currency unchanged.
Clear enough to supply this argument.
price_configuration › cost
Internal cost basis, for margin awareness only.
Clear enough to supply this argument.
price_configuration › billing_type
Omit or leave null to leave the billing type unchanged.
Clear enough to supply this argument.
price_configuration › billing_cycle
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › quantity
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › optional
Whether this line can be removed from the bundle.
Clear enough to supply this argument.
bundle_items › items › selected
Whether this line is included by default.
Clear enough to supply this argument.
bundle_items › items › item › oneOf › 0 › kind
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › item › oneOf › 0 › uuid
UUID of an existing regular catalog item to include.
Clear enough to supply this argument.
bundle_items › items › item › oneOf › 1 › kind
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › item › oneOf › 1 › title
Not provided
Missing description. Explain what this value means and how to supply it.
bundle_items › items › item › oneOf › 1 › sku
Not provided
Missing description. Explain what this value means and how to supply it.
{
"name": "catalog_item_update",
"title": "Update a product catalog item",
"description": "Update fields on an existing catalog item by UUID. This is a write operation — call `catalog_item_get` first, show the user a before → after comparison of what will change (price especially), and explicitly ask them to confirm this specific change. Do not call this from an earlier request that only found or viewed the item — only after the user has explicitly agreed to this exact change in this exchange.\nEvery field is optional — set only the ones that should change. A field that is left out, or explicitly set to `null`, is left untouched — `null` is not a way to clear a field's current value except where a field's own description says otherwise. `custom_fields`, when set to an array, replaces the item's entire custom fields list (not a merge) — send an empty array to clear it.\nOnly `type=regular` and `type=bundle` items can be updated through this tool; calling it on a \"custom\" item fails with a clear error rather than changing anything. Bundles cannot be created here — use `catalog_item_create` with `type: \"bundle\"` for that.\n`bundle_items`, when set, replaces the bundle's entire composition (not a merge) and can only be set on an item that is already a bundle — setting it on a regular item fails with a clear error rather than converting it, and it cannot be an empty list (there is no way to clear a bundle's composition through this tool). Each line is either a reference to an existing regular catalog item (`kind: \"catalog_item\"`, with its `uuid` — this fails with a clear error if the uuid doesn't resolve to an existing regular item, rather than silently dropping the line) or a one-off custom line (`kind: \"custom\"`, with its own `title`/`price`/`currency`) — see `catalog_item_create`'s `bundle_items` for the full shape. Leave `bundle_items` out entirely to leave a bundle's composition unchanged; this tool never changes an item's `type`. This fails if the bundle has customer-facing configuration (selection groups and/or rules) that reference its current lines by id, since replacing the composition risks breaking those references.\nFor flat pricing, set `price_configuration.price`. For quantity-tiered pricing, set `price_configuration.tiers` instead — never invent a flat price for a volume-priced item. Set `billing_type` to \"recurring\" only when the item is charged on a repeating cycle, and always pair it with `billing_cycle`.\n`price_configuration`'s sub-fields follow the same \"leave it out to leave it unchanged\" rule as the top-level fields — changing only `price` means sending `price_configuration: {\"price\": ...}` with nothing else in it. Never include `pricing_model`, `billing_type`, `billing_cycle`, or `currency` unless you intend to change that specific thing, and never guess a value for one of them from context — check `catalog_item_get`'s response for the current value first if you're unsure. Including one of these with the wrong value silently changes it alongside the field you meant to update.\nFor multiple items (\"raise these 5 prices\"), summarize the full change set for every item and get one explicit confirmation covering all of them before calling this tool repeatedly — cap this at roughly 20 items per run. For larger bulk repricing, point the user at catalog CSV export/import instead.\nIf the workspace's plan doesn't include Product Catalog, or the caller's role can't edit the catalog, this fails with a human-readable error rather than changing anything — never invent a result or silently retry as a different user.",
"inputSchema": {
"type": "object",
"required": [
"uuid"
],
"properties": {
"sku": {
"type": [
"string",
"null"
],
"default": null
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of the catalog item to update, from a `catalog_items_search` or `catalog_item_get` result."
},
"title": {
"type": [
"string",
"null"
],
"default": null,
"description": "Item name, shown to customers."
},
"category_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"default": null,
"description": "Set to a category UUID to move the item there. Leave null (or omit) to leave the category unchanged — this specific tool cannot remove an item from its category (that requires a separate categorization capability, not exposed here yet)."
},
"description": {
"type": [
"string",
"null"
],
"default": null,
"maxLength": 500
},
"bundle_items": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"item"
],
"properties": {
"item": {
"oneOf": [
{
"type": "object",
"required": [
"kind",
"uuid"
],
"properties": {
"kind": {
"type": "string",
"const": "catalog_item"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of an existing regular catalog item to include."
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"kind",
"title",
"price",
"currency"
],
"properties": {
"sku": {
"type": [
"string",
"null"
],
"default": null
},
"kind": {
"type": "string",
"const": "custom"
},
"price": {
"type": "number"
},
"title": {
"type": "string"
},
"currency": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
],
"default": null,
"maxLength": 500
}
},
"additionalProperties": false
}
]
},
"optional": {
"type": "boolean",
"default": false,
"description": "Whether this line can be removed from the bundle."
},
"quantity": {
"type": "integer",
"default": 1,
"minimum": 1
},
"selected": {
"type": "boolean",
"default": true,
"description": "Whether this line is included by default."
}
},
"additionalProperties": false
},
"default": null,
"maxItems": 300,
"minItems": 1,
"description": "Replaces the entire bundle composition. Only valid when the item is already a bundle and has no customer-facing configuration (selection groups or rules) set. Cannot be an empty list — there is no way to clear a bundle's composition through this tool. Leave null (or omit) to leave composition unchanged."
},
"custom_fields": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"value": {}
},
"additionalProperties": false
},
"default": null,
"description": "Replaces the entire custom fields list when set to an array (including an empty array, which clears all custom fields). Leave null (or omit) to leave custom fields unchanged."
},
"price_configuration": {
"type": "object",
"properties": {
"cost": {
"type": [
"number",
"null"
],
"default": null,
"description": "Internal cost basis, for margin awareness only."
},
"price": {
"type": [
"number",
"null"
],
"default": null,
"description": "Flat unit price. Omit or leave null when the item is priced by `tiers` instead."
},
"tiers": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "number"
},
"min_qty": {
"type": "integer",
"minimum": 1,
"description": "Minimum quantity this tier's price applies from."
}
}
},
"default": null,
"description": "Quantity price tiers. Set only one of `price` or `tiers` in the same call."
},
"currency": {
"type": [
"string",
"null"
],
"default": null,
"description": "Omit or leave null to leave the currency unchanged."
},
"billing_type": {
"anyOf": [
{
"enum": [
"one_time",
"recurring"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Omit or leave null to leave the billing type unchanged."
},
"billing_cycle": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"pricing_model": {
"anyOf": [
{
"enum": [
"fixed",
"volume_based"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Omit or leave null to leave the pricing model unchanged."
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"uuid",
"name",
"type",
"created_by",
"date_created",
"default_pricing",
"variants"
],
"properties": {
"name": {
"type": "string"
},
"type": {
"enum": [
"regular",
"bundle",
"custom"
],
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"variants": {
"type": "array",
"items": {
"type": "object",
"required": [
"uuid",
"status",
"date_created"
],
"properties": {
"sku": {
"type": [
"string",
"null"
]
},
"uuid": {
"type": "string",
"format": "uuid"
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"src"
],
"properties": {
"src": {
"type": "string"
},
"order": {
"type": [
"integer",
"null"
]
},
"is_main": {
"type": [
"boolean",
"null"
]
}
}
}
},
"status": {
"enum": [
"draft",
"active",
"not_active"
],
"type": "string"
},
"pricing": {
"type": "array",
"items": {
"type": "object",
"required": [
"billing_type",
"currency",
"pricing_source"
],
"properties": {
"cost": {
"type": [
"number",
"null"
],
"description": "Internal cost basis, for margin awareness only."
},
"price": {
"type": [
"number",
"null"
],
"description": "Flat unit price when `tiers` is absent; ignore in favor of `tiers` when present."
},
"tiers": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "number"
},
"min_qty": {
"type": "integer",
"description": "Minimum quantity this tier's price applies from."
}
}
},
"description": "Present when this item is priced by quantity — use these instead of `price`."
},
"currency": {
"type": "string"
},
"billing_type": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string"
},
"billing_period": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Set when billing_type is \"recurring\"; otherwise null."
},
"pricing_source": {
"enum": [
"custom",
"product_bundle"
],
"type": "string",
"description": "\"product_bundle\" means this price is rolled up from bundle composition rather than set directly."
}
},
"additionalProperties": false
}
},
"description": {
"type": [
"string",
"null"
]
},
"date_created": {
"type": "string",
"format": "date-time"
},
"custom_fields": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"value": {}
},
"additionalProperties": false
}
},
"date_modified": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"additionalProperties": false
}
},
"created_by": {
"type": "string",
"description": "Internal id of the user who created this item."
},
"modified_by": {
"type": [
"string",
"null"
],
"description": "Internal id of the user who last modified this item."
},
"bundle_items": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"quantity",
"optional",
"selected",
"item"
],
"properties": {
"item": {
"oneOf": [
{
"type": "object",
"required": [
"kind",
"title",
"pricing"
],
"properties": {
"sku": {
"type": [
"string",
"null"
]
},
"kind": {
"type": "string",
"const": "catalog_item"
},
"uuid": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Absent if the referenced catalog item no longer exists."
},
"title": {
"type": "string"
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"src"
],
"properties": {
"src": {
"type": "string"
},
"order": {
"type": [
"integer",
"null"
]
},
"is_main": {
"type": [
"boolean",
"null"
]
}
}
}
},
"pricing": {
"type": "object",
"required": [
"billing_type",
"currency",
"pricing_source"
],
"properties": {
"cost": {
"type": [
"number",
"null"
],
"description": "Internal cost basis, for margin awareness only."
},
"price": {
"type": [
"number",
"null"
],
"description": "Flat unit price when `tiers` is absent; ignore in favor of `tiers` when present."
},
"tiers": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "number"
},
"min_qty": {
"type": "integer",
"description": "Minimum quantity this tier's price applies from."
}
}
},
"description": "Present when this item is priced by quantity — use these instead of `price`."
},
"currency": {
"type": "string"
},
"billing_type": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string"
},
"billing_period": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Set when billing_type is \"recurring\"; otherwise null."
},
"pricing_source": {
"enum": [
"custom",
"product_bundle"
],
"type": "string",
"description": "\"product_bundle\" means this price is rolled up from bundle composition rather than set directly."
}
},
"additionalProperties": false
},
"description": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"kind",
"title",
"uuid",
"currency"
],
"properties": {
"sku": {
"type": [
"string",
"null"
]
},
"kind": {
"type": "string",
"const": "custom"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"price": {
"type": [
"number",
"null"
]
},
"title": {
"type": "string"
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"src"
],
"properties": {
"src": {
"type": "string"
},
"order": {
"type": [
"integer",
"null"
]
},
"is_main": {
"type": [
"boolean",
"null"
]
}
}
}
},
"currency": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
]
},
"optional": {
"type": "boolean",
"description": "Whether this line can be removed from the bundle."
},
"quantity": {
"type": "integer"
},
"selected": {
"type": "boolean",
"description": "Whether this line is included by default."
}
},
"additionalProperties": false
}
},
"date_created": {
"type": "string",
"format": "date-time"
},
"category_name": {
"type": [
"string",
"null"
]
},
"date_modified": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"default_pricing": {
"type": "object",
"required": [
"billing_type",
"currency",
"pricing_source"
],
"properties": {
"cost": {
"type": [
"number",
"null"
],
"description": "Internal cost basis, for margin awareness only."
},
"price": {
"type": [
"number",
"null"
],
"description": "Flat unit price when `tiers` is absent; ignore in favor of `tiers` when present."
},
"tiers": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "number"
},
"min_qty": {
"type": "integer",
"description": "Minimum quantity this tier's price applies from."
}
}
},
"description": "Present when this item is priced by quantity — use these instead of `price`."
},
"currency": {
"type": "string"
},
"billing_type": {
"enum": [
"one_time",
"recurring",
"unspecified"
],
"type": "string"
},
"billing_period": {
"anyOf": [
{
"enum": [
"weekly",
"monthly",
"annually",
"quarterly",
"semiannually"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Set when billing_type is \"recurring\"; otherwise null."
},
"pricing_source": {
"enum": [
"custom",
"product_bundle"
],
"type": "string",
"description": "\"product_bundle\" means this price is rolled up from bundle composition rather than set directly."
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Search the workspace's product catalog categories by free text against the category name. Use this to find an existing category before assigning it to a catalog item, or before renaming, moving, or deleting it by UUID. A query with no matches returns an empty list — treat that as "nothing found," not an invitation to guess a category or invent one.
This tool only matches by name — it does not browse the full hierarchy or show parent/child relationships. Use `catalog_category_tree` instead to see the complete category tree.
The description explains the capability, when to use it, and what to expect.
Inputs25/100
1 of 3 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
query
Free-text search matched against category name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
page
Not provided
Missing description. Explain what this value means and how to supply it.
per_page
Not provided
Missing description. Explain what this value means and how to supply it.
{
"type": "object",
"required": [
"categories",
"has_more_items",
"total"
],
"properties": {
"total": {
"type": "integer",
"description": "Total number of categories matching the query, across all pages."
},
"categories": {
"type": "array",
"items": {
"type": "object",
"required": [
"uuid",
"name"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "Internal identifier, for chaining into other catalog category tools (e.g. `catalog_category_get`, `catalog_category_update`, `catalog_category_delete`). Do not show this to the user — refer to the category by `name` instead, unless the user explicitly asks for the id."
}
},
"additionalProperties": false
}
},
"has_more_items": {
"type": "boolean",
"description": "Whether another page of results is available."
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "catalog_categories_search",
"title": "Search product catalog categories",
"description": "Search the workspace's product catalog categories by free text against the category name. Use this to find an existing category before assigning it to a catalog item, or before renaming, moving, or deleting it by UUID. A query with no matches returns an empty list — treat that as \"nothing found,\" not an invitation to guess a category or invent one.\nThis tool only matches by name — it does not browse the full hierarchy or show parent/child relationships. Use `catalog_category_tree` instead to see the complete category tree.",
"inputSchema": {
"type": "object",
"required": [
"query"
],
"properties": {
"page": {
"type": "integer",
"default": 1,
"minimum": 1
},
"query": {
"type": "string",
"minLength": 1,
"description": "Free-text search matched against category name."
},
"per_page": {
"type": "integer",
"default": 50,
"minimum": 1
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"categories",
"has_more_items",
"total"
],
"properties": {
"total": {
"type": "integer",
"description": "Total number of categories matching the query, across all pages."
},
"categories": {
"type": "array",
"items": {
"type": "object",
"required": [
"uuid",
"name"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "Internal identifier, for chaining into other catalog category tools (e.g. `catalog_category_get`, `catalog_category_update`, `catalog_category_delete`). Do not show this to the user — refer to the category by `name` instead, unless the user explicitly asks for the id."
}
},
"additionalProperties": false
}
},
"has_more_items": {
"type": "boolean",
"description": "Whether another page of results is available."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description90/100
Get a specific catalog category by UUID — use once a category has been identified (for example via `catalog_categories_search`) and its parent is needed.
`parent` is the immediate parent category's UUID, or null for a top-level category — `parent_name` is its human-readable name, use that when referring to the parent in a response to the user. For the full ancestry or the category's children, use `catalog_category_tree` instead.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
uuid
UUID of the catalog category, from a `catalog_categories_search` result.
{
"type": "object",
"required": [
"uuid",
"name"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "Internal identifier, for chaining into other catalog category tools. Do not show this to the user — refer to the category by `name` instead, unless the user explicitly asks for the id."
},
"parent": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Internal identifier of the immediate parent category, or null if top-level. Do not show this to the user — use `parent_name` instead, unless the user explicitly asks for the id."
},
"parent_name": {
"type": [
"string",
"null"
],
"description": "Name of the immediate parent category, or null if top-level or the parent could not be resolved."
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "catalog_category_get",
"title": "Get catalog category details",
"description": "Get a specific catalog category by UUID — use once a category has been identified (for example via `catalog_categories_search`) and its parent is needed.\n`parent` is the immediate parent category's UUID, or null for a top-level category — `parent_name` is its human-readable name, use that when referring to the parent in a response to the user. For the full ancestry or the category's children, use `catalog_category_tree` instead.",
"inputSchema": {
"type": "object",
"required": [
"uuid"
],
"properties": {
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of the catalog category, from a `catalog_categories_search` result."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"uuid",
"name"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "Internal identifier, for chaining into other catalog category tools. Do not show this to the user — refer to the category by `name` instead, unless the user explicitly asks for the id."
},
"parent": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Internal identifier of the immediate parent category, or null if top-level. Do not show this to the user — use `parent_name` instead, unless the user explicitly asks for the id."
},
"parent_name": {
"type": [
"string",
"null"
],
"description": "Name of the immediate parent category, or null if top-level or the parent could not be resolved."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Get the workspace's catalog category hierarchy as a nested tree.
Omit `category_uuid` for the complete tree of every top-level category and its descendants — use this to browse the full hierarchy or see a category's children.
Provide `category_uuid` (for example from a `catalog_categories_search` or `catalog_category_get` result) to instead get the path from the catalog's top level down to that category: the branch containing it (with its sibling categories at each level along the way, and the requested category itself as the deepest node — without its own children), plus every other top-level category as a separate, childless placeholder node. This does NOT return the requested category's children — to see those, omit `category_uuid` and find the category by name in the full tree instead.
For finding a category by name, use `catalog_categories_search` instead; for a single category's immediate parent, use `catalog_category_get`.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
category_uuid
UUID of a category to center the tree on. Omit (or pass null) to get the complete category tree instead. See the tool description — this does not return the category's own children, only the ancestor path down to it.
{
"type": "object",
"$defs": {
"CategoryTreeNode": {
"type": "object",
"required": [
"uuid",
"name",
"children"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "Internal identifier, for chaining into other catalog category tools (e.g. `catalog_category_get`, `catalog_category_update`, `catalog_category_delete`). Do not show this to the user — refer to the category by `name` instead, unless the user explicitly asks for the id."
},
"children": {
"type": "array",
"items": {
"$ref": "#/$defs/CategoryTreeNode"
}
}
},
"additionalProperties": false
}
},
"required": [
"categories"
],
"properties": {
"categories": {
"type": "array",
"items": {
"$ref": "#/$defs/CategoryTreeNode"
}
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "catalog_category_tree",
"title": "Get catalog category tree",
"description": "Get the workspace's catalog category hierarchy as a nested tree.\nOmit `category_uuid` for the complete tree of every top-level category and its descendants — use this to browse the full hierarchy or see a category's children.\nProvide `category_uuid` (for example from a `catalog_categories_search` or `catalog_category_get` result) to instead get the path from the catalog's top level down to that category: the branch containing it (with its sibling categories at each level along the way, and the requested category itself as the deepest node — without its own children), plus every other top-level category as a separate, childless placeholder node. This does NOT return the requested category's children — to see those, omit `category_uuid` and find the category by name in the full tree instead.\nFor finding a category by name, use `catalog_categories_search` instead; for a single category's immediate parent, use `catalog_category_get`.",
"inputSchema": {
"type": "object",
"properties": {
"category_uuid": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "UUID of a category to center the tree on. Omit (or pass null) to get the complete category tree instead. See the tool description — this does not return the category's own children, only the ancestor path down to it."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"$defs": {
"CategoryTreeNode": {
"type": "object",
"required": [
"uuid",
"name",
"children"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "Internal identifier, for chaining into other catalog category tools (e.g. `catalog_category_get`, `catalog_category_update`, `catalog_category_delete`). Do not show this to the user — refer to the category by `name` instead, unless the user explicitly asks for the id."
},
"children": {
"type": "array",
"items": {
"$ref": "#/$defs/CategoryTreeNode"
}
}
},
"additionalProperties": false
}
},
"required": [
"categories"
],
"properties": {
"categories": {
"type": "array",
"items": {
"$ref": "#/$defs/CategoryTreeNode"
}
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Permanently delete a category and all of its descendant categories from the workspace's product catalog. This is a hard delete with no soft-delete state and no restore.
Before calling this tool, identify the exact category by name and UUID, explain which deletion mode will be used and its consequences, and explicitly ask the user to confirm deleting that specific category. Never guess a category UUID or treat an earlier request to find, view, or modify a category as deletion approval.
Leave `all_items` false to preserve the catalog items in the deleted category subtree. The category and all descendant categories are permanently deleted, while their items are moved to the deleted category's parent. If the deleted category is top-level, those items become uncategorized.
Set `all_items` to true only when the user explicitly confirms that the items should also be permanently deleted. In this mode, the category, all descendant categories, and every catalog item in that subtree are deleted with no restore. Never infer this mode or silently retry with a different mode.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
uuid
UUID of the category to delete.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
all_items
When false, preserve subtree items by moving them to the deleted category's parent. When true, permanently delete those items too.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "catalog_category_delete",
"title": "Delete a product catalog category",
"description": "Permanently delete a category and all of its descendant categories from the workspace's product catalog. This is a hard delete with no soft-delete state and no restore.\nBefore calling this tool, identify the exact category by name and UUID, explain which deletion mode will be used and its consequences, and explicitly ask the user to confirm deleting that specific category. Never guess a category UUID or treat an earlier request to find, view, or modify a category as deletion approval.\nLeave `all_items` false to preserve the catalog items in the deleted category subtree. The category and all descendant categories are permanently deleted, while their items are moved to the deleted category's parent. If the deleted category is top-level, those items become uncategorized.\nSet `all_items` to true only when the user explicitly confirms that the items should also be permanently deleted. In this mode, the category, all descendant categories, and every catalog item in that subtree are deleted with no restore. Never infer this mode or silently retry with a different mode.",
"inputSchema": {
"type": "object",
"required": [
"uuid"
],
"properties": {
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of the category to delete."
},
"all_items": {
"type": "boolean",
"default": false,
"description": "When false, preserve subtree items by moving them to the deleted category's parent. When true, permanently delete those items too."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Create a new category in the workspace's product catalog. This is a write operation. Before calling this tool, show the user the category name and where it will be created, then explicitly ask them to confirm. Do not call it from an earlier request that only searched for or discussed categories.
Omit `parent` to create a top-level category. To create a nested category, pass the UUID of its immediate parent; resolve the category first and never guess its UUID.
The service enforces the workspace category-count and nesting-depth limits. If either limit is reached, this tool fails with a human-readable error and creates nothing. Report that error to the user instead of retrying with a different parent or name.
The description explains the capability, when to use it, and what to expect.
Inputs63/100
Explain the meaning of this value, not just its name.
name
Category name.
Explain the meaning of this value, not just its name.
parent
UUID of the immediate parent category. Omit or leave null to create a top-level category.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"name": "catalog_category_create",
"title": "Create a product catalog category",
"description": "Create a new category in the workspace's product catalog. This is a write operation. Before calling this tool, show the user the category name and where it will be created, then explicitly ask them to confirm. Do not call it from an earlier request that only searched for or discussed categories.\nOmit `parent` to create a top-level category. To create a nested category, pass the UUID of its immediate parent; resolve the category first and never guess its UUID.\nThe service enforces the workspace category-count and nesting-depth limits. If either limit is reached, this tool fails with a human-readable error and creates nothing. Report that error to the user instead of retrying with a different parent or name.",
"inputSchema": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Category name."
},
"parent": {
"type": [
"string",
"null"
],
"format": "uuid",
"default": null,
"description": "UUID of the immediate parent category. Omit or leave null to create a top-level category."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"uuid",
"name",
"parent"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"parent": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Null for a top-level category."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Rename and/or move an existing category in the workspace's product catalog. Before calling this tool, identify the exact category by UUID, resolve the target parent when moving it, show the user the before and after state, and explicitly ask them to confirm that specific update.
Set `name` to rename the category. Omit `parent_category_id` to leave its parent unchanged, set it to a category UUID to move beneath that category, or set it to null to move the category to the top level. At least one of `name` or `parent_category_id` must be supplied.
When both fields are supplied, the move runs first and the rename second. They are separate operations, not one transaction. If the move fails, the rename is not attempted. If the move succeeds but the rename fails, the category remains moved; report that partial result and fetch the category again instead of claiming the whole update was rolled back.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
uuid
UUID of the category to update.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
name
New category name; omit or leave null to keep the current name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
parent_category_id
New immediate parent UUID. Set null to move the category to the top level; omit the field to leave its parent unchanged.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"name": "catalog_category_update",
"title": "Update a product catalog category",
"description": "Rename and/or move an existing category in the workspace's product catalog. Before calling this tool, identify the exact category by UUID, resolve the target parent when moving it, show the user the before and after state, and explicitly ask them to confirm that specific update.\nSet `name` to rename the category. Omit `parent_category_id` to leave its parent unchanged, set it to a category UUID to move beneath that category, or set it to null to move the category to the top level. At least one of `name` or `parent_category_id` must be supplied.\nWhen both fields are supplied, the move runs first and the rename second. They are separate operations, not one transaction. If the move fails, the rename is not attempted. If the move succeeds but the rename fails, the category remains moved; report that partial result and fetch the category again instead of claiming the whole update was rolled back.",
"inputSchema": {
"type": "object",
"required": [
"uuid"
],
"properties": {
"name": {
"type": [
"string",
"null"
],
"default": null,
"description": "New category name; omit or leave null to keep the current name."
},
"uuid": {
"type": "string",
"format": "uuid",
"description": "UUID of the category to update."
},
"parent_category_id": {
"anyOf": [
{
"type": "string",
"format": "uuid"
},
{
"type": "null"
}
],
"description": "New immediate parent UUID. Set null to move the category to the top level; omit the field to leave its parent unchanged."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"uuid",
"name",
"parent"
],
"properties": {
"name": {
"type": "string"
},
"uuid": {
"type": "string",
"format": "uuid"
},
"parent": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "UUID of the immediate parent category, or null if top-level."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Create a short-lived upload slot for a PDF or DOCX file. Upload the file bytes to the returned presigned URL with an HTTP PUT request, then pass file_uuid to documents_create with source set to "file".
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
file_name
Original file name, including the .pdf or .docx extension.
Clear enough to supply this argument.
content_length
Exact size, in bytes, of the file that will be uploaded. When provided, the upload is rejected unless the client sends exactly this many bytes, and the request itself is rejected if this value is negative or 150 MB (157286400 bytes) or larger.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
content_type
MIME type of the file that will be uploaded, for example application/pdf. When provided, the upload is rejected unless the client sends exactly this value (case-sensitive) in the Content-Type header of the PUT request, and the request itself is rejected if this type is not allowed for the organization.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
{
"type": "object",
"required": [
"presigned_url",
"file_uuid",
"file_name"
],
"properties": {
"file_name": {
"type": "string",
"description": "Original file name associated with the upload slot."
},
"file_uuid": {
"type": "string",
"format": "uuid",
"description": "Owner-bound file reference to pass to documents_create after the upload completes."
},
"presigned_url": {
"type": "string",
"description": "Short-lived S3 URL to which the file bytes must be uploaded with an HTTP PUT request."
}
},
"additionalProperties": false
}
Original tool metadata
{
"name": "files_request_upload_url",
"title": "Request file upload URL",
"description": "Create a short-lived upload slot for a PDF or DOCX file. Upload the file bytes to the returned presigned URL with an HTTP PUT request, then pass file_uuid to documents_create with source set to \"file\".",
"inputSchema": {
"type": "object",
"required": [
"file_name"
],
"properties": {
"file_name": {
"type": "string",
"description": "Original file name, including the .pdf or .docx extension."
},
"content_type": {
"type": "string",
"description": "MIME type of the file that will be uploaded, for example application/pdf. When provided, the upload is rejected unless the client sends exactly this value (case-sensitive) in the Content-Type header of the PUT request, and the request itself is rejected if this type is not allowed for the organization."
},
"content_length": {
"type": "integer",
"minimum": 0,
"description": "Exact size, in bytes, of the file that will be uploaded. When provided, the upload is rejected unless the client sends exactly this many bytes, and the request itself is rejected if this value is negative or 150 MB (157286400 bytes) or larger."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"required": [
"presigned_url",
"file_uuid",
"file_name"
],
"properties": {
"file_name": {
"type": "string",
"description": "Original file name associated with the upload slot."
},
"file_uuid": {
"type": "string",
"format": "uuid",
"description": "Owner-bound file reference to pass to documents_create after the upload completes."
},
"presigned_url": {
"type": "string",
"description": "Short-lived S3 URL to which the file bytes must be uploaded with an HTTP PUT request."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Update one or more existing quotes on a document — sections, line items, prices, quantities, discounts, fees, and taxes. Up to 25 quotes per call; each quote is applied independently, so one quote's failure never affects the others.
This tool cannot create a new quote, and a quote cannot be created at document-creation time either — only existing quotes (already present on the document) can be updated.
Destructive replace, not a diff: including `sections` replaces the quote's ENTIRE section list — any current section whose id is left out is REMOVED. The same applies one level down: including `items` on a section replaces that section's ENTIRE item list — any current item whose id is left out is REMOVED (pass an empty list to clear all items from a section). To change only part of a quote/section, first fetch its current state and include every section/item you want to keep, changing only the fields that need to change. Fields left out of an included section/item are left untouched; a field explicitly set to `null` where the schema allows it (`name`, `billing_frequency`, `contract_term`) clears that field instead.
`options` (on a line item) and `settings` (on a section or quote) are all-or-nothing: when included, every property in them must be given a value — there is no partial update of a single property inside these objects.
Returns one result per requested quote, in the same order as the request, keyed by `id` and discriminated by `status`: `ok` carries the quote's full state after the update; `not_in_document` (the quote id is not linked to this document, or the caller lacks edit access to it), `not_found` (no such quote), and `conflict` (the quote was updated concurrently — refetch and retry) are per-quote outcomes that leave the other quotes in the batch unaffected; `internal_error` is an isolated per-quote failure safe to retry on its own.
The description explains the capability, when to use it, and what to expect.
Inputs19/100
8 of 36 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
document_id
Id of the document the quotes belong to.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
quotes › items › id
Id of the quote to update, from the document's details.
Clear enough to supply this argument.
$defs › QuoteUpdate › currency
ISO 4217 currency code (e.g. USD, EUR). Omit to leave unchanged.
Clear enough to supply this argument.
$defs › Adjustment › type
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › Adjustment › value
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › Summary › custom_fields
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › QuoteSettings › selection_type
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › SectionUpdate › id
Id of an existing section to update. Omit to create a new section.
Clear enough to supply this argument.
$defs › SectionUpdate › name
Section name. Omit to leave unchanged. Pass null to clear it.
Clear enough to supply this argument.
$defs › SectionSettings › selected
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › SectionSettings › optional
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › SectionSettings › selection_type
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › id
Id of an existing item to update. Omit to create a new item.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
$defs › ItemUpdate › sku
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › name
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › description
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › qty
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › price
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › PriceSettings › tiers › items › min_qty
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › PriceSettings › tiers › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › PriceSettings › base_value
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › cost
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › billing_frequency
Omit to leave unchanged. Pass null to clear it.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
$defs › ItemUpdate › reference_id
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemOptions › qty_editable
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemOptions › selected
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemOptions › optional
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › contract_term
Omit to leave unchanged. Pass null to clear it.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
$defs › ItemUpdate › custom_columns
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › text_columns
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › number_columns
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › currency_columns
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › multipliers
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › images
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › thumbnail
Not provided
Missing description. Explain what this value means and how to supply it.
$defs › ItemUpdate › pricing_source
Not provided
Missing description. Explain what this value means and how to supply it.
{
"name": "quotes_update",
"title": "Update quotes",
"description": "Update one or more existing quotes on a document — sections, line items, prices, quantities, discounts, fees, and taxes. Up to 25 quotes per call; each quote is applied independently, so one quote's failure never affects the others.\nThis tool cannot create a new quote, and a quote cannot be created at document-creation time either — only existing quotes (already present on the document) can be updated.\nDestructive replace, not a diff: including `sections` replaces the quote's ENTIRE section list — any current section whose id is left out is REMOVED. The same applies one level down: including `items` on a section replaces that section's ENTIRE item list — any current item whose id is left out is REMOVED (pass an empty list to clear all items from a section). To change only part of a quote/section, first fetch its current state and include every section/item you want to keep, changing only the fields that need to change. Fields left out of an included section/item are left untouched; a field explicitly set to `null` where the schema allows it (`name`, `billing_frequency`, `contract_term`) clears that field instead.\n`options` (on a line item) and `settings` (on a section or quote) are all-or-nothing: when included, every property in them must be given a value — there is no partial update of a single property inside these objects.\nReturns one result per requested quote, in the same order as the request, keyed by `id` and discriminated by `status`: `ok` carries the quote's full state after the update; `not_in_document` (the quote id is not linked to this document, or the caller lacks edit access to it), `not_found` (no such quote), and `conflict` (the quote was updated concurrently — refetch and retry) are per-quote outcomes that leave the other quotes in the batch unaffected; `internal_error` is an isolated per-quote failure safe to retry on its own.",
"inputSchema": {
"type": "object",
"$defs": {
"Summary": {
"type": "object",
"properties": {
"fees": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"taxes": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"discounts": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"custom_fields": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"description": "Discounts/fees/taxes/custom fields, at quote or section level. Omit a map to leave it unchanged; pass {} to clear it.",
"additionalProperties": false
},
"Adjustment": {
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"enum": [
"percent",
"flat"
],
"type": "string"
},
"value": {
"type": "number"
}
},
"additionalProperties": false
},
"ItemUpdate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Id of an existing item to update. Omit to create a new item."
},
"qty": {
"type": "number"
},
"sku": {
"type": "string"
},
"cost": {
"type": "number"
},
"fees": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"name": {
"type": "string"
},
"price": {
"type": "number"
},
"taxes": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"images": {
"type": "array",
"items": {
"type": "string"
}
},
"options": {
"$ref": "#/$defs/ItemOptions"
},
"discounts": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"thumbnail": {
"type": [
"string",
"null"
]
},
"description": {
"type": "string"
},
"multipliers": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"bundle_items": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/ItemUpdate"
},
"description": "This item's own bundle line items, when it represents a product bundle. Same destructive-replace semantics as a section's items."
},
"reference_id": {
"type": "string"
},
"text_columns": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"contract_term": {
"type": [
"integer",
"null"
],
"description": "Omit to leave unchanged. Pass null to clear it."
},
"custom_columns": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"number_columns": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"price_settings": {
"$ref": "#/$defs/PriceSettings"
},
"pricing_source": {
"enum": [
"custom",
"product_bundle",
null
],
"type": [
"string",
"null"
]
},
"currency_columns": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"billing_frequency": {
"enum": [
"weekly",
"monthly",
"quarterly",
"semiannually",
"annually",
null
],
"type": [
"string",
"null"
],
"description": "Omit to leave unchanged. Pass null to clear it."
}
},
"additionalProperties": false
},
"ItemOptions": {
"type": "object",
"required": [
"qty_editable",
"selected",
"optional"
],
"properties": {
"optional": {
"type": "boolean"
},
"selected": {
"type": "boolean"
},
"qty_editable": {
"type": "boolean"
}
},
"description": "All-or-nothing — every property must be given when included.",
"additionalProperties": false
},
"QuoteUpdate": {
"type": "object",
"properties": {
"summary": {
"$ref": "#/$defs/Summary"
},
"currency": {
"type": "string",
"description": "ISO 4217 currency code (e.g. USD, EUR). Omit to leave unchanged."
},
"sections": {
"type": "array",
"items": {
"$ref": "#/$defs/SectionUpdate"
},
"description": "Replaces the quote's entire section list. Omit this key to leave all sections untouched. Include it to destructively replace: any current section whose id is not in this list is removed from the quote, and the listed sections fully replace the current ones, in the given order."
},
"settings": {
"$ref": "#/$defs/QuoteSettings"
}
},
"additionalProperties": false
},
"PriceSettings": {
"type": "object",
"required": [
"tiers"
],
"properties": {
"tiers": {
"type": "array",
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "number"
},
"min_qty": {
"type": "integer"
}
},
"additionalProperties": false
},
"minItems": 1
},
"base_value": {
"type": [
"number",
"null"
]
}
},
"description": "Volume/tiered pricing for a line item.",
"additionalProperties": false
},
"QuoteSettings": {
"type": "object",
"required": [
"selection_type"
],
"properties": {
"selection_type": {
"enum": [
"custom",
"single",
"multiple"
],
"type": "string"
}
},
"description": "All-or-nothing — every property must be given when included.",
"additionalProperties": false
},
"SectionUpdate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Id of an existing section to update. Omit to create a new section."
},
"name": {
"type": [
"string",
"null"
],
"description": "Section name. Omit to leave unchanged. Pass null to clear it."
},
"items": {
"type": "array",
"items": {
"$ref": "#/$defs/ItemUpdate"
},
"description": "Replaces this section's entire line-item list. Omit this key to leave the section's items untouched. Pass an empty list to remove all items from the section. Otherwise, any current item whose id is not in this list is removed, and the listed items fully replace the current ones, in the given order."
},
"summary": {
"$ref": "#/$defs/Summary"
},
"settings": {
"$ref": "#/$defs/SectionSettings"
}
},
"additionalProperties": false
},
"SectionSettings": {
"type": "object",
"required": [
"selected",
"optional",
"selection_type"
],
"properties": {
"optional": {
"type": "boolean"
},
"selected": {
"type": "boolean"
},
"selection_type": {
"enum": [
"custom",
"single",
"multiple"
],
"type": "string"
}
},
"description": "All-or-nothing — every property must be given when included.",
"additionalProperties": false
}
},
"required": [
"document_id",
"quotes"
],
"properties": {
"quotes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"quote"
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Id of the quote to update, from the document's details."
},
"quote": {
"$ref": "#/$defs/QuoteUpdate"
}
},
"additionalProperties": false
},
"maxItems": 25,
"minItems": 1,
"description": "Quotes to update, one entry per quote. Each is applied independently — a failure on one does not affect the others."
},
"document_id": {
"type": "string",
"maxLength": 22,
"description": "Id of the document the quotes belong to."
}
},
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"$defs": {
"Item": {
"type": "object",
"required": [
"id",
"qty",
"price",
"cost",
"type",
"reference_type",
"reference_id",
"options",
"total"
],
"properties": {
"id": {
"type": "string"
},
"qty": {
"type": "string",
"description": "Decimal quantity, serialized as a numeric string."
},
"sku": {
"type": "string"
},
"cost": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"fees": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"price": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"taxes": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"total": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"images": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"options": {
"$ref": "#/$defs/ItemOptions"
},
"discounts": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"thumbnail": {
"type": [
"string",
"null"
]
},
"total_qty": {
"type": [
"string",
"null"
],
"description": "Decimal quantity, serialized as a numeric string."
},
"unit_price": {
"type": [
"string",
"null"
],
"description": "Decimal amount, serialized as a numeric string."
},
"description": {
"type": [
"string",
"null"
]
},
"multipliers": {
"type": "object",
"additionalProperties": {
"type": "string",
"description": "Decimal value, serialized as a numeric string."
}
},
"total_saved": {
"anyOf": [
{
"$ref": "#/$defs/Adjustment"
},
{
"type": "null"
}
]
},
"bundle_items": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/Item"
}
},
"reference_id": {
"type": "string"
},
"text_columns": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"contract_term": {
"type": [
"string",
"null"
]
},
"overall_total": {
"type": [
"string",
"null"
],
"description": "Decimal amount, serialized as a numeric string."
},
"custom_columns": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"number_columns": {
"type": "object",
"additionalProperties": {
"type": "string",
"description": "Decimal value, serialized as a numeric string."
}
},
"price_settings": {
"anyOf": [
{
"$ref": "#/$defs/PriceSettings"
},
{
"type": "null"
}
]
},
"pricing_method": {
"type": "string"
},
"pricing_source": {
"enum": [
"custom",
"product_bundle",
null
],
"type": [
"string",
"null"
]
},
"reference_type": {
"type": "string"
},
"currency_columns": {
"type": "object",
"additionalProperties": {
"type": "string",
"description": "Decimal value, serialized as a numeric string."
}
},
"billing_frequency": {
"enum": [
"weekly",
"monthly",
"quarterly",
"semiannually",
"annually",
null
],
"type": [
"string",
"null"
]
}
}
},
"Quote": {
"type": "object",
"required": [
"id",
"currency",
"total",
"summary",
"settings",
"sections"
],
"properties": {
"id": {
"type": "string"
},
"total": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"summary": {
"$ref": "#/$defs/QuoteSummary"
},
"currency": {
"type": "string"
},
"sections": {
"type": "array",
"items": {
"$ref": "#/$defs/Section"
}
},
"settings": {
"$ref": "#/$defs/QuoteSettings"
},
"merge_rules": {
"type": "array",
"items": {
"$ref": "#/$defs/MergeRule"
}
}
}
},
"Section": {
"type": "object",
"required": [
"id",
"total",
"summary",
"settings"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": [
"string",
"null"
]
},
"items": {
"type": "array",
"items": {
"$ref": "#/$defs/Item"
}
},
"total": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"columns": {
"type": "array",
"items": {
"$ref": "#/$defs/SectionColumn"
}
},
"summary": {
"$ref": "#/$defs/SectionSummary"
},
"settings": {
"$ref": "#/$defs/SectionSettings"
}
}
},
"Summary": {
"type": "object",
"properties": {
"fees": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"taxes": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"total": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"subtotal": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"discounts": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Adjustment"
}
},
"total_qty": {
"type": [
"string",
"null"
],
"description": "Decimal quantity, serialized as a numeric string."
},
"custom_fields": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"one_time_subtotal": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"recurring_subtotal": {
"type": "array",
"items": {
"type": "object",
"required": [
"billing_cycle",
"value"
],
"properties": {
"value": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"billing_cycle": {
"enum": [
"weekly",
"monthly",
"quarterly",
"semiannually",
"annually"
],
"type": "string"
}
}
}
}
}
},
"MergeRule": {
"type": "object",
"required": [
"id",
"enabled"
],
"properties": {
"id": {
"type": "string"
},
"enabled": {
"type": "boolean"
}
},
"description": "Data-merge automation rule attached to the quote; opaque here, informational only.",
"additionalProperties": true
},
"Adjustment": {
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"enum": [
"percent",
"flat"
],
"type": "string"
},
"value": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string (e.g. \"10.50\")."
}
}
},
"ItemOptions": {
"type": "object",
"required": [
"selected"
],
"properties": {
"optional": {
"type": "boolean"
},
"selected": {
"type": "boolean"
},
"qty_editable": {
"type": "boolean"
}
}
},
"QuoteSummary": {
"allOf": [
{
"$ref": "#/$defs/Summary"
},
{
"type": "object",
"properties": {
"total_fee": {
"type": [
"string",
"null"
]
},
"total_tax": {
"type": [
"string",
"null"
]
},
"total_savings": {
"type": [
"string",
"null"
]
},
"total_discount": {
"type": [
"string",
"null"
]
},
"total_contract_value": {
"type": [
"string",
"null"
]
}
}
}
]
},
"PriceSettings": {
"type": "object",
"required": [
"tiers"
],
"properties": {
"tiers": {
"type": "array",
"items": {
"type": "object",
"required": [
"min_qty",
"value"
],
"properties": {
"value": {
"type": "string",
"description": "Decimal amount, serialized as a numeric string."
},
"min_qty": {
"type": "string",
"description": "Quantity, serialized as a numeric string."
}
}
}
},
"base_value": {
"type": [
"string",
"null"
],
"description": "Decimal amount, serialized as a numeric string."
}
}
},
"QuoteSettings": {
"type": "object",
"required": [
"selection_type",
"data_merge_enabled"
],
"properties": {
"selection_type": {
"enum": [
"custom",
"single",
"multiple"
],
"type": "string"
},
"data_merge_enabled": {
"type": "boolean"
}
}
},
"SectionColumn": {
"type": "object",
"required": [
"name",
"hidden"
],
"properties": {
"name": {
"type": "string"
},
"header": {
"type": [
"string",
"null"
]
},
"hidden": {
"type": "boolean"
},
"merge_name": {
"type": [
"string",
"null"
]
}
}
},
"SectionSummary": {
"allOf": [
{
"$ref": "#/$defs/Summary"
},
{
"type": "object",
"properties": {
"total_section_value": {
"type": [
"string",
"null"
]
}
}
}
]
},
"SectionSettings": {
"type": "object",
"required": [
"selection_type",
"optional",
"selected",
"data_merge_enabled"
],
"properties": {
"optional": {
"type": "boolean"
},
"selected": {
"type": "boolean"
},
"selection_type": {
"enum": [
"custom",
"single",
"multiple"
],
"type": "string"
},
"data_merge_enabled": {
"type": "boolean"
}
}
}
},
"required": [
"results"
],
"properties": {
"results": {
"type": "array",
"items": {
"if": {
"required": [
"status"
],
"properties": {
"status": {
"const": "ok"
}
}
},
"then": {
"required": [
"quote"
],
"properties": {
"quote": {
"$ref": "#/$defs/Quote"
}
}
},
"type": "object",
"required": [
"id",
"status"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"quote": {
"anyOf": [
{
"$ref": "#/$defs/Quote"
},
{
"type": "null"
}
],
"description": "The quote's full state after the update. Present only when status is \"ok\"."
},
"status": {
"enum": [
"ok",
"not_in_document",
"not_found",
"conflict",
"internal_error"
],
"type": "string"
},
"description": {
"type": [
"string",
"null"
],
"description": "Human-readable detail, mainly for non-\"ok\" statuses."
}
},
"additionalProperties": false
},
"description": "One entry per requested quote, in the same order as the request."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}
}
Loading score analytics…
Put your MCP to the test
A few tasks worth trying with this server, chosen from its reviewed tools. These have not been run.
01Search contactsSearch the current workspace's contacts by first name, last name, or company.
02Search product catalog itemsSearch the workspace's product catalog by free text across item name, SKU, description and category name, with optional filters.
03List documentsPaginated document listing with structured filters: status, folder, tag, free-text search, sorting, and created/completed date ranges.
04Search documents (full-text)Full-text search with status/date filters.
05List templatesDiscover, browse, or pick a template by name, tag, or folder (e.g.
Want to run these tasks against your MCP server with us?
PandaDoc setup, tools, quality score, publishing readiness, and alternatives.
How do I add PandaDoc to Claude, ChatGPT, or Cursor?
Add PandaDoc to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://mcp.pandadoc.com/v1/mcp. This server requires OAuth, so complete the login prompt after you connect.
Is PandaDoc MCP ready for ChatGPT and Claude?
As of October 19, 2026, PandaDoc scores 96/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is PandaDoc's MCP tool documentation?
As of October 19, 2026, PandaDoc scores 85/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 42 of 42 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
What tools does the PandaDoc MCP server provide?
PandaDoc provides these MCP tools: pandadoc_documents_create, pandadoc_documents_create_from_markdown, pandadoc_documents_update, pandadoc_documents_send, pandadoc_documents_status_get, pandadoc_documents_status_change, pandadoc_documents_details_get, pandadoc_documents_summary_get, pandadoc_documents_content_get, pandadoc_documents_list, and pandadoc_documents_search.
What are the best alternatives to PandaDoc?
As of October 20, 2026, alternatives to PandaDoc in productivity on the Manufact MCP leaderboard include Autodesk Product Help, BoardWise, FlagStat, Keenable Web Search, and PomoDial.
Does PandaDoc MCP require authentication?
PandaDoc requires authentication. Connect it in Claude, ChatGPT, or Cursor and complete the OAuth login prompt.
How can PandaDoc improve its MCP documentation?
documents_update is the lowest-scoring reviewed tool at 69/100. 21 of 87 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Who develops PandaDoc?
PandaDoc is developed by PandaDoc. It is listed as partner on the Claude connector directory.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.