# Dubsado MCP tools

> Every Dubsado 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/dubsado

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)

14 tools for Dubsado on the Cotlet MCP server. Your agent picks them from tools/list.

- MCP server: `https://cotlet.dev/mcp/v1`
- Connects with: Your own Dubsado account; team members see what their permission level allows
- Integration page: https://cotlet.dev/integrations/dubsado-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `dubsado_list_projects` | read | Projects with client, lead or job, status, tags and project date. |
| `dubsado_get_project` | read | One project: client, status, dates, tags, notes, forms and invoices. |
| `dubsado_list_clients` | read | Clients with name, email, phone and their projects. |
| `dubsado_list_form_templates` | read | Your form templates by type, to pick one to apply to a project. |
| `dubsado_list_forms` | read | Forms across projects, or in one project, with type and status. |
| `dubsado_get_form_responses` | read | Answers from a completed form or lead capture form, as question and answer pairs. |
| `dubsado_list_invoices` | read | Invoices with project, total, amount paid, balance and due date. |
| `dubsado_create_project` | write | New project for a new or existing client. Nothing is sent to the client. |
| `dubsado_update_project_status` | write | Move a project to another of your statuses. |
| `dubsado_apply_form_template` | write | Add a project copy of a proposal, contract, questionnaire or sub-agreement. Not sent yet. |
| `dubsado_send_form` | write | Email a proposal, contract, questionnaire or sub-agreement to the client. |
| `dubsado_create_invoice` | write | Draft an invoice in a project from your packages or line items. Not emailed yet. |
| `dubsado_send_invoice` | write | Email the invoice to the client with a link to it. |
| `dubsado_record_manual_payment` | write | Log a payment received outside Dubsado against an invoice. |

## List projects

MCP tool: `dubsado_list_projects`

Access: read.

Lists projects newest first. Category is lead or job and follows the status: Dubsado statuses are either lead or job statuses. Filter by status name, category or creation date to see what came in since your last check. Pages hold up to 100 projects; pass next_cursor back as cursor for the next page.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `category` | enum | no | lead, job or all. Default: all. |
| `status` | string | no | Your project status name, e.g. "Proposal Sent". |
| `created_since` | date | no | Only projects created on or after this date. |
| `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": "dubsado_list_projects",
    "arguments": {}
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "projects": [
      {
        "project_id": "prj_3d81b07e",
        "title": "Spring brand shoot",
        "client": {
          "client_id": "cli_41a7e2",
          "name": "Maya Chen",
          "email": "maya@example.com"
        },
        "category": "lead",
        "status": "Proposal Sent",
        "tags": [
          "Brand"
        ],
        "project_date": "2027-04-18",
        "created_at": "2026-10-07T13:12:00Z"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## Get project

MCP tool: `dubsado_get_project`

Access: read.

Returns one project with its client, status, tags and notes, the forms in it with their status, and its invoices with balances. Use it to read a whole project in one call before you act on it.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `project_id` | string | yes | Project ID from list_projects. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "project_id": "prj_3d81b07e",
    "title": "Spring brand shoot",
    "client": {
      "client_id": "cli_41a7e2",
      "name": "Maya Chen",
      "email": "maya@example.com"
    },
    "category": "lead",
    "status": "Proposal Sent",
    "tags": [
      "Brand"
    ],
    "project_date": "2027-04-18",
    "notes": "Referred by a past client.",
    "forms": [
      {
        "form_id": "frm_6f2a91c4",
        "type": "proposal",
        "name": "Brand Photography proposal",
        "status": "sent"
      }
    ],
    "invoices": []
  },
  "isError": false
}
```

## List clients

MCP tool: `dubsado_list_clients`

Access: read.

Lists clients, the people and companies you work with. Search by name or email. Each client lists its project IDs, which you pass to get_project. Pages hold up to 100 clients.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `query` | string | no | Search by name or email. |
| `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": "dubsado_list_clients",
    "arguments": {}
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "clients": [
      {
        "client_id": "cli_41a7e2",
        "name": "Maya Chen",
        "email": "maya@example.com",
        "phone": "+1 555 0100",
        "projects": [
          "prj_3d81b07e"
        ]
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## List form templates

MCP tool: `dubsado_list_form_templates`

Access: read.

Returns the templates you built in Dubsado: proposals, contracts, questionnaires, sub-agreements and lead capture forms. Pass template_id to apply_form_template. Templates are read only here.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `type` | enum | no | proposal, contract, questionnaire, sub_agreement, lead_capture or all. Default: all. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "templates": [
      {
        "template_id": "tpl_5c20aa",
        "name": "Brand Photography proposal",
        "type": "proposal"
      },
      {
        "template_id": "tpl_81d9f3",
        "name": "Photography contract",
        "type": "contract"
      },
      {
        "template_id": "tpl_2e7b60",
        "name": "Shoot questionnaire",
        "type": "questionnaire"
      }
    ]
  },
  "isError": false
}
```

## List forms

MCP tool: `dubsado_list_forms`

Access: read.

Lists forms sent from projects, the same forms as Forms, All forms in Dubsado. Status is sent, viewed, action_required or completed. Action required means a contract waits for your countersignature. Filter by type, status or project. Pass form_id to get_form_responses.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `project_id` | string | no | Only forms in this project. |
| `type` | enum | no | proposal, contract, questionnaire, sub_agreement, lead_capture or all. Default: all. |
| `status` | string[] | no | Any of sent, viewed, action_required, completed. Default: all statuses. |
| `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": "dubsado_list_forms",
    "arguments": {
      "type": "contract",
      "status": [
        "sent",
        "viewed",
        "action_required"
      ]
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "forms": [
      {
        "form_id": "frm_a4410c7e",
        "project_id": "prj_8e15c3a2",
        "project_title": "Acme rebrand",
        "type": "contract",
        "name": "Design services contract",
        "status": "viewed"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## Get form responses

MCP tool: `dubsado_get_form_responses`

Access: read.

Returns the answers a client gave, in the order of the form, the same as the Responses view on the form. Only completed forms have responses. Questionnaires can be edited after completion, so the answers can change.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `form_id` | string | yes | Form ID from list_forms or apply_form_template. |
| `include_empty` | boolean | no | Include unanswered fields. Default: false. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dubsado_get_form_responses",
    "arguments": {
      "form_id": "frm_9b42e6d1",
      "include_empty": true
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "form_id": "frm_9b42e6d1",
    "type": "questionnaire",
    "name": "Shoot questionnaire",
    "project_id": "prj_3d81b07e",
    "responses": [
      {
        "question": "What is the shoot for?",
        "answer": "New website and press kit."
      },
      {
        "question": "Preferred location",
        "answer": "Studio, downtown"
      }
    ]
  },
  "isError": false
}
```

## List invoices

MCP tool: `dubsado_list_invoices`

Access: read.

Lists invoices, newest first. The due date comes from the invoice payment plan and is empty when the invoice has none. Balance is the total minus the payments logged, including those logged by hand. Pages hold up to 100 invoices.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `status` | enum | no | unpaid, paid or all. Default: unpaid. |
| `project_id` | string | no | Only invoices in this project. |
| `due_before` | date | no | Only invoices with a payment due before this date. |
| `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": "dubsado_list_invoices",
    "arguments": {}
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoices": [
      {
        "invoice_id": "inv_20417",
        "project_id": "prj_8e15c3a2",
        "project_title": "Acme rebrand",
        "number": "0042",
        "total": "1200.00",
        "paid": "400.00",
        "balance": "800.00",
        "due_date": "2026-10-11"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## Create project

MCP tool: `dubsado_create_project`

Access: write.

Creates a project from a title and a client email. If the email is not in Dubsado, a new client is created, with client_name if you give one. The status must be one of your project statuses and decides whether the project is a lead or a job. This call sends nothing to the client, so it asks no confirmation. You can archive or delete the project in Dubsado.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `title` | string | yes | Project title, e.g. "Brand Photography". |
| `client_email` | string | yes | Existing client, or a new one is created. |
| `client_name` | string | no | Name for a new client. |
| `status` | string | no | One of your project status names. |
| `project_date` | date | no | Project date. |
| `tags` | string[] | no | Project tags. |
| `notes` | string | no | Notes on the project. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dubsado_create_project",
    "arguments": {
      "title": "Spring brand shoot",
      "client_email": "maya@example.com",
      "client_name": "Maya Chen",
      "status": "Proposal Sent",
      "project_date": "2027-04-18"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "project_id": "prj_3d81b07e",
    "title": "Spring brand shoot",
    "client": {
      "client_id": "cli_41a7e2",
      "name": "Maya Chen",
      "email": "maya@example.com"
    },
    "category": "lead",
    "status": "Inquiry",
    "created_at": "2026-10-11T09:00:00Z"
  },
  "isError": false
}
```

## Update project status

MCP tool: `dubsado_update_project_status`

Access: write.

Moves one project to a status you already have. A project can move from a lead status to a job status; Dubsado does not turn a status from one kind into the other. The call sends nothing to the client and you undo it with one more call, so it asks no confirmation. A Flow that starts on a status change still runs.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `project_id` | string | yes | Project ID from list_projects. |
| `status` | string | yes | One of your project status names. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dubsado_update_project_status",
    "arguments": {
      "project_id": "project_8c41d2",
      "status": "status"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "project_id": "prj_3d81b07e",
    "previous_status": "Proposal Sent",
    "status": "Booked",
    "category": "job"
  },
  "isError": false
}
```

## Apply form template

MCP tool: `dubsado_apply_form_template`

Access: write.

Adds a copy of a template to one project and returns its form_id. Changes to the copy do not touch your template. Nothing is sent and the form is not added to the client portal, so this call asks no confirmation. Send it with send_form, or remove the copy in Dubsado.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `project_id` | string | yes | Project ID from list_projects. |
| `template_id` | string | yes | Template ID from list_form_templates. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dubsado_apply_form_template",
    "arguments": {
      "project_id": "project_8c41d2",
      "template_id": "template_8c41d2"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "form_id": "frm_6f2a91c4",
    "project_id": "prj_3d81b07e",
    "type": "proposal",
    "name": "Brand Photography proposal",
    "status": "not_sent"
  },
  "isError": false
}
```

## Send form

MCP tool: `dubsado_send_form`

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

Emails the form to the client with a link to it. Without subject and message it uses your default email template for the form. After the client completes it, the form is locked, except questionnaires. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `form_id` | string | yes | Form ID from list_forms or apply_form_template. |
| `subject` | string | no | Email subject. Default: from your email template. |
| `message` | string | no | Email body. Default: from your email template. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dubsado_send_form",
    "arguments": {
      "form_id": "frm_6f2a91c4",
      "subject": "Your proposal for Spring brand shoot"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "form_id": "frm_6f2a91c4",
    "project_id": "prj_3d81b07e",
    "type": "proposal",
    "status": "sent",
    "sent_to": "maya@example.com",
    "sent_at": "2026-10-11T09:02:00Z"
  },
  "isError": false
}
```

## Create invoice

MCP tool: `dubsado_create_invoice`

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

Creates an invoice in a project from saved packages, line items, or both. Dubsado numbers it automatically. The invoice date is the issue date; due_date adds a payment plan with one payment on that date. An invoice worth more than $0 appears in the client portal before it is emailed, so this call needs your OK. Email it with send_invoice. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `project_id` | string | yes | Project ID from list_projects. |
| `package_ids` | string[] | no | IDs of your saved packages to add. |
| `line_items` | object[] | no | List of { name, quantity, price, description }. |
| `due_date` | date | no | Adds a payment plan with one payment due on this date. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoice_id": "inv_20417",
    "project_id": "prj_8e15c3a2",
    "number": "0042",
    "status": "not_sent",
    "line_items": [
      {
        "name": "Logo package",
        "quantity": 1,
        "price": "1200.00"
      }
    ],
    "total": "1200.00",
    "balance": "1200.00",
    "due_date": "2026-10-25"
  },
  "isError": false
}
```

## Send invoice

MCP tool: `dubsado_send_invoice`

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

Emails the invoice to the client with the invoice link. Without a message it uses your default email template. After it is sent, the automatic payment reminders of Dubsado follow the payment plan. 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 or create_invoice. |
| `message` | string | no | Email body. Default: from your email template. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoice_id": "inv_20417",
    "status": "sent",
    "sent_to": "client@example.com",
    "sent_at": "2026-10-11T09:05:00Z"
  },
  "isError": false
}
```

## Record manual payment

MCP tool: `dubsado_record_manual_payment`

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

Logs a payment you received outside Dubsado, such as cash or a check, on one invoice. The amount cannot be more than the remaining balance, and a payment for the full balance moves the invoice to Paid. It does not cancel autopay. Only manually logged payments can be edited or deleted, in Dubsado. 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 or create_invoice. |
| `amount` | string | yes | Amount, e.g. "400.00". Not more than the remaining balance. |
| `paid_on` | date | yes | Date received. |
| `method` | enum | yes | cash, check, credit, e_transfer, paypal, stripe, square, authorize_net or other. |
| `description` | string | no | Optional note on the payment. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dubsado_record_manual_payment",
    "arguments": {
      "invoice_id": "inv_20417",
      "amount": "400.00",
      "paid_on": "2026-10-09",
      "method": "e_transfer",
      "description": "E-transfer ref 7731"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoice_id": "inv_20417",
    "amount": "400.00",
    "method": "check",
    "paid_on": "2026-10-12",
    "balance": "800.00",
    "invoice_status": "unpaid"
  },
  "isError": false
}
```
