antics-mcp
Advanced tools
+54
-3
@@ -414,3 +414,3 @@ #!/usr/bin/env node | ||
| return { | ||
| text: `Published for review: ${body.url}.${demo} It is NOT public yet \u2014 an operator approves it, and the page is not indexed until then. The URL is permanent: to change the asset later, PUT /api/models/${body.slug} rather than publishing again, or the link you share goes stale. list_my_models shows this and everything else you have published, with its status.`, | ||
| text: `Published for review: ${body.url}.${demo} It is NOT public yet \u2014 an operator approves it, and the page is not indexed until then. The URL is permanent: to change the asset later, call update_model rather than publishing again, or the link you share goes stale. list_my_models shows this and everything else you have published, with its status.`, | ||
| data: body | ||
@@ -423,2 +423,39 @@ }; | ||
| } | ||
| async function updateModelTool(client, args) { | ||
| const missing = ["model", "glb", "recipe"].filter((k) => !args[k]); | ||
| if (missing.length) { | ||
| return { | ||
| text: `update_model needs ${missing.join(", ")}. A replacement carries BOTH the .glb and the recipe that generates it \u2014 a .glb without its recipe breaks the pairing the page is built on. Rebuild with \`npx modelkit build\` and re-render the card with \`npx modelkit preview <name> --card\`.`, | ||
| data: { error: true } | ||
| }; | ||
| } | ||
| try { | ||
| const body = await client.updateModel(args.model, { | ||
| glb: args.glb, | ||
| recipe: args.recipe, | ||
| ...args.kitVersion ? { kitVersion: args.kitVersion } : {}, | ||
| ...args.summary ? { summary: args.summary } : {}, | ||
| ...args.image ? { image: args.image } : {} | ||
| }); | ||
| let demo = ""; | ||
| if (args.demoFiles && Object.keys(args.demoFiles).length) { | ||
| try { | ||
| await client.attachModelDemo(args.model, args.demoFiles); | ||
| demo = " Its demo was replaced too."; | ||
| } catch { | ||
| demo = " The demo bundle was rejected; the model still updated, so the page now pairs new geometry with the OLD demo."; | ||
| } | ||
| } | ||
| return { | ||
| text: `Updated in place: ${body.url} \u2014 same URL, so nothing already shared breaks.${demo} IT IS BACK UNDER REVIEW and the page is NOT public until an operator approves it again: what was approved is not what is behind the link any more. If it was live a moment ago, it is a 404 to everyone else right now. list_my_models shows its status.`, | ||
| data: body | ||
| }; | ||
| } catch (e) { | ||
| if (isAuthError(e)) return { text: LOGIN_HELP, data: null }; | ||
| return { | ||
| text: `Could not update (${e instanceof Error ? e.message : "network error"}). \`model\` is the slug or id of something you published \u2014 list_my_models has both. Do NOT fall back to publish_model: that mints a new URL and strands the one you shared.`, | ||
| data: { error: true } | ||
| }; | ||
| } | ||
| } | ||
| async function listMyModelsTool(client) { | ||
@@ -481,3 +518,3 @@ try { | ||
| - Leaderboard: await room.submitScore(n) | ||
| 3D MODELS: publish_model puts a modelkit asset on a permanent /m/<slug> page with its recipe, licence and downloads (review-gated); find_models searches them, including by part name. 3D GAMES: do NOT assemble primitives at page load \u2014 that is what makes a game look like a pile of boxes, and it costs startup time on every join. Model at DEV TIME with \`npm i antics-modelkit three\`, write a models module, \`npx modelkit build\` to .glb (Khronos-validated, quantised, with collider footprints in manifest.json), and ship the .glb in the files map. get_docs has the full recipe including the importmap the runtime loader needs. | ||
| 3D MODELS: publish_model puts a modelkit asset on a permanent /m/<slug> page with its recipe, licence and downloads (review-gated); update_model replaces one in place KEEPING that URL (never publish again to fix an asset \u2014 that strands the link you shared); find_models searches them, including by part name. 3D GAMES: do NOT assemble primitives at page load \u2014 that is what makes a game look like a pile of boxes, and it costs startup time on every join. Model at DEV TIME with \`npm i antics-modelkit three\`, write a models module, \`npx modelkit build\` to .glb (Khronos-validated, quantised, with collider footprints in manifest.json), and ship the .glb in the files map. get_docs has the full recipe including the importmap the runtime loader needs. | ||
| After deploying under a project, call set_share_preview to brand how its room links unfurl \u2014 set the title (name), description, and image (an https URL or uploaded image bytes) \u2014 and to fill the game's public world page: write about (what the game is) and rules (how to play) for every game. | ||
@@ -505,3 +542,3 @@ VERIFY WITHOUT A BROWSER: after deploy_game, call verify_game with the returned hash \u2014 it runs the game headlessly on the server (screenshot + live state probes via readState paths like "state.score" / "player.self.x", fast-forward with per-tick numeric traces, scripted key/pointer input, console output). Iterate on the numbers, not on screenshots: readState/trace catch bugs a final frame hides. Two-player sync check: verify_game { players: 2 } \u2014 per-page inputs: [{...}, {...}] lets both pages act. | ||
| "publish_model", | ||
| "Publish a 3D MODEL built with antics-modelkit (not a game \u2014 a model joins no rooms). Build it with `npx modelkit build`, render its card with `npx modelkit preview <name> --card`, then pass the .glb and the recipe that generates it. Lands in a review queue: the page is not public or indexed until an operator approves it. The URL is permanent \u2014 to update an asset later use PUT /api/models/<id>, never publish it again, or the link goes stale.", | ||
| "Publish a 3D MODEL built with antics-modelkit (not a game \u2014 a model joins no rooms). Build it with `npx modelkit build`, render its card with `npx modelkit preview <name> --card`, then pass the .glb and the recipe that generates it. Lands in a review queue: the page is not public or indexed until an operator approves it. The URL is permanent \u2014 to update an asset later call update_model, never publish it again, or the link goes stale.", | ||
| { | ||
@@ -521,2 +558,16 @@ name: z.string().describe("What the model is, e.g. 'Vending machine'."), | ||
| server.tool( | ||
| "update_model", | ||
| "Replace a published MODEL's asset in place, KEEPING its /m/<slug> URL \u2014 use this instead of publishing again, which mints a new page and strands the link you already shared. Pass the rebuilt .glb and the recipe that generates it. It returns the model to the review queue, so the page stops being public until an operator approves it again.", | ||
| { | ||
| model: z.string().describe("The slug or id of a model you published \u2014 list_my_models has both."), | ||
| glb: z.string().describe("The rebuilt .glb, base64."), | ||
| recipe: z.string().describe("The models module that generates it. Required: a .glb without its recipe breaks the pairing the page is built on."), | ||
| kitVersion: z.string().optional().describe("The antics-modelkit version it was rebuilt with."), | ||
| summary: z.string().optional().describe("One line for the card and the unfurl."), | ||
| image: z.string().optional().describe("Share card, base64 PNG, exactly 1200x630 \u2014 `npx modelkit preview <name> --card`. Re-render it: a stale card shows the geometry you just replaced."), | ||
| demoFiles: z.record(z.string()).optional().describe("Replacement demo, a path -> content map. Omit to leave the existing demo alone \u2014 but if the geometry moved, the old demo may no longer match it.") | ||
| }, | ||
| async (args) => wrap(await updateModelTool(client, args)) | ||
| ); | ||
| server.tool( | ||
| "find_models", | ||
@@ -523,0 +574,0 @@ "Search published 3D models by name, summary or PART name (e.g. 'coil_r1c2'). Returns URLs; fetch <url>/llms.txt for how to use one in a game. Paged \u2014 pass the returned cursor for more.", |
+1
-1
| { | ||
| "name": "antics-mcp", | ||
| "version": "0.2.6", | ||
| "version": "0.3.0", | ||
| "mcpName": "io.github.antics-gg/antics-mcp", | ||
@@ -5,0 +5,0 @@ "description": "Multiplayer for your game, in one prompt \u2014 an MCP server that lets an AI agent deploy a web game to a playable multiplayer URL (rooms, state sync, leaderboards).", |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
57423
6.37%747
7.64%