Manus MCP
# Manus MCP
[](https://pypi.org/project/manus-mcp/)
[](https://pypi.org/project/manus-mcp/)
[](https://pypistats.org/packages/manus-mcp)
[](https://github.com/aruxojuyu665/Manus-MCP/blob/main/LICENSE)
[](https://github.com/aruxojuyu665/Manus-MCP/actions/workflows/ci.yml)
[](https://github.com/aruxojuyu665/Manus-MCP/actions/workflows/live.yml)
[](https://github.com/aruxojuyu665/Manus-MCP/stargazers)
An MCP server that gives Claude Code full programmatic control over Manus.im through the official Manus API v2. Implements **all 30 documented endpoints**, **3 composite tools** for common workflows, and a **local webhook receiver** with RSA-SHA256 signature verification.
- **Status**: production-ready (single-user) — v0.1.1
- Language: Python 3.11+
- Transport: stdio (native to Claude Code)
- Base URL: `https://api.manus.ai`
## Verified coverage (v0.1.1)
| Layer | Metric |
|------|---------|
| Unit tests | 60+ (server.py dispatch, webhook ASGI app, secret-leak guard, schema stability) |
| Live e2e tests | 23 (including task.update / sendMessage / confirmAction / agent.update / website.publish) |
| Composite live | 4 (including the F2 reject check) |
| Webhook live e2e | 1 (cloudflared tunnel + receiver + Manus delivery) |
| **Manus API endpoints exercised live** | **30/30** (graceful skip only when the account lacks the prerequisite — no agents / no website) |
| Coverage | ≥ 80% (gated in CI) |
| `mypy --strict` | 0 errors |
| `ruff check` | 0 errors |
See [docs/SECURITY.md](docs/SECURITY.md) and [docs/RELEASE.md](docs/RELEASE.md) for the production flow.
## What's included
### 30 direct API wrappers
| Category | Tools |
|-----------|-------------|
| Tasks (9) | `manus_task_create`, `manus_task_detail`, `manus_task_list`, `manus_task_update`, `manus_task_stop`, `manus_task_delete`, `manus_task_send_message`, `manus_task_list_messages`, `manus_task_confirm_action` |
| Projects (2) | `manus_project_create`, `manus_project_list` |
| Skills (1) | `manus_skill_list` |
| Agents (3) | `manus_agent_list`, `manus_agent_detail`, `manus_agent_update` |
| Files (3) | `manus_file_create`, `manus_file_detail`, `manus_file_delete` |
| Webhooks (4) | `manus_webhook_create`, `manus_webhook_list`, `manus_webhook_delete`, `manus_webhook_public_key` |
| Usage (3) | `manus_usage_list`, `manus_usage_team_statistic`, `manus_usage_team_log` |
| Connectors (1) | `manus_connector_list` |
| Browser (1) | `manus_browser_online_list` |
| Website (3) | `manus_website_status`, `manus_website_list_checkpoints`, `manus_website_publish` |
### 3 composite tools
- **`manus_file_upload`** — creates a presigned URL, uploads the bytes, and waits for `status=uploaded`. Accepts `path`, `base64`, or a public `url`.
- **`manus_task_wait`** — polls a task until it reaches a terminal status (`stopped` / `waiting` / `error`) and returns new messages plus wait details (event_id + response schema).
- **`manus_website_publish_and_wait`** — publishes a site and waits until it becomes `published` or `failed`.
### 3 webhook tools (read from the local SQLite DB)
- `manus_webhook_events_list` — list received events with filters.
- `manus_webhook_events_get` — fetch an event by `event_id`.
- `manus_webhook_events_clear` — delete received events.
Total: **36 MCP tools**.
## Installation
```bash
pip install manus-mcp
```
This pulls the package from PyPI. The `manus-mcp` and `manus-mcp-webhook` console scripts become available, plus the `python -m manus_mcp` and `python -m manus_mcp.webhook_receiver` module entry points.
### From source (for contributors)
```bash
git clone https://github.com/aruxojuyu665/Manus-MCP.git
cd Manus-MCP
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS/Linux:
# source .venv/bin/activate
pip install -e ".[dev]"
```
## API key configuration
Place a `.env` file in the project root (a `.env.example` template is provided). Both variable names are accepted:
```env
MANUS_API_KEY=sk-...
# or, for backwards compatibility:
# ManusAPI=sk-...
```
Priority: `process.env` > `.env`.
Optional settings:
```env
MANUS_BASE_URL=https://api.manus.ai
MANUS_HTTP_TIMEOUT=60
MANUS_LOG_LEVEL=INFO
```
## Registering with Claude Code
Add the following to `.claude/settings.json` (project-level) or `~/.claude/settings.json` (global):
```json
{
"mcpServers": {
"manus": {
"command": "python",
"args": ["-m", "manus_mcp"],
"cwd": "path/to/Manus-MCP"
}
}
}
```
If `MANUS_API_KEY` is not set globally, pass it explicitly:
```json
{
"mcpServers": {
"manus": {
"command": "python",
"args": ["-m", "manus_mcp"],
"cwd": "path/to/Manus-MCP",
"env": { "MANUS_API_KEY": "sk-..." }
}
}
}
```
Restart Claude Code — the `manus_*` tools will appear in the tool list.
## Verification
Without launching the server:
```bash
python scripts/list_tools.py
```
Against the real API:
```bash
python scripts/smoke.py
```
Unit tests:
```bash
pytest
```
Lint and types:
```bash
ruff check .
mypy manus_mcp
```
## Usage examples from Claude Code
```
manus_task_create { "message": { "content": "Give me a 5-bullet summary of today's AI news" } }
```
The response contains a `task_id`. Then:
```
manus_task_wait { "task_id": "<id>", "timeout_sec": 600 }
```
When it finishes you get `last_assistant_message` with the final reply and `new_messages` with the conversation history.
Uploading a file and attaching it to a task:
```
manus_file_upload { "source": { "path": "C:/docs/report.pdf" } }
manus_task_create {
"message": {
"content": [
{ "type": "text", "text": "Summarize this report" },
{ "type": "file", "file_id": "<file_id>" }
]
}
}
```
## Webhook receiver (optional)
A local receiver for `task_created` / `task_stopped` events with full RSA-SHA256 signature verification per `ManusAPIDocs/webhooks/security.md`.
### 1. Configure environment variables
```env
MANUS_WEBHOOK_PUBLIC_URL=https://your-tunnel.example.com/manus/webhook
MANUS_WEBHOOK_HOST=127.0.0.1
MANUS_WEBHOOK_PORT=8787
# MANUS_WEBHOOK_DB_PATH=... # defaults to %LOCALAPPDATA%\manus-mcp\events.db on Windows
```
`MANUS_WEBHOOK_PUBLIC_URL` **must exactly match** the URL Manus calls. The Manus signing payload includes this URL, so even a typo will cause every event to be rejected.
### 2. Start a tunnel
For example, with Cloudflare Tunnel:
```bash
cloudflared tunnel --url http://localhost:8787
```
or ngrok:
```bash
ngrok http 8787
```
### 3. Run the receiver
```bash
python -m manus_mcp.webhook_receiver
# or: manus-mcp-webhook --host 127.0.0.1 --port 8787
```
### 4. Register the webhook with Manus
In Claude Code:
```
manus_webhook_create { "url": "https://your-tunnel.example.com/manus/webhook" }
```
### 5. Read events
```
manus_webhook_events_list { "event_type": "task_stopped", "limit": 20 }
manus_webhook_events_get { "event_id": "..." }
manus_webhook_events_clear { "before_received_at": 1704000000 }
```
## Architecture
```
manus_mcp/
├── __main__.py # stdio entrypoint
├── server.py # MCP Server bootstrap
├── config.py # pydantic-settings
├── logger.py # stderr-only logger
├── client/
│ ├── manus_client.py # async httpx client + retry
│ ├── rate_limiter.py # per-endpoint token bucket (from rate-limits.md)
│ ├── retry.py # exponential backoff + jitter
│ └── errors.py # ManusApiError / ManusNetworkError
├── schemas/ # pydantic models for each resource (tasks, projects, ...)
├── tools/ # @manus_tool registration for all 36 tools
│ ├── tasks.py projects.py skills.py agents.py
│ ├── files.py webhooks.py usage.py connectors.py
│ ├── browser.py website.py
│ └── composite.py # task_wait / file_upload / website_publish_and_wait
└── webhook_receiver/
├── signature.py # RSA-SHA256 verification using {ts}.{url}.{sha256_hex(body)}
├── storage.py # SQLite WAL
├── server.py # Starlette + uvicorn
├── tools.py # events_list / events_get / events_clear
└── __main__.py
```
## Rate limits
The client honours the API limits (60-second sliding window) and transparently retries 429 responses with backoff + jitter. Limits come from `ManusAPIDocs/getting-started/rate-limits.md`:
- 10/min: `task.create`, `task.sendMessage`
- 40/min: all mutations
- 100/min: all read-only calls
- 600/min: `usage.*`
## Security
- The API key is never logged.
- The webhook receiver verifies signatures and rejects timestamps older than 5 minutes.
- The public key is cached for 1 hour.
- SQLite is opened in WAL mode with `check_same_thread=False` for safe multi-reader access.
## License
MIT.
TDQS
Scored across 36 tools
Each tool targets a distinct resource and action within well-defined domains (agent, file, task, webhook, website, etc.). There is no overlap in purpose; for example, manus_task_create, manus_task_send_message, and manus_task_stop are clearly different operations.
All tools follow a consistent 'manus_<domain>_<action>' pattern (e.g., manus_agent_list, manus_file_upload, manus_task_wait). Even compound names like manus_task_list_messages adhere to this structure, making tool names predictable and easy to parse.
With 36 tools, the server covers a broad set of features (agents, browsers, connectors, files, projects, skills, tasks, usage, webhooks, websites). While this is on the higher side, each tool is justified by the complexity of the platform and no obvious bloat is present.
The tool surface provides CRUD-like coverage for most domains: task management includes create, read, list, update, delete, stop, wait, confirm; files have create, upload, detail, delete; webhooks have full lifecycle. Minor gaps exist (no file update or project update), but these are acceptable given the domain.