Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
SATISFACTORY_DOCSNoPath to the game's CommunityResources/Docs/en-US.json file, overriding install auto-detection.
SATISFACTORY_SAVESNoOverride 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

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
factory_mapA

Proposed factories, from power islands and belt topology, plus what is named.

Three independent signals are reported rather than one answer, because none is right alone: power islands separate outposts but leave a grown-together base as one 476-machine blob; belt components shatter that blob into fragments; foundation slabs are the sharpest of the three but say nothing about the ground-built parts of a factory. Where they disagree, carve the difference with name_factory and a product:, near: or slab: selector.

show=slabs also lists BARE platforms -- poured foundations carrying no machine yet -- with tile count, extent, bounding box and elevation, because a freshly built platform is a real place a build plan refers to. Pads under a stated tile threshold are summarised in one line.

factory_queryA

Ask one thing about one factory: what it makes, needs, draws, or touches.

show accepts several at once, e.g. "balance,power,links". offset pages every table in the answer at once, so asking for one aspect at a time is what you want when a factory has more machines than fit.

  • summary size, position, top recipes, net power

  • balance per-item produced vs consumed vs net -- the sign is the point

  • outputs net surplus: it leaves the factory, or it backs up

  • inputs net deficit: it has to be fed in from outside

  • internal made and eaten inside the set -- the mark of a self-contained line

  • machines every machine with its building, recipe and clock

  • recipes / buildings counts

  • power draw vs generation, nameplate AND measured -- which factory is really burning the grid, rather than which could

  • nodes resource nodes its extractors sit on

  • links which other factories it exchanges material with

  • issues paused, recipe-less, or unresolved machines

Every rate is printed twice. NAMEPLATE is the machine's recipe rate at its saved clock, which a starved factory still reports in full. MEASURED is that rate scaled by the share of its own productivity window each machine spent producing -- the window that ended when the save was written, so a line idle at that moment measures 0 and is not broken. A machine keeping no monitor is left out of measured entirely and shown separately, because counting it in full there would invent output.

factory_healthA

Measured uptime per machine, and WHY each stopped one is stopped.

The only measured numbers in this MCP. Every manufacturing building keeps a fixed 300-second productivity window; uptime is seconds-producing over that window.

States, worst first: paused, dead node (extractor bound to no resource -- a game update removed it), no recipe, blocked (output stack full), starved (input empty), stalled (has input, output has room, still not running), intermittent, saturated, unmonitored.

A stalled machine no generator can reach over the wires says so in its cause, and every such machine is named in a note whatever state it is in -- separately for "no wire at all" and "wired to a circuit no generator stands on", which are different builds to finish. The save records no "has power" flag, so a machine a generator CAN reach is never called unpowered here whatever the grid is doing: the wire is the only electrical fact the file carries.

For a STARVED machine it also says what physically feeds the input it lacks: the run that arrives, what stands at its far end and that feeder's own state, ONE hop back -- trace_upstream walks the rest. "No conduit of that medium arrives" and "one arrives and the save joins its far end to nothing" are different rows and are never merged.

A missing FLUID is diagnosed on the plumbing manual's own ladder -- (1) connection, (2) head lift, (3) flow rate -- and the cause names the FIRST rung that fires, so a line that cannot climb to the machine is never answered with its supply rates. Solids have no head-lift rung and read exactly as before.

Blocked counts as needing action, alongside dead node, no recipe, starved and stalled: a full output box means nothing is taking what the machine makes. The sweep's todo column counts those five.

The sweep over every factory also reports three plumbing faults that belong to no machine set: fluid buffers holding too little to output at their intake rate, pipeline pumps no wire reaches, and points where a line climbs above the head lift pushing it. All three are world-wide there, not scoped to a factory.

offset pages every table in the answer at once, worst first throughout.

propose_factoriesB

One coherence score over every signal, agglomerated into proposed factories.

Combines foundation slabs, proximity, belt connectivity, shared products and supply links. Validated leave-one-factory-out against the player's twelve hand-named factories: precision 1.000, recall 0.945, and precision was 1.000 on every fold -- it never merges two factories, it only ever splits one.

Use name_factory on what it proposes. unnamed_only=True answers "what have I built and not named". The # column is the proposal:<n> selector every other tool takes, and it counts over ALL proposals -- so it does not shift when you page.

select_machinesA

Preview which machines a selector picks, before naming them.

Worth running first on anything product-based: 17 machines make Concrete on the reference save, but 15 of them are a construction feed inside the steel site and only one is the player's "concrete setup".

slab:<n> answers "what stands on this platform", and answers it for an empty one too: a poured platform with nothing on it yet is described rather than refused.

name_factoryA

Name a set of machines and persist it for this world.

The label stores the machine instance ids, which are stable across saves, so it survives moving machines, adding to the factory, and autosave rotation. Calling this again with the same name RE-ANCHORS it to the current selection, dropping every machine the new selector misses -- amend_factory adds or drops a few without that, and rename_factory changes the name without touching the membership.

rename_factoryB

Rename a factory label. The machines it holds are not touched and nothing re-anchors.

The label keeps its anchors, notes, centroid, signature and dates -- the name is the only thing here a player picked, and correcting one used to mean naming the whole selection again under a second name and forgetting the first.

Stored plans scoped to this factory follow the new name. Renaming onto a name this world already uses is refused and says which label holds it.

amend_factoryA

Add or drop individual machines on a label, without re-anchoring the rest of it.

name_factory re-anchors a label to whatever its selector picks, so correcting one wrongly-included machine meant re-selecting the whole factory. This edits the membership: every anchor add and drop do not name is left exactly as it was, including ids this save no longer has.

add runs first, then drop, then prune_missing, which clears the anchors list_factories reports gone. One machine is machine:<instance> on either side. Dropping the last machine is refused -- deleting a label is forget_factory.

list_factoriesC

Named factories for this world, with how much of each is still standing.

forget_factoryB

Delete a factory label. The machines themselves are untouched.

trace_upstreamA

What feeds a machine, or what it feeds -- walked on the save's own connections.

factory_query answers this between LABELLED sets. This answers it for one machine or one building type, which is the question a cutover actually asks: thirteen Oil Extractors sit on the Spire nodes and twenty Fuel Generators are burning, and repiping the wrong extractor first drops several GW.

Direction is READ, not guessed. Every material edge carries its connector role, and 92.5% of the connectors landing on a machine name their direction outright; the rest are all on extractors or generators, whose own nature settles them. Where even that fails the edge is walked BOTH ways -- over-reporting a feeder is recoverable, missing one is not.

Belts and pipes are walked THROUGH and left out of the table: a trace from the generators touches 331 nodes at depth 72, nearly all of it conveyor. What the route crossed is named instead in a note -- how many runs of each medium, and the ids search_conduits takes for the ones that have them.

factory_floorsA

How many decks a factory has and what stands on each.

Nothing in the save says "floor". Floors are recovered from geometry: a platform is a 4-connected run of 8 m foundation cells, and its storeys are the levels its tops cluster at, with no assumed storey pitch. A band holding less than a quarter of the platform's largest deck is marked minor -- a mezzanine or a machine plinth, reported rather than merged away.

Whole-world by default: one row per platform, largest first. Narrow with platform= (an index that is stable across calls on one save) or factory=, and a single platform is answered floor by floor instead.

search_itemsC

Find items by name. Returns form, energy and sink points.

recipe_detailA

Exact numbers for one recipe: rates, machine, power, unlock source.

Takes a class id OR a display name. Refusing the name cost a caller two round trips to fetch an id this function could resolve itself, which is a poor trade for strictness that buys nothing -- match_recipes already does exactly this resolution for exclude_recipes.

alternates_for_itemB

Every automatable recipe that makes an item, alternates first.

When a save is readable, each row is marked HAVE or LOCKED, and a LOCKED one says which schematic would grant it -- a hard drive and a milestone are different work.

search_recipesA

Search recipes by name, or by what they consume/produce. Marks HAVE/LOCKED.

consumes="Rubber" is the reverse lookup: every recipe that eats an item. recipe_kind is "part" (default), "building" (build-gun costs), "manual" or "all" -- and the header counts EVERY kind over the whole recipe table whatever it is set to, so a part-only view still says how many buildings eat the item.

list_buildingsA

Buildings by kind: production, extractor, generator, logistics, foundation, ramp, wall, pillar, beam, architecture (all five families together), or all.

Rows are marked HAVE or LOCKED against the save when one can be read. That matters most for logistics: a planner assuming a belt or pipe tier it has not unlocked gets every line count wrong by a factor and nothing says so, which is the worst failure mode a planner has.

Paged: all is 539 buildings and unpaged it ran to ~60k characters, which is not an answer, it is a context eviction. The envelope says how many more there are and which offset fetches them.

list_pending_hard_drive_choicesC

The pending hard-drive choices stored in the save, with rerolls left.

advise_hard_drive_pickA

Rank one pending drive's options by marginal value, via counterfactual LP.

Each option is solved for and against across several objectives, because a recipe can be worthless for power yet excellent for parts. Deltas are reported per objective and never collapsed into one score.

sources is plan_factory's selector list and means the same thing here, so the baseline printed is the same quantity plan_factory reports for the same nodes.

stockA

What you own, by item: spendable stock apart from what merely exists.

Spendable is carried + storage + Dimensional Depot -- exactly the set every affordability check in this surface spends. Machine buffers and crate contents get their own columns and are never added in: buffer material is in transit, and a crate exists because something went wrong and deletes itself when emptied.

where=True answers "and where is it": one row per container or crate holding the item, with the region it stands in and its coordinate. Carried and Depot stock has no place, so it is reported on the summary line instead. Fluids are in m3.

storageA

Which container holds what, where it stands, and how full it is.

Every storage container, Personal Storage Box, Depot uploader and fluid buffer the player built -- not splitters and mergers, whose one to three items in transit are not stock, and not machine buffers, which belong to their machine. Fullest first, or by how much of item they hold when one is named.

fill is measured, not stated by the save: a container is its used slots over its slots, stacking each item at its own stack size, and a buffer is its m3 over what the class holds. It is - where either number is unknown.

cratesB

The crates lying on the ground: what is in each one and where to walk to get it.

A death crate is what you dropped when you died; a dismantle crate is the overflow from dismantling with a full inventory. Both are recoverable and NEITHER counts as spendable stock -- a crate deletes itself the moment it is emptied, so a plan that spent it would depend on somebody walking back there first.

Whose crate it is the save does not say: the crate's only saved property is its type, so there is no owner, no timestamp and no cause to report.

list_plansA

Plans saved for this world, their versions, and whether the world has moved under them.

name prints one plan in full instead: the arguments as they were stored, what its source selectors resolved to when saved, and its whole siting. Nothing is solved, so this answers "what did I ask for" -- plan_factory plan=<name> answers the other question, what those arguments resolve to today, and pays an LP solve for it.

Every plan carries a version (v14). Pass it as base_rev to any tool that changes the plan; plan_log lists the versions and undoes them.

forget_planA

Delete a saved plan. Nothing in the world is touched, and plan_log can undo it.

rename_planA

Rename a saved plan. Nothing is re-solved and nothing else about it changes.

The plan keeps its key, its recorded field, its siting and its notes -- a name is the only thing here a player picked, and it was the only thing they could not correct without saving the plan again under a second name and forgetting the first.

site_planA

Record, update or clear WHERE a stored plan stands. Nothing is re-solved.

A plan stores what to build; this stores where -- origin (x, y and optionally z, in metres, at the footprint's centre), orientation (yaw about world Z, the same convention the save stores machine facing with), and footprint (width x depth, metres). The footprint defaults to the square plan_layout budgets for the plan's largest floor, and the record keeps track of whether it was measured or derived.

Once sited: plan recalls print the siting; diff_vs_save plan=<name> adds an approximate what-stands-on-the-pad census; show_on_map at='plan:<name>' centres a map link on the origin.

The siting is a RECORD of your decision, not a constraint on the solve -- re-running the plan neither reads nor moves it, and save_as over the same name keeps it.

plan_factoryA

Optimise a factory with an LP over this world's unlocked recipes.

sources says which resource nodes may feed the plan, as a list of selectors -- named regions, radii, grid cells, compass directions, or specific node ids::

["north"]                        everything in the northern half
["region:Northern Forest"]       one named region
["near:0,-2000@900"]             within 900 m of (0, -2000) metres
["node:BP_ResourceNode30_103"]   one exact node (repeatable)
["grid:X3Y4", "grid:X3Y5"]       specific grid cells
["north", "resource:Crude Oil"]  narrow a location to one resource

Omit it and the whole map is in scope. Use search_resource_nodes to discover ids.

Machine counts are whole buildings at a derived clock: a 52.8 machine-equivalent result is reported as 53 machines at 99.6%. That is exact, always a clean ratio, and provably the power-optimal way to run that throughput, so ordinary ratio underclocking is automatic and needs no parameter.

extractor_clocks overclocks the SOURCE NODES only, e.g. [1.0, 1.5, 2.0, 2.5]. That is the usual play: a node set is fixed, so speed is the only way to get more out of it, whereas overclocking production machines mostly burns power. Each machine above 100% needs Power Shards, which nothing here counts.

clocks is only for asking a different question: passing [0.5, 1.0] lets the solver SPREAD throughput over more machines to save power, which is real but not free, so each machine is priced at machine_cost_mw (default 5 MW, just above the 2.58 MW/machine that trade was measured to be worth). Overclock modes are not offered by default because they consume Power Shards, which nothing here counts.

objective: max_mw | max_item | min_raw | min_machines | min_power. Every item is balanced as an EQUALITY, so a byproduct with no consumer makes the plan infeasible rather than silently vanishing.

exports is the whitelist of what may leave, and the single most load-bearing argument here; default is power only, which is often infeasible for crude oil::

exports=["MW"]                        power out, plant must be self-powered
exports=["Plastic", "Rubber"]         items out, NO power export
exports=["MW", "Plastic", "Rubber"]   both -- MW must be listed explicitly

Two things worth reading twice. The power token is MW (mw, power and Power all work too), not the item name of anything. And exports replaces the default rather than extending it: naming an item drops MW, which is deliberate, because exporting MW also forbids drawing from the existing grid. A token matching no item is refused by name rather than solved around.

sloops is a BUDGET, not a switch: it is how many Somersloops you will actually commit, and the solver spends up to that many wherever they buy the most. Default 0 spends none, because only a fixed number exist on the whole map and a plan that quietly assumed them would be unbuildable. Each one costs 4x power for 2x output on its machine, so they are placed one at a time across many machines rather than filling one -- output is linear in sloops and power is quadratic, so spreading wins.

required names recipes (exact name or class id) that must make their item: every other recipe whose main product is that item is excluded. A locked or banned one is refused by name.

logistics_items pins named items into the belt/pipe table however small their flow, as rows ADDED to the limit biggest by volume. Without it, a two-item question can fall off the bottom of a big plan's flow table.

save_as stores the request. Over an existing plan it needs base_rev, the version you read (list_plans name=): edits to different settings since then merge, the same setting changed by someone else is refused as outdated and nothing is saved.

site_at says where the plan will STAND. On its own it makes the plan's water assumption MEASURED rather than assumed: the terrain at that pad is read and the note quotes how much of it is under water, at what level, and how far below the dry ground. It never changes a number the LP produced -- how many extractors a body of water holds is placement geometry no data here carries. With save_as it is also recorded, with yaw and footprint, so later calls can answer "does what stands there match it" (diff_vs_save) and "show me" (show_on_map at='plan:'); a recalled plan that was sited is measured at its own site without being told again. Use site_plan to set or move the siting of an already-stored plan.

plan_layoutA

Turn a plan into a buildable schematic: blocks, buses and floors.

Same arguments as plan_factory, plus show: "floors" (default, the stack), "blocks" (every module with its size and rates), "buses" (item flows), "trunks" (which resource nodes share each pipe or belt run into the site), "materials" (what the whole thing costs to build, machines plus deck), or "sites" (cut the plan into named modules and report what crosses between them).

This is a SCHEMATIC, not a blueprint. It gives modules, connections, floor assignment and a space budget. It deliberately does NOT give world coordinates or belt routing -- there is no terrain data here, so those would be invented.

Blocks are split by throughput: 46 Refineries needing 1380 m3/min of crude cannot share one manifold when a Mk2 pipe carries 600, so that is 3 blocks. Floors follow chain depth, with a logistics deck between each pair of production floors.

diff_vs_saveA

What to change to get from the factory you have to the one plan_factory plans.

Takes exactly plan_factory's arguments and re-solves, because the server keeps no state. Both tools print a plan id hashed over the arguments AND the save-derived solve inputs, so two responses carrying the same id are provably the same plan.

Machines are matched by IDENTITY, never by position: a manufacturer on (building, recipe), a generator on its building alone since its fuel is piped in rather than set on the machine, an extractor on the node it occupies. A Refinery running some other recipe is busy, not spare, so it never counts toward the plan.

Actions are ordered free-first -- UNPAUSE, then SETRECIPE on machines that produce nothing today, then BUILD. Stages follow the plan's own chain depth and the power arithmetic is INCREMENTAL, charging only the machines you have yet to place. Where a machine cannot be identified at all (Water Extractors have no recipe and no resolvable node) the answer is a RANGE, never a number.

Recall a stored plan with plan= and the diff is also grouped by STARTUP STAGE -- the same partition commission_plan emits -- so it answers "which stage am I in". stage=<n> narrows to one stage's delta; stage=0 asks for the overview without a stored plan, at the cost that the numbering moves when the arguments do.

Built and energised are DIFFERENT states and the save separates them in one direction only: a machine that produced in the last 300s window certainly had power, while one that did not may be unpowered, starved, blocked or idle. Grid membership is not persisted at all, so a stage is never reported as "unpowered" -- only as built with nothing proven running, which is exactly what a finished but not-yet-energised block looks like.

Saves are read-only: this never proposes writing one, and there is no dismantle action. Machines standing among the plan but not in it are listed for you to judge.

explain_byproductsB

Explain which byproducts stall a plan, and what can legally consume them.

Every item balance is an equality, so a byproduct with no consumer makes a plan INFEASIBLE rather than silently vanishing. This says WHICH item is stuck, whether it can be sunk (solids only -- a fluid must be consumed exactly or packaged first), and which recipes would absorb it, split into ones this world has unlocked and ones it does not.

Pass item to focus on one byproduct instead of the whole plan.

compare_recipe_optionsA

Rank whole ROUTES to make an item by what each actually costs.

Not a recipe list -- alternates_for_item already does that. Each route is solved end to end with the LP, so the comparison is Crude -> Alt HOR -> Diluted Fuel against Crude -> Fuel, priced in raw resource per unit, whole buildings, net power, and byproducts needing an outlet.

bomC

Flattened bill of materials: total raw and intermediate rates for qty/min of an item.

qty is a RATE, per minute. Solved by the LP, never by expanding the recipe tree: Recycled Plastic and Recycled Rubber form a real 2-cycle, so an expansion has no correct depth limit. Every row names the recipe chosen for that item, because alternates change the totals materially.

commission_planA

In what order to switch a built plant on, without blowing the fuse.

This is a STARTUP order, not a build order, and the difference removes most of the problem. Building costs materials, not power -- a machine draws only when it runs -- so the whole plant can be constructed at leisure, drawing nothing, and then energised block by block. Nothing here tells you what to build first.

The constraint is one line, and it is hard: at every step, energised consumer draw must stay under the headroom plus generation from generators already burning fuel. Exceeding it in Satisfactory does not degrade gracefully -- the fuse blows and the whole grid stops until it is reset by hand, including the plant that was feeding it.

Generators are free to energise (0 MW draw, read from the dump), so a wave costs its consumers and refunds its generators, and that refund pays for the next wave.

Takes plan_factory's arguments, or recall a saved plan with plan=.

rank_unlocksA

What every locked alternate recipe would be worth to THIS plan.

One counterfactual per candidate: solve the plan, solve it again with the recipe added, report the difference. It answers "which unlock should I chase" with a number in the plan's own units instead of a tier list, because a recipe's worth depends entirely on what you already have.

A zero is an answer. Most candidates change nothing, and "you are not missing anything here" is a decision -- it is otherwise reached by walking the recipe tree by hand.

Deltas are an UPPER bound: a candidate needing a machine you have not built is judged as if you had it, and the machine is named. Alternates currently offered by a pending hard drive are flagged, which is the difference between "worth having" and "claimable now".

plan_logA

One plan's versions, newest first: who changed what, from chat or from the page.

undo=<v> writes a new version that reverses that one; restore=<v> writes a new version equal to that one. Both take base_rev and merge like any other edit. A forgotten plan is found too, so its forget can be undone.

ui_contextB

What the web page has open, and what changed in plans since this session last looked.

Call it first when the user says "this", "here" or "what I have open": it names the page's view, plan and version, tab and selection, whether the page reads the same save as you, and every plan version and chat solve by someone else since your last look.

phase_requirementsC

What the Space Elevator still wants, live record and deprecated record apart.

The per-phase item table in the save is DEPRECATED and frozen, so it is shown labelled rather than believed. Read the header line first.

power_shardsB

Power Shards held, committed and free, plus what an overclock plan would cost.

plan_machines machines at plan_clock costs shards per machine; the answer says whether the free pool covers it.

mam_researchB

MAM research: what is left, what it costs, and what you can afford right now.

The MAM is where CAPABILITIES live, as opposed to recipes -- the Dimensional Depot, the Power Augmenter, and Production Amplifier, which is the one that lets a Somersloop go into a machine at all.

That last one has no flag in the save. BP_UnlockSubsystem_C records overclocking as mIsBuildingOverclockUnlocked, but nothing anywhere in the file records production amplification, so it is derived from the purchased-schematic set instead. Capability rows are marked LOCKS so it is obvious which research gates a tool argument rather than just adding a recipe.

milestonesA

HUB milestones: what is left, what each costs, and what you can afford right now.

The questions mam_research answers about the MAM tree, asked of the other ladder and in the same words -- both walk one SchematicLadder priced against the same spendable stock, so a status here means what it means there.

READY is about the BILL, not about access: tiers are opened by Space Elevator deliveries, that gate is in no shipped data, and phase_requirements is where the elevator stands.

somersloopsB

Somersloops held, slotted and owned -- the sibling of power_shards.

sloop_budget has existed since sloops became spendable and nothing exposed it, so the only way to learn how many you had was to guess a sloops= budget and read the shortfall warning: you had to guess the budget to discover the budget.

Free and committed are both exact. Slotted ones live in InventoryPotential, the same component as Power Shards, so this counts slot contents rather than inverting a boost multiplier.

collected_from_worldA

Map collectibles: how many exist, how many you took, what is left and what is closest.

Slugs, somersloops, Mercer spheres and their shrines, mushrooms, drop pods and the loot caches around them. Two sources, and neither is asked the other's question:

  • the map says what exists and where, read from the installed game's own cooked packages, so placed is exact and every coordinate is exact;

  • the save says what is gone. The world is not saved -- a save never mentions a slug still lying there -- so its destroyed-actor list is the collected list, and it is exact too. remaining is the subtraction of the two.

Views: census (default) counts every category; collected and remaining list individual placements with coordinates; nearest lists the remaining ones by distance from near, defaulting to the player.

A placement in a cell no save has ever loaded is counted as remaining and reported as never_streamed. It is never called present -- the map says where it is and nothing on disk says whether it is still there.

list_regionsA

Named map regions, optionally only those containing a given resource.

Region names are ADVISORY: the boundaries are the game's own map areas, downsampled to a 256 m grid to publish and a 64 m one to look up in, so a name near a boundary can be one cell out. Use them to talk about places, not to compute with -- every node row also carries an exact grid cell.

anchor is a coordinate that provably lies in the region, which a centroid does not: a concave region's mean lands on its neighbour's ground, and the map has drawn its names at the anchor all along.

describe_locationA

Name the region at a place, sample its elevation, and count what runs through.

at= takes 'x,y' in metres, or anything else this project prints an id for: me, a named factory, slab:<n> from factory_map show=slabs -- including the bare platforms nothing else would take -- or a chain:/pipe: run from search_conduits.

Returns 'off-map or ocean' rather than guessing the nearest land region.

Elevation is answered two ways and the two are never averaged. Where this machine carries the extracted 1 m terrain field, terrain_m is one texel read at exactly this coordinate, with the layer that answered, that layer's measured accuracy, and the water surface and depth where water stands. Everything else is a SAMPLE population reported with its count and spread: resource nodes rest on terrain and are quoted as ground, foundations and buildings are quoted separately as built elevation because a platform is wherever the player put it, and the gap between the two is the fill already stacked there.

Belts and pipes are counted too, measured against the runs' drawn lines rather than their corner points, so a conduit crossing mid-span is seen. With a readable save, a zero here means nothing runs through -- absence in this output is absence in the world. search_conduits lists the runs themselves.

search_conduitsA

Belt and pipe runs near a point or between two areas: ends, length, elevation.

The web map has drawn these all along; this is the text answer to "is there a pipe between those extractors and that platform, where does it run, how long is it". A run is one belt CHAIN (consecutive conveyor pieces, split at splitters, mergers and machines) or one placed pipeline piece. Longest first; each row carries both ends with what stands there where known, the drawn length, and the elevation span.

show="networks" answers the other size of question: one row per FLUID NETWORK in the whole world, what each carries, how much pipe it is, where its middle is and what it ends on. A network is one connected plumbing system, so that is the view that tells you which system a run belongs to; radius_m and to do not narrow it, and the distance column places each network relative to near.

near and to accept a coordinate in metres, me, a named factory, or one of this tool's own run ids -- chain:7, pipe:333 -- which centres on that run's midpoint, so the ids in the connects column can be followed one call at a time. With to set, only runs passing within both radii are listed. Proximity is measured against the runs' drawn lines, not their corner points, so a run crossing mid-span counts.

Long lists page with offset=, and the truncation line names the next offset -- a busy junction can carry hundreds of chains and the tail of that list is as real as its head.

search_resource_nodesA

Resource nodes, in one of three views.

  • fields (default) clusters nodes within 200 m and ranks by yield -- "where is there a lot of iron".

  • nodes lists one row per node, ranked by yield, with ids reusable as selectors.

  • nearest lists one row per node ranked by DISTANCE from near, with the distance shown -- "what is closest". Requires near.

sources is a list of selectors; locations union, filters intersect::

["north"]                          northern half of the map
["region:Northern Forest"]         one named region
["near:0,-2000@800"]               within 800 m of (0, -2000) metres
["grid:X3Y4"]                      one 1.024 km grid cell
["node:BP_ResourceNode26_99"]      one specific node
["north", "resource:Crude Oil"]    crude oil in the north
["bbox:-500,-2500,600,-1800"]      a rectangle, metres

near accepts a coordinate in metres, me for the player, or the name of a labelled factory -- "the nearest free coal to the coal powerplant" needs no coordinates. Giving near in any view adds a distance column.

All three views page with offset=; the ranking is stable, so the tail of 127 iron nodes is reachable 25 at a time.

Water is the exception to everything above. Open water carries no node, so asking for it returns only the fracking satellites; the bodies already being pumped, the pumps on each and the measured sea level are printed beside them instead.

show_on_mapA

Map links centred on something: this project's own map, and the public one.

Two links for every place. The LOCAL one opens this project's web map, which draws the reader's own save -- their machines, their belts, their siting. The satisfactory-calculator.com one opens a third-party map of the vanilla world, which knows the terrain and the nodes and nothing the player built.

at is the same place vocabulary every other tool takes (see docs/selectors.md), plus one kind of its own: resource:<name> centres on the centroid of EVERY node of that resource and switches its overlays on, which is a viewport rather than a place and is why no other tool accepts it.

Only the Crude Oil layer tokens are confirmed; the rest follow the same pattern and are flagged. A wrong token still opens the map in the right place, just without that overlay.

rank_build_sitesA

Rank candidate fields for a new extraction site, best first.

Scores untapped REACHABLE capacity against spread, distance to your existing buildings, and purity mix. Every raw component is shown so you can re-weight: the single score is a starting point, not a verdict.

sources narrows the search area using the same selectors as search_resource_nodes; omit it to search the whole map.

A ranking does not page: the rows below the cut score worse by construction, so raise limit or narrow sources rather than looking for an offset.

whereamiB

Where the player is standing, and what is around them.

Position comes from the Char_Player_C pawn in the save, so it is wherever you were when it was written -- an autosave can be several minutes stale. Use near:me@<radius> as a source selector in the planning tools to scope work to here.

list_worldsA

List save games grouped by world, newest first.

Unsupported files are reported separately rather than failing the scan -- pre-1.0 saves cannot be parsed at all.

world_summaryC

Progress, power and problems for one world.

unlocked_recipesB

Which recipes this world has. Defaults to alternates, never all 872.

Sorted by name and paged with offset=, so the whole list is reachable.

power_reportB

Generation capacity vs machine draw, nameplate AND measured.

Nameplate is what everything built would draw running at once. Measured weights each machine by the 300 s productivity monitor the save already carries, which on a factory with idle blocks is a very different number -- and it is the one that says what is free right now. Both are shown because they answer different questions.

Generation is capacity on both figures, with one exception the answer names: a generator whose fuel or supplemental water has run dry AND whose own monitor read zero is listed as starved, because those MW will not arrive when the grid asks for them.

factory_sitesC

Built production buildings clustered into sites, largest first.

Prompts

Interactive templates invoked by user choice

NameDescription
design_factoryPlan a factory for a target item, respecting what this world has unlocked.
plan_power_plantPlan a power plant from a given resource and area.
pick_hard_driveAdvise which alternate recipe to take from a pending hard drive.

Resources

Contextual data attached and managed by the client

NameDescription
docs_summaryOne-line census of the normalized game data, plus its content hash.
current_saveWhich world and file the server would read right now, and its headline state.
factory_labelsFactory labels for the current world, as the JSON another tool can consume. Labels are the one thing in this server a player authored by hand, so they are the one thing worth publishing as a stable interface rather than a private cache. The file is per world, keyed by the save header's ``saveIdentifier``, and carries a ``schema`` integer so a reader can refuse a shape it does not know. ``anchors`` are machine instance names, which were verified stable across saves -- 365 of 365 kept id and position between two files. That is what makes a label portable: a consumer can join it against its own read of the same save without needing anything from this server.
map_regionsRegion names available as source selectors, with their accuracy caveat.

TDQS

B3/5.0

Scored across 54 tools

Disambiguation3/5

Descriptions are unusually detailed and most tools have a specific niche, but overlapping factory_* and recipe/plan vocabularies create real selection risk. An agent could confuse factory_map, propose_factories, and factory_sites, or search_recipes, alternates_for_item, and compare_recipe_options without careful reading.

Naming Consistency3/5

All names use snake_case, but the convention is mixed: some are verb_noun (search_items, plan_factory), while many are bare nouns (stock, bom, factory_map, world_summary). Pluralization and phrasing are uneven, though the set remains readable.

Tool Count2/5

With 54 tools, the server is far beyond the 3-15 sweet spot and well past the 25+ 'too many' threshold. The domain is broad, but the surface feels like several toolsets merged, making discovery and context management difficult.

Completeness4/5

Coverage is strong for recipes, factories, plans, resources, power, research, collectibles, and map analysis, with lifecycle operations for plans and factory labels. Missing or thin areas include vehicle/train/drone logistics and blueprint editing, but core planning workflows are well supported.

Maintenance

ActivityActive
ResponsivenessNo issues