{"ok":true,"site":{"host":"arcana-table.pages.dev","url":"https://arcana-table.pages.dev/","type":"live","desc":"A WebMCP-powered tabletop where an AI agent co-runs the game — and real exercise earns heroic dice. Do the push-ups, claim the natural 20.","tools":[{"name":"get_board_state","kind":"answer","impl":"imperative","description":"Read the full game board: scene, map grid with legend, all tokens with positions and HP, combat status, active Heroic Effort boosts, party loot, and the recent story log. Call this first, and again whenever you need fresh eyes on the table.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_character_sheet","kind":"answer","impl":"imperative","description":"Read a character sheet: HP, AC, ability scores, conditions, inventory. Defaults to the first player character.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"tokenId":{"type":"string","description":"Token id or name, e.g. \"Brannok\""}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_fitness_log","kind":"answer","impl":"imperative","description":"Read the session workout log: total reps, reps per exercise, challenges completed, dice rewards earned, unspent boosts, and any challenge in progress. Use it to pace the player — vary muscle groups and scale reps to how they are doing.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_quest","kind":"answer","impl":"imperative","description":"Read the run: which of the five beats the party is on, its objective, what is already done, what is still ahead, and whether a hero is down. Call this when you are unsure what the party should be doing — this is the destination the whole session is driving toward.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"advance_quest","kind":"act","impl":"imperative","description":"REFUSED while combat is running or the beat's own monster still stands — a beat is cleared over the body, not around it. Mark the current beat achieved and move the run to the next one. This pays out the milestone loot, swaps the map when the next beat is elsewhere, and on the final beat spawns the boss. Call it the moment the party has actually done what the objective asked — never before, and never twice for the same beat. Advancing past the last beat wins the run.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"summary":{"type":"string","description":"One line on how the party pulled it off, in DM voice"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"roll_dice","kind":"act","impl":"imperative","description":"Roll dice on the table, visibly, with animation. Formula like \"d20\", \"2d6+3\". Any earned Heroic Effort boosts (bonus, advantage, or a set die) apply automatically to a single d20 and are consumed. Rolls are public — no fudging. PACED: after two rolls with nothing staked this refuses once and asks you to offer a Heroic Effort or an Oath for the roll first — so stake something roughly every other roll and you will never see it.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"formula":{"type":"string","description":"Dice formula, e.g. \"d20\" or \"2d6+3\""},"reason":{"type":"string","description":"What the roll is for, e.g. \"Brannok attacks the goblin\""}},"required":["formula"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"narrate","kind":"act","impl":"imperative","description":"Speak as the Dungeon Master: describe rooms, voice NPCs, react to rolls. Text is posted to the story log the player reads. Keep it vivid and under ~60 words per call.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"Narration text"},"speaker":{"type":"string","description":"Optional speaker label, default \"DM\""}},"required":["text"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_scene","kind":"act","impl":"imperative","description":"Retitle the scene and set its mood line. It CANNOT change the map: each quest beat owns its map and only advance_quest moves the party between them — because that is the call that pays the milestone. Passing a different mapId is refused and points you at advance_quest.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"mapId":{"type":"string","enum":["dungeon","forest","crypt"],"description":"Which battle map"},"title":{"type":"string","description":"Scene title"},"mood":{"type":"string","description":"One-line mood, shown under the title"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"reveal_area","kind":"act","impl":"imperative","description":"Clear fog of war in a circle. Use when the party gains sight of a new area.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"x":{"type":"number","description":"Grid x (0-21)"},"y":{"type":"number","description":"Grid y (0-13)"},"radius":{"type":"number","description":"Cells, default 3, max 10"}},"required":["x","y"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"move_token","kind":"act","impl":"imperative","description":"Move a token to a grid cell (walls are rejected). The move animates on the board. Moving a PC also reveals fog around them.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"tokenId":{"type":"string","description":"Token id or name"},"x":{"type":"number","description":"Grid x (0-21)"},"y":{"type":"number","description":"Grid y (0-13)"}},"required":["tokenId","x","y"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"attack","kind":"act","impl":"imperative","description":"Make one attack and resolve it: rolls to hit against the target's AC, applies damage, and lifts the fog around whatever was hit. REACH IS ENFORCED HERE — a melee attack must be adjacent (or within the attacker's reach) and will be REFUSED with the exact cell to move to if it is not; ranged and spell attacks work out to the attacker's range. Use this for every swing, shot and spell instead of rolling dice and adjusting HP by hand: it is what keeps the board honest, and any Heroic Effort boost the player earned is spent on the roll automatically.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"attackerId":{"type":"string","description":"Who is attacking — token id or name"},"targetId":{"type":"string","description":"Who they are attacking — token id or name"},"kind":{"type":"string","enum":["melee","ranged","spell"],"description":"melee needs adjacency; ranged and spell work at the attacker's range"},"damage":{"type":"number","description":"Damage on a hit. Omit for a sensible default (more on a critical)."},"reason":{"type":"string","description":"What the attack is, in DM voice — \"Brannok brings the longsword down\""}},"required":["attackerId","targetId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"move_party","kind":"act","impl":"imperative","description":"Move the WHOLE party to a grid cell in one call — use this whenever the players travel: through a door, into the next room, across the hall, following something. The leader lands on the cell, companions take open cells beside them, and the fog lifts around all of them. Walls are rejected. Prefer this over repeated move_token calls: if you describe the party going somewhere, call this in the same turn or the board will contradict you.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"x":{"type":"number","description":"Grid x (0-21)"},"y":{"type":"number","description":"Grid y (0-13)"},"who":{"type":"string","description":"Omit to move everyone. A token id or name moves only that hero."}},"required":["x","y"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_token","kind":"act","impl":"imperative","description":"Spawn a creature or object on the board. Eleven creature arts plus a chest: goblin, skeleton, dragon, wolf, ooze, spider, wraith, ogre, rat, warden (a carved stone guardian), knight, wizard, villager. NEVER use \"knight\" or \"wizard\" for an enemy — those are the player's own heroes, and the board would look like the party is fighting itself. Pick the one that actually fits what you are describing, and vary it — a hall of identical goblins looks like a bug, not an encounter.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Display name, e.g. \"Snaggle the Goblin\""},"kind":{"type":"string","enum":["monster","npc","object"],"description":"What it is"},"art":{"type":"string","enum":["knight","wizard","goblin","skeleton","dragon","wolf","ooze","spider","wraith","ogre","rat","warden","wight","chest","villager"],"description":"Token art. VARY IT — do not spawn two of the same art in one scene if another fits."},"x":{"type":"number","description":"Grid x"},"y":{"type":"number","description":"Grid y"},"hp":{"type":"number","description":"Hit points (also max HP unless maxHp given)"},"maxHp":{"type":"number","description":"Max hit points"},"scale":{"type":"number","description":"How big it draws, 1-2.5. Leave it at 1 for ordinary creatures; use 2 for a boss you want to read as one from across the room."}},"required":["name"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"remove_token","kind":"act","impl":"imperative","description":"Remove a token from the board (defeated monster, opened chest). Clearing monsters and objects is immediate; removing a PLAYER CHARACTER requires the player's approval — that call waits for their ✓.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"tokenId":{"type":"string","description":"Token id or name"}},"required":["tokenId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"start_combat","kind":"act","impl":"imperative","description":"Begin initiative. Registers the combat tools. Every combatant comes out of the fog. MONSTERS ACT ON THEIR OWN TURN: if a monster wins initiative it closes and attacks the nearest hero immediately, and the result comes back in monstersActed — narrate it, then hand the turn to the player. You never need to make a monster swing; the turn order does it.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"order":{"type":"array","items":{"type":"string"},"description":"Optional initiative order (token ids or names)"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"end_combat","kind":"act","impl":"imperative","description":"End combat and clear initiative. The combat-only tools unregister.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"award_loot","kind":"act","impl":"imperative","description":"Grant treasure to the party: items and/or gold. Shows up in the party panel and story log.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"string"},"description":"Item names"},"gold":{"type":"number","description":"Gold pieces"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"propose_challenge","kind":"act","impl":"imperative","description":"HEROIC EFFORT — stake a real exercise against the dice. Offer this before a roll that matters: the player does the reps, the reward auto-applies to their next d20. Always optional. Effort and reward scale together — five push-ups is worth +2, ten is worth +5, twenty-five buys a natural 20 — so ask bigger when you want to pay bigger. OFFER OFTEN: about every second exchange, not once a session. ALWAYS check get_fitness_log first: offer ONLY from its availableExercises list for mode \"reps\", and ONLY from its availableHolds list for mode \"hold\" — those are the sets this player can actually do, and the two lists are not interchangeable. The call resolves when the player finishes or declines (or returns \"pending\" if they take longer than 90s — check back with get_fitness_log).","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"mode":{"type":"string","enum":["reps","hold"],"description":"reps = counted repetitions (default) · hold = a timed hold, e.g. a plank or a stretch"},"exercise":{"type":"string","enum":["push-ups","crunches","jumping jacks","squats","sit-ups","lunges","high knees","mountain climbers","burpees","plank","side plank","high plank","wall sit","squat hold","dead hang","hollow hold","glute bridge"],"description":"A rep exercise for mode \"reps\", or a hold for mode \"hold\""},"reps":{"type":"number","description":"Repetition count for mode \"reps\" (1-100). Keep it achievable: 5-25 for most people."},"seconds":{"type":"number","description":"Hold length in seconds for mode \"hold\" (5-300). 20-45s is a real hold for most people."},"reward":{"type":"string","enum":["bonus+2","bonus+3","bonus+5","bonus+8","advantage","set10","nat20"],"description":"What it buys. PRICE LIST — 5 reps/20s → bonus+2 · 8/25s → bonus+3 · 10/30s → bonus+5 · 12/40s → advantage · 15/45s → bonus+8 · 20/60s → set10 (next d20 is a 10) · 25/90s → nat20 (next d20 is a natural 20). Ask bigger, pay bigger. OMIT this and the size of your ask picks the right one."},"reason":{"type":"string","description":"Why fate demands sweat right now, in DM voice"}},"required":["exercise"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"propose_task_list","kind":"act","impl":"imperative","description":"A TASK LIST instead of a single ask: put 2-3 small pieces of effort on the table at once, each worth its own flat bonus, and let the player tick off whatever they actually do. Five push-ups (+2), a twenty-second plank (+2) and five squats (+2) means the whole card is +6 — but two out of three is +4 and that is a real result. Reach for this when you want the best odds of getting SOMETHING: a player who would decline one big ask will usually take part of a list. Bonuses add up, so this never pays advantage or a natural 20 — use propose_challenge for those. Modes per item: \"reps\", \"hold\", or \"oath\" (a real-world task, amount in minutes).","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"items":{"type":"array","minItems":2,"maxItems":4,"description":"2-3 items. Each: {exercise, mode, amount}. For mode \"oath\", put the task itself in \"exercise\", e.g. {\"exercise\":\"clear the sink\",\"mode\":\"oath\",\"amount\":10}.","items":{"type":"object","properties":{"exercise":{"type":"string","description":"Exercise name for reps/hold, or the task itself for an oath"},"mode":{"type":"string","enum":["reps","hold","oath"],"description":"reps · hold (seconds) · oath (minutes)"},"amount":{"type":"number","description":"Reps, or seconds for a hold, or minutes for an oath"}},"required":["exercise"]}},"reason":{"type":"string","description":"Why, in character — what is at stake on this roll"}},"required":["items"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"propose_oath","kind":"act","impl":"imperative","description":"OATH — the other way to pay. Stake something real in the room that this app cannot see: clearing the sink, twenty minutes of study, ten pages of reading, practising an instrument, one dreaded email. The table LOCKS for the minutes agreed — the board freezes, you wait, and the player confirms on their honour when they return. It pays exactly the same dice rewards as a Heroic Effort, and you must treat it as an equal, never a consolation prize. Reach for it when a player cannot or would rather not exercise, when they mention something they are avoiding, or simply to vary what the table asks of them. Keep the minutes honest: 5-25 for most things.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"label":{"type":"string","description":"The actual commitment, in their words: \"clear the sink\", \"read 10 pages of the textbook\""},"kind":{"type":"string","description":"chores · study · reading · practice · admin · tidy"},"minutes":{"type":"number","description":"How long the table waits (1-60). Match it to the real job."},"reward":{"type":"string","enum":["bonus+2","bonus+3","bonus+5","bonus+8","advantage","set10","nat20"],"description":"Same rewards as a Heroic Effort"},"reason":{"type":"string","description":"Why the fates accept this, in DM voice"}},"required":["label","minutes","reward"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"start_warmup","kind":"act","impl":"imperative","description":"Offer the guided warm-up: twenty standing stretches, head to ankle, each with a cue and a self-advancing timer. CALL IT WITH NO PLAN and a card appears asking the player to pick 90 seconds, 3 minutes, 5 minutes, or skip — that is what you want almost every time, at the very top of a run. Say one warm line inviting them to stand up, then WAIT for them to choose; do not pick for them. Pass a plan only if the player has already named one out loud. Finishing grants +2 on the first roll.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"plan":{"type":"string","enum":["90s","3min","5min","10min"],"description":"Omit this to show the choice card, which is the normal use"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","favicon":"/favicons/arcana-table.pages.dev.svg","apiSurface":"spec","toolCount":21}}