Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
| [`@jbcom/agentic-meshy`](packages/meshy-content-generator) | TypeScript | Declarative Meshy 3D asset generation pipelines | [Docs](https://agentic.coach/packages/meshy-content-generator/) |
| [`@jbcom/agentic-providers`](packages/providers) | TypeScript | LLM provider implementations (Ollama, Jules, Cursor) | [Docs](https://agentic.coach/packages/control/) |
| [`game-generator`](packages/game-generator) | Rust | Visual-first vintage game generator with AI assistance | [Docs](https://agentic.coach/packages/game-generator/) |
| [`game-asset-mcp`](packages/game-asset-mcp) | Python | MCP server for local 3D game asset libraries — search, browse, PolyHaven integration | [README](packages/game-asset-mcp/README.md) |

### Testing Plugins

Expand Down Expand Up @@ -123,7 +124,8 @@ agentic/
│ ├── providers/ # @jbcom/agentic-providers (TypeScript)
│ ├── game-generator/ # game-generator (Rust)
│ ├── vitest-agentic-control/ # @jbcom/vitest-agentic (TypeScript)
│ └── pytest-agentic-crew/ # pytest-agentic-crew (Python)
│ ├── pytest-agentic-crew/ # pytest-agentic-crew (Python)
│ └── game-asset-mcp/ # game-asset-mcp (Python)
├── actions/ # GitHub Marketplace actions
├── docs/ # Documentation site (Astro + Starlight)
└── scripts/ # Ecosystem automation
Expand Down
16 changes: 16 additions & 0 deletions packages/game-asset-mcp/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Changelog

## [0.1.0] - 2026-03-07

### Added
- Initial release
- SQLite catalog with FTS5 full-text search
- Idempotent ingest (O(1) skip check, stale removal)
- `browse_taxonomy` tool for macro/meso/micro/pack hierarchy navigation
- `search_assets` hybrid keyword + FTS search
- `copy_asset`, `get_preview`, `generate_preview` tools
- PolyHaven CC0 integration (`search_polyhaven`, `download_polyhaven_asset`)
- Pydantic-settings configuration with TOML file support
- Interactive setup wizard (`game-asset-init`)
- Optional `bpy` extra for in-process Blender rendering
- Pure-Python GLB stats reader (no Blender required for ingest)
188 changes: 188 additions & 0 deletions packages/game-asset-mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# game-asset-mcp

**MCP server for local 3D game asset libraries** — search, browse, catalog, and download GLB/GLTF assets from your file system and PolyHaven.

Built with [FastMCP](https://github.com/jlowin/fastmcp) · Works with Claude Code, Cursor, Windsurf, and any MCP-compatible client · CC0 PolyHaven integration included

---

## Quick Start

### Install

```bash
pip install "game-asset-mcp[server,polyhaven]"
```

### Configure

Set your asset library root:

```bash
export ASSETS_ROOT=/path/to/your/3d-assets
export CATALOG_DB=~/.local/share/game-asset-mcp/catalog.db # optional, this is the default
```

### Ingest your library

```bash
game-asset-ingest
```

This scans all `.glb` files in `ASSETS_ROOT`, extracts mesh stats (vertices, faces, materials, animations), and builds a searchable SQLite catalog. **Idempotent** — only re-processes files that have changed size.

---

## Add to Claude Code

```bash
claude mcp add game-asset-library \
-e ASSETS_ROOT=/path/to/your/3d-assets \
-- game-asset-mcp
```

Or add to `~/.claude.json` manually:

```json
{
"mcpServers": {
"game-asset-library": {
"type": "stdio",
"command": "game-asset-mcp",
"env": {
"ASSETS_ROOT": "/path/to/your/3d-assets"
}
}
}
}
```

## Add to Cursor

Add to `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):

```json
{
"mcpServers": {
"game-asset-library": {
"command": "game-asset-mcp",
"env": {
"ASSETS_ROOT": "/path/to/your/3d-assets"
}
}
}
}
```

## Add to Windsurf

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
"mcpServers": {
"game-asset-library": {
"command": "game-asset-mcp",
"env": {
"ASSETS_ROOT": "/path/to/your/3d-assets"
}
}
}
}
```

---

## Available Tools

| Tool | Description |
|------|-------------|
| `search_assets` | Hybrid keyword + FTS search across all GLBs |
| `browse_taxonomy` | Navigate your directory taxonomy (macro → meso → micro → pack) |
| `list_categories` | List all categories with GLB counts |
| `get_asset_info` | Full metadata for one asset (mesh stats, preview path, etc.) |
| `copy_asset` | Copy a GLB into your game project directory |
| `get_preview` | Return path to an existing PNG thumbnail |
| `generate_preview` | Render a 512×512 thumbnail via headless Blender |
| `run_ingest` | Re-scan library and update catalog (idempotent) |
| `get_catalog_stats` | Summary statistics (total assets, with textures, with armatures) |
| `search_polyhaven` | Search [PolyHaven](https://polyhaven.com) for free CC0 models/HDRIs/textures |
| `download_polyhaven_asset` | Download a PolyHaven asset and auto-add to your catalog |

---

## Taxonomy Convention

`game-asset-mcp` works best with assets organized as:

```
ASSETS_ROOT/
├── 3DLowPoly/
│ ├── Characters/
│ │ ├── Animated/
│ │ │ └── <pack-name>/ ← GLBs here
│ │ └── Animals/
│ ├── Props/
│ │ └── Weapons/
│ └── Environment/
│ └── Nature/
├── 3DPSX/
│ └── ...
└── 2DPhotorealistic/
├── HDRIs/
└── Textures/
```
Comment on lines +118 to +134
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to fenced code block.

The static analysis tool flags this block as missing a language specifier. For directory tree structures, use text or plaintext.

📝 Suggested fix
-```
+```text
 ASSETS_ROOT/
 ├── 3DLowPoly/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
ASSETS_ROOT/
├── 3DLowPoly/
│ ├── Characters/
│ │ ├── Animated/
│ │ │ └── <pack-name>/ ← GLBs here
│ │ └── Animals/
│ ├── Props/
│ │ └── Weapons/
│ └── Environment/
│ └── Nature/
├── 3DPSX/
│ └── ...
└── 2DPhotorealistic/
├── HDRIs/
└── Textures/
```
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 118-118: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/game-asset-mcp/README.md` around lines 118 - 134, The fenced code
block in README.md showing the ASSETS_ROOT directory tree lacks a language
specifier; update the block delimiter from ``` to ```text (or ```plaintext) so
the tree is treated as plain text language (e.g., change the opening fence
before "ASSETS_ROOT/" in the README file to ```text) to satisfy the static
analysis rule.


The `browse_taxonomy` tool navigates this as **style → category → sub-category → pack**. Flat libraries work too — `search_assets` does full-text search on filenames and directory names regardless of structure.

---

## PolyHaven Integration

Search and download free CC0 assets from [polyhaven.com](https://polyhaven.com):

```
search_polyhaven("oak tree", asset_type="models")
download_polyhaven_asset("oak_tree", asset_type="models", resolution="1k")
```
Comment on lines +144 to +147
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to fenced code block.

This code block shows Python function calls but lacks a language specifier.

📝 Suggested fix
-```
+```python
 search_polyhaven("oak tree", asset_type="models")
 download_polyhaven_asset("oak_tree", asset_type="models", resolution="1k")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
search_polyhaven("oak tree", asset_type="models")
download_polyhaven_asset("oak_tree", asset_type="models", resolution="1k")
```
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 144-144: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/game-asset-mcp/README.md` around lines 144 - 147, The fenced code
block showing the Python calls search_polyhaven(...) and
download_polyhaven_asset(...) is missing a language specifier; update the block
to use a Python fence (add "python" after the opening ``` fence) so syntax
highlighting is applied for the functions search_polyhaven and
download_polyhaven_asset.


Downloads are automatically placed in the correct taxonomy directory and added to the catalog.

| PolyHaven Type | Local Path |
|----------------|------------|
| `models` | `ASSETS_ROOT/3DLowPoly/<category>/polyhaven/<id>/` |
| `hdris` | `ASSETS_ROOT/2DPhotorealistic/HDRIs/polyhaven/<id>/` |
| `textures` | `ASSETS_ROOT/2DPhotorealistic/Textures/polyhaven/<id>/` |

---

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `ASSETS_ROOT` | `~/assets` | Root directory of your 3D asset library |
| `CATALOG_DB` | `~/.local/share/game-asset-mcp/catalog.db` | SQLite catalog path |
| `BLENDER` | `/opt/homebrew/bin/blender` | Blender binary (only needed for `generate_preview`) |

---

## Development

```bash
# From the monorepo root
uv sync
uv run --package game-asset-mcp game-asset-mcp
```

Or directly:

```bash
cd packages/game-asset-mcp
uv run game-asset-mcp
```

---

## License

MIT © Jon Bogaty — PolyHaven assets are [CC0](https://polyhaven.com/license)
26 changes: 26 additions & 0 deletions packages/game-asset-mcp/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "game-asset-mcp",
"tags": ["lang:py", "scope:mcp", "scope:game-assets"],
"targets": {
"test": {
"command": "uv run pytest tests/ -v --tb=short --ignore=tests/e2e/",
"inputs": ["{projectRoot}/src/**/*.py", "{projectRoot}/tests/**/*.py", "{projectRoot}/pyproject.toml"]
},
"test:e2e": {
"command": "uv run pytest tests/e2e/ -v --tb=short -m e2e",
"inputs": ["{projectRoot}/src/**/*.py", "{projectRoot}/tests/**/*.py"]
},
"lint": {
"command": "uvx ruff check {projectRoot}",
"inputs": ["{projectRoot}/src/**/*.py"]
},
"typecheck": {
"command": "uvx mypy {projectRoot}/src/",
"inputs": ["{projectRoot}/src/**/*.py"]
},
"ingest": {
"command": "uv run game-asset-ingest",
"inputs": []
}
}
}
104 changes: 104 additions & 0 deletions packages/game-asset-mcp/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "game-asset-mcp"
version = "0.1.0"
description = "MCP server and catalog library for local 3D game asset libraries — search, browse, and manage GLB/GLTF assets"
requires-python = ">=3.10"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Python version mismatch with monorepo root.

This package declares requires-python = ">=3.10", but the root pyproject.toml requires >=3.11. This inconsistency could cause confusion. The coding guidelines also specify "Maintain Python 3.11+ compatibility."

Consider aligning to >=3.11 for consistency, or document why this package specifically needs 3.10 support.

📝 Suggested fix for consistency
-requires-python = ">=3.10"
+requires-python = ">=3.11"

If keeping 3.10 support:

-    "tomli>=2.0; python_version < \"3.11\"",  # tomllib backport

This line can be removed if requiring 3.11+.

As per coding guidelines: "Maintain Python 3.11+ compatibility"

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
requires-python = ">=3.10"
requires-python = ">=3.11"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/game-asset-mcp/pyproject.toml` at line 9, The package currently
declares the Python requirement via the pyproject.toml key "requires-python =
\">=3.10\"" which conflicts with the monorepo root requirement (>=3.11) and the
guideline to maintain 3.11+ compatibility; update the "requires-python" entry to
">=3.11" to align with the root (or remove the entry if you intentionally rely
on the root constraint) so the package and monorepo are consistent.

license = { text = "MIT" }
readme = "README.md"
authors = [{ name = "Jon Bogaty", email = "jon@jonbogaty.com" }]
keywords = [
"mcp", "model-context-protocol", "3d-assets", "game-development",
"glb", "gltf", "polyhaven", "asset-management", "claude", "cursor",
]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Games/Entertainment",
"Topic :: Multimedia :: Graphics :: 3D Modeling",
"Topic :: Software Development :: Libraries :: Python Modules",
]
# Core dependencies
dependencies = [
"fastmcp>=3.0",
"tomli>=2.0; python_version < \"3.11\"", # tomllib backport
"pygltflib>=1.16.0",
"pydantic>=2.0",
"pydantic-settings>=2.0",
"pydantic-cli>=4.0",
]

[project.optional-dependencies]
# PolyHaven integration (download free CC0 assets)
polyhaven = [
"httpx>=0.27",
]
# Semantic search (vector embeddings)
semantic = [
"sqlite-vec>=0.1",
"sentence-transformers>=3.0",
"langchain-community>=0.3",
"langchain>=0.3",
]
# Everything
all = [
"fastmcp>=3.0",
"httpx>=0.27",
"sqlite-vec>=0.1",
"sentence-transformers>=3.0",
"langchain-community>=0.3",
"langchain>=0.3",
]
tests = [
"pytest>=8.0",
"pytest-mock>=3.14",
]

[project.scripts]
game-asset-mcp = "game_asset_mcp.server:main"
game-asset-ingest = "game_asset_mcp.ingest:main"
game-asset-init = "game_asset_mcp.wizard:main"

[project.urls]
Homepage = "https://github.com/jbcom/agentic"
Repository = "https://github.com/jbcom/agentic"
Documentation = "https://github.com/jbcom/agentic/tree/main/packages/game-asset-mcp#readme"
Issues = "https://github.com/jbcom/agentic/issues"

[tool.hatch.build.targets.wheel]
packages = ["src/game_asset_mcp"]

[tool.semantic_release]
version_toml = ["pyproject.toml:project.version"]
build_command = "uv build"
commit_parser = "angular"
commit_author = "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
tag_format = "game-asset-mcp-v{version}"
changelog_file = "CHANGELOG.md"
upload_to_vcs_release = true

[tool.semantic_release.commit_parser_options]
allowed_tags = ["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore", "ci", "build"]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]

[tool.semantic_release.branches.main]
match = "main"
prerelease = false

[tool.semantic_release.remote]
type = "github"
token = { env = "GH_TOKEN" }

[tool.semantic_release.publish]
dist_glob_patterns = ["dist/*"]
upload_to_vcs_release = true
5 changes: 5 additions & 0 deletions packages/game-asset-mcp/src/game_asset_mcp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""game-asset-mcp — MCP server and catalog library for local 3D game asset libraries."""
from __future__ import annotations


__version__ = "0.1.0"
Loading
Loading