# `documents_search`

**Search documents.** Finds documents by title, category or words in them.

**Who can use it:** Everyone in the community. Residents find only documents shared with residents; owners and managers find all of them.

| Scope | Effect | Hints |
|---|---|---|
| `documents:read` | read | reads only, idempotent |

## Description shown to assistants

> Use this when the user asks to find a document by title, category, or keyword.

## Arguments

| Argument | Type | Required | About |
|---|---|---|---|
| `property_id` | string | No | The community's public id (`prop_web…`). Pass it on every call. |
| `query` | string | No | Words to search for. |
| `limit` | integer | No | How many to return. From 1 to 100. |

## What it returns

Every result has `content` (one short sentence for the person) and `structuredContent` (the data below). A tool that could not run answers with `isError: true` and a sentence saying why; see [Errors and limits](/developers/mcp/errors-and-limits).

- `query`: the words searched for.
- `documents`: each with `id`, `title`, `category`, `uploadedAt`, `description`, `hasAttachment`, `downloadUrl`, `visibleToResidents` and `indexingStatus`. Owners and managers also get `uploadedBy`.

`structuredContent` follows this JSON Schema, also in `tools/list` as `outputSchema`:

```json
{
  "type": "object",
  "properties": {
    "property": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "name": { "type": "string" },
        "addressLine1": { "type": ["string", "null"] },
        "addressLine2": { "type": ["string", "null"] },
        "city": { "type": ["string", "null"] },
        "state": { "type": ["string", "null"] },
        "postalCode": { "type": ["string", "null"] },
        "timezone": { "type": ["string", "null"] },
        "billingFrequency": { "type": ["string", "null"] },
        "demoClone": { "type": "boolean" },
        "demoPersona": { "type": ["string", "null"] },
        "demoExpiresAt": { "type": ["string", "null"] }
      },
      "required": ["id", "name"]
    },
    "query": { "type": ["string", "null"] },
    "documents": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "category": { "type": ["string", "null"] },
          "uploadedAt": { "type": "string" },
          "description": { "type": ["string", "null"] },
          "hasAttachment": { "type": "boolean" },
          "downloadUrl": { "type": ["string", "null"] },
          "visibleToResidents": { "type": ["boolean", "null"] },
          "indexingStatus": { "type": ["string", "null"] },
          "uploadedBy": {
            "type": ["string", "null"],
            "description": "Owners and managers only."
          }
        },
        "required": ["id", "title", "uploadedAt", "hasAttachment"]
      }
    }
  },
  "required": ["property", "documents"]
}
```

## Notes

- With `query`, PorchQ runs a full-text search; without it, the most recently uploaded documents come first.
- `downloadUrl` is a PorchQ address that needs the person to be signed in to PorchQ in their browser.
- `limit` defaults to 25, at most 100.

## Example

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "documents_search",
    "arguments": {
      "property_id": "prop_web4k2m9q7x1v8c3n5b6z0a2s4d",
      "query": "pet policy"
    }
  }
}
```
