-
Notifications
You must be signed in to change notification settings - Fork 1
feat(game-asset-mcp): add open-source MCP server for 3D game asset libraries #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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) |
| 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/ | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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
Suggested change
🧰 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 |
||||||||||
|
|
||||||||||
| 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) | ||||||||||
| 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": [] | ||
| } | ||
| } | ||
| } |
| 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" | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python version mismatch with monorepo root. This package declares Consider aligning to 📝 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 backportThis line can be removed if requiring 3.11+. As per coding guidelines: "Maintain Python 3.11+ compatibility" 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| 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 | ||||||
| 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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add language specifier to fenced code block.
The static analysis tool flags this block as missing a language specifier. For directory tree structures, use
textorplaintext.📝 Suggested fix
📝 Committable suggestion
🧰 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