nova3d-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nova3d_mcp-0.1.0/.claude/settings.local.json +9 -0
- nova3d_mcp-0.1.0/.env.example +8 -0
- nova3d_mcp-0.1.0/.gitignore +11 -0
- nova3d_mcp-0.1.0/CLAUDE.md +62 -0
- nova3d_mcp-0.1.0/PKG-INFO +300 -0
- nova3d_mcp-0.1.0/README.md +270 -0
- nova3d_mcp-0.1.0/docs/superpowers/plans/2026-05-28-api-key-integration.md +761 -0
- nova3d_mcp-0.1.0/docs/superpowers/plans/2026-05-29-pre-launch-readiness.md +384 -0
- nova3d_mcp-0.1.0/docs/superpowers/specs/2026-05-28-api-key-integration-design.md +174 -0
- nova3d_mcp-0.1.0/docs/superpowers/specs/2026-05-29-pre-launch-readiness.md +180 -0
- nova3d_mcp-0.1.0/nova3d_mcp/__init__.py +0 -0
- nova3d_mcp-0.1.0/nova3d_mcp/__main__.py +3 -0
- nova3d_mcp-0.1.0/nova3d_mcp/client.py +460 -0
- nova3d_mcp-0.1.0/nova3d_mcp/models.py +416 -0
- nova3d_mcp-0.1.0/nova3d_mcp/server.py +437 -0
- nova3d_mcp-0.1.0/pyproject.toml +65 -0
- nova3d_mcp-0.1.0/server.json +27 -0
- nova3d_mcp-0.1.0/tests/test_client.py +411 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Nova3D MCP Server — environment variables
|
|
2
|
+
# Copy to .env and fill in your values
|
|
3
|
+
|
|
4
|
+
# Required: API key from nova3d.xyz → Settings → API Keys
|
|
5
|
+
NOVA3D_TOKEN=n3d_your-api-key-here
|
|
6
|
+
|
|
7
|
+
# Optional: override the API base URL (advanced / self-hosted only)
|
|
8
|
+
# NOVA3D_API_URL=https://nova3d.xyz/api
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
An MCP server that wraps Nova3D's hosted 3D generation API as callable tools for Claude Code and other MCP-compatible agents. Users bring their own LLM provider key (Google, Anthropic, or OpenAI) and a Nova3D JWT token.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# First-time setup — create venv and install dev dependencies
|
|
13
|
+
python3.10 -m venv .venv
|
|
14
|
+
source .venv/bin/activate
|
|
15
|
+
pip install -e ".[dev]"
|
|
16
|
+
|
|
17
|
+
# Run tests (venv must be active)
|
|
18
|
+
pytest
|
|
19
|
+
|
|
20
|
+
# Run a single test
|
|
21
|
+
pytest tests/test_client.py::test_generate_success
|
|
22
|
+
|
|
23
|
+
# Run the server locally
|
|
24
|
+
python -m nova3d_mcp.server
|
|
25
|
+
# or after install:
|
|
26
|
+
nova3d-mcp
|
|
27
|
+
|
|
28
|
+
# Lint
|
|
29
|
+
ruff check .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Package layout note
|
|
33
|
+
|
|
34
|
+
The source directory on disk is `nova3d_mcp/` (underscore), matching the Python import name. Always activate `.venv` before running tests.
|
|
35
|
+
|
|
36
|
+
## Architecture
|
|
37
|
+
|
|
38
|
+
**Three-file package:**
|
|
39
|
+
|
|
40
|
+
- `nova3d_mcp/server.py` — FastMCP server. Registers 5 tools (`generate_3d`, `regenerate_part`, `add_part`, `articulate_model`, `get_generation_status`). Each tool creates a `Nova3DClient` context manager, calls the matching method, and maps the result to a flat dict. Auth (`NOVA3D_TOKEN`) and base URL (`NOVA3D_API_URL`) are read from env inside each tool call.
|
|
41
|
+
|
|
42
|
+
- `nova3d_mcp/client.py` — Async HTTP client wrapping `httpx.AsyncClient`. Workflow pattern: readiness check → POST `/run/state/{workflow}` → poll `/status/{id}` every 3 s until terminal → GET `/result/{id}`. Transient 404/502/503/504 errors during polling are retried via `_is_recoverable()`. Auth and budget errors are never retried. Workflow IDs are microsecond timestamps (`state-{epoch_us}`).
|
|
43
|
+
|
|
44
|
+
- `nova3d_mcp/models.py` — Pydantic models. `GenerationResult.from_api()` contains all response-parsing logic — the Nova3D API response structure is nested and has multiple fallback key paths (e.g. `model_url` vs `model_artifact.url`). `WorkflowState.parse()` normalizes state strings (`"succeeded"` → `COMPLETED`, etc.) and `is_terminal` drives the polling loop.
|
|
45
|
+
|
|
46
|
+
**Data flow for a generation:**
|
|
47
|
+
```
|
|
48
|
+
tool call → _get_token() + _get_api_url()
|
|
49
|
+
→ Nova3DClient.__aenter__()
|
|
50
|
+
→ client.generate() → check_readiness() → _start_workflow() → _poll_and_collect()
|
|
51
|
+
→ GenerationResult.from_api(raw_dict, workflow_id)
|
|
52
|
+
→ tool returns flat dict to MCP caller
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Test setup:** `tests/test_client.py` uses `respx` to mock `httpx` at the transport level. `asyncio.sleep` is monkey-patched to `sleep(0)` inside tests to avoid real delays. The `mock_api` fixture scopes the mock to the test function with `assert_all_called=False`.
|
|
56
|
+
|
|
57
|
+
## Environment variables
|
|
58
|
+
|
|
59
|
+
| Variable | Required | Default |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `NOVA3D_TOKEN` | Yes | — |
|
|
62
|
+
| `NOVA3D_API_URL` | No | `https://nova3d.xyz/api` |
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nova3d-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Nova3D MCP server — structured, part-aware 3D generation for AI agents
|
|
5
|
+
Project-URL: Homepage, https://nova3d.xyz
|
|
6
|
+
Project-URL: Repository, https://github.com/RareSense/nova3d-mcp
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/RareSense/nova3d-mcp/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/RareSense/nova3d-mcp#readme
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: 3d-assets,3d-generation,ai,blender,generative-ai,mcp,model-context-protocol,nova3d
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: httpx>=0.27.0
|
|
22
|
+
Requires-Dist: mcp[cli]>=1.27.0
|
|
23
|
+
Requires-Dist: pydantic>=2.0.0
|
|
24
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: respx>=0.21.0; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# nova3d-mcp
|
|
32
|
+
|
|
33
|
+
**Structured, part-aware 3D generation for AI agents.**
|
|
34
|
+
|
|
35
|
+
nova3d-mcp is an [MCP](https://modelcontextprotocol.io) server that exposes
|
|
36
|
+
[Nova3D](https://nova3d.xyz)'s generation pipeline as a callable tool inside
|
|
37
|
+
Claude Code, Cursor, and any MCP-compatible agent.
|
|
38
|
+
|
|
39
|
+
One tool call. A washing machine comes back with named drum, door, control
|
|
40
|
+
panel, and hose connectors — separately editable, not fused into a blob.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Why Nova3D
|
|
45
|
+
|
|
46
|
+
Every major AI 3D generator today produces **mesh blobs** — a single fused
|
|
47
|
+
object that looks plausible in a render and collapses the moment you try to
|
|
48
|
+
edit, rig, or pipeline it.
|
|
49
|
+
|
|
50
|
+
Nova3D is different. Instead of diffusion → mesh, it runs:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
prompt / image
|
|
54
|
+
↓
|
|
55
|
+
LLM writes Blender Python construction code
|
|
56
|
+
↓
|
|
57
|
+
headless Blender executes + validates + repairs
|
|
58
|
+
↓
|
|
59
|
+
structured GLB — named parts, intact hierarchy, real joints
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The result is a 3D asset that **survives contact with real workflows**: game
|
|
63
|
+
engines, configurators, robotics simulations, AR scenes. Parts have names.
|
|
64
|
+
Hierarchy is intact. Joints are real. You can change one component without
|
|
65
|
+
regenerating everything.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quickstart
|
|
70
|
+
|
|
71
|
+
### 1. Install
|
|
72
|
+
|
|
73
|
+
**Once on PyPI (coming soon):**
|
|
74
|
+
```bash
|
|
75
|
+
uvx nova3d-mcp
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**From source (available now):**
|
|
79
|
+
```bash
|
|
80
|
+
git clone https://github.com/RareSense/nova3d-mcp.git
|
|
81
|
+
cd nova3d-mcp
|
|
82
|
+
python3.10 -m venv .venv && source .venv/bin/activate
|
|
83
|
+
pip install .
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Get an API key
|
|
87
|
+
|
|
88
|
+
Sign in at [nova3d.xyz](https://nova3d.xyz), go to **Settings → API Keys**, and create a key.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
export NOVA3D_TOKEN="n3d_your-api-key-here"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
API keys never expire unless revoked. The MCP server validates your key on startup
|
|
95
|
+
and prints a clear error if it's missing or invalid.
|
|
96
|
+
|
|
97
|
+
### 3. Add to Claude Code
|
|
98
|
+
|
|
99
|
+
**Once on PyPI:**
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"mcpServers": {
|
|
103
|
+
"nova3d": {
|
|
104
|
+
"command": "uvx",
|
|
105
|
+
"args": ["nova3d-mcp"],
|
|
106
|
+
"env": {
|
|
107
|
+
"NOVA3D_TOKEN": "n3d_your-api-key-here"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**From source (after `pip install .`):**
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"nova3d": {
|
|
119
|
+
"command": "nova3d-mcp",
|
|
120
|
+
"env": {
|
|
121
|
+
"NOVA3D_TOKEN": "n3d_your-api-key-here"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 4. Generate
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Generate a vending machine with separate door, glass panel, coin slot,
|
|
132
|
+
button grid, frame, and interior shelving. Use Google Gemini with my
|
|
133
|
+
API key AIza...
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The agent calls `generate_3d`. You get back:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"glb_url": "https://nova3d.xyz/assets/abc123.glb",
|
|
141
|
+
"preview_url": "https://nova3d.xyz/preview/state-...",
|
|
142
|
+
"parts": ["door", "glass_panel", "coin_slot", "button_grid", "frame", "shelf_1", "shelf_2"],
|
|
143
|
+
"joint_count": 1,
|
|
144
|
+
"code_artifact": { ... },
|
|
145
|
+
"workflow_id": "state-..."
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Open `preview_url` in your browser — interactive Three.js viewer, named parts,
|
|
150
|
+
orbit controls, part explosion. No Blender required to preview.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Tools
|
|
155
|
+
|
|
156
|
+
### `generate_3d`
|
|
157
|
+
|
|
158
|
+
Generate a structured 3D asset from text (and optional reference image).
|
|
159
|
+
|
|
160
|
+
| Parameter | Type | Required | Description |
|
|
161
|
+
|---|---|---|---|
|
|
162
|
+
| `prompt` | string | ✓ | Asset description. Be specific about parts. |
|
|
163
|
+
| `provider` | string | ✓ | `"google"` · `"anthropic"` · `"openai"` |
|
|
164
|
+
| `api_key` | string | ✓ | Your BYOK key for the provider |
|
|
165
|
+
| `llm` | string | | Model ID. Defaults to recommended per provider. |
|
|
166
|
+
| `image_base64` | string | | Reference image as plain base64 |
|
|
167
|
+
| `image_mime` | string | | e.g. `"image/jpeg"` |
|
|
168
|
+
|
|
169
|
+
**Recommended provider:** `google` with `gemini-2.0-flash` — best spatial
|
|
170
|
+
reasoning for complex multi-part objects.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### `regenerate_part`
|
|
175
|
+
|
|
176
|
+
Regenerate one named part without rebuilding the whole asset.
|
|
177
|
+
|
|
178
|
+
| Parameter | Type | Required | Description |
|
|
179
|
+
|---|---|---|---|
|
|
180
|
+
| `code_artifact` | object | ✓ | From prior `generate_3d` result |
|
|
181
|
+
| `part_type` | string | ✓ | Part name e.g. `"door"`, `"handle"` |
|
|
182
|
+
| `description` | string | ✓ | What the new part should look like |
|
|
183
|
+
| `provider` | string | ✓ | LLM provider |
|
|
184
|
+
| `api_key` | string | ✓ | BYOK key |
|
|
185
|
+
| `llm` | string | | Model ID |
|
|
186
|
+
|
|
187
|
+
**Finding part names:** Open the `preview_url` from your generation — each
|
|
188
|
+
mesh is labeled. Use that exact name as `part_type`.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### `add_part`
|
|
193
|
+
|
|
194
|
+
Add a new component to an existing asset.
|
|
195
|
+
|
|
196
|
+
| Parameter | Type | Required | Description |
|
|
197
|
+
|---|---|---|---|
|
|
198
|
+
| `code_artifact` | object | ✓ | From prior generation result |
|
|
199
|
+
| `description` | string | ✓ | Description of the new part and where it goes |
|
|
200
|
+
| `provider` | string | ✓ | LLM provider |
|
|
201
|
+
| `api_key` | string | ✓ | BYOK key |
|
|
202
|
+
| `llm` | string | | Model ID |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### `articulate_model`
|
|
207
|
+
|
|
208
|
+
Add joints, hinges, or rotational articulation to an existing asset.
|
|
209
|
+
|
|
210
|
+
| Parameter | Type | Required | Description |
|
|
211
|
+
|---|---|---|---|
|
|
212
|
+
| `code_artifact` | object | ✓ | From prior generation result |
|
|
213
|
+
| `model_url` | string | ✓ | `glb_url` from prior generation |
|
|
214
|
+
| `articulation_request` | string | ✓ | What should move and how |
|
|
215
|
+
| `provider` | string | ✓ | LLM provider |
|
|
216
|
+
| `api_key` | string | ✓ | BYOK key |
|
|
217
|
+
| `llm` | string | | Model ID |
|
|
218
|
+
| `selected_meshes` | list | | Specific mesh names to articulate |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### `get_generation_status`
|
|
223
|
+
|
|
224
|
+
Check the status of a running workflow by ID.
|
|
225
|
+
|
|
226
|
+
| Parameter | Type | Required | Description |
|
|
227
|
+
|---|---|---|---|
|
|
228
|
+
| `workflow_id` | string | ✓ | From any prior generation tool |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Typical workflow
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
1. generate_3d("robot dog with four legs, head, torso, and tail")
|
|
236
|
+
→ glb_url, preview_url, parts, code_artifact
|
|
237
|
+
|
|
238
|
+
2. Open preview_url in browser
|
|
239
|
+
→ see named parts, identify what needs changing
|
|
240
|
+
|
|
241
|
+
3. regenerate_part(code_artifact, part_type="head", description="...")
|
|
242
|
+
→ updated glb_url, new preview_url
|
|
243
|
+
|
|
244
|
+
4. articulate_model(code_artifact, model_url, "make legs rotate at hip joints")
|
|
245
|
+
→ glb_url with working joints
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Provider reference
|
|
251
|
+
|
|
252
|
+
| Provider | `provider` | Default `llm` | Notes |
|
|
253
|
+
|---|---|---|---|
|
|
254
|
+
| Google Gemini | `google` | `gemini-2.0-flash` | Recommended |
|
|
255
|
+
| Anthropic | `anthropic` | `claude-sonnet-4-20250514` | Strong reasoning |
|
|
256
|
+
| OpenAI | `openai` | `gpt-4o` | Widely available |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Environment variables
|
|
261
|
+
|
|
262
|
+
| Variable | Required | Description |
|
|
263
|
+
|---|---|---|
|
|
264
|
+
| `NOVA3D_TOKEN` | ✓ | API key from nova3d.xyz → Settings → API Keys (recommended) or session JWT |
|
|
265
|
+
| `NOVA3D_API_URL` | | Override API base URL (default: `https://nova3d.xyz/api`) |
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## How it differs from blender-mcp
|
|
270
|
+
|
|
271
|
+
[blender-mcp](https://github.com/ahujasid/blender-mcp) (21.9k ★) gives AI
|
|
272
|
+
agents a remote control for a **locally running Blender instance**. It requires
|
|
273
|
+
Blender installed, produces unstructured output, and inherits all the bpy
|
|
274
|
+
hallucination problems of raw LLM → Blender code generation.
|
|
275
|
+
|
|
276
|
+
nova3d-mcp is different in kind:
|
|
277
|
+
|
|
278
|
+
| | blender-mcp | nova3d-mcp |
|
|
279
|
+
|---|---|---|
|
|
280
|
+
| Blender required | Yes | No |
|
|
281
|
+
| Output | Unstructured scene | Named, hierarchical GLB |
|
|
282
|
+
| Validation | None | Server-side repair loop |
|
|
283
|
+
| Part awareness | No | Yes — named, addressable |
|
|
284
|
+
| Joints | Manual scripting | First-class output |
|
|
285
|
+
| Hosted backend | No | Yes |
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Contributing
|
|
290
|
+
|
|
291
|
+
Issues, PRs, and workflow feedback welcome.
|
|
292
|
+
[github.com/RareSense/nova3d-mcp](https://github.com/RareSense/nova3d-mcp)
|
|
293
|
+
|
|
294
|
+
Community Discord: [discord.gg/QEH8mzcwdR](https://discord.gg/QEH8mzcwdR)
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## License
|
|
299
|
+
|
|
300
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# nova3d-mcp
|
|
2
|
+
|
|
3
|
+
**Structured, part-aware 3D generation for AI agents.**
|
|
4
|
+
|
|
5
|
+
nova3d-mcp is an [MCP](https://modelcontextprotocol.io) server that exposes
|
|
6
|
+
[Nova3D](https://nova3d.xyz)'s generation pipeline as a callable tool inside
|
|
7
|
+
Claude Code, Cursor, and any MCP-compatible agent.
|
|
8
|
+
|
|
9
|
+
One tool call. A washing machine comes back with named drum, door, control
|
|
10
|
+
panel, and hose connectors — separately editable, not fused into a blob.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Why Nova3D
|
|
15
|
+
|
|
16
|
+
Every major AI 3D generator today produces **mesh blobs** — a single fused
|
|
17
|
+
object that looks plausible in a render and collapses the moment you try to
|
|
18
|
+
edit, rig, or pipeline it.
|
|
19
|
+
|
|
20
|
+
Nova3D is different. Instead of diffusion → mesh, it runs:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
prompt / image
|
|
24
|
+
↓
|
|
25
|
+
LLM writes Blender Python construction code
|
|
26
|
+
↓
|
|
27
|
+
headless Blender executes + validates + repairs
|
|
28
|
+
↓
|
|
29
|
+
structured GLB — named parts, intact hierarchy, real joints
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The result is a 3D asset that **survives contact with real workflows**: game
|
|
33
|
+
engines, configurators, robotics simulations, AR scenes. Parts have names.
|
|
34
|
+
Hierarchy is intact. Joints are real. You can change one component without
|
|
35
|
+
regenerating everything.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quickstart
|
|
40
|
+
|
|
41
|
+
### 1. Install
|
|
42
|
+
|
|
43
|
+
**Once on PyPI (coming soon):**
|
|
44
|
+
```bash
|
|
45
|
+
uvx nova3d-mcp
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**From source (available now):**
|
|
49
|
+
```bash
|
|
50
|
+
git clone https://github.com/RareSense/nova3d-mcp.git
|
|
51
|
+
cd nova3d-mcp
|
|
52
|
+
python3.10 -m venv .venv && source .venv/bin/activate
|
|
53
|
+
pip install .
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Get an API key
|
|
57
|
+
|
|
58
|
+
Sign in at [nova3d.xyz](https://nova3d.xyz), go to **Settings → API Keys**, and create a key.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
export NOVA3D_TOKEN="n3d_your-api-key-here"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
API keys never expire unless revoked. The MCP server validates your key on startup
|
|
65
|
+
and prints a clear error if it's missing or invalid.
|
|
66
|
+
|
|
67
|
+
### 3. Add to Claude Code
|
|
68
|
+
|
|
69
|
+
**Once on PyPI:**
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"nova3d": {
|
|
74
|
+
"command": "uvx",
|
|
75
|
+
"args": ["nova3d-mcp"],
|
|
76
|
+
"env": {
|
|
77
|
+
"NOVA3D_TOKEN": "n3d_your-api-key-here"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**From source (after `pip install .`):**
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"nova3d": {
|
|
89
|
+
"command": "nova3d-mcp",
|
|
90
|
+
"env": {
|
|
91
|
+
"NOVA3D_TOKEN": "n3d_your-api-key-here"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 4. Generate
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Generate a vending machine with separate door, glass panel, coin slot,
|
|
102
|
+
button grid, frame, and interior shelving. Use Google Gemini with my
|
|
103
|
+
API key AIza...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The agent calls `generate_3d`. You get back:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"glb_url": "https://nova3d.xyz/assets/abc123.glb",
|
|
111
|
+
"preview_url": "https://nova3d.xyz/preview/state-...",
|
|
112
|
+
"parts": ["door", "glass_panel", "coin_slot", "button_grid", "frame", "shelf_1", "shelf_2"],
|
|
113
|
+
"joint_count": 1,
|
|
114
|
+
"code_artifact": { ... },
|
|
115
|
+
"workflow_id": "state-..."
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Open `preview_url` in your browser — interactive Three.js viewer, named parts,
|
|
120
|
+
orbit controls, part explosion. No Blender required to preview.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Tools
|
|
125
|
+
|
|
126
|
+
### `generate_3d`
|
|
127
|
+
|
|
128
|
+
Generate a structured 3D asset from text (and optional reference image).
|
|
129
|
+
|
|
130
|
+
| Parameter | Type | Required | Description |
|
|
131
|
+
|---|---|---|---|
|
|
132
|
+
| `prompt` | string | ✓ | Asset description. Be specific about parts. |
|
|
133
|
+
| `provider` | string | ✓ | `"google"` · `"anthropic"` · `"openai"` |
|
|
134
|
+
| `api_key` | string | ✓ | Your BYOK key for the provider |
|
|
135
|
+
| `llm` | string | | Model ID. Defaults to recommended per provider. |
|
|
136
|
+
| `image_base64` | string | | Reference image as plain base64 |
|
|
137
|
+
| `image_mime` | string | | e.g. `"image/jpeg"` |
|
|
138
|
+
|
|
139
|
+
**Recommended provider:** `google` with `gemini-2.0-flash` — best spatial
|
|
140
|
+
reasoning for complex multi-part objects.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### `regenerate_part`
|
|
145
|
+
|
|
146
|
+
Regenerate one named part without rebuilding the whole asset.
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Required | Description |
|
|
149
|
+
|---|---|---|---|
|
|
150
|
+
| `code_artifact` | object | ✓ | From prior `generate_3d` result |
|
|
151
|
+
| `part_type` | string | ✓ | Part name e.g. `"door"`, `"handle"` |
|
|
152
|
+
| `description` | string | ✓ | What the new part should look like |
|
|
153
|
+
| `provider` | string | ✓ | LLM provider |
|
|
154
|
+
| `api_key` | string | ✓ | BYOK key |
|
|
155
|
+
| `llm` | string | | Model ID |
|
|
156
|
+
|
|
157
|
+
**Finding part names:** Open the `preview_url` from your generation — each
|
|
158
|
+
mesh is labeled. Use that exact name as `part_type`.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### `add_part`
|
|
163
|
+
|
|
164
|
+
Add a new component to an existing asset.
|
|
165
|
+
|
|
166
|
+
| Parameter | Type | Required | Description |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| `code_artifact` | object | ✓ | From prior generation result |
|
|
169
|
+
| `description` | string | ✓ | Description of the new part and where it goes |
|
|
170
|
+
| `provider` | string | ✓ | LLM provider |
|
|
171
|
+
| `api_key` | string | ✓ | BYOK key |
|
|
172
|
+
| `llm` | string | | Model ID |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### `articulate_model`
|
|
177
|
+
|
|
178
|
+
Add joints, hinges, or rotational articulation to an existing asset.
|
|
179
|
+
|
|
180
|
+
| Parameter | Type | Required | Description |
|
|
181
|
+
|---|---|---|---|
|
|
182
|
+
| `code_artifact` | object | ✓ | From prior generation result |
|
|
183
|
+
| `model_url` | string | ✓ | `glb_url` from prior generation |
|
|
184
|
+
| `articulation_request` | string | ✓ | What should move and how |
|
|
185
|
+
| `provider` | string | ✓ | LLM provider |
|
|
186
|
+
| `api_key` | string | ✓ | BYOK key |
|
|
187
|
+
| `llm` | string | | Model ID |
|
|
188
|
+
| `selected_meshes` | list | | Specific mesh names to articulate |
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### `get_generation_status`
|
|
193
|
+
|
|
194
|
+
Check the status of a running workflow by ID.
|
|
195
|
+
|
|
196
|
+
| Parameter | Type | Required | Description |
|
|
197
|
+
|---|---|---|---|
|
|
198
|
+
| `workflow_id` | string | ✓ | From any prior generation tool |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Typical workflow
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
1. generate_3d("robot dog with four legs, head, torso, and tail")
|
|
206
|
+
→ glb_url, preview_url, parts, code_artifact
|
|
207
|
+
|
|
208
|
+
2. Open preview_url in browser
|
|
209
|
+
→ see named parts, identify what needs changing
|
|
210
|
+
|
|
211
|
+
3. regenerate_part(code_artifact, part_type="head", description="...")
|
|
212
|
+
→ updated glb_url, new preview_url
|
|
213
|
+
|
|
214
|
+
4. articulate_model(code_artifact, model_url, "make legs rotate at hip joints")
|
|
215
|
+
→ glb_url with working joints
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Provider reference
|
|
221
|
+
|
|
222
|
+
| Provider | `provider` | Default `llm` | Notes |
|
|
223
|
+
|---|---|---|---|
|
|
224
|
+
| Google Gemini | `google` | `gemini-2.0-flash` | Recommended |
|
|
225
|
+
| Anthropic | `anthropic` | `claude-sonnet-4-20250514` | Strong reasoning |
|
|
226
|
+
| OpenAI | `openai` | `gpt-4o` | Widely available |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Environment variables
|
|
231
|
+
|
|
232
|
+
| Variable | Required | Description |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| `NOVA3D_TOKEN` | ✓ | API key from nova3d.xyz → Settings → API Keys (recommended) or session JWT |
|
|
235
|
+
| `NOVA3D_API_URL` | | Override API base URL (default: `https://nova3d.xyz/api`) |
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## How it differs from blender-mcp
|
|
240
|
+
|
|
241
|
+
[blender-mcp](https://github.com/ahujasid/blender-mcp) (21.9k ★) gives AI
|
|
242
|
+
agents a remote control for a **locally running Blender instance**. It requires
|
|
243
|
+
Blender installed, produces unstructured output, and inherits all the bpy
|
|
244
|
+
hallucination problems of raw LLM → Blender code generation.
|
|
245
|
+
|
|
246
|
+
nova3d-mcp is different in kind:
|
|
247
|
+
|
|
248
|
+
| | blender-mcp | nova3d-mcp |
|
|
249
|
+
|---|---|---|
|
|
250
|
+
| Blender required | Yes | No |
|
|
251
|
+
| Output | Unstructured scene | Named, hierarchical GLB |
|
|
252
|
+
| Validation | None | Server-side repair loop |
|
|
253
|
+
| Part awareness | No | Yes — named, addressable |
|
|
254
|
+
| Joints | Manual scripting | First-class output |
|
|
255
|
+
| Hosted backend | No | Yes |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Contributing
|
|
260
|
+
|
|
261
|
+
Issues, PRs, and workflow feedback welcome.
|
|
262
|
+
[github.com/RareSense/nova3d-mcp](https://github.com/RareSense/nova3d-mcp)
|
|
263
|
+
|
|
264
|
+
Community Discord: [discord.gg/QEH8mzcwdR](https://discord.gg/QEH8mzcwdR)
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT — see [LICENSE](LICENSE)
|