Your first module¶
Tutorial. How a module registers itself, using the ERPNext connector as the worked example. Honest scope: the entry-point mechanism is small, and the "module" boundary is still a target the code is moving toward (see the architecture page).
What "module" means here, today¶
fsmes info lists modules by reading the fsmes.modules entry-point group.
As of 2026-09-07 one thing registers there: the ERPNext connector. The ERP
factory resolves any MES_ERP_MODE it does not know built in (rest,
file, off) by looking up an entry point of that name, so a connector in
a separate package plugs in without a change here.
That is the whole mechanism. Quality, maintenance and scheduling are not yet separately installable packages; they ship in the kernel wheel. Turning them into entry-point modules is on the roadmap, not done.
The worked example: ERPNext¶
pyproject.toml:
[project.entry-points."fsmes.modules"]
erpnext = "fsmes.integrations.erp.erpnext_adapter:from_settings"
from_settings(settings) builds an adapter that satisfies the ErpAdapter
protocol — three methods:
class ErpAdapter(Protocol):
def fetch_orders(self) -> list[ProductionRequest]: ...
def acknowledge(self, order_code: str) -> None: ...
def send_confirmation(self, confirmation: Confirmation) -> None: ...
The models are typed (contract.py); every MES-side rule lives in
services.erp, so an adapter is transport only.
Write your own connector, in its own package¶
- New package, say
fsmes-sap, depending onfactorysemantics-mes. - Implement the three methods against
fsmes.integrations.erp.contract. -
Register:
[project.entry-points."fsmes.modules"] sap = "fsmes_sap.adapter:from_settings" -
pip install fsmes-sap;fsmes infonow listserpnext, sap;MES_ERP_MODE=sapselects it.
Settings your connector needs come from the same MES_ environment; read
them off the Settings object you are handed, or from os.environ if they
are yours alone.
What to test¶
The ERPNext connector's tests (tests/test_erpnext.py) run against a fake
ERPNext in-process: the shape to copy. Name tests after the promise they
pin, not the function they call — house rule 5.
See also¶
- Decision records 0002 and 0008
- The ERPNext connector