Bryan Thompson
MCP Infrastructure Engineer, Anthropic
I build the pipelines that get plugins to Claude users.
Two of them: the Claude plugin directory and the MCPB desktop-extension pipeline. Build, audit, publish — across six source ecosystems, with drift detection running daily over thousands of listings.
The public trace
Most of this work happens in public repositories, so you don’t have to take my word for any of it. Every number below links to a live GitHub search that recomputes when you open it.
| Repository | Stars | PRs I authored | Merged through the pipeline |
|---|---|---|---|
| anthropics/claude-plugins-official | 33k+ | 210+ | 2,500+ |
| anthropics/knowledge-work-plugins | 23k+ | 50+ | 490+ |
| anthropics/claude-plugins-community | 340+ | 75+ | 2,100+ |
| modelcontextprotocol/mcpb | 2k+ | 10+ | 85+ threads |
| Total | 350+ | 5,000+ |
The 350+ are mine. Most are catalog operations, a good share of them emitted by the same automation — and in among them are the changes that built it, which you can read: the bump loop and the recovery job that catches it. The 5,000+ are submissions and rolling updates moving through that automation: each one scanned, validated, and policy-checked before it reaches a merge decision. Building the system was the work; the volume is what it produced.
† The modelcontextprotocol/mcpb row is open-source maintenance — issue and pull request threads participated in — not pipeline throughput, and it is not included in the throughput total. Every figure above is a floor, not an estimate: these counts only grow, and the totals moved by several hundred in the days it took to write this page. Floors verified against the GitHub API on 2026-08-10, and re-checked in CI; each links to a live search that recomputes the exact number when you open it.
Before this: a career in reliability engineering on Fortune 500 payment systems at PayPal and Fiserv. That’s where the instinct for staged rollouts and blast-radius containment comes from.
MCP Infrastructure & Quality Engineering
Building automation infrastructure and systematic review frameworks that power Claude Desktop's MCP ecosystem
Across four public directory repositories
Nobody does this by hand — that is the point
Into 75+ external repositories. The MCP schema defaults destructiveHint and openWorldHint to true, so an unannotated tool is already assumed destructive.
The pipelines
How the build-audit-publish automation is put together: what runs untrusted code and where, what the model is allowed to decide, and what it is never allowed to decide.
The repositories
The public half — MCP servers, assessment tooling and developer tools you can clone and run. Every link checked signed out.
An instruction in an agent's context is not a control surface
I move agent work onto boundaries a machine can check, measure the boundaries instead of asserting them, and fix by rule rather than by trust what one agent may conclude from another's report. Each page below names what its boundary still does not cover, and each hands you a line you can paste into a Python REPL or a browser console.
A skipped step leaves a gap you can query for, not silence
if not s.strip(): allow() is the obviously correct short-circuit at the top of a gate that runs before an agent emits text a human will act on, and it is deliberately absent from mine: a gate written in one language guarding a sender written in another inherits every disagreement between their standard libraries. A body of nothing but U+001C–U+001F and U+0085 is length 0 to Python's strip(), which allows it, and length 5 to JavaScript's trim(), which sends it. A corrective rule had been loaded into context and the steps it governed were skipped anyway — so the load-bearing ones came out of prose and onto boundaries a machine can see.
The crude attack failed and the polite one worked
A black-box harness I built drives a real agent runtime against fixtures I control and scores what happened rather than reasoning from the spec. Almost every such measurement reports an absence — which is also what a broken instrument reports for free — so what publishes is the instrument discipline: positive controls on the same capture surface, and “I failed to observe” kept separate from “I observed a failure”. The fixtures move one variable at a time, which you can check in a line: the four-character matcher returns no term at all for a positional tool name, and two for a descriptive one. The one result that ships: in those fixtures an instruction shaped like ordinary documentation was followed by one model where a blatant override was refused by both. No rate is attached, because a fraction a reader cannot re-derive is not evidence.
A message can say where to look, never what is concluded
Between agent sessions I let a message select what to verify, and never let it supply what is concluded. One stock-Python line shows why the obvious if "\n" in msg: reject() anti-forgery filter is not enough: a message carrying U+2028 contains no newline and is nonetheless two lines to splitlines(), so its second line can begin with the renderer's own output prefix and arrive as a forged record. Every layer that can act on a message stays deterministic, and a differential test proves that rather than asserting it. The parts that are still only convention — which session may merge, which may only read — are named on the page as unenforced, because no hook or permission profile checks the caller.