Skip to main content
Glama
arielshad
by arielshad
       +------------+
      /            /|      _____ ____       _                 _
     /            / |     |___ /|  _ \     / \   ___ ___  ___| |_
    +------------+  |       |_ \| | | |   / _ \ / __/ __|/ _ \ __|
    |            |  |      ___) | |_| |  / ___ \\__ \__ \  __/ |_
    |            |  +     |____/|____/  /_/   \_\___/___/\___|\__|
    |            | /       ____
    |            |/       / ___|  ___ _ ____   _____ _ __
    +------------+        \___ \ / _ \ '__\ \ / / _ \ '__|
                           ___) |  __/ |   \ V /  __/ |
                          |____/ \___|_|    \_/ \___|_|

        one search box for 3D models, materials, textures, HDRIs & game assets
                         HTTP API  *  MCP server  *  web UI  *  CLI

3d-asset-server searches 17 asset sites at once and downloads what you pick, ready to drop into a game or a website. Use it from a browser, from curl, from the command line, or let your AI assistant drive it over MCP.

"I need a low-poly tree pack, a mossy rock material and a sunset HDRI for my Three.js scene."

Your assistant calls search_assets three times, shows you the options with their licences, and download_asset puts glTF, textures and the HDRI into your project's assets/ folder.

  • One query, many sources. Results are merged and ranked, with a status line for every site.

  • Real downloads. From free sources you get files directly: glTF with its .bin and textures, PBR maps at the resolution you ask for, HDRIs, or zipped packs (extracted for you).

  • Licence first. Every result says what licence it has, whether it is free, and whether you must credit the author.

  • Honest about what's blocked. Sites that block bots come back as links to their own search, so you still know where else to look.


Contents


Related MCP server: Blender MCP Server

How it works

   +-----------+   +-----------+   +-----------+   +-----------+
   |  Web UI   |   |   curl /  |   |  Claude,  |   |    CLI    |
   | (browser) |   |  your app |   |  Cursor.. |   |           |
   +-----+-----+   +-----+-----+   +-----+-----+   +-----+-----+
         |               |               |               |
         |   GET /       |  /v1/*        | MCP           | search
         |               |               | stdio or /mcp |
         v               v               v               v
   +-----------------------------------------------------------+
   |                      3d-asset-server                      |
   |                                                           |
   |   +-----------------+   +-------------------------------+ |
   |   |  REST API (Hono)|   |  MCP tools                    | |
   |   |  /v1/search     |   |  search_assets   get_asset    | |
   |   |  /v1/assets/..  |   |  download_asset  list_provid..| |
   |   +--------+--------+   +---------------+---------------+ |
   |            |                            |                 |
   |            +-------------+--------------+                 |
   |                          v                                |
   |   +-------------------------------------------------------+
   |   |  AssetService                                         |
   |   |   fan-out --> per-site timeout --> rank --> dedupe    |
   |   +-------------------------------------------------------+
   |                          |                                |
   |   +----------------------+--------------------------------+
   |   |  HTTP client: User-Agent, timeouts, LRU cache,        |
   |   |  in-flight request dedupe                             |
   |   +-------------------------------------------------------+
   +-----------------------------+-----------------------------+
                                 |
         +-------------+---------+---------+-------------+
         v             v                   v             v
   +-----------+ +-----------+       +-----------+ +-----------+
   | API       | | scrape    |  ...  | scrape    | | link-only |
   | Poly Haven| | Kenney    |       | itch.io   | | Fab       |
   | ambientCG | | TextureCan|       | HDRI Hub  | | Poliigon  |
   | BlenderKit| | Quaternius|       | ...       | | TurboSquid|
   +-----------+ +-----------+       +-----------+ +-----------+

What a single search does:

  "sunset" type=hdri free=true
           |
           v
  +------------------+   skip sites that don't carry HDRIs, or are paid-only
  |   pick sources   |-----------------------------------------------------+
  +--------+---------+                                                     |
           |  in parallel, each with its own timeout (default 12s)         |
     +-----+------+------------+------------+------------+                 |
     v            v            v            v            v                 v
  Poly Haven   ambientCG   BlenderKit    HDRMaps     Poliigon        cgbookcase,
   ok 24        ok 24        ok 24        ok 12      link ->         kenney, ...
     |            |            |            |            |            skipped
     +------------+-----+------+------------+            |
                        v                                 |
  +---------------------------------------------+         |
  | rank:  60% text match (title > tags > desc) |         |
  |        20% the site's own ranking           |         |
  |        10% API > scrape                     |         |
  |        +free  +direct download              |         |
  |        diversity penalty per site           |         |
  +---------------------+-----------------------+         |
                        v                                 v
           results[]  +  per-site report (ok / error / timeout / skipped / link)

A slow or broken site never fails the search. It shows up in the per-site report with its error and a link to the same search on that site.


Sources

Source

Best for

Search

Direct download

Licence

Poly Haven

HDRIs, PBR textures, scanned models

API

yes: glTF / blend / fbx, maps, HDR / EXR

CC0

ambientCG

Realistic materials, HDRIs, models

API

yes: per-resolution zips

CC0

CGBookcase

PBR textures

API (catalogue)

no: hotlink-protected CDN, links to the download page

CC0

ShareTextures

Textures and realistic models

API (tag search)

no: its licence forbids automated downloads

CC0 + site terms

BlenderKit

Blender assets of every kind

API

yes for free assets (GLB / blend); paid ones need BLENDERKIT_API_KEY

CC0 / royalty free

Fab

Game assets, environments, characters

link only (bot wall)

no

per listing

Kenney

Low-poly 3D, 2D, UI and audio packs

scrape

yes: pack zips, auto-extracted

CC0

Poliigon

Premium materials and models

link only (bot wall)

no

per listing

Quaternius

Low-poly models, animated characters

scrape

no: Google Drive / itch.io links

CC0 / QAL

3DTextures.me

Realistic and stylized PBR

WordPress API

no: Google Drive folders

CC0

TextureCan

PBR materials and a few models

scrape

yes: 1K-4K zips

CC0

Textures.com

Photo textures, 3D foliage, decals, skies

JSON API

no: credit system

Textures.com licence

HDRMaps

HDRIs and backplates

WooCommerce API

yes for free HDRIs (EXR)

royalty free

HDRI Hub

HDRI environments

scrape

no: checkout

royalty free

CGTrader

Free and paid models

JSON listing

no: login

per listing

TurboSquid

Free and paid models

link only (bot wall)

no

per listing

itch.io

Indie art, 3D packs, UI, audio

scrape

no: itch's download flow

per listing

  search + direct download    Poly Haven, ambientCG, BlenderKit (free), Kenney,
                              TextureCan, HDRMaps (free)

  search + link to the page   CGBookcase, ShareTextures, Quaternius, 3DTextures.me,
                              Textures.com, HDRI Hub, CGTrader, itch.io

  link to the site's search   Fab, Poliigon, TurboSquid

Notes:

  • Results without direct downloads still have full metadata and a link to the asset page.

  • CGTrader sits behind an IP-based bot wall that often blocks cloud and datacenter IPs. It works from home connections. On a server, run behind a proxy with NODE_USE_ENV_PROXY=1. When it is blocked, the report says so and links to CGTrader's own search.

  • Scraped sites can change their HTML. If one breaks, only that source shows as failed; the others keep working. npm run test:live checks every site.


Quick start

Needs Node.js 20 or newer.

git clone https://github.com/arielshad/3d-asset-server.git
cd 3d-asset-server
npm install
npm run build

npm start                    # web UI + HTTP API + MCP on http://localhost:8787
node dist/cli.js mcp         # MCP over stdio, for Claude Desktop / Claude Code / Cursor
node dist/cli.js search "low poly tree" --type model --free

With Docker:

docker build -t 3d-asset-server .
docker run -p 8787:8787 3d-asset-server

Web UI

Run npm start and open http://localhost:8787.

 +--------------------------------------------------------------------------+
 | [#] 3D Asset Search  [ wooden chair                         ] [ Search ] |
 | (Models) (Materials) (Textures) (HDRIs) (Sprites) (UI) ..                |
 | [ ] Free only   [ ] Direct download   > Sources: all                     |
 +--------------------------------------------------------------------------+
 | Poly Haven 24 | BlenderKit 24 | itch.io 24 | Kenney 2 | Fab -> | ...      |
 |                                                                          |
 | +------------+ +------------+ +------------+ +------------+              |
 | |            | |            | |            | |            |              |
 | |   [img]    | |   [img]    | |   [img]    | |   [img]    |              |
 | |            | |            | |            | |            |              |
 | | Wooden     | | Vintage    | | Outdoor    | | Chair 24   |              |
 | | Chair 01   | | Wooden ... | | wooden ... | |            |              |
 | | PolyHaven  | | BlenderKit | | CGTrader   | | ShareText. |              |
 | | Free CC0   | | Free       | | 18 USD     | | Free CC0   |              |
 | | v direct   | | v direct   | |            | |            |              |
 | +------------+ +------------+ +------------+ +------------+              |
 +--------------------------------------------------------------------------+

  click a card -->  +--------------------------------------+
                    | Poly Haven . model               [x] |
                    | Wooden Chair 01                      |
                    |  +--------------------------------+  |
                    |  |            [preview]           |  |
                    |  +--------------------------------+  |
                    | Price     Free                       |
                    | Licence   CC0 . commercial use OK    |
                    | Formats   gltf, blend, fbx, usd      |
                    | Polygons  19992                      |
                    |                                      |
                    | [Open on Poly Haven ->]              |
                    | +----------------------------------+ |
                    | | [Auto format v] [2k v] [Download]| |
                    | |  WoodenChair_01_2k.gltf          | |
                    | |  + 4 companion files     2.2 MB  | |
                    | +----------------------------------+ |
                    +--------------------------------------+
  • Search and filter. Filter by type, free only, or direct download, and choose which sources to query. The search is kept in the address bar, so /?q=sunset&type=hdri&free=true can be bookmarked or shared.

  • Per-site status bar. Shows how many results each site returned. Sites that can't be searched automatically, or that failed, link to their own search.

  • Detail panel. Shows licence, author, formats, polygon count, tags and description. Pick a format and resolution to see exactly which files you'll get and their total size. Download gives you the file, or one zip when the asset has several files.

  • Works anywhere. Light and dark mode, works on phones, no build step: the whole page is src/ui/index.html.

  • API key. If ASSET_SERVER_API_KEY is set, the page asks for the key once and remembers it in that browser.


MCP: use it from an AI assistant

  you: "find me a free sci-fi crate model and put it in the project"
   |
   v
  assistant --search_assets("sci-fi crate", types=[model], free_only)--> ranked results
   |
   +--------get_asset("polyhaven:...", format="gltf")-----------------> formats, licence,
   |                                                                     files, size
   +--------download_asset("polyhaven:...", resolution="2k")----------> ./assets/polyhaven-.../
   |
   v
  "Done: CC0, no credit needed. Saved to assets/polyhaven-.../crate_2k.gltf"

Claude Code

claude mcp add 3d-assets -e ASSET_DOWNLOAD_DIR="$PWD/assets" -- node /path/to/3d-asset-server/dist/cli.js mcp

Claude Desktop, Cursor, or any stdio MCP client

{
  "mcpServers": {
    "3d-assets": {
      "command": "node",
      "args": ["/path/to/3d-asset-server/dist/cli.js", "mcp"],
      "env": { "ASSET_DOWNLOAD_DIR": "/path/to/your/game/assets" }
    }
  }
}

Remote (Streamable HTTP)

Point the client at http://<host>:8787/mcp. If you set ASSET_SERVER_API_KEY, send Authorization: Bearer <key>.

Over HTTP, download_asset is off by default because it would write to the server's disk, not yours. Instead, get_asset returns direct file URLs plus a one-click bundleUrl zip. Set ASSET_SERVER_HTTP_DOWNLOADS=true if the server and the files should live on the same machine.

Tools

Tool

What it does

search_assets

query, plus optional types (model, texture, material, hdri, sprite, ui, audio, font, pack), providers, free_only, downloadable_only, limit, offset. Returns ranked results, also_search_on links for link-only sites, and any sites that failed.

get_asset

Details for an id such as polyhaven:ArmChair_01: description, licence, available formats and resolutions, and exactly which files a download would fetch for a given format / resolution.

download_asset

Saves into <dest_dir>/<provider>-<id>/ (default ./assets), keeps companion files in place and extracts zips. Returns the paths, licence and an attribution line when credit is required.

list_providers

Every source: what it's best for, asset types, pricing, licence, and whether it supports direct downloads.


HTTP API

Endpoint

GET /v1/search?q=&type=&providers=&free=&downloadable=&limit=&offset=

Ranked, merged results plus a per-site report (ok, error, timeout, skipped, link).

GET /v1/providers

The source catalogue.

GET /v1/assets/{provider}:{id}

Full details, including every file.

GET /v1/assets/{id}/files?format=&resolution=&maps=&all=

The files a download would fetch.

GET /v1/assets/{id}/download?format=&resolution=

302 to the file when it is one self-contained file; otherwise a streamed zip with its companions.

POST /mcp

MCP endpoint (Streamable HTTP, stateless).

GET /openapi.json

OpenAPI 3.1 description.

GET /

Web UI in a browser; a JSON index of endpoints for API clients.

GET /health

Liveness check.

curl 'localhost:8787/v1/search?q=brick+wall&type=material&free=true&limit=5'
curl -OJ 'localhost:8787/v1/assets/polyhaven:WoodenChair_01/download?format=gltf&resolution=1k'

Search response (shortened):

{
  "query": "brick wall",
  "results": [
    {
      "id": "polyhaven:brick_wall_001",
      "title": "Brick Wall 001",
      "type": "material",
      "url": "https://polyhaven.com/a/brick_wall_001",
      "license": { "name": "CC0", "commercialUse": true, "attributionRequired": false },
      "price": { "free": true },
      "resolutions": ["1k", "2k", "4k", "8k"],
      "downloadable": true,
      "score": 1
    }
  ],
  "providers": [
    { "provider": "polyhaven", "status": "ok", "count": 5, "tookMs": 210 },
    { "provider": "fab", "status": "link", "searchUrl": "https://www.fab.com/search?q=brick+wall&is_free=1" }
  ]
}

CLI

$ node dist/cli.js search "low poly tree" --type model --free --limit 5

1.00  model    free   blenderkit:72fac4cb-901c-4a48-8fc8-84a0baa0bd21
      Low poly tree — https://www.blendkit.com/asset-gallery-detail/72fac4cb-.../
0.93  model    free   cgtrader:lowpoly-tree-collection-01-200-trees-lowpoly-collection
      Low Poly Trees Mega Pack - 200 Trees — https://www.cgtrader.com/free-3d-models/...
0.93  model    free   itchio:brokenvector/low-poly-tree-pack
      Low Poly Tree Pack — https://brokenvector.itch.io/low-poly-tree-pack
0.91  model    free   blenderkit:346d99d8-36fb-4f9d-a4a1-2f9ad9233e79
      Low poly tree — https://www.blendkit.com/asset-gallery-detail/346d99d8-.../
0.84  model    free   itchio:mark-auman/low-poly-trees-asset-pack
      Low-Poly Trees Asset Pack — https://mark-auman.itch.io/low-poly-trees-asset-pack

Sources:
  polyhaven        ok       1
  blenderkit       ok       5
  fab              link     0  https://www.fab.com/search?q=low+poly+tree&is_free=1
  kenney           ok       2
  quaternius       ok       5
  cgtrader         ok       5
  turbosquid       link     0  https://www.turbosquid.com/Search/3D-Models/free/low-poly-tree
  itchio           ok       5
  ...
3d-asset-server serve                    HTTP API + web UI + MCP at /mcp
3d-asset-server mcp                      MCP over stdio
3d-asset-server search <query> [--type model,hdri] [--providers a,b] [--free] [--limit N]

Downloads

Unless you say otherwise, a download picks game- and web-friendly files:

  asset type   preferred format, in order          resolution
  ----------   ---------------------------------   --------------------------
  model        glb > gltf > fbx > obj > blend      closest to 2k
  hdri         hdr > exr                           closest to 2k
  material     jpg maps > png maps > zip           closest to 2k
  texture      jpg > png > zip > exr               closest to 2k
  packs        zip (extracted)                     -

Companion files keep their relative paths, so a glTF loads straight away:

  assets/
  `-- polyhaven-WoodenChair_01/
      |-- WoodenChair_01_2k.gltf
      |-- WoodenChair_01.bin
      `-- textures/
          |-- WoodenChair_01_diff_2k.jpg
          |-- WoodenChair_01_nor_gl_2k.jpg
          `-- WoodenChair_01_arm_2k.jpg

  assets/
  `-- kenney-nature-kit/              <- zip downloaded and extracted
      `-- kenney_nature-kit/
          |-- Models/GLTF format/...
          `-- License.txt

Safety:

  • Only http(s) URLs to public hosts are fetched. Private and loopback addresses are refused.

  • Paths that try to escape the target folder (zip-slip, ../) are rejected or skipped.

  • Each download has a size guard (ASSET_SERVER_MAX_DOWNLOAD_BYTES, default 2 GiB).

  • Login, checkout and hotlink protection are never bypassed.


Configuration

Variable

Default

PORT / HOST

8787 / 0.0.0.0

HTTP bind address

ASSET_SERVER_API_KEY

–

Require Authorization: Bearer <key>, x-api-key or ?api_key= on /v1/* and /mcp

ASSET_SERVER_PUBLIC_URL

request origin

Base URL used in links handed to MCP clients

ASSET_SERVER_PROVIDERS

all

Comma list to enable only some sources, e.g. polyhaven,ambientcg,kenney

ASSET_DOWNLOAD_DIR

./assets

Default download folder for MCP

ASSET_SERVER_HTTP_DOWNLOADS

false

Expose download_asset on the HTTP MCP endpoint (writes to the server's disk)

ASSET_SERVER_MAX_DOWNLOAD_BYTES

2 GiB

Per-download size guard

ASSET_SERVER_PROVIDER_TIMEOUT_MS

12000

Per-site search timeout

ASSET_SERVER_HTTP_TIMEOUT_MS

15000

Per-request HTTP timeout

ASSET_SERVER_CACHE_TTL_MS

10 min

In-memory HTTP cache TTL

ASSET_SERVER_USER_AGENT

3d-asset-server/0.1

User-Agent sent to the sites

BLENDERKIT_API_KEY

–

Optional; unlocks plan and purchased BlenderKit assets

NODE_USE_ENV_PROXY

–

Set to 1 so Node's fetch uses HTTPS_PROXY

If you set ASSET_SERVER_API_KEY on a public server, note that ?api_key= (used by the web UI's download button) can end up in browser history and server logs.


Project layout

src/
|-- cli.ts               serve | mcp | search
|-- index.ts             library exports
|-- core/
|   |-- types.ts         Asset, AssetFile, Provider, SearchQuery ...
|   |-- http.ts          fetch wrapper: UA, timeouts, LRU cache, in-flight dedupe
|   |-- service.ts       fan-out search, ranking, per-site reports
|   |-- download.ts      file selection, safe downloads, zip extraction, zip streaming
|   `-- util.ts          matching/scoring, type inference, helpers
|-- providers/           one adapter per site, plus index.ts (the registry)
|   |-- polyhaven.ts  ambientcg.ts  blenderkit.ts  kenney.ts  quaternius.ts
|   |-- itchio.ts  cgtrader.ts  texturescom.ts  threedtextures.ts  hdrmaps.ts
|   |-- sharetextures.ts  cgbookcase.ts  texturecan.ts  hdrihub.ts
|   `-- linked.ts        Fab, Poliigon, TurboSquid (link-only)
|-- api/
|   |-- app.ts           Hono REST API, web UI route, MCP Streamable HTTP mount
|   `-- openapi.ts
|-- mcp/
|   `-- server.ts        MCP tool definitions (shared by stdio and HTTP)
`-- ui/
    `-- index.html       the web UI (static HTML/CSS/JS)
test/
|-- providers/           offline tests per site, against trimmed fixtures
|-- live/                live smoke tests (LIVE=1)
`-- service.test.ts      ranking, downloads, API, MCP

Adding a source: implement the Provider interface (see docs/PROVIDERS_GUIDE.md), add it to src/providers/index.ts, and add an offline test with fixtures.

  interface Provider
    id, name, homepage, description, assetTypes, access: api | scrape | link, pricing, license
    search(query, ctx)     -> { assets, total?, searchUrl? }
    getAsset?(id, ctx)     -> { ...asset, files[] } | null
    buildSearchUrl(query)  -> link to the same search on the site

Development

npm test            # offline tests (fixtures, no network)
npm run test:live   # live smoke tests against the real sites
npm run typecheck
npm run build       # compiles to dist/ and copies the web UI
npm run dev         # watch-mode server

CI (.github/workflows/ci.yml) runs typecheck, tests and build on every push and pull request.


Licences & etiquette

  +----------------------------------------------------------------------+
  |  This server finds and fetches assets. It does not own them.         |
  |  Every result shows its licence: respect it, and credit authors      |
  |  when it says so.                                                    |
  +----------------------------------------------------------------------+
  • Sites are queried gently: responses are cached, there are a few requests per search, and the User-Agent identifies the server.

  • Paid, login-gated and hotlink-protected content is never bypassed; those results link to the source site.

  • ShareTextures' terms forbid automated downloads, so it is search-only.

The server's own code is licensed under Apache-2.0.

Related MCP Connectors

Related MCP Servers