---
title: "Tech Scroll 135: PeaBrain is learning, and the MCP that kept it honest in pure ASM"
slug: "peabrain-learning-saphira-build-mcp"
description: "Little strokes fell great oaks. PeaBrain started as a 614-byte assembly webserver and became a persistent-memory MCP server with a trainable neural network. The less expected story is the infrastructu"
date: "2026-11-05T01:01:06.000+00:00"
updated_at: "2026-11-05T01:01:06.000+00:00"
feature_image: "https://articles.akadata.co.uk/content/images/2026/11/peabrain-article-image.png"
canonical_url: "https://articles.akadata.co.uk/peabrain-learning-saphira-build-mcp/"
---

## Little strokes fell great oaks.

PeaBrain started as a 614-byte assembly webserver and became a persistent-memory MCP server with a trainable neural network. The less expected story is the infrastructure that carried the work between sessions.The problem with agent memory

The problem is familiar to anyone who has worked with a coding agent for more than one session. The agent is useful on Tuesday, then Wednesday arrives with a fresh context window and the whole investigation starts again. Files on disk remember the code, but the reasoning behind the code does not survive. Which approaches failed, which measurements were trusted, what the operator decided, and what remains unverified all live in a transcript that scrolls away.

The standard answer is to give the agent a memory: a place to store facts, tasks, and notes outside the conversation. That is necessary but not sufficient. A store that accepts writes is easy. A record that lets the next session continue correctly, with evidence instead of rumor, is the actual engineering challenge. This article describes a small system that takes that challenge seriously, and the checkpoint infrastructure that kept its development honest across dozens of sessions.

## The standard starting point: a tiny server

Every systems programmer has written one: a socket, a bind, a listen loop, a reply. The PeaBrain story starts exactly there, in a file called server.asm that is 130 lines long and assembles to a 614-byte executable. It does one thing. It accepts a connection on 127.0.0.1 port 8080, reads up to 4096 bytes, and checks whether the request starts with the letters POST. If it does, the bytes are echoed to standard output and the client gets a 200 reply. Anything else gets a 405.

```
    ; socket(AF_INET, SOCK_STREAM, 0)
    mov eax, 41
    mov edi, 2
    mov esi, 1
    xor edx, edx
    syscall
```

There is no libc here, no runtime, no framework. Each comment names the syscall and each instruction sets up its arguments directly. That style never changed through everything that followed. Readers who want the full file can download it with the links in the References section at the end; the whole program fits on a single screen and remains the clearest possible statement of intent. It says: start with the machine as it is.

## From 614 bytes to a real webserver

The next step kept the same shape and added the one thing a toy server needs to become useful: serving real files. webserver.asm is 839 lines and builds to a 3,323-byte binary. It adds SO\_REUSEADDR so restarts do not fight the previous socket, null-terminates the request buffer so the path can be parsed safely, and branches on GET as well as POST. A GET request is mapped onto the htdocs directory that sits next to the binary, with a trailing slash resolving to index.html and a guard on the path after the htdocs prefix.

```
handle_get:
    ; rsi = start of path (buffer+4), rbx = path len up to space/CR/LF
    lea rsi, [buffer + 4]
    xor ebx, ebx
scan_path:
    mov eax, ebx
    add eax, 4
    cmp eax, r14d
    jae send_400
    mov al, [rsi + rbx]
    cmp al, ' '
    je path_found
```

The htdocs folder in the working tree holds a real index page, so this is a genuine if minimal webserver. A short transcript from the build tree shows it answering real requests and closing the classic hole in the same breath.

```
$ ./webserver &
$ curl -s http://127.0.0.1:8080/test.html
yes this is a file
$ curl -s --path-as-is http://127.0.0.1:8080/../linux -o /dev/null -w '%{http_code}'
403
```

The progression matters more than the feature. Nothing was rewritten. The accept loop survived, the syscall discipline survived, and each capability arrived as a small addition with its own comments. That habit, of growing the program without breaking its shape, is what made the later jumps possible.

## think and mcp: the MCP turn

The third program changed the transport but kept the philosophy. think.asm is 1,421 lines building to a 6,426-byte binary, and it speaks MCP stdio: newline-delimited JSON-RPC 2.0 on standard input and output, the same framing every Model Context Protocol server uses. Its header comment states the contract plainly.

```
; think.asm - ultra tiny sequential-thinking MCP server, FASM ELF64, no libc.
; Transport: newline-delimited JSON-RPC 2.0 on stdin/stdout (MCP stdio).
; Methods: initialize, server/discover, ping, tools/list, tools/call.
; Ring buffer: 64 thoughts; history length counts all recorded.
```

Where the webservers answered HTTP, think answers tool calls. Its single tool, sequential\_thinking, mimics the reference sequential-thinking server published by the Model Context Protocol project: thoughts arrive with numbers, branches, and revision flags, and a 64-entry ring buffer keeps the history for as long as the process lives. A live exchange from the build tree shows the shape of a reply.

```
$ echo '{"jsonrpc":"2.0","id":1,"method":"tools/call",
  "params":{"name":"sequential_thinking",
  "arguments":{"thought":"Little strokes fell great oaks.",
  "nextThoughtNeeded":true,"thoughtNumber":1,"totalThoughts":3}}}' | ./think
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text",
  "text":"{\"thoughtNumber\":1,\"totalThoughts\":3,\"nextThoughtNeeded\":true,
  \"thoughtHistoryLength\":1}"}]}}
```

A fourth local file carried the persistence problem in miniature. mcp.asm, 1,405 lines building to a 6,885-byte binary, adds three tools, write\_fact, read\_fact, and list\_facts, and holds each remembered fact as one ASCII file in a data directory resolved from the executable's own path, so the server works from any client working directory. think keeps its thoughts in RAM and dies with the process; mcp gives memory a first durable body beside the binary. The shape of the future is visible at this point: tools listed over stdio, facts given names, state kept next to the executable. These four programs are not four examples. They are one lineage, every binary still runnable today, every source downloadable below, showing how a POST-echoing socket became a protocol-speaking memory experiment without ever leaving assembly or linking a library.

## What PeaBrain actually does

PeaBrain is that lineage grown up. The repository at [github.com/akadatalimited/PeaBrain](https://github.com/akadatalimited/PeaBrain?ref=articles.akadata.co.uk) holds its server source as tinythink.asm, 13,126 lines, while the shipped executable still carries its historical name, tinythink. Both numbers measure different things and both deserve care: the line count reflects handwritten coverage of protocol parsing, JSON handling, an on-disk database format, ranking math, and neural network code, while the binary stays small because large tables live in zero-backed memory and the program issues syscalls instead of dragging in a toolchain. Large source, compact binary, no contradiction. The build story was checked rather than assumed: assembling tinythink.asm with FASM 1.73.35 reproduces the shipped 73,597-byte executable byte for byte. The tree also keeps peabrain.asm, a 13,016-line earlier revision that still builds at 62,159 bytes and serves 21 tools, so the line count you meet at the head of the repository is history, not the current shape.

The headline figures were measured against commit 7b21106 on the Master branch and confirmed by running the shipped binary: 27 tools over MCP stdio, backed by a genuine on-disk SQLite database with 4096-byte pages that passes integrity checks and opens in stock sqlite3. The tool set covers sequential thinking with history and reset, versioned facts with tombstoning, entities with observations, relations, tasks with query and update, explicit useful and misleading feedback, an explanation tool that shows why a memory scored as it did, and six model tools for initializing, training, predicting, saving, loading, and reporting on the on-board network. The database file is created next to the executable on first write with locked-down permissions, so each copy of the binary is a separate store. Copy the binary somewhere else and you have a scratch database, a property the test suites exploit constantly. A fresh scratch copy makes the format compatibility testable in seconds.

```
$ printf '%s\n' '{"jsonrpc":"2.0","id":2,"method":"tools/call",
  "params":{"name":"write_fact","arguments":{"name":"ts135-probe",
  "text":"Tech Scroll 135 database format probe"}}}' | ./tinythink
{"rowid":1,"name":"ts135-probe"}
$ sqlite3 tinythink.db "PRAGMA integrity_check"
ok
$ sqlite3 tinythink.db "SELECT rowid,name FROM facts WHERE name='ts135-probe'"
1|ts135-probe
```

Three capabilities need separating because the names blur together. Persistent memory means storing and retrieving information across restarts. Adaptive ranking means adjusting usefulness scores from explicit feedback without claiming the feedback proves truth; a popular memory is not automatically a correct one, and the design says so. Neural training means updating numerical parameters from labelled examples. PeaBrain does the first natively, does the second through a scored usage table with feedback joins, and does the third through a small trainable network: a two-input, single-hidden-layer multilayer perceptron in FP32, with a handwritten AVX2 and FMA path plus a scalar reference backend that differential suites assert to be identical, living in a 4 GiB sparse arena and checkpointed in a versioned file format that refuses corrupt loads while leaving the live model intact. None of this implies the network understands language or learns facts by itself. It adjusts numbers from examples, and the article will show exactly how those examples are built.

## What we tested: two defects and their fixes

A real development story includes the defects. The strongest evidence in this one comes from independent testing by a second agent, Codex, against builds the primary agent produced. Twice it found real faults, and twice the fixes were verified rather than asserted.

The first fault was in model loading. Saving a trained model worked, but loading it back in the same running MCP process failed. Investigation established two defects: model staging exhausted the arena live-region allowance, and a Linux syscall clobbered a register that was preserving a byte counter across the call. The correction made loading two-pass, validating the file before changing any live state, then staging and restoring safely. The proof was repeated save, reset, and load cycles with bit-identical predictions afterward, plus suites passing on both the vector and scalar backends and a byte-identical shipped binary. Checkpoint 51 in the project journal records the commit, the root causes, and the verification in one place.

The second fault was in the persistent-memory database itself. Concurrent write testing exposed duplicate and out-of-order row identifiers: a shared in-memory counter was being reused across tables and processes, and the restore path forgot what it had allocated. The fix takes a fresh tail maximum under lock on every flush and tracks the scan reason maximum, with a mid-work regression caught and corrected during development itself. Testing and applying the repair were two separate phases, and the distinction matters. The repair was first validated on an isolated copy only, cell by cell, with row multisets compared byte-identical before and after and integrity checks clean, while the live database was fingerprinted and left untouched throughout. Then, on explicit operator approval, the repaired database was deployed with an atomic rename plus directory sync, and verified after the swap with a live engine smoke test covering health counts, a fresh write at a new row identifier, recorded feedback, clean integrity, and zero duplicates, with timestamped backups preserved and the rollback path unused. Checkpoints 53, 56, and 57 record the allocator fix, the staged repair with its unexecuted deploy script awaiting approval, and the approved deployment with its post-swap verification, alongside a four-process hammer test with zero duplicates against the old build producing dozens.

The pattern is worth naming. Neither defect was found by staring at code. Both were found by running the software the way it would actually be used, with concurrent clients and restart cycles, and both fixes shipped with tests that would catch a recurrence. That is stronger evidence of quality than any claim that development passed first time.

## Why Saphira Build MCP mattered

This is the unexpected star of the story and the reason the article exists on this site. Saphira Build MCP was developed around Saphira Linux build operations, and its name still points there. But its portable capability is not tied to Saphira at all. With one environment variable, SBM\_SAPHIRA set to off, the builder integration disappears and what remains is a journal: checkpoints with save, list, resume, and close; durable notes and decision records; controlled historical recall through total\_recall; source and execution provenance on every record. No Saphira installation, no recipe tree, no package repository required. The PeaBrain work used exactly this mode, and it is why the previous two sections can cite checkpoint numbers instead of reconstructed recollections.

Each concept earns its place. A checkpoint is a pre-restart write meant to be consumed after one: label, title, what was done, repository and commit state, findings, and the next action. Checkpoints form a register of unfinished work shared by every agent on the host, and the ritual is strict: a new session lists the register first and resumes only what the operator selects, never automatically. Notes carry decisions and their reasons. total\_recall retrieves the history behind the checkpoints with ranked queries or timelines, bounded by budgets, only when asked. Provenance records hostname, user, directory, and session so that a year later someone can establish what was worked on, where, and what was verified, without re-reading a transcript that no longer exists.

The rules matter as much as the tools, and this is the point most memory pitches miss. A database that can save a checkpoint does not make an agent save one at the right moment with the right content. The agent instructions installed alongside the MCP server establish the discipline: list first, resume by selection, record before context compacts, close finished work without deleting its history. The checkpoint is the recovery record and the repository is the implementation. Together they let the next session continue without reconstructing the previous conversation. The test for every handover is mechanical: could another agent resume from the checkpoint plus the repository, without asking the previous agent what happened. If not, the handover was not finished.

Adoption is deliberately small. Install the binary, point three environment variables at it, the journal path among them, and append the checkpoint rules to the agent persistent instructions. The server speaks MCP stdio, so any client that can launch a command with environment variables can use it, and one journal can be shared by many agents over SSH with the database staying put. Nothing here builds, signs, publishes, or installs anything. It remembers, with receipts, and that is the whole product. There is a fitting consequence to close the circle: this article was produced through the same process, and its preparation history sits in checkpoints 72 through 75 of the journal at the time of writing.

## A checkpoint, concretely

Abstract discipline is unconvincing, so here is what one of these records actually contains. The checkpoint behind the database repair names the branch and commit, states the root cause in one line each for the shared counter and the restore amnesia, admits the self-caught regression mid-fix, then lists the verification: the old build producing duplicates under the same hammer test that the new build survives cleanly, the repair validated on a copy with byte-identical row multisets, integrity checks passing, and the live database explicitly untouched until a later approved deployment. Decision, evidence, next action, three paragraphs, written at the time by the agent doing the work. No secrets, no host internals, nothing reconstructed afterward. That record is why this article can describe the defect precisely in a later session, without relying on recollection.

## PeaBrain begins continual learning

The newest work connects the feedback path to the network. On a branch called rank-learn, closed at commit 473db2a with Master and the live database untouched, the loop runs end to end in shadow: every retrieval snapshots its features into a 256-entry ring, explicit useful or misleading feedback joins the freshest matching snapshot, labelled examples persist in an append-only table capped at 4096 rows and independent of model checkpoints, bounded training consumes only snapshot-time features in small batches, and inference appears as an advisory field in the explanation and status tools while deterministic ordering stays authoritative. The safeguards were operator-ordered and binding: training inputs must reflect information available before feedback, because measurement proved that surfacing a memory bumps its counters and re-reading them would leak the answer; automation goes fully dormant when a human-created model exists, so the ranker can never overwrite user weights; evaluation examples are grouped by stable identity so the same memory always lands on the same side of the split.

The honest result is reported, including the part that flatters nobody. A fixed-input test confirms the model genuinely learns: predictions move toward their targets and loss falls, restart produces bit-identical neural output, and file round-trips through the public tools are exact. But the lift metric on held-out examples reads negative 0.67 after forty mixed feedbacks, with three examples held out per the project record. The model trains; there is no evidence yet that it ranks better than the deterministic scorer. Per the standing decision, the deterministic ranker remains authoritative and the neural output stays advisory until testing demonstrates an improvement. A larger, more diverse feedback history is the stated requirement for the next step. Having the ability to train is not the same as having an operational learning system, and the project journal records that distinction instead of blurring it.

## What was deliberately not built

Engineering includes refusals. PeaBrain investigated GPU computation with standalone FASM prototypes that demonstrated direct driver communication and resource allocation. Real computation was not achieved under the strict no-libcuda constraint, and the project documented the verdict rather than recreating a significant portion of a vendor userspace driver inside an assembly codebase that defines itself by having no dependencies. The CPU backend, vector plus scalar with differential suites, remains the supported path. This section is short on purpose. It is context, not a second article, and its lesson is one line: know what you are not building, write it down, and keep the binary small.

## Why this matters beyond Saphira Linux

Return to the infrastructure, because that is the transferable part. An agent transient context is bounded; durable engineering state is not, provided somebody writes it down with enough structure to be resumed. The repository holds the implementation and the journal holds the decisions, failures, commit pins, and verification results. Either alone is insufficient. Code without the record of why invites repeated investigations. Records without the code invite drift. The combination survived real use here: dozens of checkpoints across model arenas, row identifier repairs, GPU verdicts, releases, branch audits, and continual learning, with closed work retained resumable rather than deleted.

For another developer the path is the portable mode described above, with the official documentation as the reference rather than any installation manual reproduced here. One caution travels with it: the tool does not capture conversations or tool outputs automatically, and no retrieval system here can reproduce them. Its value depends entirely on what the agent deliberately records. That limitation is stated in its own documentation and repeated here because it is load-bearing. Useful agent memory is not remembering previous conversations. It is preserving enough verified engineering context for work to continue correctly.

## Conclusion

PeaBrain demonstrates what can be built in a compact assembly-language MCP implementation: from a 614-byte socket experiment through a file-serving webserver and a thinking-protocol server to a 73,597-byte persistent-memory system with adaptive ranking and a trainable network, all without libc and all verified by testing that found real defects. Saphira Build MCP demonstrates how an agent preserves engineering work across a long sequence of implementation, testing, correction, and verification, and why that capability has nothing to do with any particular Linux distribution. The closing lesson is about measurement. Agent usefulness should not be scored only on generated code. It should also be scored on whether the agent can explain its work, recover its state, preserve decisions, admit failures, and continue without repeating resolved investigations. Both repositories are public and linked below. Engineers should inspect the sources and the evidence and judge accordingly.

## References

The PeaBrain repository, including the model directory, the BUILD notes, and the shipped tinythink binary, lives at the address below, with the measurements in this article taken at Master commit 7b21106 and the continual-learning work on the rank-learn branch at 473db2a.

[https://github.com/akadatalimited/PeaBrain](https://github.com/akadatalimited/PeaBrain?ref=articles.akadata.co.uk)

The canonical source that rebuilds the shipped 73,597-byte binary byte for byte is tinythink.asm:

[https://raw.githubusercontent.com/akadatalimited/PeaBrain/Master/tinythink.asm](https://raw.githubusercontent.com/akadatalimited/PeaBrain/Master/tinythink.asm?ref=articles.akadata.co.uk)

The earlier 21-tool revision, peabrain.asm, is retained for history:

[https://raw.githubusercontent.com/akadatalimited/PeaBrain/Master/peabrain.asm](https://raw.githubusercontent.com/akadatalimited/PeaBrain/Master/peabrain.asm?ref=articles.akadata.co.uk)

The Saphira Build MCP server, its portable-mode documentation, checkpoint discipline rules, and SSH sharing guide live at the address below; the checkpoint rules template that the installed instructions adapt is at the second address.

[https://github.com/SaphiraLinux/saphira-build-mcp](https://github.com/SaphiraLinux/saphira-build-mcp?ref=articles.akadata.co.uk)

[https://raw.githubusercontent.com/SaphiraLinux/saphira-build-mcp/Master/rules/AGENT\_MCP\_RULES.md](https://raw.githubusercontent.com/SaphiraLinux/saphira-build-mcp/Master/rules/AGENT_MCP_RULES.md?ref=articles.akadata.co.uk)

The SHAMPOO product line, the Shared Human-Agent-Model Platform for Orchestration and Operations toward which longer-term memory work points, is described at the first address below, and the Saphira Linux project follows it.

[https://shampoo.op2.uk](https://shampoo.op2.uk/?ref=articles.akadata.co.uk)

[https://saphira.vm2.uk](https://saphira.vm2.uk/?ref=articles.akadata.co.uk)

The three ancestor programs from the development working tree, server.asm, webserver.asm, and think.asm, are preserved as a public gist with one file per program:

[https://gist.github.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b](https://gist.github.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b?ref=articles.akadata.co.uk)

Direct downloads for each ancestor file:

[https://gist.githubusercontent.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b/raw/36764fe5f20117a736e45f564c3ac934d13592d8/server.asm](https://gist.githubusercontent.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b/raw/36764fe5f20117a736e45f564c3ac934d13592d8/server.asm?ref=articles.akadata.co.uk)

[https://gist.githubusercontent.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b/raw/f0729b4d76e3f7b75f7c876f249fc06902e3abd0/webserver.asm](https://gist.githubusercontent.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b/raw/f0729b4d76e3f7b75f7c876f249fc06902e3abd0/webserver.asm?ref=articles.akadata.co.uk)

[https://gist.githubusercontent.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b/raw/37b859f7e72b4db78a13186de9023c04a60dd9c5/think.asm](https://gist.githubusercontent.com/akadata/0c55fdaa3f4e46ed17509af6eb03587b/raw/37b859f7e72b4db78a13186de9023c04a60dd9c5/think.asm?ref=articles.akadata.co.uk)

> Source: https://articles.akadata.co.uk/peabrain-learning-saphira-build-mcp
