Thicken

io.github.bikemeardsley由 GitHub 账号 bikemeardsley 发布v0.3.0更新于 Nov 6, 2026

Photos in: a 3D model at the object's real size and its metadata as JSON, for any kind of object.

已验证STDIO仅桌面文件与存储媒体与设计

概览

AI 生成的概览

把真实物品的照片转成实际尺寸的 GLB 三维模型和 JSON 元数据,通过两个 MCP 工具调用。

可以做什么
  • 列出可用配置档:thicken 能建模的每类物品、由什么照片生成、产出什么,以及视觉模型能读出什么
  • 生成模型:把单个物品、图案、文字或图书 ISBN 的照片转成以毫米为实际尺寸的 GLB 模型和配套 JSON 元数据
  • 为图书、评级卡砖、裸卡、盒子、徽章或立体字选择配置档,或由条形码、二维码或视觉模型自动判定
适用场景
当你希望助手用已有照片为实体物品(如书、评级卡、盒子或徽章)生成三维模型和结构化元数据,用于书架或藏品目录展示时适用。
运行要求
以 npm 包 thicken 在本地通过 stdio 运行,用 npx -y thicken mcp 启动;需要 Node 22.18 或更高版本。可选密钥:GOOGLE_BOOKS_API_KEY 用于图书尺寸,THICKEN_VISION_KEY 用于视觉端点。可选 THICKEN_VISION_URL(兼容 OpenAI 的视觉端点)和 THICKEN_VISION_MODELS。目录查询需要网络访问。
安装前请注意
设置 THICKEN_VISION_URL 后,照片本身会被发送到该主机,托管端点会看到每一张照片;网关还会转发给模型提供方。图书查询会把 ISBN 或从物品上读出的书名和作者发送给 Open Library、美国国会图书馆和 Google Books。每次运行都会在第一张图片旁写入 GLB 和 JSON 文件。照片离开本机前会重新编码并去除 EXIF。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Thicken,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

[thicken, in gold 3D bubble letters, drifting slowly: the logo is a thicken model]

[Latest release] [npm] [CI tests] [In the official MCP Registry] [On skills.sh] [On cursor.directory] [Antigravity plugin] [On Smithery] [thicken MCP server, quality and maintenance score on Glama] [glTF 2.0]
[TypeScript] [Node 22.18 or later] [MIT license] [Buy Me a Coffee] [Donate to ALS research]

Photos in. Out comes the object: its 3D model and its metadata.

thicken turns photos of a real object into a GLB model at its real size and its metadata as JSON, read off the object by vision models and looked up in public catalogs. What it knows about each kind of object lives in a profile: a few come with thicken, and you can add your own.

[Photos of the front and back of a CGC-graded Giannis Antetokounmpo autograph card on a wooden table, beside the clear 3D slab thicken made from them, turning all the way round] [Photos of the front and back of a PSA-graded 1976 Topps Julius Erving in a tall holder, beside its 3D model, turning all the way round] [Photos of the front and back of a reverse-holo Psyduck card, beside its 3D model, the foil shimmering as it turns]

In each, the photos going in and the model coming out, with its metadata, like the one below. The logo above is a thicken model too, made by its lettering profile: thicken lettering thicken.

The other half: its metadata. Part of the first one's, a graded Giannis Antetokounmpo card:

json
{  "profile": "slab",  "holder": "cgc",  "grader": "cgc",  "cert": "6072896005",  "widthMm": 80.5, "heightMm": 135, "depthMm": 7.5,  "read": {    "grade": "9", "gradeName": "MINT",    "autoGrade": "10", "autoGradeName": "AUTO",    "signed": "G. ANTETOKOUNMPO, 8/2/25",    "name": "Giannis Antetokounmpo", "year": "2024-25", "maker": "Panini",    "set": "Court Kings Basketball", "number": "#5", "variant": "Blank Slate"  },  "readBy": { "grade": "agreed", "autoGrade": "agreed", "set": "disputed" },  "inside": {    "card": { "widthMm": 63.5, "heightMm": 88.9, "corners": "square", "foil": "none" },    "label": { "widthMm": 66.4, "heightMm": 26.9 }  }}

The grader and certificate number come from the label's QR code; the vision models read the rest off the slab. What each profile records is in the table of profiles, and every field is described in USAGE.md.

Contents

Try it

sh
npm install -g thicken                      # Node 22.18 or later; or npx thicken …thicken photo.jpg                           # it works out what it is: a code on it, or the vision modelsthicken book cover.heic back.heic spine.heicthicken --isbn 9780061120084                # no photo: the cover and size from Open Librarythicken slab front.jpg back.jpgthicken card front.jpg back.jpg --pt 130    # a thick patch cardthicken badge badge.png --width 50          # cut-out artwork, extrudedthicken lettering thicken                   # the logothicken batch ~/Pictures/books --preview    # a model per photo, PDF, video or folderthicken profiles --json                     # each profile's name, about and photo-search phrases

Each run writes <name>.glb and <name>.json beside the first picture, and with --preview a picture of both sides. Photos straight on and cropped work as they are; uncropped photos, angled shots and video need a vision roster, any OpenAI-compatible endpoint (Vision). As a library: import { thicken } from 'thicken', then thicken(files, options) gives the GLB's bytes and the sidecar.

From an AI agent

thicken is an MCP server too (thicken mcp), with an Agent Skill that tells the agent when and how to use it: ask for a model of the book on your desk, and the agent makes it. In Claude Code:

/plugin marketplace add bikemeardsley/thicken/plugin install thicken@thicken

Or for any MCP client, npx -y thicken mcp on stdio. Codex, Copilot, Cursor, Antigravity, Gemini CLI and the rest are in USAGE.md.

How it works

[Photos, a video, words or an ISBN go in; thicken matches them to a profile, processes them (the vision models find each face, cut it out and straighten it, and read what's printed), builds the object at its real size, and writes a GLB model and a JSON sidecar.]

What thicken knows about a kind of object lives in its profile: how to recognize it, its faces, what to read off it, and how to build it at its real size. A code on the object picks the profile (an ISBN barcode, a grader's QR code), or the vision models say which it is. thicken is not a photogrammetry tool: everything it handles is close to a box or a flat outline, so it builds the geometry from known sizes and maps your photos onto it.

The thicken object

What thicken makes is more than a 3D shape. Each run writes a thicken object: the model (a GLB at the object's real size, in millimeters) and, beside it, its metadata (the JSON sidecar), which knows what the object is, in its profile's own terms. For the profiles that come with thicken, for example:

  • A book: its ISBN, its catalog record (title, authors, publishers, dates, subjects, Dewey and Library of Congress classes, pages), and how sure the match is when it was found by title.
  • A graded slab: its grader, cert number and verification link, its holder, and the card and label inside it, each sized and placed. With vision, the label read: the card's grade (its number and words, "9 MINT", any qualifier and subgrades), an autograph's own grade when the label grades one apart from the card ("AUTO 10"), who signed it and when, and the card as the grader names it.
  • A raw card: its size, its thickness in points for a thick card, its corners and its foil. With vision, what's printed on it: player or character, team, year, maker, set, number, parallel.
  • A box: with vision, its name, brand, edition, rating and year.
  • A badge: with vision, what it names, who issued it, its level, subject, date, any credential number, and every other word on it.
  • Every object: what the vision models read off it, and how sure; which faces are your photos and which are stand-ins, how each fact was found, what is still worth photographing, and what each vision model answered.

An app shows the model and reads the sidecar: a library shelf of your books, a vault of your slabs. The fields are under What the sidecar records.

What it makes

thicken makes the 3D object; what it knows about kinds of object lives in profiles, one file each in src/profiles. Anyone can add one (CONTRIBUTING.md). Every profile there today:

ProfileWhat it isFromMakesWith vision, reads
badgecut-out digital artwork: a certification badge, logo or sticker designArtwork with transparency around its shape (--width, --depth in mm)The artwork's own outline, extruded: the art on its face, its edge color on the sides and backname, issuer, level, subject, date, id, text
booka book, hardcover or paperbackFront cover, back, spine and page sides, in any order and any of them; or just an ISBNThe book at its real size, from its ISBN's catalog record: a paperback softly rounded, a hardcover with boards standing past its pagestitle, subtitle, authors, series, publisher, edition
carda single trading card on its own, not sealed in a plastic holderFront, and its backA thin plate, 63.5 × 88.9 mm unless --size says, 0.35 mm unless --pt gives a thick card's points; its corners cut and its foil shimmering as the vision models see themname, team, year, maker, set, number, variant
letteringwords made into puffy 3D bubble lettersWords, typed where pictures would go (--width mm across, --depth mm thick)Puffy gold bubble letters, round in section like a balloon, in the Titan One font–
slaba graded trading card sealed in a clear plastic holder with a labelFront, and its backA clear plastic holder at its grader's size, with the card and the grade label inside it, each cut from the photosgrader, grade, gradeName, qualifier, subgrades, autoGrade, autoGradeName, autograph, signed, cert, name, team, year, maker, set, number, variant
boxa box-shaped object (a game case, a phone, a deck of cards, packaging)Front, and any of its back and sides; its size (--size), or the vision models' estimateA softly rounded box with the photos on its facestitle, brand, edition, rating, year

What each one records in its sidecar, beside what every model has (its size and where it came from, its faces and pictures, its codes, what the vision models read and how sure, what's worth a second look: all in USAGE.md):

badge: edge, regions, measuredBy
FieldWhat it holds
edgethe color just inside its outline, used for its sides and back (#rrggbb)
regionshow many separate shapes the artwork is (a medal and its ribbon are two)
measuredBywhere its width and depth came from: given, or the default (artwork carries no scale)
book: isbn, catalog, match, pages, binding, bindingBy, measuredBy, depthEstimates, coverUrl, sticker, pageEdges, finish, finishBy, lookups
FieldWhat it holds
isbnits ISBN: given, read off its barcode, or from a title match with one edition
catalogOpen Library's record of the edition and its work: title, authors, publishers, dates, edition, format, series, languages, subjects, Dewey and LC classes, contents, every id, links, cover
matchwhen found by the title read off it: what was read, how sure the match is, the work and its editions
pagesits page count
bindinghardcover or paperback
bindingByhow that was found: vision, catalog or assumed
measuredBywhere each of its sizes came from: measured, openlibrary, loc, googlebooks, pages, photos, cover or trim
depthEstimatesevery thickness estimate made: from the photos and from the page count
coverUrlOpen Library's cover, when it stands in for a front not photographed
stickerwhere a foil seal or sticker is on its front cover, and whether it's round
pageEdgesits page edges' color (#rrggbb), whether gilt, and how found: photo (a photo shows them), vision (the models' colors) or assumed (cream)
finishits cover's finish: glossy or matte
finishByhow that was found: vision or assumed
lookupsevery catalog request: host, path, status and time
card: corners, cornersBy, foil, foilBy, foilLook, foilLookBy, pictureBox, pictureBoxBy, border, borderBy, frame, frameBy, texture, textureBy, pt, format, formatBy, stock, stockBy, finish, finishBy, measuredBy
FieldWhat it holds
cornershow its corners are cut: square, slight or round
cornersByhow that was found: vision or assumed
foilits foil: none, holo (the picture shines), reverse (all but the picture) or full
foilByhow that was found: vision or assumed
foilLookits foil's pattern, when it shines (src/patterns.ts): "shards", "flow wave", "circles"…
foilLookByhow that was found: parallel (a word in the variant read off it), vision or assumed
pictureBoxwhere its picture box is, in fractions of the front, for holo and reverse foil
pictureBoxByhow that was found: vision or the standard layout
borderits printed border: foil (it shines, as on Pokémon-ex and LV.X cards) or plain
borderByhow that was found: vision or assumed
frameinside its foil border, in fractions of the front
frameByhow that was found: vision or the standard layout
textureits front's surface: textured (raised ridges, embossed in the model from the photo's own lines) or smooth
textureByhow that was found: vision or assumed
pta thick card's thickness in points, when given
formatits size of card: standard, small (Yu-Gi-Oh! and Japanese size) or other
formatByhow that was found: vision or assumed
stockits stock: standard, or thick (a patch, relic or acrylic card)
stockByhow that was found: vision or assumed
finishits front's finish: glossy or matte
finishByhow that was found: vision or assumed
measuredBywhere its size came from: its format (as the models see it) or given; its thickness: standard, thick, given or pt
lettering: text, font, fontLicense, color, measuredBy
FieldWhat it holds
textthe words, as lettered
fontthe font they were drawn in
fontLicenseits license (OFL-1.1)
colortheir color
measuredBywhere its width and depth came from: given, the default, or round in section
slab: grader, cert, verifyUrl, holder, inside, measuredBy
FieldWhat it holds
graderwho graded it: psa, bgs, cgc, sgc or tag, from its QR code or its label
certits certification number: from its QR code or barcode, else as read off its label (identifiedBy.cert says which, and whether both agreed)
verifyUrlthe grader's page for this cert: its QR code's link, else built from the grader and the cert (PSA, CGC, BGS)
holderthe holder it was built as (psa, cgc-tall…)
insidethe card and the label inside: each one's size, middle and what placed it; the card's corners, foil and its pattern, border and texture; the label's finish (foil or paper) and where its hologram is; and the grader's logo on the insert, where it was found
measuredBywhere its size came from: the holder table, or measured
box: barcode, measuredBy, rounding, roundingBy, finish, finishBy
FieldWhat it holds
barcodeits product barcode (UPC or EAN) and its kind, when a photo shows one
measuredBywhere each of its sizes came from: measured, photos (its proportions there, scaled by a measured size or the estimate), or the vision models' estimate
roundinghow rounded its corners and edges are: sharp, slight, round or very
roundingByhow that was found: vision or assumed
finishits surface: glossy or matte
finishByhow that was found: vision or assumed

Name the profile, or leave it out and thicken picks one:

  • An ISBN barcode on any picture, or --isbn, means a book.
  • A QR code pointing at a grader's site (psacard.com, beckett.com, cgccards.com, gosgc.com, taggrading.com) means a slab, and says whose. The sidecar keeps the grader, the cert number from the link, and the link itself (verifyUrl).
  • So does an older label's Code 128 cert barcode, but only on a photo shaped like a holder. The grader is then the one the vision models read off the label; with no vision, a PSA-size holder is assumed, with a warning.
  • Artwork with transparency around a shape that isn't just a rectangle means a badge.
  • Otherwise, with vision, the models are shown the profiles and say which it is, and roughly how big: two agreeing settle it, as with faces, and box takes anything box-shaped the others don't cover.
  • Anything still unknown is refused with a request to name the profile. Other barcodes don't count: books carry UPCs, QR codes and library stickers.

The sidecar's identifiedBy.profile says which way it was chosen: given, recognized (codes or the artwork), or vision.

Adding a profile is one file in src/profiles, found by itself, nothing else to change: its name; a few words on what it is and on each of its faces, which is all the vision models are told; what to read off it (more is better: the sidecar is for apps to take what they want from); optionally how its codes or pictures give it away unaided; and how to build it from the photos placed on its faces. Generic profiles are named for the shape they build (box, and later perhaps flat or cylinder), not "unknown": a shape thicken can't build is refused rather than forced into one it can. Contributions welcome: CONTRIBUTING.md says how.

Pictures are placed on faces by what they show (see Photos). With no front, Open Library's cover stands in, marked for review, so one photo of the back is enough to start a book.

What leaves your machine

With THICKEN_VISION_URL set, the photos themselves (re-encoded, so without their EXIF) go to that host. A LAN server you control still forwards each photo to the model's provider; a hosted endpoint sees every photo. With THICKEN_BENCH_URL naming a Benchwarmers gateway with a vision collection, the photos go to that gateway, which forwards each to the providers of every seat it picks. The only other calls out are a book's catalog lookups (Open Library, the Library of Congress, Google Books), which send its ISBN, or the title and author the models read off it; never a photo.

Nothing else is sent anywhere, and nothing is fetched at run time but those lookups: previews draw with model-viewer served from your own disk.

Adding a profile

A profile is one file, found by itself: what the object is, its faces, what to read off it, and how to build it. Make your own while you use thicken, or improve one of its own, and offer it back:

sh
thicken profile new vinyl          # from the template, in ~/.thicken/profiles: used at oncethicken profile check vinyl        # what thicken's CI will checkthicken profile contribute vinyl   # forks, branches, checks and opens the pull request

The template, templates/profile.ts, works as it is (a box at the size you give) and says on every field what goes there, the records it writes included. CONTRIBUTING.md has the rest. The table above is made from the profiles themselves.

Security

Report a vulnerability privately, as SECURITY.md says. It also lists what thicken touches: files, the network, and the programs it runs.

Built on

PartHowChoice
Triangulating badge outlinesDependencymapbox/earcut (ISC)
Writing GLBDependencydonmccurdy/glTF-Transform (MIT)
Decoding HEICDependencycatdad-experiments/libheif-js (LGPL-3.0, used unmodified). sharp's binaries leave out HEVC.
Reading barcodesDependencySec-ant/zxing-wasm (MIT). Its .wasm is loaded from node_modules, not its default CDN.
Pictures from scanner PDFsDependencyunjs/unpdf (MIT, pdf.js inside)
Frames from videoOutside programFFmpeg, run from the PATH, never bundled: it is GPL, thicken MIT. eugeneware/ffmpeg-static (GPL-3.0) would put a GPL binary in every install, video or not; ffmpegwasm/ffmpeg.wasm is built for browsers. Choosing the frames is ours.
Reading camera details (EXIF)Dependencydevongovett/exif-reader (MIT): parses the EXIF block sharp returns
Drawing previewsDependencygoogle/model-viewer (Apache-2.0): frames and lights a GLB; three.js inside
Running the preview browserDependencymicrosoft/playwright (playwright-core, Apache-2.0): drives an installed Chrome or Edge, no browser download
MCP serverDependencymodelcontextprotocol/typescript-sdk (MIT), the official SDK, with colinhacks/zod (MIT) for its tools' inputs
Book dimension sourcesWriteRead palmerabollo/node-isbn's provider fallback. Ours is per dimension, not first-provider-wins. The Library of Congress's one field (MARC 300) is read with a regular expression, not a MARC library.
HardcoversWriteFour rounded boxes from src/glb.ts, and the binding asked of the vision models like a card's corners.
HolofoilWriteWhich areas shine for each kind of foil read from simeydotme/pokemon-cards-css (GPL-3.0: facts read, nothing copied); the film values are KHR_materials_iridescence's defaults, as KhronosGroup/glTF-Sample-Assets uses them; glTF-Transform, already a dependency, writes the extension.
Profiles, box, classifier, CLIWrite
Slab holder, card and labelWriteglTF-Transform's materials (already a dependency) for the clear holder; the card and label plates, where they sit, and putting them together are ours. Khronos's glTF-Sample-Assets were the reference for clear materials.
Finding faces in photosWriteVision models over any OpenAI-compatible endpoint, primary and peer (src/vision.ts): one POST each, no SDK.
Straightening facesAdapt, don't dependjlouthan/perspective-transform (MIT): the 4-point homography; the resampling over sharp's pixels is ours. sharp has no perspective warp, and OpenCV.js is megabytes for one.
Snapping corners to edgesWritesnap in src/image.ts moves a model's corners (about 1% off) onto the real edges. It samples brightness steps along each side, takes the line they support nearest the model's, and fits it by least squares, in about 70 ms a face. puffinsoft/jscanify's corner ranking was read; a line fit near the model's corners was enough.
Lettering's fontDependencyopentypejs/opentype.js (MIT) reads it: the words' outlines, kerned. The font is Titan One by Rodrigo Fuenzalida, shipped unmodified under the SIL Open Font License 1.1 (fonts/OFL.txt; "Titan" is its Reserved Font Name).
Inflating lettersAdapt, don't dependEach pixel's distance from the outline is mapbox/tiny-sdf's (BSD-2-Clause) exact distance transform, ported; it places the outline to a fraction of a pixel. The rise is ours: √u, where ∇²u = −2 inside the letters, round in section across any stroke.

For refractor and holo effects in a viewer, simeydotme/pokemon-cards-css is a reference only. It is GPL-3.0, so read it and don't copy it.

Development

TypeScript on Node 22.18+, with sharp for images. From a clone it runs directly (Node strips the types). The npm package is JavaScript built into dist (npm run build, run by npm pack and npm publish), because Node won't strip types inside node_modules. Every push installs the packed package on Windows, macOS and Linux and runs it.

From a clone: npm install, then node src/cli.ts … in place of thicken …; npm test, npm run check, and npm run readme after changing a profile.

License

MIT. See LICENSE.

The lettering font, Titan One, is under the SIL Open Font License 1.1 (fonts/OFL.txt).

来源:README.md,提交 9d1bd7c

工具

2

thicken_profiles

The kinds of object thicken makes

Lists thicken's profiles: each kind of object it can make into a 3D model at its real size, what it is made from, what it makes, and what the vision models read off it. Call it to choose a profile for thicken_make, or to tell the user what thicken can make.

无需输入参数。

thicken_make

Make a 3D model with thicken

Turns photos of one real object (or artwork, or words, or a book's ISBN) into two files that belong together: a GLB model at the object's real size, in millimeters, and its metadata as JSON, read off it by vision models and looked up in public catalogs (thicken_profiles lists each kind of object and the metadata it records). Writes both files and returns their paths and the main facts. Photos need not be cropped when a vision roster is set up (THICKEN_VISION_URL, THICKEN_VISION_MODELS); without one, give straight-on photos cropped to the object, and name the profile. One object a call: for several, call once each.

输入参数ptoutisbnholderinputscornerscroppedpreviewprofilesize_mmdepth_mmwidth_mm

版本历史

4
  1. v0.3.0最新Nov 6, 2026
  2. v0.2.1Oct 26, 2026
  3. v0.1.1Oct 23, 2026
  4. v0.1.0Oct 14, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分