mcp-curl-downloader
# mcp-curl-downloader
[](https://www.npmjs.com/package/mcp-curl-downloader)
[](https://www.npmjs.com/package/mcp-curl-downloader)
[](https://nodejs.org/)
[](LICENSE)
MCP server for downloading files via HTTP/HTTPS — like `curl` but integrated with AI assistants (Claude Desktop, VS Code, Cursor, etc.).
## Quick Start
```bash
npx -y mcp-curl-downloader
```
No installation needed. The server starts on stdio and speaks the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/).
## Claude Desktop Configuration
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"curl-downloader": {
"command": "npx",
"args": ["-y", "mcp-curl-downloader"]
}
}
}
```
Config file location:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
## Tool: `download_file`
Downloads a file from a URL to any local directory or file path.
### Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|:--------:|---------|-------------|
| `url` | `string` | yes | — | File URL (http/https only) |
| `dest_path` | `string` | yes | — | Destination directory or full file path |
| `filename` | `string` | no | auto-detected | Custom filename (only when `dest_path` is a directory) |
| `headers` | `object` | no | `{}` | HTTP headers as key-value pairs |
| `overwrite` | `boolean` | no | `false` | Overwrite existing file |
### Examples
**Download to a directory** (filename auto-detected from URL):
```json
{
"url": "https://example.com/report.pdf",
"dest_path": "/home/user/downloads"
}
```
**Download with custom filename**:
```json
{
"url": "https://example.com/data.csv",
"dest_path": "/tmp",
"filename": "my_data.csv"
}
```
**Download with auth headers**:
```json
{
"url": "https://api.example.com/export",
"dest_path": "./output.json",
"headers": { "Authorization": "Bearer token123" }
}
```
**Overwrite existing file**:
```json
{
"url": "https://example.com/latest.zip",
"dest_path": "/home/user/archive.zip",
"overwrite": true
}
```
### Response
**Success**:
```json
{
"success": true,
"file_path": "/home/user/downloads/report.pdf",
"file_size": 1048576,
"content_type": "application/pdf",
"message": "Successfully downloaded: /home/user/downloads/report.pdf (1.00 MB)"
}
```
**Failure**:
```json
{
"success": false,
"error": "File already exists: \"/home/user/downloads/report.pdf\". Set overwrite=true to replace.",
"url": "https://example.com/report.pdf",
"dest_path": "/home/user/downloads"
}
```
## Security
- **Protocol whitelist**: Only `http:` and `https:` are allowed
- **URL validation**: Malformed URLs are rejected
- **Path traversal protection**: Filenames are sanitized (`../`, Windows-illegal characters, control characters removed)
- **File size limit**: 500 MB default (configurable via `CONFIG.MAX_FILE_SIZE`)
- **Overwrite protection**: Existing files are not overwritten unless `overwrite: true`
- **Timeout**: 5 minutes per download (configurable via `CONFIG.TIMEOUT_MS`)
## Development
```bash
# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run dev
# Test with MCP Inspector
npx @modelcontextprotocol/inspector node dist/index.js
```
## Requirements
- Node.js >= 18 (uses built-in `fetch` and `stream/promises`)
## License
MIT
TDQS
Scored across 1 tool
There is only one tool, so there is zero ambiguity between tools. The tool has a single, clearly defined purpose: downloading files from a URL.
With only one tool, there is no pattern to evaluate for consistency. The name 'download_file' uses a reasonable verb_noun convention, but a single tool doesn't demonstrate any naming system.
A single tool feels thin for a downloader server. The downloader domain could reasonably include tools like list_directory, delete_file, or check_file_status to provide a more complete surface, though a minimalist download-only server is defensible.
The tool covers download functionality well, but represents a dead-end surface. There is no way to check whether a download succeeded (no status/history), no way to remove downloaded files, or resolve/validate URLs before downloading. Agents hit a hard wall after invoking download_file.