Why so many?

From the outside this looks like a collection — tools someone piled up over the years and never tidied away. That is the obvious suspicion, and it is wrong.

None of the tools on this site came first. What came first, every time, was something missing while we were building something else. Three starting points, and a chain running from each.

A system that watches refrigerators

The largest piece of software here monitors temperatures, storage rooms and spaces — for pharmacies, laboratories and food businesses, with an audit trail and reports that hold up to inspection. Much of what stands beside it exists because that system needed something that did not.

Readings you still understand six months later

Drawing a temperature curve is no great feat. Drawing one where you can still tell months later what happened on Tuesday night is: that takes thresholds, zones, markers and annotations — precisely the part that makes up the real work in an incident analysis.

MLTimeGraph draws the same curve in the browser and on the server, in TypeScript and in Go. That both really draw the same chart is checked on every test run. For occupancy and distribution across an area, the isometric heatmap followed.

sensor monitoringreadings have to reach the reportMLTimeGraphIsometric Heatmap

Every probe needs a label

Measuring points, devices, calibration certificates — all of it needs to be labelled unambiguously and read back later. The libraries for that were written for our own use first.

Then an LLM got an MCP server alongside them, so it could create and read codes itself. And the interface we had originally built only for testing turned out to be useful to other people too — so today it exists for iPhone, iPad and Android, as a desktop app and on the command line.

sensor monitoringlabel it, read it backinternal libraryMCP server for the LLMMLC Barcode

A report an inspector believes

Producing an audit report as a PDF is easy. Producing one where you can still prove months later that it has not been altered takes a signature and a timestamp — and for that, a certificate somebody has to issue.

For our customers that used to be a product of its own: a contract with a certificate authority, monthly fees, and a piece of software they used maybe five per cent of. For signing a temperature report, that is the wrong arithmetic.

So we issue the certificates ourselves. They come with the products, with no annual fee and no second contract. The same machinery seals photographs on the other side of the house — parts of OpticScript use it.

audit reportsmust be provably unalteredsomeone else's product, monthly, 5 % useda PKI of our own

A tool we barely need ourselves any more

The audit reports started life as HTML and were poured into PDF from there. That is a sound approach, and the service doing it still does it well.

Our reporting engine now runs on Markdown instead. We generate the PDFs from that directly — considerably faster than going through an embedded Chrome. Which has left the PDF Server largely out of work here.

We released it anyway rather than mothballing it. It still solves the problem it was built for; that we solve it differently today does not make it any worse for anyone else.

audit reportsHTML to PDFPDF Servermoved to Markdownbarely used here now

A local LLM that could not touch anything

We wanted to use an LLM locally for certain tasks — without data leaving the building. Setting it up was quick. Then we found that something was missing.

Talking is not enough

A model that can only answer is of limited help in a working day. The moment it should actually do something — generate a code, draw a series of readings, file something away — it has no way to get there. The Model Context Protocol is that way, but somebody has to write the servers.

So we wrote them. First for what we needed ourselves every day — the barcode server further up was one of the first — then for what turned out to be useful beyond that.

local LLMcannot touch anythingour own MCP servers

Explaining was harder than building

Writing an MCP server is not hard. Writing one a model then uses the way you intended is. So that this knowledge would not sit in a few heads, we wrote down what we had learned.

From the basics to agentic servers and sampling — including the part that cost us the most: how to design a server so that it explains itself.

our own MCP serversspread the knowledge in-houseThe MCP Handbook

The tests cost more than the server

Our MCP servers did not always do what they were supposed to. Worse: some stopped working with newer clients from one day to the next — without anything having changed on our side. So we needed something that checks against the current specification, not the one that applied when the code was written.

Unit tests for MCP servers were laborious and cost LLM calls on every run. So the tester got a query language of its own: a script describes what a call should return, and checks it without a single model. And because writing the documentation by hand was just as tedious, it produces a document showing how an LLM sees the server.

our own MCP serversbreak with new clientsMCP Testerits own query languagegenerated docs

Three servers, one dataset — and none of it belongs in the model

A question like “show me this table as a chart” passes through several hands: one server fetches the data, one computes, one draws. The intermediate results have to travel from one to the next — but not through the model.

The large providers have dedicated services for exactly this. Locally there are none. And passing data along through the context is not merely expensive: with a database on one side and an image generator on the other, it is a security problem.

mlcartifact is the store in between. One server files its result and passes on an identifier; the next one fetches it with that. The model sees the identifier, not the data.

several MCP servers on one taskpass intermediate results alongbut not through the contextmlcartifact

Models cannot do arithmetic

“How long was the sensor outside the permitted range?” sounds like an easy question. For a language model it is not: the answers were often plausible and wrong. Asking for the average of a series of readings between two dates gave the same picture.

Rather than teaching the model to calculate, we let it write a function. It states the problem as TypeScript, the function runs, and what comes out is a number from a calculation rather than one from a prediction. In practice this works remarkably well.

questions about measurement seriesmodel computes plausibly and wronglymodel writes the function itselfWollmilchsau

Our own working day

The third starting point is the least spectacular. We develop remotely, document in Markdown, and need images for it. Each of those three produced a tool.

The machine we build on is somewhere else

Development here happens almost entirely remotely, on a server reachable only over SSH. A terminal alone is not enough: you want to see files, change one quickly, watch the containers running beside it — and preferably in one window rather than six.

The first attempt was called MLCRemote and worked the way VS Code does: an agent is installed on the remote machine and everything else talks to it. That worked excellently — just not on small servers, and certainly not at a customer site. Nobody wants something installed on their production system merely because we are supposed to take a look at it.

So we started again, this time over plain SSH: MLC Terminal. Because the same thing makes it easy to support customer systems, the Docker and server-monitoring parts followed. Building on that came a small tray icon showing who is currently connected to a machine.

development only over SSHMLCRemoteagent on the target systemnot an option at a customer siteMLC TerminalSSH Tray Agent

Manuals get written in Markdown

We document almost everything in Markdown — manuals, standard operating procedures, internal notes. What was missing was an editor that also turns them into something you can hand to someone, and that keeps the documents on your own machine while doing it.

everything in Markdownit has to become a formMarkSafe

Adjusting images by hand is busywork

Good documentation needs images, and images want cropping, scaling, labelling and saving in three formats. By hand that is the same half hour every time.

OpticScript turns it into a script: crop, scale, label, write out as PNG, JPEG or WebP — repeatably and without a mouse. Our unit tests use it for image comparison. And Photo Protection, which sits on the same engine, seals and marks images so it can later be shown who they came from.

images for the documentationthe same half hour every timeMLC OpticScriptPhoto Protection

Images without taking a weekend off

There are very good tools for generating images locally — ComfyUI and others. But not everyone wants to, or can, spend hours reading up on how to set such a thing up. And it should run on an employee laptop, not only on a machine with an expensive graphics card.

That produced two prototypes built on open models, plus a studio that makes the generated images findable again through tags and styles. And because such images turned out to pick up artefacts when enlarged for print, a service of its own for upscaling followed.

images for manualsno weekend spent on setupZ-ImageMLC SDOllama Studioartefacts when printedMLCUpscale

Did I forget to commit something?

Anyone working on several projects at once has a dozen working copies on disk by Friday afternoon and no idea any more which of them is clean. The question is trivial; the answer, across twelve directories, is tedious.

GitPulseMLC answers it at a glance, for local and remote repositories at the same time. The smallest tool here — and one everybody in the house uses.

a dozen working copiesdid I commit everything?GitPulseMLC

And why always the same three languages?

TypeScript, Go and Rust — almost everything here is written in one of the three. That is not a matter of taste; it follows from the same necessity as everything else.

We develop for Windows, macOS and Unix. What we build should run on all three without becoming three projects every time. Go and Rust compile to a single file you drop in place and run — no runtime, no dependency missing on someone else’s machine. TypeScript runs wherever there is a browser anyway.

Python and C# are good languages; that is not the issue. But with both, the work starts for the user with a setup that looks different on every operating system — and for a tool somebody needs once a month, that is exactly the point where they give up.

What follows from that

Most of what you see here we use ourselves every day. It gets maintained and extended when using it shows that something is missing. None of it is a weekend project still pointing at the same version it did two years ago — and where a tool has fallen out of step with us, it says so above.

Much of it is open source, and it is open whenever we believe it can help someone else too. That is not altruism: feedback from people who use a tool differently than we do has found more bugs here than any internal test.

This site is an example of it

What you are reading is built with the same tools. The product pages are generated by mlcprodweb, a Go program of our own, from one meta.yaml per project, kept in that project’s own repository — change the product and you change its page with it. The sign-in at the top right runs on mlcauth.

The figures in the MLCRough manual are drawn by the library the manual describes. The same goes for the MLTimeGraph manual, plus fifteen demos that run in the browser rather than sitting beside the text as screenshots.

Next, the images on this site will go through OpticScript — signed and marked, as already happens on the OpticScript pages. That our own site is where we notice first when something is missing is no accident: it is the first customer.

A word about money

Much of what is here is open source. Some of it costs a small fee, and there is a reason for that which we would rather write down than leave unsaid.

An internal tool is finished when it runs here. It only becomes a product once it also runs on someone else’s machine, has instructions, ships signed, and somebody answers when it gets stuck. That difference is work, and it costs money continuously — hosting, certificates for signing, files that have to sit somewhere and be delivered.

The prices are calculated to cover exactly that, and no more. Selling software is not our bread and butter — we earn our living with the thing these tools were built for. What you pay here keeps the tool available.

To the catalogue →