SatisfactoryMCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SATISFACTORY_DOCS | No | Path to the game's CommunityResources/Docs/en-US.json file, overriding install auto-detection. | |
| SATISFACTORY_SAVES | No | Override the save directory (default: %LOCALAPPDATA%\FactoryGame\Saved\SaveGames). |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| boostersA | Power Shards or Somersloops: free, committed and owned, and which machines hold them. kind=shards also says whether |
| collected_from_worldA | Map collectibles (slugs, sloops, spheres, mushrooms, drop pods): how many exist, taken, left, closest. Existence is read from the installed game's map data, removal from the save's destroyed-actor list; remaining is the difference. show=census counts per category; collected and remaining list placements with coordinates; nearest lists remaining by distance from near=. A placement this save never loaded counts as remaining, flagged never_streamed. |
| factory_mapA | Raw factory signals: power islands (base:), belt components (line:), foundation slabs (slab:). Also the named factories. Islands merge a grown-together base, belt components fragment it, slabs are sharpest but miss ground-built machines; propose_factories combines them. Where they disagree, carve with edit_factory and a product:, near: or slab: term. show=slabs also lists bare platforms (foundations with no machine) with tile count, extent and elevation. |
| propose_factoriesA | Proposed factories: what is built, clustered by slabs, proximity, belts, shared products and supply. Errs toward splitting: never merges two factories, may return one in pieces. The # column is the proposal: selector other tools take, numbered over all proposals so paging does not shift it. Name one with edit_factory. unnamed_only=true answers 'what have I built and not named'. |
| select_machinesA | Preview which machines a selector picks, before naming them with edit_factory. Run it first on product: terms, which also pick machines feeding that product inside other sites. slab: answers what stands on a platform, and describes an empty one. |
| factory_floorsA | Floors of a foundation platform: how many decks and what stands on each. Floors are recovered from geometry (clustered foundation tops, no assumed pitch); a band under a quarter of the largest deck is marked minor (mezzanine or plinth). Default: one row per platform, largest first. platform= (index stable on one save) or factory= narrows to one platform, answered floor by floor. |
| factory_healthA | Why machines are stopped: measured uptime per machine and each stopped one's cause; 'all' sweeps. Uptime: share of the save's 300 s productivity window spent producing. States, worst first: paused, dead node (extractor on no resource), no recipe, blocked (output full), starved (input short), stalled (input and room, still not running), intermittent, saturated, unmonitored; todo counts the first five. A machine no generator reaches over the wires says so (no wire, or a circuit with no generator); a reachable one is never called unpowered. A starved machine names its missing input's feeder one hop back (the run, its far end, that feeder's state); trace_upstream walks further. A missing fluid is diagnosed on the plumbing ladder: connection, head lift, flow rate; the first failing rung is the cause. factory='all' adds world-wide plumbing faults: fluid buffers too low to output at intake rate, unwired pipeline pumps, lines above head lift. offset pages every table at once. |
| edit_factoryA | Name, amend, rename or forget a named factory (a set of machine ids), or set its storage stance. Ids survive moves and autosaves. name on an existing name replaces its machines. amend adds, drops, then prune_missing clears gone anchors; one machine is machine:; the last can't be dropped. rename: saved plans follow. forget keeps the machines. storage: is full storage at a line's end stock or a blockage. dry_run previews. |
| list_factoriesB | Named factories of this world (the names factory= takes), with how much of each still stands. |
| factory_queryB | One question about one factory: what it makes, needs, draws or touches; show= takes several views. Every rate is nameplate (at the saved clock) and measured (scaled by each machine's 300 s productivity window, so an idle line measures 0 without being broken); unmonitored machines are shown apart. offset pages every table at once. |
| trace_upstreamA | What feeds a machine, factory or building type, or what it feeds, walked on the save's connections. factory_query show=links answers this between named factories; this walks from one seed, e.g. which feed can be repiped without dropping the generators behind it. Direction is read from connector roles or the machine's nature; an edge with neither is walked both ways, so a feeder may be over-reported, never missed. Belts and pipes are walked through, not listed; a note names the runs crossed by the chain:/pipe: ids search_conduits takes. |
| search_itemsC | Find items by name: form, MJ and sink points. |
| recipe_detailC | One recipe's exact numbers: in/out per minute, machine, cycle, power, unlock source. |
| alternates_for_itemB | Every recipe that makes an item, alternates first, marked HAVE/LOCKED against the save. A LOCKED row names the schematic that grants it. With |
| search_recipesB | Search recipes by name, or by what they consume/produce; marks HAVE/LOCKED against the save.
|
| list_buildingsA | Buildings by kind: power, max clock, sloop slots, footprint; marked HAVE/LOCKED against the save.
|
| hard_drivesB | Unclaimed hard drives, each with its pick and why; Measured on this world: shortages, open goals, raw saved on what is built, grid MW.
|
| inventoryA | What you own: per-item totals, or each container, crate and fluid buffer with place and fill (show=containers). spendable = carried + storage + Dimensional Depot, the pool every cost check spends;
machine buffers and crates are shown apart, never added in. Fluids are m3. |
| cratesB | Crates on the ground (death and dismantle crates): contents and where to walk to. Recoverable, never spendable stock. |
| explain_byproductsB | Which byproduct stalls a plan (INFEASIBLE) and what can consume it: sink (solids only) or recipes, unlocked vs locked. Item balances are equalities, so an unconsumed byproduct makes the solve infeasible; a fluid must be consumed or packaged first. Reads an infeasible solve: handle too. |
| compare_recipe_optionsA | Rank whole routes to make an item by cost: raw per unit, buildings, net power, byproducts needing an outlet. Each route is solved end to end (Crude -> Alt HOR -> Diluted Fuel against Crude -> Fuel); alternates_for_item only lists recipes. |
| bomB | Flattened bill of materials for qty/min of an item: raw and intermediate rates, chosen recipe and machines per row. qty is a rate per minute. Solved by LP, not tree expansion (recipe cycles have no safe depth), so each row names its recipe; alternates change the totals. |
| rank_unlocksB | Value of each locked alternate recipe to THIS plan: re-solve with it added and report the delta in the plan's own units. A zero delta is an answer. Deltas are an upper bound: a candidate needing an unbuilt machine is judged as if built, and the machine is named. Alternates on a pending hard drive are flagged as claimable now. |
| plan_from_factoryB | Save a plan mirroring a named factory as built, to edit or extend. Recipes pinned, inputs supplied, surplus exported (sunk under the flow stance); an unedited equal plan is reused. Differences from the build go in the notes. |
| plan_layoutB | Plan to schematic: blocks, buses, floors, materials, space budget; no coordinates or belt routing (site_plan places it). The belt/pipe tier is solved with, so schematic and plan agree. |
| ui_contextA | What the web page has open; call first when the user says 'this', 'here' or quotes an ask: or pin: id. Names the page's view, plan and version, tab and selection, whether the page reads the same save as you, queued asks, advisories (adv: ids), and every plan version or chat solve by someone else since your last look. Listed asks are marked seen on the page; pass answered= once answered. dismissed= hides an advisory, only when the user asks. |
| share_planC | A saved plan as a link that opens a copy on the page, or as a sfplan: line. |
| import_planC | Import a shared plan (link, sfplan: line or file) as a new plan. |
| site_planA | Record, update or clear where a saved plan stands (origin, yaw, footprint). Nothing is re-solved. Origin is the footprint centre in metres; yaw is degrees about world Z as the save stores facing; footprint defaults to plan_layout's square for the largest floor, and the record says whether it was measured or derived. A siting is a record, not a constraint: re-solving ignores it, save_as over the same name keeps it. Once sited, recalls print it, diff_vs_save adds an approximate on-pad census, show_on_map at='plan:' centres on it. |
| plan_factoryA | Solve a factory plan by LP over this world's unlocked recipes: machines, rates, power, exports, byproducts. sources= node selectors, combinable; omit = whole map: "north", "region:Northern Forest",
"near:@<radius_m>", "node:" (search_resource_nodes lists ids), "grid:X3Y4",
"resource:Crude Oil".
objective: max_mw | max_item | min_raw | min_raw_power | min_machines | min_power.
Omitted: min_raw_power when export_minimums asks for an item, else max_mw. Machine
counts are whole buildings at one derived clock.
exports= whitelist of what may leave, REPLACING the default (omitted: a goalless rate
exports its items on grid power, else power only); [] = only export_minimums, grid power.
Listing "MW" exports power and forbids grid draw: ["MW","Plastic"].
extractor_clocks overclocks source nodes only; clocks spreads a row over more, slower
machines at machine_cost_mw each. Power Shards are not counted.
required= recipes (exact name or class id) that must make their item, excluding their
rivals; a locked one is refused.
save_as= stores the request, never the solution; over an existing plan pass base_rev.
plan= recalls a saved plan and re-solves it.
Unsaved, the answer ends |
| diff_vs_saveA | Steps from the factory as built to a plan: UNPAUSE, SETRECIPE, then BUILD, with the power the new machines add. Re-solves the plan. Machines match by identity (building + recipe; generators by building; extractors by node), never by position; one on another recipe is busy. Water Extractors cannot be identified, so their count is a range. A saved plan's diff is grouped by startup stage (commission_plan's partition): stage=n narrows to one, stage=0 shows the stage overview of an unsaved solve. Power is proven one way only: a machine that produced in its last 300 s had power; one that did not is 'nothing proven running', never 'unpowered'. Read-only, no dismantle action: machines on the plan's ground but not in it are listed for you to judge. |
| commission_planA | Startup order for a built plant: which blocks to energise in which wave without blowing the fuse. Not a build order: build everything first, then energise wave by wave. A wave's consumer draw must fit in headroom plus the output of generators already burning, or the fuse blows and stops the whole grid until reset by hand. Generators energise free and pay for the next wave. |
| plansA | List this world's saved plans (version, last change, world moved?), or one plan's versions with name=. With name=, show='request' prints the stored arguments, what the selectors resolved to and the siting, solving nothing; a forgotten plan is found too. Pass the version (v14 -> base_rev=14) to any tool that changes the plan; edit_plan renames, forgets, undoes, restores. |
| edit_planA | Rename, forget, undo or restore a saved plan; each edit is a new version and needs base_rev. Nothing is re-solved. rename keeps key, siting and notes; forget deletes it (undoing that version brings it back); undo writes the inverse of version=; restore makes the head equal version= again. |
| phase_requirementsC | Space Elevator: the current phase and what it still wants. The save's per-phase item table is deprecated; trust the header line over it. |
| researchA | HUB milestones or MAM research: what is left, what it costs, what spendable stock affords now. HUB: READY is about the bill; a tier the Space Elevator has not opened shows the phase
that opens it (phase_requirements). MAM rows marked LOCKS gate a capability (Depot,
Power Augmenter, Somersloop amplification), not a recipe. |
| settingsA | Settings the page and chat share; change one only when the user asks. stage_headroom: what diff_vs_save and commission_plan stage a plan against when it stores none. biomass: default of every biomass= parameter. payback_hours, overclock_last: what a plan that sets neither follows. The page's Settings tab shares the file and follows a change. Base map types are listed read-only. |
| search_conduitsA | Belt and pipe runs near a place or between two areas: both ends, length, elevation, what each end connects to. A run is one belt chain (split at splitters, mergers and machines) or one placed pipe;
longest first; its id (chain:, pipe:) is a place every tool takes. Proximity is
measured against the drawn line, so a run crossing mid-span counts. |
| show_on_mapA | Map links centred on a place: this project's map (draws your save) and the public one (vanilla world, nothing built). 'resource:' centres on every node of that resource with its overlays on (Crude
Oil layers confirmed; a wrong token still opens the right place). |
| search_resource_nodesA | Resource nodes as fields (clusters within 200 m, by yield), nodes (one row each) or nearest (by distance from near=).
|
| rank_build_sitesA | Rank fields for a new extraction site of one resource, best first. Scores untapped reachable capacity against spread, distance to your buildings, purity
and terrain; every raw component is shown to re-weight, the score is a start, not a
verdict. |
| list_regionsA | Named map regions with anchor coordinate, area and node count; Names are advisory (boundaries about 256 m); any name works as a region: selector. The anchor provably lies inside the region. |
| describe_locationA | What is at a place: region, terrain height, sampled elevations, belts and pipes through it, nearest node and field. terrain_m is the terrain field's reading at the point (water surface and depth where it stands); ground and built elevations are sampled from nodes and buildings within radius_m, never averaged, and their gap is fill already stacked. Conduit counts read the save: zero means nothing runs through; search_conduits lists them. |
| whereamiB | Where the player stands, and the nodes, buildings and cave around them. Position is the save's, so an autosave can be minutes stale. |
| list_worldsB | Saves grouped by world, newest first: the names save= and world= take (default: newest save). world= lists one world's saves, offset= pages them. |
| world_summaryB | One-screen overview of a world: progress, power, problems and advisories (adv: ids). |
| unlocked_recipesC | Recipes this world has unlocked; alternates only unless only_alternates=false. Paged by offset=. |
| power_reportB | Grid generation capacity vs machine draw, nameplate and measured, and what is free now. Nameplate: everything built running at once. Measured: each machine weighted by its 300 s productivity window. Generation is capacity on both, except a generator out of fuel or water whose monitor read zero is listed starved: those MW will not arrive. |
| factory_sitesC | Built production buildings clustered by distance into sites, largest first, each with a near: selector. The selector goes in as a select= term or as factory=; propose_factories groups by more than distance. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 49 tools
Most tools are clearly differentiated by detailed descriptions, but several related clusters blur at the edges, e.g. factory_map/propose_factories/factory_sites and plan_factory/plan_from_factory/plans. An expert agent can usually select correctly after reading, but the cognitive load is high enough to risk occasional misselection.
All tool names consistently use snake_case and are readable. The convention is not strictly verb_noun throughout, since noun-only tools like inventory, crates, plans, and bom mix with verb-led names, but the deviations are minor.
At 49 tools, the surface is far above the 3-15 well-scoped range and squarely in the rubric's 25+ 'too many' band. Even for a deep Satisfactory planning domain, this many tools create significant selection overhead and should be consolidated into narrower groups.
Coverage is broad across planning, factories, recipes, resources, inventory, research, power, and map views, with few obvious dead ends for core workflows. Minor gaps remain around vehicle/train logistics and direct build/dismantle actions, but the main domain lifecycle is well supported.