Numbers in this article were read from the public live page on 30 October 2026.
I run a two-person software company in the Czech Republic. For the last six weeks I have been running an experiment in public: an open-source product where the code, the tests, the pull requests and the merges are done by AI developers, and a person steps in only where a person is actually needed.
The product is called mcp4mail. This article is the story of how it was built, with the numbers, and with links that let you check every one of them yourself.
What mcp4mail is
mcp4mail is your mailbox as an MCP server. You connect an IMAP account, and your AI assistant can read and search your mail, authorized over OAuth 2.1. It is MIT-licensed, self-hostable with one docker compose up, and there is a hosted instance at mcp4mail.online that runs from the same code.
Today it exposes 14 tools: list accounts and folders, search headers, read messages, download attachments, look up contacts. It can also change a mailbox (flag, move, trash, create folders, save drafts, send), but every mailbox is read-only by default. The write tools only work where the mailbox owner switched on "Allow the AI to make changes" and ticked the matching permission. Even then, send_message only prepares an email; it leaves after a human presses Send.
A few more details from the README, because people always ask:
- It talks plain IMAP with an app password, so it works with Gmail, iCloud, Fastmail, Outlook.com, Yahoo and your own IMAP host. There is no Gmail or Microsoft Graph API involved.
- The mail password is stored encrypted with Active Record Encryption (AES-256-GCM) and decrypted only in memory to open the IMAP connection. If you self-host, you hold the keys.
- It keeps only message headers in its own database, refreshed every 15 minutes, so searches do not hit your mail server every time. Bodies are fetched when the AI asks for one.
- Every tool call goes to an audit log, and there are rate limits and a search budget per account, so a runaway loop cannot walk a whole mailbox.
The stack is boring on purpose: Ruby 3.4, Rails 8.1, PostgreSQL, Hotwire, Tailwind, Solid Queue.
The code is here: https://github.com/jchsoft/mcp4mail
How the work flows
The development runs on our own task tracker and on a program we call the runner. The flow is the same for every change, and it is the same flow a new developer on their first day would get.
- A task waits in the queue. It has a brief: context, what to do, acceptance criteria.
- A runner takes it. The runner is a single binary that runs on one of our own machines. It picks the next task that is ready, triages it, chooses a model, and starts a coding CLI. The runner can drive Claude Code, Codex CLI or OpenCode; on mcp4mail it drives Claude Code.
- The coding CLI works on its own branch. It writes the code and the tests, runs the project's own test entry points, and opens a pull request that links back to its task.
- CI decides. Lint, security scan, unit tests, system tests. Red means it goes no further.
-
Merge only after green CI. The
mainbranch of mcp4mail is protected by a repository ruleset: an open pull request, a linear history and green status checks are required before a squash merge is allowed. That applies to people and runners alike. Nobody pushes tomaindirectly. - Deploy. The hosted site picks up merged changes in a daily deploy, on work days around 18:00 Prague time.
The runner is not a dumb launcher around the CLI. It watches the run with a watchdog, respects a daily quota, logs its progress on the task as it goes, and when a task turns out to be bigger than one run, it sets it aside for a person instead of half-implementing it.
One thing worth saying plainly, because it is how we think about it: a runner is a user of the account with its own seat, exactly like a person on the team. It is not free and not unlimited, and it gets no access a new developer would not get.
The two moments I stepped in
This is the part people find hardest to believe, so here it is precisely.
Moment one: the plan. I sat down with Claude Desktop and let it design the project with me: what mcp4mail should be, the architecture, and then the breakdown into epics, stories and tasks with briefs and acceptance criteria. Those tasks went into the queue.
Moment two: production. When the app was ready, I deployed it to the production server.
Everything between those two moments was done by the AI developers: the code, the tests, the CI configuration, the pull requests and the merges.
That does not mean nothing ever broke. It means the ordinary problems of development did not need me. A test somebody else broke, a run that got stuck, a crash and restart: the runners handle those themselves. They create a task for the problem, fix it, merge it, and carry on with what they were doing.
The numbers
As of 30 October 2026, from the live page:
| Days of development | 42 |
| Tasks finished | 182 |
| Pull requests merged | 146 |
| Hours of work logged | 140 |
| Pull requests that passed CI on the first run | 90 % |
The last week is quiet: only 2 tasks were finished in the last 7 days, because the queue ran dry. The runners finished what was ready and are waiting for new tasks. They run around the clock, weekends and holidays included, and when the queue is empty they simply wait.
You do not have to trust these numbers. Two places to verify them:
-
The repository. Open the Pull requests tab of https://github.com/jchsoft/mcp4mail. Every PR links its task and shows its CI runs, including the failed ones. The instructions the runners work from are in the repo too:
CLAUDE.md, the.claude/directory and.github/workflows/ci.yml. - The live page (linked at the end of this article). It shows the runners right now (working or waiting), the task queue, the counters above, and the latest changes with their CI result.
What happens when CI is red
10 % of pull requests did not pass CI on the first run. That is where the checks are doing their job, so here is what happens then.
The runner's own PR fails. The runner reads the failure, fixes it on the same branch, and pushes again. The live page shows this as it happened. On 26 October, the task "Backlog refill: weekly audit that turns signals into tasks" went into PR #201; the first CI run failed, the runner fixed it, and run 2 passed. Only then was it merged.
Something unrelated is broken. This is the more interesting case. Say a runner is working on task A and hits a failing test that has nothing to do with A, for example a test somebody else's change broke. It does not stop and wait for me, and it does not quietly "fix" the test inside task A's pull request either. Instead:
- It files a new, urgent task for the broken test.
- That task is pinned to the front of the queue and runs next, once the working copy is clean.
- The fix goes through the same path: branch, pull request, green CI, merge.
- The runner then picks task A back up from where it left off and finishes it.
If a runner crashes mid-task, it picks the task up again on its next loop. A hard failure of the runner itself files its own bug task with the run log attached.
A concrete example from the mcp4mail history: on 23 October, local CI on a newer macOS started failing because a refused IMAP connection raised EINVAL instead of the expected error. That became its own task, PR #200, merged with CI green on the first try. Nobody had to wake me up for it.
What this is, and what it is not
It is a real open-source product that we use ourselves, and at the same time a public demonstration of a process. People still write the task briefs and decide what ships. A runner executes a task end to end, but it is not deciding what to build.
It is also not magic. The reason it works is the same reason it works with a new human developer: small, well-specified tasks, a protected main branch, a CI that means something, and nothing reaching production without passing it.
If you want to see it working, the live page shows it in real time, and the task tracker and runner behind it are at our website. The code, the tests and every pull request, the red ones included, are open at https://github.com/jchsoft/mcp4mail.
Send it to the most sceptical senior developer you know and let them read the pull requests. That is exactly how I would want it judged.
Top comments (0)