# Joist MCP tools

> Every Joist MCP tool on the Cotlet server: tool names, input schemas, a tools/call example and an example result for each tool.

Source: https://cotlet.dev/docs/mcp/joist

Docs sections: [Get started](https://cotlet.dev/docs.md) · [REST API](https://cotlet.dev/docs/api.md) · [MCP](https://cotlet.dev/docs/mcp.md) · [SDKs & CLI](https://cotlet.dev/docs/sdks.md) · [Integrations](https://cotlet.dev/docs/integrations.md)

13 tools for Joist on the Cotlet MCP server. Your agent picks them from tools/list.

- MCP server: `https://cotlet.dev/mcp/v1`
- Connects with: Your own Joist account (email and password at pro.joistapp.com; Joist accounts have a single user)
- Integration page: https://cotlet.dev/integrations/joist-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `joist_list_estimates` | read | Estimates with number, client, total, expiry date, status, and whether the client opened the email or signed. |
| `joist_list_invoices` | read | Invoices with number, client, total, amount paid, balance due and due date. Active or Paid. |
| `joist_get_document` | read | Full estimate or invoice: client, line items, tax, discount, deposit and the payments recorded. |
| `joist_list_clients` | read | Clients in your account with name, email, phone and address. |
| `joist_list_items` | read | Saved items from your Items list, with name, description and rate, to reuse as line items. |
| `joist_get_report` | read | A Joist report for a date range: revenue, invoices, estimates or sales tax. |
| `joist_export_documents` | read | Joist's monthly CSV of estimates or invoices, as a download link. |
| `joist_add_client` | write | New client in your Clients list, ready for estimates and invoices. |
| `joist_add_item` | write | Save a service or material to your Items list. |
| `joist_create_estimate` | write | New saved estimate with line items, optional deposit and expiry. Nothing is sent to the client. |
| `joist_convert_estimate_to_invoice` | write | Generate an invoice with everything from the estimate. Not sent until you call send_document. |
| `joist_record_payment` | write | Record a payment received outside Joist Payments; a fully paid invoice moves to Paid. |
| `joist_send_document` | write | Email an estimate or invoice to the client from Joist. |

## List estimates

MCP tool: `joist_list_estimates`

Access: read.

Lists the estimates in your Joist account, newest first. Each item shows the status (pending until approved), the expiry date if one is set, and the two markers Joist shows in its list: client opened the email, and signed. Pass estimate_id to convert_estimate_to_invoice or get_document.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `search` | string | no | Client name or estimate number. |
| `limit` | integer | no | 1 to 100. Default: 25. |
| `cursor` | string | no | Next page cursor from the previous call. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_list_estimates",
    "arguments": {}
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "estimates": [
      {
        "estimate_id": "est_20418",
        "number": "318",
        "client": "Dana Lee",
        "total": 700,
        "status": "pending",
        "expires_on": "2026-10-25",
        "email_opened": true,
        "signed": false
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## List invoices

MCP tool: `joist_list_invoices`

Access: read.

Lists invoices from the Active view (not paid in full) or the Paid view, newest first. Balance due is the total less recorded payments, so a partly paid invoice shows what is left. The due date is the creation date plus your Payment Terms, and overdue is true where Joist shows the Overdue badge. Each item shows whether the client opened the email and whether it is signed.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `view` | enum | no | active (not paid in full) or paid. Default: active. |
| `search` | string | no | Client name or invoice number. |
| `limit` | integer | no | 1 to 100. Default: 25. |
| `cursor` | string | no | Next page cursor from the previous call. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_list_invoices",
    "arguments": {
      "view": "active",
      "limit": 100
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoices": [
      {
        "invoice_id": "inv_58213",
        "number": "1042",
        "client": "Mark Ruiz",
        "total": 2400,
        "amount_paid": 1200,
        "balance_due": 1200,
        "due_on": "2026-10-01",
        "overdue": true,
        "email_opened": true,
        "signed": true
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## Get estimate or invoice

MCP tool: `joist_get_document`

Access: read.

Returns one estimate or invoice with its client, every line item, tax, discount, requested deposit and, for an invoice, the payments recorded on it. Use it before changing or sending a document so your agent sees what the client will see.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `document_id` | string | yes | Estimate or invoice ID from list_estimates or list_invoices. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_get_document",
    "arguments": {
      "document_id": "document_8c41d2"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "document_id": "inv_58213",
    "type": "invoice",
    "number": "1042",
    "client": {
      "client_id": "cl_2210",
      "name": "Mark Ruiz"
    },
    "line_items": [
      {
        "name": "Kitchen cabinet install",
        "quantity": 1,
        "rate": 2400
      }
    ],
    "tax": 0,
    "discount": 0,
    "total": 2400,
    "payments": [
      {
        "amount": 1200,
        "method": "bank_transfer",
        "paid_on": "2026-09-25"
      }
    ]
  },
  "isError": false
}
```

## List clients

MCP tool: `joist_list_clients`

Access: read.

Lists the clients in your Joist account. Use client_id from an item in create_estimate. Search matches part of a name, email or phone.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `search` | string | no | Part of a name, email or phone. |
| `limit` | integer | no | 1 to 200. Default: 50. |
| `cursor` | string | no | Next page cursor from the previous call. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_list_clients",
    "arguments": {}
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "clients": [
      {
        "client_id": "cl_3307",
        "name": "Dana Lee",
        "email": "dana@example.com",
        "phone": "+1 555 0100",
        "address": "14 Maple Street"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## List items

MCP tool: `joist_list_items`

Access: read.

Lists the items you saved in Joist (Joist does not ship with prices built in). Your agent reuses their names and rates on new estimates instead of guessing prices.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `search` | string | no | Part of the item name. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_list_items",
    "arguments": {}
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "items": [
      {
        "item_id": "it_104",
        "name": "Interior door, installed",
        "description": "Supply and hang a pre-hung interior door",
        "rate": 350
      }
    ]
  },
  "isError": false
}
```

## Get report

MCP tool: `joist_get_report`

Access: read.

Returns one of Joist's Reports for a date range, optionally for one client: revenue received (partial payments included), invoice balances and statuses, estimate volume and statuses, or sales tax collected by jurisdiction. Joist reports only include data entered after 1 September 2022. If your account has no Reports, the call returns the error the app shows.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `report` | enum | yes | revenue, invoices, estimates or sales_tax. |
| `from` | date | yes | Start of the range. |
| `to` | date | yes | End of the range. |
| `client` | string | no | Only this client, by name. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_get_report",
    "arguments": {
      "report": "revenue",
      "from": "2026-10-01",
      "to": "2026-10-01"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "report": "revenue",
    "from": "2026-09-01",
    "to": "2026-09-30",
    "total_received": 8450,
    "invoices_with_payments": 6
  },
  "isError": false
}
```

## Export documents

MCP tool: `joist_export_documents`

Access: read.

Runs the same export as Joist's website, for one month: number, client name, subtotal, tax, total, date issued, date created and payment received less refunds. Line items are not in the export; use get_document for those. Returns a download link and the row count.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `type` | enum | yes | estimates or invoices. |
| `month` | string | yes | Month as YYYY-MM. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_export_documents",
    "arguments": {
      "type": "estimates",
      "month": "month"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "type": "invoices",
    "month": "2026-09",
    "rows": 14,
    "download_url": "https://files.cotlet.example/joist-invoices-2026-09.csv"
  },
  "isError": false
}
```

## Add client

MCP tool: `joist_add_client`

Access: write.

Creates a client in your Joist account. It reaches no one and nothing is sent, so it runs without asking; you can delete the client in Joist. Check list_clients first to avoid a duplicate.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Client or company name. |
| `email` | string | no | Used when you send documents. |
| `phone` | string | no | Phone number. |
| `address` | string | no | Job or billing address. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_add_client",
    "arguments": {
      "name": "Jane Doe"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "client_id": "cl_3312",
    "name": "Priya Nair",
    "email": "priya@example.com"
  },
  "isError": false
}
```

## Add item

MCP tool: `joist_add_item`

Access: write.

Saves an item with a name, rate and optional description to your Items list, so it can be reused on later estimates. It reaches no one, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `name` | string | yes | Item name. |
| `rate` | string | yes | Price per unit, e.g. "350.00". |
| `description` | string | no | Shown on the line item. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_add_item",
    "arguments": {
      "name": "Jane Doe",
      "rate": "350.00"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "item_id": "it_105",
    "name": "Baseboard, installed",
    "rate": 4.5
  },
  "isError": false
}
```

## Create estimate

MCP tool: `joist_create_estimate`

Access: write.

Creates and saves an estimate for a client. Nothing is sent: the client sees it only after send_document. A deposit is a percent or an amount and shows under the total as Deposit Due. The expiry date cannot be in the past. It reaches no one, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `client_id` | string | yes | Client ID from list_clients or add_client. |
| `line_items` | object[] | yes | List of { name, description, quantity, rate }. |
| `tax_rate` | string | no | Tax percent applied to the estimate, e.g. "8.25". |
| `discount` | object | no | { type: percent or amount, value }. |
| `deposit` | object | no | Requested deposit: { type: percent or amount, value }. |
| `expires_on` | date | no | Expiry date. Must not be in the past. |
| `notes` | string | no | Note shown on the estimate. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_create_estimate",
    "arguments": {
      "client_id": "cl_3307",
      "line_items": [
        {
          "name": "Interior door, installed",
          "description": "Supply and hang a pre-hung interior door",
          "quantity": 2,
          "rate": "350.00"
        }
      ],
      "tax_rate": "8.25",
      "deposit": {
        "type": "percent",
        "value": 50
      },
      "expires_on": "2026-10-26"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "estimate_id": "est_20418",
    "number": "318",
    "client": "Dana Lee",
    "line_items": [
      {
        "name": "Interior door, installed",
        "quantity": 2,
        "rate": 350,
        "amount": 700
      }
    ],
    "total": 700,
    "deposit_due": 350,
    "expires_on": "2026-10-25",
    "sent": false
  },
  "isError": false
}
```

## Convert estimate to invoice

MCP tool: `joist_convert_estimate_to_invoice`

Access: write.

Does what Generate Invoice does in Joist: the new invoice carries all the information from the estimate. The estimate stays in your Estimates list and its status changes from pending to approved. Nothing is sent to the client, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `estimate_id` | string | yes | Estimate ID from list_estimates. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_convert_estimate_to_invoice",
    "arguments": {
      "estimate_id": "est_20418"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoice_id": "inv_58300",
    "number": "1051",
    "from_estimate": "est_20418",
    "total": 700,
    "deposit_due": 350,
    "sent": false,
    "estimate_status": "approved"
  },
  "isError": false
}
```

## Record payment

MCP tool: `joist_record_payment`

Access: write. Confirm: waits for the user's OK before it runs.

Records a payment on an invoice, as Record Payment does in Joist. Partial payments are allowed, and an invoice can hold several. Once the invoice is paid in full it moves from Active to Paid. Payments made through Joist Payments are recorded by Joist itself. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `invoice_id` | string | yes | Invoice ID from list_invoices. |
| `amount` | string | yes | Amount received, e.g. "1200.00". |
| `method` | enum | yes | cash, check, credit or bank_transfer. |
| `paid_on` | date | no | Payment date. Default: today. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_record_payment",
    "arguments": {
      "invoice_id": "inv_58213",
      "amount": "1200.00",
      "method": "check",
      "paid_on": "2026-10-09"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoice_id": "inv_58213",
    "number": "1042",
    "total": 2400,
    "amount_paid": 2400,
    "balance_due": 0,
    "list": "paid",
    "payments": [
      {
        "amount": 1200,
        "method": "bank_transfer",
        "paid_on": "2026-09-25"
      },
      {
        "amount": 1200,
        "method": "check",
        "paid_on": "2026-10-09"
      }
    ]
  },
  "isError": false
}
```

## Send estimate or invoice

MCP tool: `joist_send_document`

Access: write. Confirm: waits for the user's OK before it runs.

Emails the document from Joist on your behalf, as the Email button does. The recipient is prefilled from the client on the document, and subject and body can be changed. The client sees it, and Joist marks it when they open the email or sign. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `document_id` | string | yes | Estimate or invoice ID from list_estimates or list_invoices. |
| `to` | string | no | Recipient email. Default: the client email on the document. |
| `subject` | string | no | Email subject. Default: the Joist subject. |
| `message` | string | no | Email body. Default: the Joist message. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "joist_send_document",
    "arguments": {
      "document_id": "document_8c41d2"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "document_id": "inv_58300",
    "to": [
      "dana@example.com"
    ],
    "status": "sent",
    "sent_at": "2026-10-11T09:20:00+02:00"
  },
  "isError": false
}
```
