Built on top of aria2 — the world's fastest download utility.
⚡ The AI Agent download tool that finally gets it right.
AI Agent First · MCP Native · Zero Dependencies · Cross-Platform · 100% Open Source
Quick Start · Why aria2-agent · Safety & Trust · MCP Integration · 10 Iron Rules
🔒 Safety & Trust
I built this for myself first. Then I thought, maybe someone else needs it too.
Let me be straightforward with you:
This is a wrapper, not a reimplementation. aria2-agent doesn't replace aria2 — it wraps aria2's JSON-RPC interface with safety rules that AI Agents need. The actual downloading is still done by aria2, a battle-tested open-source project with 35,000+ stars and 20+ years of history.
No backdoors. No telemetry. No data collection. None.
- 📄 One file, 959 lines. You can read the entire source code in 10 minutes. There's nowhere to hide anything.
- 🚫 Zero network calls except to your own machine. The only connection is
127.0.0.1— your local aria2 daemon. No "phone home", no analytics, no update checks. - 📦 Zero dependencies. Pure Python 3.8 standard library. No
pip installsupply chain risk. No hidden transitive dependencies. What you see is what you get. - 🔑 Your secrets stay yours. The RPC secret token is auto-generated locally and stored in
~/.aria2_agent/state.json. It never leaves your machine. - 🌐 The daemon only listens on localhost.
--rpc-listen-all=falsemeans no external machine can connect. Not even your LAN. - 📝 MIT licensed. Do whatever you want with it. Read it, audit it, fork it, sell it. No strings attached.
I'm a developer who got tired of AI Agents reporting "download complete" on corrupted files. So I wrote this. That's the whole story.
🎯 The Problem
When AI Agents (Claude, GPT, Cursor, etc.) download large files using aria2c, they hit a silent killer:
Agent: "Download this 50GB model file."
aria2c: *pre-allocates 50GB instantly*
Agent: *checks file size* → "50GB? Download complete!"
Agent: *tries to use the file* → 💥 CORRUPTED / INCOMPLETE
aria2's default file-allocation=prealloc creates a full-size placeholder file before any data arrives. Any agent that checks file size to determine completion gets a false positive 100% of the time.
This isn't a bug in aria2 — it's a fundamental mismatch between aria2's human-oriented design and what AI Agents need.
💡 The Solution
aria2-agent is a purpose-built CLI + MCP Server that wraps aria2's JSON-RPC interface with 10 architecturally-enforced rules:
- Forces
file-allocation=none— no phantom files, ever - Completes judgment via RPC only —
status == "complete"ANDcompletedLength == totalLength - Pure JSON output —
json.loads(stdout)and you're done - Blocks rule circumvention —
FORBIDDEN_PER_TASK_OPTSprevents per-task overrides
# One command. Agent gets clean JSON. No false positives. Ever.
python aria2cli.py add "https://example.com/model.safetensors" \
--dir ./downloads --out model.safetensors --wait --timeout 3600
{"ok": true, "gid": "2089b056ea1d1f3c", "complete": true, "timed_out": false,
"elapsed": 120.5, "status": "complete",
"totalLength": "15200000000", "completedLength": "15200000000",
"files": [{"path": "./downloads/model.safetensors", "length": "15200000000"}]}
Agent logic: if result["complete"]: done — that's it.
✨ Features
| Feature | aria2c (raw) | aria2p | wget | aria2-agent |
|---|---|---|---|---|
| AI Agent JSON output | ❌ | ❌ | ❌ | ✅ |
| Pre-allocation false-positive fix | ❌ | ❌ | ❌ | ✅ |
| Built-in retry + resume | Manual | Manual | ❌ | ✅ |
| MCP Server mode | ❌ | ❌ | ❌ | ✅ |
| Rule circumvention prevention | ❌ | ❌ | ❌ | ✅ |
| Zero dependencies | ✅ | ❌ | ✅ | ✅ |
| Cross-platform | ✅ | ✅ | ✅ | ✅ |
| Multi-source mirror download | ✅ | ✅ | ❌ | ✅ |
| BT / Magnet support | ✅ | ✅ | ❌ | ✅ |
🏁 Quick Start
Prerequisites
- Python 3.8+
- aria2c in PATH (install guide)
Install
# Option 1: pip (recommended)
pip install aria2-agent
# Option 2: just download the single file — zero dependencies
curl -O https://raw.githubusercontent.com/Rehui-2006/aria2-agent/main/aria2cli.py
3-Step Usage
# Step 1: Start the RPC daemon (once per session)
python aria2cli.py start --dir ~/Downloads
# Step 2: Download and wait for completion
python aria2cli.py add "https://example.com/large_file.bin" \
--dir ~/Downloads --out file.bin --wait --timeout 3600
# Step 3: Agent reads JSON → checks "complete" field → done
Verify Rules Are Enforced
python aria2cli.py verify
{
"ok": true,
"file_allocation": "none",
"no_file_allocation_limit": "0",
"rules_checked": {
"rule2_file_allocation_none": true,
"rule2_no_file_allocation_limit_zero": true,
"rule3_completion_via_rpc_only": true,
"rule4_no_local_file_for_judgment": true
}
}
📖 Core Usage
Standard Download (most common)
python aria2cli.py add "https://example.com/file.zip" \
--dir ./downloads --out file.zip --wait --timeout 3600
Large File Download (models, datasets)
python aria2cli.py add "https://huggingface.co/model.bin" \
--dir ./models --out model.bin \
--split 16 --wait --timeout 3600 --retries 3
--split 16: 16 parallel connections--retries 3: auto-resubmit on failure (same dir+out = aria2 resume, no re-download)
Async Download (submit then poll)
# Submit, get gid
python aria2cli.py add "https://example.com/file.zip" --dir ./dl --out f.zip
# Poll later
python aria2cli.py status <gid>
python aria2cli.py wait <gid> --timeout 3600
Multi-Source Mirror
python aria2cli.py add \
"https://mirror1.example.com/file.iso" \
"https://mirror2.example.com/file.iso" \
"https://mirror3.example.com/file.iso" \
--dir ./isos --out ubuntu.iso --wait
Proxy / Custom Headers / SSL Bypass
# Via JSON options (no shell escaping issues)
python aria2cli.py add "https://example.com/file" \
--dir ./dl --out file --wait \
--options '{"all-proxy":"http://127.0.0.1:1080","check-certificate":"false"}'
# Or use --options-file to avoid shell quoting hell
echo '{"header":["Authorization: Bearer xxx","Referer: https://example.com"]}' > opts.json
python aria2cli.py add "https://example.com/file" \
--dir ./dl --out file --wait --options-file opts.json
Task Management
python aria2cli.py status <gid> # Check status (complete field = done check)
python aria2cli.py list # List all tasks
python aria2cli.py pause <gid> # Pause
python aria2cli.py resume <gid> # Resume
python aria2cli.py remove <gid> # Remove (keeps downloaded data)
python aria2cli.py remove <gid> --force # Force remove
python aria2cli.py stop # Stop daemon
🔌 MCP Server Mode
aria2-agent ships with a built-in Model Context Protocol server — 8 tools, zero config:
pip install "aria2-agent[mcp]"
python aria2cli.py mcp
MCP Tools
| Tool | Description |
|---|---|
aria2_add | Submit download task, returns gid |
aria2_status | Query normalized status (complete via RPC only) |
aria2_wait | Poll until complete (built-in retry + resume) |
aria2_pause | Pause a task |
aria2_resume | Resume a paused task |
aria2_remove | Remove a task |
aria2_list | List all tasks |
aria2_verify | Verify iron rules are enforced |
Claude Desktop Integration
Add to claude_desktop_config.json:
{
"mcpServers": {
"aria2-agent": {
"command": "python",
"args": ["-m", "aria2cli", "mcp"]
}
}
}
Cursor / VS Code Integration
{
"mcp.servers": {
"aria2-agent": {
"command": "python",
"args": ["aria2cli.py", "mcp"]
}
}
}
See docs/AGENT_INTEGRATION.md for detailed integration guides.
🛡️ The 10 Iron Rules
These rules are architecturally enforced — not guidelines, not config defaults. Violating any rule requires a rewrite.
| # | Rule | Enforcement |
|---|---|---|
| 1 | RPC daemon only — no blocking aria2c single commands | start_daemon() is the only entry point |
| 2 | Force --file-allocation=none --no-file-allocation-limit=0 | MANDATORY_DAEMON_ARGS tuple, always prepended |
| 3 | Complete = RPC tellStatus double check | is_complete() checks status=="complete" AND completedLength==totalLength |
| 4 | Never read local file size for completion | Only show_local flag reads size, labeled local_file_size_display_only |
| 5 | All params via JSON-RPC, never shell strings | rpc_call() uses json.dumps(), never shell=True |
| 6 | Clean subcommand CLI | argparse with add/status/pause/resume/remove/start/stop/wait/list/verify/mcp |
| 7 | Pure JSON output, no logs/progress/colors | emit() writes json.dumps() to stdout, nothing else |
| 8 | Built-in 3x retry, 3600s timeout, resume | wait_for_complete() with max_retries=3, DEFAULT_TIMEOUT=3600 |
| 9 | Cross-platform Windows/Linux/macOS | os.name detection, DETACHED_PROCESS on Windows, start_new_session on POSIX |
| 10 | Optional MCP Server | run_mcp_server() with 8 FastMCP tools |
Rule Circumvention Prevention
FORBIDDEN_PER_TASK_OPTS = {
"file-allocation",
"no-file-allocation-limit",
"enable-rpc",
"rpc-listen-port",
"rpc-listen-all",
"rpc-secret",
"rpc-allow-origin-all",
}
Even if an agent passes {"file-allocation": "prealloc"} in --options, it's silently rejected with a warning. The iron rules cannot be bypassed.
📋 Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success / download complete |
| 1 | Business error (RPC error, download failed) |
| 2 | Wait timeout (file may be partially downloaded, can resume) |
🎯 Use Cases
Downloading AI Models
python aria2cli.py add "https://huggingface.co/llama/model.safetensors" \
--dir ./models --split 16 --wait --timeout 7200 --retries 3
Downloading Datasets
python aria2cli.py add "https://data.example.com/dataset.tar.gz" \
--dir ./data --out dataset.tar.gz --wait
BT / Magnet Links
python aria2cli.py add "magnet:?xt=urn:btih:..." \
--dir ./torrents --wait --timeout 7200
Multi-Source ISO Download
python aria2cli.py add \
"https://mirror1/ubuntu.iso" "https://mirror2/ubuntu.iso" \
--dir ./isos --out ubuntu.iso --wait
❓ FAQ
Why not just use aria2c directly?
aria2c is designed for humans. Its default file-allocation=prealloc creates full-size placeholder files instantly. AI agents that check file size get false completion signals 100% of the time. aria2-agent forces file-allocation=none and uses RPC tellStatus for reliable completion detection.
Why not use huggingface-cli for model downloads?
Use huggingface-cli for HuggingFace downloads — it has native ETag verification and hf_transfer acceleration. aria2-agent is for everything else: direct HTTP links, FTP, BT, magnet, multi-source mirrors, and any scenario needing RPC-precise completion checking.
Why not yt-dlp for video downloads?
Use yt-dlp for YouTube/Bilibili etc. aria2-agent is for direct file downloads — models, datasets, ISOs, archives, BT torrents.
Is the RPC daemon secure?
Yes. The daemon binds to 127.0.0.1 only (--rpc-listen-all=false), auto-generates a random secret token, and stores state in ~/.aria2_agent/state.json.
Can I use an external aria2 RPC daemon?
Yes:
python aria2cli.py start --external http://your-host:6800/jsonrpc
🏗️ Architecture
┌──────────────────────────────────────────────────┐
│ AI Agent │
│ (Claude / GPT / Cursor / ...) │
└──────────────┬──────────────────┬────────────────┘
│ CLI │ MCP
▼ ▼
┌──────────────────────┐ ┌───────────────────────┐
│ aria2cli.py │ │ MCP Server (8 tools) │
│ │ │ │
│ ┌────────────────┐ │ │ ┌─────────────────┐ │
│ │ 10 Iron Rules │ │ │ │ FastMCP │ │
│ │ Enforcement │ │ │ │ Tool Registry │ │
│ └───────┬────────┘ │ │ └───────┬─────────┘ │
│ │ │ │ │ │
│ ┌───────▼────────┐ │ │ ┌───────▼─────────┐ │
│ │ JSON-RPC │◄─┼──┼──┤ JSON-RPC │ │
│ │ Client │ │ │ │ Client │ │
│ └───────┬────────┘ │ │ └───────┬─────────┘ │
└──────────┼───────────┘ └──────────┼───────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────┐
│ aria2c RPC Daemon │
│ --enable-rpc --file-allocation=none │
│ --no-file-allocation-limit=0 │
│ (mandatory, non-overridable) │
└──────────────────────────────────────────────────┘
See docs/ARCHITECTURE.md for the full design document.
📦 Installation (Detailed)
Install aria2c
| Platform | Command |
|---|---|
| Windows | choco install aria2 or scoop install aria2 |
| macOS | brew install aria2 |
| Ubuntu/Debian | sudo apt install aria2 |
| CentOS/RHEL | sudo yum install aria2 |
| Arch Linux | sudo pacman -S aria2 |
Install aria2-agent
# Via pip (with MCP support)
pip install "aria2-agent[mcp]"
# Via pip (CLI only, zero deps)
pip install aria2-agent
# Or just download the single file
wget https://raw.githubusercontent.com/Rehui-2006/aria2-agent/main/aria2cli.py
🤝 Contributing
Contributions are welcome! Please read the 10 Iron Rules first — any PR that weakens a rule will be rejected.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing) - Open a Pull Request
📝 Changelog
See CHANGELOG.md.
📄 License
MIT — see LICENSE.
📊 Dashboards
- 📋 Health Dashboard — Daily automated health check results
- 📈 Stats Dashboard — Weekly repository statistics
⭐ Star History
If this tool saved your agent from a corrupted download, give it a ⭐!
Made with ❤️ for the AI Agent community