Skip to content

Commit 0454291

Browse files
committed
feat: add Runware MCP CLI tool and comprehensive example scripts for multi-modal generation
1 parent fa907f4 commit 0454291

10 files changed

Lines changed: 496 additions & 277 deletions

File tree

‎.kiro/steering/openclaw_runware.md‎

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,38 @@
22
inclusion: always
33
---
44

5-
# OpenClaw Runware Skill
5+
# OpenClaw Runware skill
66

7-
Multi-modal Runware.ai skill for OpenClaw: image, video, audio, text, and 3D generation through the official `runware-sdk`, plus MCP-style tooling. Python 3.11+.
7+
Multi-modal Runware.ai skill for OpenClaw: image, video, audio, text, and 3D generation through the official `runware-sdk` library and MCP tooling. Requires Python 3.11+.
88

99
## Architecture
1010

11-
- `scripts/generate.py` — main CLI generator. Builds a task payload from `--mode` (`image`/`video`/`audio`/`text`/`3d`), sends it via the async `Runware` client, saves each result to disk.
12-
- `scripts/runware_mcp.py` — MCP-style CLI exposing discrete tools (`run`, `list-models`, `model-pricing`, `model-details`, `account`) mirroring the hosted Runware MCP server's tool set.
13-
- `skill-config.json` — non-secret defaults (`default_size`, `default_format`, `default_output_dir`); `last_output_dir` is auto-updated by `generate.py` after a save.
14-
- `RUNWARE_API_KEY` comes from `.env` (see `.env_sample`) or the environment — never from `skill-config.json`.
15-
- Both scripts open the SDK client per call as an async context manager: `async with Runware(api_key=..., transport="rest") as client:`. Don't hold a client open across multiple requests.
16-
- This is v2: generation always goes through `runware-sdk`'s `Runware` client. Don't reintroduce raw `requests.post` calls to the old REST API or resurrect `generate_image.py`.
11+
- `scripts/generate.py`: Main CLI generator. Builds task payloads from `--mode` (`image`, `video`, `audio`, `text`, `3d`), submits requests via an asynchronous `Runware` client session, and saves outputs to disk.
12+
- `scripts/runware_mcp.py`: MCP CLI exposing discrete tools (`run`, `list-models`, `model-pricing`, `model-details`, `account`) matching the hosted Runware MCP server tool catalog.
13+
- `skill-config.json`: Non-sensitive configuration defaults (`default_size`, `default_format`, `default_output_dir`). The `last_output_dir` property is updated automatically by `generate.py` after writing an output file.
14+
- `RUNWARE_API_KEY`: Sourced from `.env` (see `.env_sample`) or system environment variables. Never stored in `skill-config.json`.
15+
- SDK sessions: Both scripts initialize `Runware` as an asynchronous context manager (`async with Runware(api_key=..., transport="rest") as client:`). Do not share or persist client connections across separate runs.
16+
- Generation engine: Generation routes through `runware-sdk`. Avoid raw REST requests or legacy standalone image scripts.
1717

1818
## Conventions
1919

20-
- Target Python 3.11+; use PEP 604 unions (`str | None`), not `Optional[str]`.
21-
- Import the SDK lazily/defensively (`_import_runware()`), printing a `pip install runware-sdk` hint and `sys.exit(1)` on `ImportError` instead of letting it raise.
22-
- Module-private helpers are prefixed with `_` (`_parse_size`, `_slugify`, `_resolve_outpath`, etc.) and are the pytest-covered unit surface — keep new helpers named and tested the same way.
23-
- CLI parsing uses `argparse`. When a change applies to both entry points, update `generate.py` and `runware_mcp.py` together.
24-
- Modes are driven by lookup tables (`SUPPORTED_MODES`, `MODES_TO_TASKTYPE`, `MODES_TO_EXT`, `_default_model()`). Adding a modality means extending all of them, per `CONTRIBUTING.md`.
25-
- Catch `RunwareError` (has `.code`) before a generic `Exception` fallback; report failures to `stderr` and exit non-zero rather than letting a traceback surface to the CLI user.
26-
- Settings precedence is CLI flag > `skill-config.json` value > hardcoded default — preserve this order when adding new configurable options.
20+
- Python runtime: Python 3.11+. Use PEP 604 union syntax (`str | None`) rather than `Optional[str]`.
21+
- Dependency checks: Import the SDK with `_import_runware()`, logging a `pip install runware-sdk` hint and exiting with code 1 when the package is missing.
22+
- Private helpers: Prefix internal utilities with `_` (`_parse_size`, `_slugify`, `_resolve_outpath`, etc.) and maintain unit test coverage in `tests/`.
23+
- CLI arguments: Use `argparse`. Keep flags and options consistent across `generate.py` and `runware_mcp.py`.
24+
- Modality mapping: Modalities are defined in `SUPPORTED_MODES`, `MODES_TO_TASKTYPE`, `MODES_TO_EXT`, and `_default_model()`. Adding a modality requires updating all mappings and test cases.
25+
- Error handling: Catch `RunwareError` before general `Exception` handlers. Write error details to `sys.stderr` and exit with a non-zero code.
26+
- Configuration precedence: Command-line arguments override `skill-config.json` values, which override module defaults.
2727

28-
## Safety & secrets
28+
## Safety and secrets
2929

30-
- Never log, print, or persist `RUNWARE_API_KEY` or any credential.
31-
- `skill-config.json` is committed — keep it secret-free.
32-
- Keep `_validate_prompt()`'s minor-safety check intact when touching prompt handling; it must hard-block (exit non-zero), not just warn, despite the "WARNING" text in its message.
33-
- Don't remove `.env` from `.gitignore`; use placeholders (e.g. `your_key_here`) in examples and docs, never real keys.
30+
- Do not log, print, or persist API credentials.
31+
- Keep `skill-config.json` free of credentials.
32+
- Retain prompt validation in `_validate_prompt()` to block requests referencing minors.
33+
- Ensure `.env` is ignored by git. Use placeholder strings in example commands.
3434

35-
## Testing & docs
35+
## Testing and documentation
3636

37-
- Unit tests live in `tests/test_generate.py`, one `Test*` class per function under test. Run with `pytest -q`.
38-
- The integration test skips automatically without `RUNWARE_API_KEY` (`skipif`); CI (`.github/workflows/ci.yml`) runs Python 3.11–3.13 with `pytest -q -m "not integration"`.
39-
- `README.md` and `SKILL.md` both carry CLI flag tables and quick-start snippets — update both when CLI behavior changes, and add matching usage examples to `examples/README.md`.
37+
- Unit tests reside in `tests/test_generate.py` and `tests/test_runware_mcp.py`. Run tests using `pytest -q -m "not integration"`.
38+
- Live integration tests require `RUNWARE_API_KEY` and are marked with `integration`.
39+
- Maintain CLI reference tables and quick start examples in both `README.md` and `SKILL.md` when command options change.

‎CONTRIBUTING.md‎

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
# Contributing to runware-mcp
22

3-
Thank you for your interest in improving this skill!
3+
Thank you for helping improve this project.
44

5-
## Getting Started
5+
## Getting started
66

7-
1. Fork the repository and submit a pull request against `main`.
8-
2. Install development dependencies: `pip install -r requirements.txt`
9-
3. Run tests: `pytest -q`
10-
4. For integration tests, set `RUNWARE_API_KEY` in your environment.
7+
1. Fork the repository and open a pull request against `main`.
8+
2. Install development packages: `pip install -r requirements.txt`
9+
3. Run the test suite: `pytest -q -m "not integration"`
10+
4. To run live integration tests, set `RUNWARE_API_KEY` in your environment.
1111

1212
## Guidelines
1313

14-
- **Keep changes focused** — open separate PRs for separate features
15-
- **Include tests** — add unit tests for new behaviors, update existing tests when behavior changes
16-
- **Update docs** — if you add a feature, update `SKILL.md`, `README.md`, and examples as appropriate
17-
- **Use clear commit messages** — reference issue numbers where applicable
18-
- **Minimal dependencies** — avoid adding new packages unless necessary
14+
- Keep pull requests focused on a single change or feature.
15+
- Include unit tests for bug fixes or new functionality.
16+
- Update `SKILL.md`, `README.md`, and `examples/README.md` when changing CLI arguments or default settings.
17+
- Write clear commit messages.
18+
- Keep external dependencies minimal.
1919

20-
## Adding a New Mode
20+
## Adding a new mode
2121

22-
To add a new generation mode (e.g., a new modality):
22+
When adding a new generation modality:
2323

24-
1. Add the mode to `SUPPORTED_MODES`, `MODES_TO_TASKTYPE`, `MODES_TO_EXT`, and `_default_model()` in `scripts/generate.py`
25-
2. Add the corresponding `--mode` choice in `scripts/runware_mcp.py`
26-
3. Update tests accordingly
27-
4. Add example commands to `examples/README.md`
24+
1. Update `SUPPORTED_MODES`, `MODES_TO_TASKTYPE`, `MODES_TO_EXT`, and `_default_model()` in `scripts/generate.py`.
25+
2. Update the `--mode` choices in `scripts/runware_mcp.py`.
26+
3. Add corresponding tests in `tests/test_generate.py` and `tests/test_runware_mcp.py`.
27+
4. Add example commands in `examples/README.md`.
2828

29-
## Reporting Issues
29+
## Reporting issues
3030

31-
Open issues for bugs, feature requests, or documentation corrections. Include steps to reproduce and minimal examples when possible.
31+
Open an issue for bugs, documentation errors, or feature suggestions. Please include steps to reproduce unexpected behavior and sample inputs when possible.

‎README.md‎

Lines changed: 66 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44
[![Repository](https://img.shields.io/badge/Repository-OpenClaw__Runware__API-blue?style=flat&logo=github)](https://github.com/GeekLord/OpenClaw_Runware_API)
55
[![Python](https://img.shields.io/badge/Python-3.11%2B-blue?style=flat&logo=python)](https://www.python.org/)
66

7-
**Multi-modal Runware.ai skill** — image, video, audio, text, and 3D generation via the official `runware-sdk` Python library, plus MCP-style tooling.
7+
OpenClaw skill for media generation with the official Runware Python SDK (`runware-sdk`) and Model Context Protocol (MCP) tooling. Supports image, video, audio, text, and 3D generation.
88

9-
This repository contains an OpenClaw-compatible skill that connects to [Runware.ai's MCP server](https://runware.ai/mcp) and exposes a clean Python CLI for generating media, browsing models, checking pricing, and managing your account.
9+
This repository connects to the [Runware MCP server](https://runware.ai/mcp) and provides a Python CLI to generate media, browse models, check pricing, and check account balances.
1010

11-
## Features
11+
## Capabilities
1212

13-
- **Multi-modal** — Generate images, videos, audio, text, and 3D models
14-
- **Official SDK** — Uses `runware-sdk` (async, typed, JSON-Schema validated)
15-
- **MCP integration** — MCP-style tools (`run`, `list-models`, `model-pricing`, `model-details`, `account`)
16-
- **Hosted MCP server** — Can connect directly to `https://mcp.runware.ai` (OAuth 2.1, no local install needed)
17-
- **Sync + async** — Sync delivery for fast tasks, async polling for long-running ones
18-
- **Safe-by-default** — Lightweight prompt filtering
19-
- **Configurable** — Default model, size, format via `skill-config.json`
20-
- **Tested** — Pytest unit tests + optional integration tests
13+
- Image, video, audio, text, and 3D generation
14+
- Direct integration with `runware-sdk` (async and schema validated)
15+
- MCP tool wrappers for `run`, `list-models`, `model-pricing`, `model-details`, and `account`
16+
- Connection options for hosted MCP (`https://mcp.runware.ai`), local npm package (`@runware/mcp`), or local Python scripts
17+
- Synchronous delivery for fast requests and asynchronous polling for long tasks
18+
- Prompt guard for minor safety
19+
- Configurable defaults in `skill-config.json`
20+
- Unit test suite with pytest
2121

22-
## Quick Start
22+
## Quick start
2323

2424
```bash
2525
# Install dependencies
@@ -34,18 +34,18 @@ python scripts/generate.py --prompt "A serene mountain landscape" --mode image -
3434
# Generate a video
3535
python scripts/generate.py --prompt "Waves crashing on a beach" --mode video --duration 8 --outfile waves.mp4
3636

37-
# Browse models via MCP-style CLI
37+
# Browse models via MCP CLI
3838
python scripts/runware_mcp.py list-models --category image --search "flux"
3939

4040
# Check account balance
4141
python scripts/runware_mcp.py account
4242
```
4343

44-
## MCP Server Connection
44+
## MCP server connection
4545

46-
### 1. Hosted (easiest — no install)
46+
### 1. Hosted server
4747

48-
Any MCP-compatible client can connect to Runware's hosted server:
48+
Any MCP-compatible client can connect directly to Runware's hosted endpoint:
4949

5050
```json
5151
{
@@ -55,9 +55,9 @@ Any MCP-compatible client can connect to Runware's hosted server:
5555
}
5656
```
5757

58-
Authentication is handled via OAuth 2.1 — your API key stays server-side, encrypted in the OAuth session.
58+
Authentication uses OAuth 2.1, keeping the API key inside the session.
5959

60-
### 2. Local (self-hosted)
60+
### 2. Local Node package
6161

6262
```json
6363
{
@@ -71,7 +71,7 @@ Authentication is handled via OAuth 2.1 — your API key stays server-side, encr
7171
}
7272
```
7373

74-
### 3. Python (this skill)
74+
### 3. Local Python script
7575

7676
```json
7777
{
@@ -88,61 +88,68 @@ Authentication is handled via OAuth 2.1 — your API key stays server-side, encr
8888

8989
| File | Purpose |
9090
|------|---------|
91-
| `scripts/generate.py` | Main multi-modal generator |
92-
| `scripts/runware_mcp.py` | MCP-style CLI tool interface |
93-
| `skill-config.json` | Default settings (no secrets) |
94-
| `SKILL.md` | OpenClaw skill metadata & usage |
95-
| `tests/test_generate.py` | Pytest tests |
96-
| `examples/` | Example commands |
91+
| `scripts/generate.py` | CLI generator for all supported modalities |
92+
| `scripts/runware_mcp.py` | MCP CLI tool interface |
93+
| `skill-config.json` | Default settings (non-sensitive) |
94+
| `SKILL.md` | Skill definition and integration docs |
95+
| `tests/test_generate.py` | Unit and integration tests for generation |
96+
| `tests/test_runware_mcp.py` | Unit tests for MCP CLI interface |
97+
| `examples/` | Sample commands for each modality |
9798

9899
## Configuration
99100

100-
`skill-config.json` fields:
101+
Default settings live in `skill-config.json`:
101102

102-
- `default_size` — default image size (e.g. `"1024x1024"`)
103-
- `default_format` — output format (`png`/`jpg`/`webp`/`mp4`/`wav`/`glb`)
104-
- `default_output_dir` — default output directory
105-
- `last_output_dir` — auto-updated by the script
103+
- `default_size`: default image dimensions (e.g. `"1024x1024"`)
104+
- `default_format`: default output format (`png`, `jpg`, `mp4`, `wav`, `glb`)
105+
- `default_output_dir`: default save location
106+
- `last_output_dir`: automatically updated by the script after each save
106107

107-
## CLI Reference
108+
## CLI reference
108109

109110
### `scripts/generate.py`
110111

111112
| Flag | Description |
112113
|------|-------------|
113-
| `--prompt` | Text prompt |
114-
| `--mode` | `image`, `video`, `audio`, `text`, or `3d` |
115-
| `--model` | Runware model ID (e.g. `runware:400@1`) |
114+
| `--prompt` | Text prompt for generation |
115+
| `--mode` | Generation mode: `image`, `video`, `audio`, `text`, or `3d` |
116+
| `--model` | Model ID (e.g. `runware:400@1`) |
116117
| `--size` | Dimensions (e.g. `1024x1024`) |
117-
| `--sync` / `--no-sync` | Sync vs async delivery |
118-
| `--duration` | Video duration (seconds) |
119-
| `--num-results` | Number of outputs |
120-
| `--extra KEY VALUE` | Extra payload parameters |
121-
| `--outfile` | Output filename |
118+
| `--sync` / `--no-sync` | Synchronous delivery vs asynchronous polling |
119+
| `--duration` | Video duration in seconds |
120+
| `--num-results` | Number of outputs to create |
121+
| `--extra KEY VALUE` | Extra payload parameters (repeatable) |
122+
| `--outfile` | Output file path |
122123

123124
### `scripts/runware_mcp.py`
124125

125126
| Command | Description |
126127
|---------|-------------|
127-
| `run --prompt "..."` | Run inference task |
128-
| `list-models` | Browse model catalog |
129-
| `model-pricing --model X` | Get model pricing |
128+
| `run --prompt "..."` | Run an inference task |
129+
| `list-models` | Browse the model catalog |
130+
| `model-pricing --model X` | Check pricing for a model |
130131
| `model-details --model X` | Get model metadata |
131-
| `account` | Show account info & balance |
132+
| `account` | View account details and balance |
132133

133134
## Testing
134135

136+
Run unit tests:
137+
135138
```bash
136-
pytest -q
139+
pytest -q -m "not integration"
137140
```
138141

139-
Integration tests require `RUNWARE_API_KEY` set in the environment.
142+
To run the live integration test, set `RUNWARE_API_KEY` in your environment:
143+
144+
```bash
145+
pytest -q
146+
```
140147

141148
## Safety
142149

143-
- Prompt filter blocks requests referencing minors
144-
- Users must follow [Runware's terms of service](https://runware.ai/terms)
145-
- API key stays client-side or in OAuth session — never committed
150+
- Prompts referencing minors are blocked locally before sending requests.
151+
- Requests must follow [Runware terms of service](https://runware.ai/terms).
152+
- API keys stay in local `.env` files or OAuth sessions and are never committed to version control.
146153

147154
## Architecture
148155

@@ -152,39 +159,39 @@ graph TD
152159
User -->|Tool call| MCP[scripts/runware_mcp.py]
153160
Gen -->|async with Runware| SDK[runware-sdk]
154161
MCP -->|async with Runware| SDK
155-
SDK -->|"run()"| API[Runware.ai API]
162+
SDK -->|run| API[Runware.ai API]
156163
API -->|Results| SDK
157164
SDK -->|Decoded output| Gen
158165
SDK -->|Decoded output| MCP
159166
Gen -->|Save| Output[Local file]
160167
MCP -->|Print| Output2[JSON stdout]
161168
162169
MCP_Client[MCP Client e.g. Claude Desktop]
163-
MCP_Client -->|stdio / HTTP| MCP_Server["npx @runware/mcp"]
170+
MCP_Client -->|stdio / HTTP| MCP_Server[npx @runware/mcp]
164171
MCP_Server --> API
165172
```
166173

167174
## Migration from v1.x
168175

169-
| Old | New |
170-
|-----|-----|
176+
| Version 1.x | Version 2.0 |
177+
|-------------|-------------|
171178
| `scripts/generate_image.py` | `scripts/generate.py` |
172-
| `requests.post` to `/v1/tasks` | `runware-sdk` `client.run()` |
173-
| Manual UUIDs & response parsing | SDK handles schema, validation, delivery |
174-
| Image-only | Image + video + audio + text + 3D |
179+
| Direct HTTP calls to `/v1/tasks` | `runware-sdk` via `client.run()` |
180+
| Manual request IDs and payload formatting | SDK schema validation and delivery handling |
181+
| Image only | Image, video, audio, text, and 3D |
175182
| Python 3.8+ | Python 3.11+ |
176183

177184
## Author
178185

179-
**Shobhit Kumar Prabhakar** — [@GeekLord](https://github.com/GeekLord/)
186+
**Shobhit Kumar Prabhakar** ([@GeekLord](https://github.com/GeekLord/))
180187

181188
## License
182189

183-
MIT — see LICENSE.
190+
MIT (see LICENSE)
184191

185192
## Links
186193

187194
- [Runware MCP Server](https://runware.ai/mcp)
188-
- [Runware MCP Docs](https://runware.ai/docs/platform/mcp)
195+
- [Runware MCP Documentation](https://runware.ai/docs/platform/mcp)
189196
- [Runware Python SDK](https://runware.ai/docs/platform/python)
190-
- [Official @runware/mcp GitHub](https://github.com/runware/mcp)
197+
- [Official @runware/mcp GitHub repository](https://github.com/runware/mcp)

0 commit comments

Comments
 (0)