> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prisme.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# WebDAV

> Browse, read and write files on any WebDAV server (Nextcloud, ownCloud, generic HTTPS WebDAV) from Agent Factory agents and Builder workflows

<img src="https://mintcdn.com/prismeai/wAgJDx_RXqITi8An/images/connectors/webdav.jpg?fit=max&auto=format&n=wAgJDx_RXqITi8An&q=85&s=643bffa972b173a0eeb655244c0684a2" alt="WebDAV" width="96" height="96" noZoom style={{ float: "left", marginRight: "1.25rem", marginBottom: "0.5rem" }} data-path="images/connectors/webdav.jpg" />

The WebDAV app provides read/write access to any [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918)-compatible file server — Nextcloud, ownCloud, a generic Apache `mod_dav` instance or any vendor-specific WebDAV endpoint. It can be consumed two ways: as a remote MCP server that **Agent Factory** agents call as tools, or as a Builder app whose instructions you call directly from DSUL. Authentication is a **per-workspace credential** — HTTP Basic (username + password) or a Bearer token — pasted into the app instance and resolved server-side; agents never see it. An optional `allowedPath` restricts every operation to a subtree of the server. The connector exposes a single `files` tool that dispatches across 10 file/directory operations: listing, reading, writing, copying, moving, deleting, recursive search, full directory trees and directory creation.

<CardGroup cols={3}>
  <Card title="Browse" icon="folder-tree">
    List directories, fetch metadata, walk full nested trees, search by name and modification date.
  </Card>

  <Card title="Read & Write" icon="file-pen">
    Download file content, upload or overwrite files with a custom MIME type, create directories.
  </Card>

  <Card title="Organize" icon="arrow-right-arrow-left">
    Move, rename, copy or delete files and directories — with optional overwrite-on-target.
  </Card>
</CardGroup>

## Who is this for?

This connector is used by three different roles. Jump to the section that matches yours — each one is self-contained.

<CardGroup cols={3}>
  <Card title="Agent builder" icon="robot">
    You build agents in **Agent Factory** and want them to read and write files on a WebDAV server. → *Agent builder* tab.
  </Card>

  <Card title="Platform admin" icon="shield-halved">
    You run the platform and want to publish WebDAV as a reusable capability. → *Platform admin setup* accordion below.
  </Card>

  <Card title="Workspace builder" icon="puzzle-piece">
    You write Builder automations (DSUL) that call WebDAV operations directly. → *Workspace builder* tab.
  </Card>
</CardGroup>

## Prerequisites

* A reachable **WebDAV server** with a stable base URL. Examples:
  * **Nextcloud / ownCloud** — `https://cloud.example.com/remote.php/dav/files/<username>`
  * **Generic Apache `mod_dav`** — `https://files.example.com/dav`
  * **Vendor-specific** — refer to the provider's documentation for the WebDAV endpoint.
* Credentials matching the chosen authentication mode:
  * **Basic** — a username + password (often an *app password* if the provider supports 2FA, e.g. Nextcloud).
  * **Token** — a Bearer token issued by the provider.
* (Optional) An **allowed path** to restrict every operation to a single subtree — useful when the WebDAV user has access to more than you want to expose.

<Warning>
  When using `basic` auth against a Nextcloud or ownCloud instance with two-factor authentication enabled, create a dedicated **app password** in the user settings (*Security → Devices & sessions → Create new app password*) and use it as the password. The main account password will be rejected.
</Warning>

<Accordion title="Platform admin (Governance) — one-time platform setup" icon="shield-halved">
  **Goal:** WebDAV is a **per-workspace** connector — each workspace pastes its own WebDAV base URL and Basic / Bearer credential into the app config (see the *Workspace builder* tab), so there is **no platform-wide credential to provision** and **no central OAuth client**. The only optional platform task is to publish WebDAV as a reusable **capability** in AI Governance so agent builders can enable it from the catalog instead of pasting a raw MCP endpoint.

  <Note>
    There is no shared WebDAV credential for this connector. The base URL, the Basic / Bearer credentials and the optional `allowedPath` always live in the consuming workspace's app configuration. A Governance capability you publish here points at a specific workspace's MCP endpoint; that workspace still owns the credential.
  </Note>

  ## Declare the capability in AI Governance (optional)

  <Steps>
    <Step title="Open AI Governance > Capabilities">
      Create (or edit) the **WebDAV** capability.
    </Step>

    <Step title="Point it at the MCP endpoint">
      Set the capability's MCP server URL to the connector's **MCP Endpoint** (the workspace running the connector), and set its **Scope** to:

      ```text theme={null}
      context_id,agent_id,user_id
      ```

      The `agent_id` in the scope is what lets Agent Factory identify the calling agent.
    </Step>

    <Step title="Make it available to agent builders">
      Once created, the capability appears in the capability picker for agent builders in your organization, who enable it on their agents. Access to the catalog follows your organization's existing roles; there is no per-capability role grant for this connector.
    </Step>
  </Steps>

  <Warning>
    Declaring the capability makes the connector **available**; it does not by itself authorize a specific agent. The WebDAV credential is resolved per-workspace from the app configuration — there is **no OAuth auth-config JSON** to attach in Governance, since authentication is a server-side Basic / Bearer credential, not a per-user OAuth flow.
  </Warning>
</Accordion>

***

<Tabs>
  <Tab title="Agent builder (Agent Factory)">
    ## Agent builder

    **Goal:** let an agent you build in Agent Factory read and write files on a WebDAV server through MCP tools.

    <Note>
      Before an agent can call the connector, a *Workspace builder* must have installed and configured the WebDAV app in a workspace (see the *Workspace builder* tab). Optionally, a *Platform admin* may have published a WebDAV capability in AI Governance (see the *Platform admin setup* accordion above).
    </Note>

    The WebDAV credential is resolved server-side from the app configuration of the workspace running the connector — it is never exposed to the agent. Your agent is identified by the `agent_id` that Agent Factory injects through the capability *Scope*.

    <Steps>
      <Step title="Install and configure the connector in your workspace">
        Follow the *Workspace builder* tab: install **WebDAV** in your workspace, then fill in the base URL, authentication type and Basic / Bearer credentials in the app instance config.
      </Step>

      <Step title="Add the MCP capability to your agent">
        In your agent, add a capability pointing at your workspace's **MCP Endpoint** URL (auto-populated on install), and set its **Scope** to:

        ```text theme={null}
        context_id,agent_id,user_id
        ```

        The `agent_id` lets Agent Factory identify the calling agent. The WebDAV credential is resolved server-side from the app config — no credential is pasted into the agent.
      </Step>

      <Step title="Brief the agent in its system prompt">
        Wiring the capability is not enough — the agent also needs to know the MCP exists and when to reach for it. Add a short paragraph to the agent's system prompt. Copy-pasteable starter:

        ```text theme={null}
        You have access to the WebDAV MCP server (mapped to <provider, e.g. Nextcloud, ownCloud, a corporate file server>) through the `files` tool, which takes an `action` argument. Use it whenever the user asks to browse files, read a document, write or overwrite a file, move/copy/rename files, walk a directory tree, or search by name or modification date. Prefer `list` for one level of children and `getTree` only when the user explicitly asks for a recursive view (it can be expensive). Always confirm with the user before destructive actions (`delete`, `move`/`upload` with overwrite of an existing file).
        ```

        Refine the trigger keywords (resource names, business domains, typical user phrasings) so the agent reliably picks up the right intent in your context.
      </Step>
    </Steps>

    <Note>
      **Legacy AI Knowledge agents** (no native MCP picker): add the connector under **Advanced > Tools > MCP** and paste the **MCP Endpoint** URL. The WebDAV credential is still resolved server-side from the workspace's app configuration.
    </Note>

    ## Available Tools

    The MCP server exposes a single entity-level tool, `files`, which dispatches across 10 actions through its `action` argument.

    ### `files`

    | Action          | Description                                                              |
    | --------------- | ------------------------------------------------------------------------ |
    | `list`          | List files / directories at a given path (depth 0 or 1).                 |
    | `get`           | Download file content.                                                   |
    | `getProperties` | Get metadata of a file or directory without its content.                 |
    | `upload`        | Upload or overwrite a file with a given MIME type.                       |
    | `delete`        | Delete a file or a directory (recursive).                                |
    | `move`          | Move or rename a file or directory.                                      |
    | `copy`          | Copy a file or directory.                                                |
    | `getTree`       | Walk the full nested directory tree under a path.                        |
    | `search`        | Search files recursively by name and modification date, with pagination. |
    | `createDir`     | Create a new directory (parent must exist).                              |

    ## Output Formats

    The `files` tool accepts an `outputFormat` argument that controls the MCP response shape:

    * **`verbose`** (default) — human-readable text for LLM consumption.
    * **`structured`** — machine-readable JSON in `structuredContent`.
    * **`both`** — both text and structured content.

    ## Tool Details

    ### `files` (action: `list`)

    ```json theme={null}
    {
      "name": "files",
      "arguments": {
        "action": "list",
        "path": "/Documents",
        "depth": 1
      }
    }
    ```

    | Parameter | Required | Description                                                                                    |
    | --------- | -------- | ---------------------------------------------------------------------------------------------- |
    | `action`  | Yes      | Must be `list`.                                                                                |
    | `path`    | No       | Directory to list. Defaults to `/`.                                                            |
    | `depth`   | No       | `1` (default) for immediate children; `0` to return only the path's own info (akin to a stat). |

    ### `files` (action: `upload`)

    ```json theme={null}
    {
      "name": "files",
      "arguments": {
        "action": "upload",
        "path": "/Generated/2026-05-26-summary.md",
        "content": "# Daily summary\n\n…",
        "contentType": "text/markdown"
      }
    }
    ```

    | Parameter     | Required | Description                                                                                                                       |
    | ------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
    | `action`      | Yes      | Must be `upload`.                                                                                                                 |
    | `path`        | Yes      | Target file path. Existing files at the same path are overwritten.                                                                |
    | `content`     | Yes      | The file content (text). For binary uploads, prefer copying from an existing file via `copy` after staging the content elsewhere. |
    | `contentType` | No       | MIME type of the content. Defaults to `text/plain`. Common values: `text/markdown`, `application/json`, `text/csv`.               |

    ### `files` (action: `move`)

    ```json theme={null}
    {
      "name": "files",
      "arguments": {
        "action": "move",
        "sourcePath": "/Exports/2026-05-25.csv",
        "destinationPath": "/Archive/2026-05-25.csv",
        "overwrite": false
      }
    }
    ```

    | Parameter         | Required | Description                                                         |
    | ----------------- | -------- | ------------------------------------------------------------------- |
    | `action`          | Yes      | Must be `move`.                                                     |
    | `sourcePath`      | Yes      | Current path of the file or directory.                              |
    | `destinationPath` | Yes      | New path (must be inside `allowedPath` if configured).              |
    | `overwrite`       | No       | Whether to overwrite if the destination exists. Defaults to `true`. |

    ### `files` (action: `search`)

    ```json theme={null}
    {
      "name": "files",
      "arguments": {
        "action": "search",
        "path": "/Reports",
        "query": "q2",
        "dateFrom": "2026-04-01T00:00:00Z",
        "dateTo": "2026-07-01T00:00:00Z",
        "sortOrder": "desc",
        "page": 1,
        "pageSize": 25
      }
    }
    ```

    | Parameter   | Required | Description                                                    |
    | ----------- | -------- | -------------------------------------------------------------- |
    | `action`    | Yes      | Must be `search`.                                              |
    | `path`      | No       | Search root (defaults to `/`). The search is always recursive. |
    | `query`     | No       | Case-insensitive substring match on file names.                |
    | `dateFrom`  | No       | ISO 8601 — only files modified on or after this date.          |
    | `dateTo`    | No       | ISO 8601 — only files modified on or before this date.         |
    | `sortOrder` | No       | `desc` (default, newest first) or `asc`.                       |
    | `page`      | No       | Page number, 1-indexed. Default `1`.                           |
    | `pageSize`  | No       | Items per page. Default `50`.                                  |

    ### `files` (action: `getTree`)

    ```json theme={null}
    {
      "name": "files",
      "arguments": {
        "action": "getTree",
        "path": "/Projects/Acme"
      }
    }
    ```

    | Parameter | Required | Description               |
    | --------- | -------- | ------------------------- |
    | `action`  | Yes      | Must be `getTree`.        |
    | `path`    | Yes      | Root of the tree to walk. |

    <Warning>
      `getTree` can return very large responses on deep directories. When the tree is large, prefer `list` with `depth: 1` and recurse client-side, or call `search` with a path filter.
    </Warning>
  </Tab>

  <Tab title="Workspace builder (DSUL)">
    ## Workspace builder

    **Goal:** install the connector in a workspace, configure the WebDAV credential, and call WebDAV operations from your automations.

    ## Installation

    1. Go to **Apps** in your workspace
    2. Search for **WebDAV** and install it
    3. Open the app instance configuration and fill in the base URL, authentication type and Basic / Bearer credentials

    ## Configuration

    | Field                       | Description                                                                                                                                     |
    | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
    | **WebDAV Base URL**         | WebDAV server base URL — e.g. `https://cloud.example.com/remote.php/dav/files/user`. All paths in tool calls are resolved relative to this URL. |
    | **Authentication Type**     | `basic` for username/password, `token` for Bearer token.                                                                                        |
    | **Username**                | Username for Basic Auth (ignored in token mode).                                                                                                |
    | **Password**                | Password (or app password) for Basic Auth (stored as a workspace secret).                                                                       |
    | **Bearer Token**            | Bearer token for token mode (stored as a workspace secret).                                                                                     |
    | **Allowed path (optional)** | If set, every file operation is rejected when the resolved path falls outside this subtree. Leave empty to expose the full base URL.            |
    | **MCP Endpoint**            | Auto-populated on install — URL of the MCP endpoint for this instance.                                                                          |

    Pick one of the two authentication modes:

    | Auth mode | What you provide                                | Best for                                                      |
    | --------- | ----------------------------------------------- | ------------------------------------------------------------- |
    | `basic`   | A **username** + **password** (or app password) | Nextcloud / ownCloud / generic `mod_dav` with HTTP Basic auth |
    | `token`   | A **Bearer token** issued by the provider       | Providers that issue API tokens instead of passwords          |

    <Note>
      The Basic / Bearer credentials are stored as workspace secrets and resolved server-side. The **MCP Endpoint** is generated automatically by the `onInstall` flow.
    </Note>

    ## Available Instructions

    Every instruction resolves credentials from the workspace configuration. All paths are interpreted relative to the `baseUrl`; a leading `/` is allowed but optional.

    ### Files & Directories

    | Instruction         | Description                                                                                                                  | Returns                                                                     |
    | ------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
    | `listFiles`         | List a directory by `path` (default `/`); `depth` = `1` for immediate children (default) or `0` for path info only.          | `{ files: [{ name, path, isDirectory, size, lastModified, contentType }] }` |
    | `getFile`           | Download file content by `path`.                                                                                             | `{ path, content, size, contentType }`                                      |
    | `getFileProperties` | Fetch metadata of a file or directory by `path` without its content.                                                         | `{ path, isDirectory, size, lastModified, contentType, etag }`              |
    | `uploadFile`        | Create or overwrite a file at `path` with `content`; optional `contentType` (default `text/plain`).                          | `{ path, size }`                                                            |
    | `deleteFile`        | Delete a file or directory by `path` (directories are deleted recursively).                                                  | Empty (HTTP 204)                                                            |
    | `moveFile`          | Move/rename from `sourcePath` to `destinationPath`; `overwrite` (default `true`) controls overwrite-on-target.               | `{ sourcePath, destinationPath }`                                           |
    | `copyFile`          | Copy from `sourcePath` to `destinationPath`; `overwrite` (default `true`) controls overwrite-on-target.                      | `{ sourcePath, destinationPath }`                                           |
    | `getDirectoryTree`  | Walk the full nested directory tree under `path`.                                                                            | `{ path, tree: [{ name, path, isDirectory, children }] }`                   |
    | `searchFiles`       | Recursive search under `path` filtered by `query` (name substring), `dateFrom`/`dateTo`, with `page`/`pageSize`/`sortOrder`. | `{ matches: [{ name, path, lastModified, size }], page, pageSize, total }`  |
    | `createDirectory`   | Create a directory at `path` (parent must exist).                                                                            | `{ path }`                                                                  |

    <Note>
      `Returns` shows the shape of the operation output. `depth` accepts `0` (path info only) or `1` (immediate children, default). `deleteFile` deletes directories recursively.
    </Note>

    ## DSUL Examples

    ### List the contents of a folder

    ```yaml theme={null}
    - WebDAV.listFiles:
        path: '/Documents'
        depth: 1
        output: listing
    ```

    ### Download a file and emit an excerpt

    ```yaml theme={null}
    - WebDAV.getFile:
        path: '/Reports/2026/q1-results.md'
        output: report
    - emit:
        event: report.fetched
        payload:
          size: '{{report.size}}'
          excerpt: '{% slice({{report.content}}, 0, 500) %}'
    ```

    ### Upload a generated markdown file

    ```yaml theme={null}
    - WebDAV.uploadFile:
        path: '/Generated/{{run.date}}-summary.md'
        content: |
          # Daily summary

          {{summary.body}}
        contentType: 'text/markdown'
    ```

    ### Move yesterday's exports to an archive folder

    ```yaml theme={null}
    - WebDAV.moveFile:
        sourcePath: '/Exports/{{yesterday}}.csv'
        destinationPath: '/Archive/{{yesterday}}.csv'
        overwrite: false
    ```

    ### Search for recent reports by name

    ```yaml theme={null}
    - WebDAV.searchFiles:
        path: '/Reports'
        query: 'q2'
        dateFrom: '2026-04-01T00:00:00Z'
        dateTo: '2026-07-01T00:00:00Z'
        sortOrder: desc
        pageSize: 25
        output: matches
    ```
  </Tab>
</Tabs>

***

## Error Handling

WebDAV uses standard HTTP status codes plus a handful of WebDAV-specific ones (RFC 4918).

| HTTP Status           | Meaning              | Typical Cause                                                                                               |
| --------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------- |
| `400`                 | Bad Request          | Malformed path, invalid `depth`, missing required parameter.                                                |
| `401`                 | Unauthorized         | Wrong username / password, expired or revoked Bearer token.                                                 |
| `403`                 | Forbidden            | The configured user lacks the WebDAV permission for the operation, or the path falls outside `allowedPath`. |
| `404`                 | Not Found            | The path does not exist on the server.                                                                      |
| `405`                 | Method Not Allowed   | Calling a method (e.g. `MKCOL`) on a path that already exists.                                              |
| `409`                 | Conflict             | `createDirectory` called on a path whose parent does not exist (`MKCOL` parent missing).                    |
| `412`                 | Precondition Failed  | `move`/`copy` with `overwrite: false` but the destination already exists.                                   |
| `423`                 | Locked               | Another client holds a WebDAV lock on the resource — retry later.                                           |
| `429`                 | Rate Limited         | Provider throttling (Nextcloud rate limits, reverse-proxy WAF).                                             |
| `507`                 | Insufficient Storage | The user is over quota on the provider.                                                                     |
| `500` / `502` / `503` | Server Error         | Transient error from the upstream server or proxy. Retry with exponential backoff.                          |

### Common Issues

**"WebDAV not configured"** — The app instance is missing either `baseUrl` or the credentials for the chosen `type` (Basic or token). Open the app configuration and fill in the base URL, authentication type and credentials.

**"Basic Auth requires username and password"** — `type` is `basic` but the username or password is empty. Provide both in the app config (use an app password on 2FA-enabled accounts).

**"Token auth requires a Bearer token"** — `type` is `token` but no Bearer token is set. Paste a valid token in the app config.

**Nextcloud / ownCloud 401 with the right password** — Two-factor authentication on the account requires an **app password**. Create one in *Security → Devices & sessions* and use it as the `password`.

**"Access denied - path outside allowed scope" (403)** — The resolved path is not under the configured `allowedPath`. Either widen the allowed path or rewrite the call to a path within it.

**`getTree` times out on a large folder** — Prefer `listFiles` with `depth: 1` and recurse from the client, or use `searchFiles` with `dateFrom`/`dateTo` to scope the request.

**`upload` with binary content fails** — The `content` parameter is a string. For binary payloads, stage the file elsewhere (a previously uploaded file in WebDAV, a public URL, etc.) and use `copy` or an out-of-band upload. The connector does not currently accept base64-encoded `content`.

**Trailing slashes** — Some WebDAV servers are strict about trailing slashes on directories. If a directory listing returns 404, retry with a trailing `/`.

## External Resources

<CardGroup cols={2}>
  <Card title="WebDAV (RFC 4918)" icon="book" href="https://datatracker.ietf.org/doc/html/rfc4918">
    Official WebDAV protocol specification.
  </Card>

  <Card title="Tool Agents" icon="robot" href="/products/agent-factory/capabilities">
    Learn how Agent Factory agents consume MCP tools in Prisme.ai.
  </Card>
</CardGroup>
