minmcs — minimalistic mission control system
minmcs is a web-browser mission control system: operators monitor telemetry (TM) and
uplink telecommands (TC) from a dashboard in their browser, backed by a Python API that
decodes packets against a spacecraft model and stores them. It runs from containers with
minimal configuration.

The operator’s browser talks to the API directly over REST/WS on :9300 — the data_proxy
bridge is not in that path. Its job is separate: it relays TM/TC between the ground link’s TCP
socket and the API’s HTTP endpoints. 21001 is the ground-link port the repo’s example config
uses by default; the code itself falls back to 9310/9311 when nothing is configured — see
Configuration.
Getting started
See Quickstart for the first steps — copying .env.example, placing the
XTCE database, and bringing up the stack (with Docker, or running the pieces locally).
minscs is a
simulator that speaks the same ground-link wire format and pairs well with minmcs in place of
(or alongside) the local bin/egse_link.py stub.
Repository layout
minmcs-lib/— the Python/FastAPI core. It builds aSpacecraftmodel from an XTCE mission database, decodes TM into parameters, builds and tracks TC, and exposes all of that over a REST API plus a/wsWebSocket. The API itself never opens a socket to the ground — that’s the job of the ground-link bridge,bin/data_proxy.py.minmcs-ui/— a Vue 3 + Pinia + vue-router operator dashboard, built on a Bootstrap admin template and adapted for MCS use. Its domain components live inminmcs-ui/src/components/minmcs/; they talk to the API over REST and refresh reactively on the/wsbroadcast.containers/+docker-compose.yaml— the full stack: Postgres/TimescaleDB, InfluxDB, the API, and the UI behind nginx, one container each.
Backend flow: packet in → parameters out
api.pybuilds one globalMinMCSfor the mission named byMINMCS_MISSION— see The API service.Missionholds theSpacecraftmodel and the SQL engine. The live mission builds that model at load time from an XTCE file.- Telemetry ingest parses each packet with
minspp, identifies which container it belongs to by walking the XTCE containers’ restriction rules, and decodes it bit-level into stored parameters. - Telecommand uplink looks up the command, packs its opcode and
arguments, and derives the packet header straight from its XTCE container. The built packet
is stored with
sent=False; the ground-link bridge is what actually puts it on the wire.
minspp (PyPI minspp, github.com/nunorc/minspp) owns
the CCSDS/PUS-C wire format underneath all of this: framing, the TM/TC secondary headers, and
everything that’s filled in on the ground (sequence count, packet length, the CRC-16 PEC).
Read next
- Quickstart — first steps: environment, the XTCE database, and bringing up the stack.
- The spacecraft model — the domain types, and how they’re derived from XTCE.
- Telemetry ingest — packet → parameters, and the two persistence stores.
- Telecommand uplink — building, scheduling, and verifying commands.
- The API service — how it’s all wired into the running FastAPI process.
- Ground link bridge — the bridge process that actually talks to the ground.
- The operator UI — the Vue dashboard.
- Configuration — environment variables and the Docker build.