# WebDAV MCP Server

A Model Context Protocol (MCP) server that enables CRUD operations on a WebDAV endpoint with basic authentication. This server enables Claude Desktop and other MCP clients to interact with WebDAV file systems through natural language commands.

## Features

- Connect to any WebDAV server with optional authentication
- Perform CRUD operations on files and directories
- Expose file operations as MCP resources and tools
- Run via stdio transport (for Claude Desktop integration) or HTTP/SSE transport
- Secure access with optional basic authentication
- Support for bcrypt-encrypted passwords for MCP server authentication (WebDAV passwords must be plain text due to protocol limitations)
- Connection pooling for better performance with WebDAV servers
- Configuration validation using Zod
- Structured logging for better troubleshooting

## Prerequisites

- Node.js 18 or later
- npm or yarn
- WebDAV server (for actual file operations)

## Installation

### Option 1: Install from npm package

```bash
# Global installation
npm install -g webdav-mcp-server

# Or with npx
npx webdav-mcp-server
```

### Option 2: Clone and build from source

```bash
# Clone repository
git clone https://github.com/yourusername/webdav-mcp-server.git
cd webdav-mcp-server

# Install dependencies
npm install

# Build the application
npm run build
```

### Option 3: Docker

```bash
# Build the Docker image
docker build -t webdav-mcp-server .

# Run the container without authentication
docker run -p 3000:3000 \
  -e WEBDAV_ROOT_URL=http://your-webdav-server \
  -e WEBDAV_ROOT_PATH=/webdav \
  webdav-mcp-server
  
# Run the container with authentication for both WebDAV and MCP server
docker run -p 3000:3000 \
  -e WEBDAV_ROOT_URL=http://your-webdav-server \
  -e WEBDAV_ROOT_PATH=/webdav \
  -e WEBDAV_AUTH_ENABLED=true \
  -e WEBDAV_USERNAME=admin \
  -e WEBDAV_PASSWORD=password \
  -e AUTH_ENABLED=true \
  -e AUTH_USERNAME=user \
  -e AUTH_PASSWORD=pass \
  webdav-mcp-server
```

## Configuration

Create a `.env` file in the root directory with the following variables:

```env
# WebDAV configuration
WEBDAV_ROOT_URL=http://localhost:4080
WEBDAV_ROOT_PATH=/webdav

# WebDAV authentication (optional)
WEBDAV_AUTH_ENABLED=true
WEBDAV_USERNAME=admin

# WebDAV password must be plain text (required when auth enabled)
# The WebDAV protocol requires sending the actual password to the server
WEBDAV_PASSWORD=password

# Server configuration (for HTTP mode)
SERVER_PORT=3000

# Authentication configuration for MCP server (optional)
AUTH_ENABLED=true
AUTH_USERNAME=user
AUTH_PASSWORD=pass
AUTH_REALM=MCP WebDAV Server

# Auth password for MCP server can be a bcrypt hash (unlike WebDAV passwords)
# AUTH_PASSWORD={bcrypt}$2y$10$CyLKnUwn9fqqKQFEbxpZFuE9mzWR/x8t6TE7.CgAN0oT8I/5jKJBy
```

### Encrypted Passwords for MCP Server Authentication

For enhanced security of the MCP server (not WebDAV connections), you can use bcrypt-encrypted passwords instead of storing them in plain text:

1. Generate a bcrypt hash:
   ```bash
   # Using the built-in utility
   npm run generate-hash -- yourpassword
   
   # Or with npx
   npx webdav-mcp-generate-hash yourpassword
   ```

2. Add the hash to your .env file with the {bcrypt} prefix:
   ```
   AUTH_PASSWORD={bcrypt}$2y$10$CyLKnUwn9fqqKQFEbxpZFuE9mzWR/x8t6TE7.CgAN0oT8I/5jKJBy
   ```

This way, your MCP server password is stored securely. Note that WebDAV passwords must always be in plain text due to protocol requirements.

## Usage

### Running with stdio transport

This mode is ideal for direct integration with Claude Desktop.

```bash
# If installed globally
webdav-mcp-server

# If using npx
npx webdav-mcp-server

# If built from source
node dist/index.js
```

### Running with HTTP/SSE transport

This mode enables the server to be accessed over HTTP with Server-Sent Events for real-time communication.

```bash
# If installed globally
webdav-mcp-server --http

# If using npx
npx webdav-mcp-server --http

# If built from source
node dist/index.js --http
```

## Quick Start with Docker Compose

The easiest way to get started with both the WebDAV server and the MCP server is to use Docker Compose:

```bash
# Start both WebDAV and MCP servers
cd docker
docker-compose up -d

# This will start:
# - hacdias/webdav server on port 4080 (username: admin, password: admin)
# - MCP server on port 3000 (username: user, password: pass)
```

This setup uses [hacdias/webdav](https://github.com/hacdias/webdav), a simple and standalone WebDAV server written in Go. The configuration for the WebDAV server is stored in `webdav_config.yml`, which you can modify to adjust permissions, add users, or change other settings.

The WebDAV server stores all files in a Docker volume called `webdav_data`, which persists across container restarts.

## WebDAV Server Configuration

The `webdav_config.yml` file configures the hacdias/webdav server used in the Docker Compose setup. Here's what you can customize:

```yaml
# Server address and port
address: 0.0.0.0
port: 6060

# Root data directory
directory: /data

# Enable/disable CORS
cors:
  enabled: true
  # Additional CORS settings...

# Default permissions (C=Create, R=Read, U=Update, D=Delete)
permissions: CRUD

# User definitions
users:
  - username: admin
    password: admin      # Plain text password
    permissions: CRUD    # Full permissions
  
  - username: reader
    password: reader
    permissions: R       # Read-only permissions
    
  # You can also use bcrypt-encrypted passwords
  - username: secure
    password: "{bcrypt}$2y$10$zEP6oofmXFeHaeMfBNLnP.DO8m.H.Mwhd24/TOX2MWLxAExXi4qgi"
```

For more advanced configuration options, refer to the [hacdias/webdav documentation](https://github.com/hacdias/webdav).

## Testing

To run the tests:

```bash
npm test
```

## Integrating with Claude Desktop

1. Ensure the MCP feature is enabled in Claude Desktop

<details>
<summary>Using npx</summary>
2. Open Claude Desktop settings and click edit config (`claude_desktop_config.json`)
3. Add
```json
{
    "mcpServers": {
        "webdav": {
            "command": "npx",
            "args": [
                "-y",
                "webdav-mcp-server"
            ],
            "env": {
                "WEBDAV_ROOT_URL": "<WEBDAV_ROOT_URL>",
                "WEBDAV_ROOT_PATH": "<WEBDAV_ROOT_PATH>",
                "WEBDAV_USERNAME": "<WEBDAV_USERNAME>",
                "WEBDAV_PASSWORD": "<WEBDAV_PASSWORD>",
                "WEBDAV_AUTH_ENABLED": "true|false"
            }
        }
    }
}
```
</details>
<details>
<summary>Using node and local build</summary>
2. Clone this repository and run `setup.sh` on mac/linux or `setup.bat` on windows
3. Open Claude Desktop settings and click edit config (`claude_desktop_config.json`)
4. Add
```json
{
    "mcpServers": {
        "webdav": {
            "command": "node",
            "args": [
                "<path to repository>/dist/index.js"
            ],
            "env": {
                "WEBDAV_ROOT_URL": "<WEBDAV_ROOT_URL>",
                "WEBDAV_ROOT_PATH": "<WEBDAV_ROOT_PATH>",
                "WEBDAV_USERNAME": "<WEBDAV_USERNAME>",
                "WEBDAV_PASSWORD": "<WEBDAV_PASSWORD>",
                "WEBDAV_AUTH_ENABLED": "true|false"
            }
        }
    }
}
```
</details>

## Available MCP Resources

- `webdav://{path}/list` - List files in a directory
- `webdav://{path}/content` - Get file content
- `webdav://{path}/info` - Get file or directory information

## Available MCP Tools

- `webdav_create_remote_file` - Create a new file on a remote WebDAV server
- `webdav_get_remote_file` - Retrieve content from a file stored on a remote WebDAV server
- `webdav_update_remote_file` - Update an existing file on a remote WebDAV server
- `webdav_delete_remote_item` - Delete a file or directory from a remote WebDAV server
- `webdav_create_remote_directory` - Create a new directory on a remote WebDAV server
- `webdav_move_remote_item` - Move or rename a file/directory on a remote WebDAV server
- `webdav_copy_remote_item` - Copy a file/directory to a new location on a remote WebDAV server
- `webdav_list_remote_directory` - List files and directories on a remote WebDAV server

## Available MCP Prompts

- `webdav_create_remote_file` - Prompt to create a new file on a remote WebDAV server
- `webdav_get_remote_file` - Prompt to retrieve content from a remote WebDAV file
- `webdav_update_remote_file` - Prompt to update a file on a remote WebDAV server
- `webdav_delete_remote_item` - Prompt to delete a file/directory from a remote WebDAV server
- `webdav_list_remote_directory` - Prompt to list directory contents on a remote WebDAV server
- `webdav_create_remote_directory` - Prompt to create a directory on a remote WebDAV server
- `webdav_move_remote_item` - Prompt to move/rename a file/directory on a remote WebDAV server
- `webdav_copy_remote_item` - Prompt to copy a file/directory on a remote WebDAV server

## Example Queries in Claude

Here are some example queries you can use in Claude Desktop once the WebDAV MCP server is connected:

- "List files on my remote WebDAV server"
- "Create a new text file called notes.txt on my remote WebDAV server with the following content: Hello World"
- "Get the content of document.txt from my remote WebDAV server"
- "Update config.json on my remote WebDAV server with this new configuration"
- "Create a directory called projects on my remote WebDAV server"
- "Copy report.docx to a backup location on my remote WebDAV server"
- "Move the file old_name.txt to new_name.txt on my remote WebDAV server"
- "Delete temp.txt from my remote WebDAV server"

## Programmatic Usage

You can also use this package programmatically in your own projects:

```javascript
import { startWebDAVServer } from 'webdav-mcp-server';

// For stdio transport without authentication
await startWebDAVServer({
  webdavConfig: {
    rootUrl: 'http://your-webdav-server',
    rootPath: '/webdav',
    authEnabled: false
  },
  useHttp: false
});

// For stdio transport with WebDAV authentication (password must be plain text)
await startWebDAVServer({
  webdavConfig: {
    rootUrl: 'http://your-webdav-server',
    rootPath: '/webdav',
    authEnabled: true,
    username: 'admin',
    password: 'password'
  },
  useHttp: false
});

// With bcrypt hash for MCP server password (HTTP auth only)
await startWebDAVServer({
  webdavConfig: {
    rootUrl: 'http://your-webdav-server',
    rootPath: '/webdav',
    authEnabled: true,
    username: 'admin',
    password: 'password' // WebDAV password must be plain text
  },
  useHttp: true,
  httpConfig: {
    port: 3000,
    auth: {
      enabled: true,
      username: 'user',
      password: '{bcrypt}$2y$10$CyLKnUwn9fqqKQFEbxpZFuE9mzWR/x8t6TE7.CgAN0oT8I/5jKJBy'
    }
  }
});

// For HTTP transport with MCP authentication
await startWebDAVServer({
  webdavConfig: {
    rootUrl: 'http://your-webdav-server',
    rootPath: '/webdav',
    authEnabled: true,
    username: 'admin',
    password: 'password'
  },
  useHttp: true,
  httpConfig: {
    port: 3000,
    auth: {
      enabled: true,
      username: 'user',
      password: 'pass',
      realm: 'MCP WebDAV Server'
    }
  }
});

// For HTTP transport without authentication
await startWebDAVServer({
  webdavConfig: {
    rootUrl: 'http://your-webdav-server',
    rootPath: '/webdav',
    authEnabled: false
  },
  useHttp: true,
  httpConfig: {
    port: 3000,
    auth: {
      enabled: false
    }
  }
});
```

## License

MIT
