# PeoplePerHour MCP tools

> Every PeoplePerHour 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/peopleperhour

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)

11 tools for PeoplePerHour on the Cotlet MCP server. Your agent picks them from tools/list.

- MCP server: `https://cotlet.dev/mcp/v1`
- Connects with: Your own PeoplePerHour account (a freelancer account for proposals, Offers and invoices)
- Integration page: https://cotlet.dev/integrations/peopleperhour-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `peopleperhour_search_projects` | read | Projects buyers posted, newest first, with title, budget, category and proposal count. |
| `peopleperhour_get_project` | read | Full project brief with budget, skills and the proposals already sent. |
| `peopleperhour_list_proposals` | read | Proposals you sent, newest first, with project, price and status. |
| `peopleperhour_list_workstreams` | read | Your WorkStream threads with buyer, project and the last message. |
| `peopleperhour_get_workstream` | read | One WorkStream with its messages, proposals and invoices, oldest first. |
| `peopleperhour_list_offers` | read | Your Offers with title, price and status. |
| `peopleperhour_send_proposal` | write | Send a proposal to a project with your brief, price, delivery time and an optional deposit. |
| `peopleperhour_cancel_proposal` | write | Cancel a proposal the buyer has not accepted yet. |
| `peopleperhour_send_message` | write | Send a message to the buyer in a WorkStream, as you. |
| `peopleperhour_create_invoice` | write | Raise an invoice in a WorkStream for the buyer to pay. |
| `peopleperhour_create_offer` | write | Publish a fixed-price Offer on your profile. |

## Search projects

MCP tool: `peopleperhour_search_projects`

Access: read.

Returns projects from the same search as the website, newest first. Filter by keyword or by posting time to read only what came in since your last check. Each item has the budget the buyer set; get_project returns the full brief. Pass next_cursor back as cursor for the next page.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `query` | string | no | Keywords to search for. |
| `since` | datetime | no | Only projects posted after this time. |
| `limit` | integer | no | 1 to 50. Default: 20. |
| `cursor` | string | no | Next page cursor from the previous call. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "peopleperhour_search_projects",
    "arguments": {
      "query": "web design",
      "since": "2026-10-11T07:00:00Z",
      "limit": 20
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "projects": [
      {
        "project_id": "pj_48213",
        "title": "Landing page design for a SaaS launch",
        "budget": {
          "amount": 500,
          "currency": "GBP"
        },
        "category": "Design",
        "proposals": 4,
        "posted_at": "2026-10-10T08:12:00Z",
        "url": "https://www.peopleperhour.com/freelance-jobs/design/landing-page-design-for-a-saas-launch-48213"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## Get project

MCP tool: `peopleperhour_get_project`

Access: read.

Returns one project with the buyer's full brief, budget, required skills and how many proposals it has. Use it before send_proposal so your agent reads the brief instead of the title.

### Parameters

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

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "project_id": "pj_48213",
    "title": "Landing page design for a SaaS launch",
    "brief": "We need a one-page design in Figma for our launch on 1 November. Copy is ready.",
    "budget": {
      "amount": 500,
      "currency": "GBP"
    },
    "skills": [
      "Web design",
      "Figma"
    ],
    "proposals": 4,
    "posted_at": "2026-10-10T08:12:00Z"
  },
  "isError": false
}
```

## List proposals

MCP tool: `peopleperhour_list_proposals`

Access: read.

Lists the proposals on your account, newest first, with the project, your price and whether the buyer has accepted it. Filter by status to find the ones still waiting. Pass proposal_id to cancel_proposal.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `status` | string | no | Only proposals with this status, for example pending. |
| `limit` | integer | no | 1 to 50. Default: 20. |
| `cursor` | string | no | Next page cursor from the previous call. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "proposals": [
      {
        "proposal_id": "pp_90412",
        "project_id": "pj_48213",
        "project_title": "Landing page design for a SaaS launch",
        "price": 450,
        "status": "pending",
        "sent_at": "2026-10-10T09:30:00Z"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## List WorkStreams

MCP tool: `peopleperhour_list_workstreams`

Access: read.

Lists your WorkStreams, most recent first, each with the buyer, the project and a preview of the last message. Set awaiting_reply to see only threads where the buyer wrote last. Use the workstream_id with get_workstream, send_message and create_invoice.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `awaiting_reply` | boolean | no | Only threads where the buyer sent the last message. |
| `limit` | integer | no | 1 to 50. Default: 20. |
| `cursor` | string | no | Next page cursor from the previous call. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "workstreams": [
      {
        "workstream_id": "ws_7731",
        "buyer": "Maria S.",
        "project_title": "Landing page design for a SaaS launch",
        "last_message": "Can you start on Monday?",
        "last_from": "buyer",
        "updated_at": "2026-10-11T07:40:00Z"
      }
    ],
    "next_cursor": null
  },
  "isError": false
}
```

## Get WorkStream

MCP tool: `peopleperhour_get_workstream`

Access: read.

Returns one WorkStream in order, oldest first: messages, the proposals sent in it, invoices raised and file names shared. Read it before replying so your agent sees the whole history with this buyer.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `workstream_id` | string | yes | WorkStream ID from list_workstreams. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "workstream_id": "ws_7731",
    "buyer": "Maria S.",
    "items": [
      {
        "type": "proposal",
        "proposal_id": "pp_90412",
        "price": 450,
        "sent_at": "2026-10-10T09:30:00Z"
      },
      {
        "type": "message",
        "from": "buyer",
        "body": "Can you start on Monday?",
        "sent_at": "2026-10-11T07:40:00Z"
      }
    ]
  },
  "isError": false
}
```

## List Offers

MCP tool: `peopleperhour_list_offers`

Access: read.

Lists the fixed-price Offers on your profile, newest first, with title, price and whether each is live. Use it to check what you already sell before creating another.

### Parameters

No parameters.

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "offers": [
      {
        "offer_id": "of_2209",
        "title": "Landing page design in Figma",
        "price": 350,
        "status": "live"
      }
    ]
  },
  "isError": false
}
```

## Send proposal

MCP tool: `peopleperhour_send_proposal`

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

Sends a proposal on one project under your name. It takes a brief of what you will deliver, a price, a delivery time and optionally a deposit to hold in Escrow. It counts against your free Proposals for the month; more are bought as Proposal credits. 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 search_projects. |
| `brief` | string | yes | What you will deliver and by when. |
| `price` | number | yes | Your price in the project currency. |
| `delivery_days` | integer | yes | Days to deliver. |
| `deposit_percent` | integer | no | Share of the price to hold in Escrow up front. Default: none. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "peopleperhour_send_proposal",
    "arguments": {
      "project_id": "pj_48213",
      "brief": "I will design the landing page in Figma and hand over the files, with two rounds of changes.",
      "price": 450,
      "delivery_days": 7,
      "deposit_percent": 20
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "proposal_id": "pp_90412",
    "project_id": "pj_48213",
    "status": "pending",
    "price": 450,
    "delivery_days": 7,
    "deposit_percent": 20,
    "workstream_id": "ws_7731",
    "sent_at": "2026-10-10T09:30:00Z"
  },
  "isError": false
}
```

## Cancel proposal

MCP tool: `peopleperhour_cancel_proposal`

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

Cancels one pending proposal. An accepted proposal cannot be cancelled and the call fails. The buyer sees the proposal withdrawn, so use it before sending a corrected one. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `proposal_id` | string | yes | Proposal ID from list_proposals. |

### tools/call

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

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "proposal_id": "pp_90412",
    "status": "cancelled"
  },
  "isError": false
}
```

## Send message

MCP tool: `peopleperhour_send_message`

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

Posts a message in one WorkStream under your name. Each WorkStream is one buyer and one project, so a message never reaches other buyers. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `workstream_id` | string | yes | WorkStream ID from list_workstreams. |
| `body` | string | yes | Message text. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "peopleperhour_send_message",
    "arguments": {
      "workstream_id": "ws_7731",
      "body": "Tuesday at 10:00 works for me. I will bring the second layout so we can pick one on the call."
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "workstream_id": "ws_7731",
    "message_id": "msg_5120",
    "status": "sent",
    "sent_at": "2026-10-11T08:05:00Z"
  },
  "isError": false
}
```

## Create invoice

MCP tool: `peopleperhour_create_invoice`

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

Raises an invoice in one WorkStream. The buyer is asked to pay it, so it reaches money and the other person. Amount and description are the ones you pass. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `workstream_id` | string | yes | WorkStream ID from list_workstreams. |
| `amount` | number | yes | Invoice amount in the project currency. |
| `description` | string | yes | What the invoice is for. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "peopleperhour_create_invoice",
    "arguments": {
      "workstream_id": "ws_7731",
      "amount": 450,
      "description": "Landing page design in Figma, final files delivered and approved"
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "invoice_id": "inv_3318",
    "workstream_id": "ws_7731",
    "amount": 300,
    "description": "Landing page design, week 2",
    "status": "sent",
    "raised_at": "2026-10-16T16:00:00Z"
  },
  "isError": false
}
```

## Create Offer

MCP tool: `peopleperhour_create_offer`

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

Publishes an Offer on your profile with a title, description and price, visible to buyers. It reaches the public, so it asks first. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `title` | string | yes | Offer title. |
| `description` | string | yes | What the buyer gets. |
| `price` | number | yes | Price in your account currency. |

### tools/call

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "peopleperhour_create_offer",
    "arguments": {
      "title": "title",
      "description": "description",
      "price": 1
    }
  }
}
```

### Example response

```json
{
  "content": [
    {
      "type": "text",
      "text": "{ ... same JSON as structuredContent ... }"
    }
  ],
  "structuredContent": {
    "offer_id": "of_2210",
    "title": "Logo refresh in 3 days",
    "price": 120,
    "status": "live"
  },
  "isError": false
}
```
