Skip to content

Instantly share code, notes, and snippets.

@decagondev
Created July 20, 2026 17:47
Show Gist options
  • Select an option

  • Save decagondev/5ffdf12c1b3d29233ad45fb843155ce0 to your computer and use it in GitHub Desktop.

Select an option

Save decagondev/5ffdf12c1b3d29233ad45fb843155ce0 to your computer and use it in GitHub Desktop.

MCP Factory — Intro Deck · Presenter Script

Deck: mcp-factory-intro-deck.html · 14 slides · ~12 minutes at a steady pace (plus Q&A).

How to use this: one entry per slide, in order. The Cue line is a rough timing/intent marker; the paragraph beneath it is what to say — paraphrase it, don't read it. Advance with the arrow keys (or number keys 1–9 to jump). Press O in the deck for the slide overview, F for fullscreen.


Slide 1 — Title

On screen: MCP Factory

Cue: ~45s · warm open

MCP Factory is scaffolding for building MCP servers. If you've ever wired an API into an AI assistant by hand, you know the boilerplate repeats every time — HTTP client, response formatting, tool registration. MCP Factory turns that repetition into a factory line: a clean, SOLID foundation where every API you add is a self-contained "plugin." Drop the plugin in, and its tools appear automatically in Cursor, Claude Desktop, or any MCP client — with zero changes to existing code. Today I'll show what it is, how it's built, and the exact repeatable process for spinning up a brand-new MCP.


Slide 2 — Why it exists

On screen: Every new API means the same wiring — again

Cue: ~50s

Quick context. MCP — the Model Context Protocol — is the open standard that lets an AI agent call tools and read data through a simple interface. It's great, but here's the catch: every server repeats the same plumbing. An async HTTP client. Try/except error handling. Turning JSON into readable Markdown. Registering each tool so the agent can discover it. You rewrite that for every API. MCP Factory's whole premise is on the right: one API becomes one plugin. The framework owns the repetitive plumbing; you write only what's genuinely specific to your API. That's the shift — from re-plumbing to plugging in.


Slide 3 — What it is

On screen: An extensible MCP server, ready to be extended or forked

Cue: ~55s

So what actually ships? Four things worth knowing. One — the architecture: every API is a plugin folder under services/, holding its own config, HTTP client, formatter, validation, and tools. Nothing leaks between services. Two — it's built on FastMCP and Python 3.13, async httpx for I/O, stdio transport, managed with uv. Three — it comes with two reference services on purpose: NASA's APOD, a classic REST API, and Code Guardian, a local code scanner — proving the pattern works for HTTP calls and local logic. Four — you can fork the whole thing as a template: rename it, delete the sample, and you've got your own clean MCP scaffold.


Slide 4 — The big idea

On screen: Add a plugin. The tools appear. Existing code never changes.

Cue: ~50s · the "aha"

This is the one slide to remember. On the left: plugins — APOD, Weather, and a new one you're adding — all feed into a single ServiceRegistry. The registry collects them and applies them to the FastMCP server, which exposes every tool to every client. On the right is the punchline in code: to light up a whole new API, you import your service and add one lineregistry.add(YourService()). That's it. You never touch the registry, the server loop, or any other service. That's the Open/Closed Principle in the wild: the system is open to extension but closed to modification. New capability, zero risk to what already works.


Slide 5 — Architecture

On screen: From launch command to live tools

Cue: ~55s

Here's the whole machine in one line. main.py is a thin entry point. It hands off to server.py, which builds the FastMCP instance and a ServiceRegistry. The registry holds the plugins; each plugin's register() wires its tools onto FastMCP, which then talks to MCP clients. Underneath, the boot runs in four phases: Import the plugin classes, Build the registry by adding each service, Apply them all — which calls every plugin's register — and finally Serve the stdio loop. The key insight for extending it: when you add a new API, you only touch phases one and two. Apply and Serve are generic; they never change. That's why adding a service is safe and boring — exactly what you want in infrastructure.


Slide 6 — Base abstractions

On screen: Small contracts you inherit, extend, and plug in

Cue: ~55s

Four small contracts do all the load-bearing work. BaseAPIClient — an abstract class; you subclass it and implement one method, fetch, which returns a dict or None and never throws. BaseFormatter — also abstract; implement format, a pure function that turns data into a Markdown string, with no I/O. ServicePlugin — this one's a Protocol, structural typing: any class with a register(mcp) method counts, no inheritance needed. And ServiceRegistry — the little factory that collects plugins and applies them. Notice how thin these are. A plugin is asked for exactly one method and nothing more — that's Interface Segregation — and any client can stand in for any other, which is Liskov. Small contracts, big leverage.


Slide 7 — Anatomy of a service

On screen: Five small files, one clear job each

Cue: ~50s

Open any service and you'll always see the same five files — that predictability is the point. config.py: constants only — base URL, timeout, and the API key loaded from an environment variable, never hardcoded. client.py: the one and only place HTTP happens; it returns a dict or None. formatter.py: a pure function, data in and Markdown out, trivially testable because it does no I/O. validation.py: optional — date checks, ID checks — so your tools stay thin. And init.py: the service class that composes the client and formatter and defines the actual tools inside its register method. Single Responsibility, file by file: if the output format changes, you know exactly which file to open.


Slide 8 — The 8-step process

On screen: Eight steps to a new MCP service

Cue: ~60s · the centerpiece

This is the recipe — memorize the shape, not the details. One: make a folder under services/. Two: add config — URL, key from an env var, timeout. Three: the client, extending BaseAPIClient. Four: the formatter, extending BaseFormatter. Five: the service class with your tools inside register. Six: register it — that one line in server.py, highlighted in amber because it's the only existing file you touch. Seven: tests, unit and end-to-end. Eight: uv run pytest -v. For a simple REST API this is a 30-to-60-minute job. And crucially — steps one through five and seven all create brand-new files. The blast radius on existing code is a single line.


Slide 9 — A tool call, end to end

On screen: Validate → fetch → format → return

Cue: ~55s

Zoom into one tool call. First, the agent chooses the tool by reading its docstring — so the docstring is a real API surface, not a comment. Write it for the model. Then the tool body follows a fixed rhythm: validate the input and bail out with a friendly string if it's wrong; call client.fetch, which gives you a dict or None; if None, return an error message; otherwise hand the data to format and return the Markdown. The iron rule, bottom-left: a tool always returns a string and never raises. The agent should get a helpful message, never a stack trace. And one distinction to keep straight — a tool is an action the agent calls; a resource is read-only reference data it reads at a URI, like a curated list.


Slide 10 — Scaffolding

On screen: Copy the template, fill the TODOs

Cue: ~45s

You don't write those five files from a blank page. The repo ships templates/service_template/ — the exact same five files, pre-stubbed with TODO markers, correct imports, and the right method signatures. So the real workflow is: cp -r the template into a new service folder, then go file by file replacing TODOs and renaming the Template classes to your own. Set your URL and env var in config, implement fetch, implement format, add validation if you need it, and define your tools in the service class. Then the two-line hookup in server.py and uv run pytest. You're editing a working skeleton, not architecting from scratch — that's what keeps it a 30-minute task.


Slide 11 — Test & ship

On screen: Tested at two levels, always green

Cue: ~45s

Two levels of testing keep the factory trustworthy. Unit tests hit each module in isolation, with HTTP mocked by respx so there's never a real network call — you test the client's success and failure paths, the formatter's output, and your validation. End-to-end tests boot a real FastMCP-plus-registry-plus-service stack and call your tools through the actual MCP interface; that suite is the contract test for "no breaking changes." The gate is simple: uv run pytest -v, and everything — old and new — has to be green before you merge. If it's green, the external interface is intact and you can ship.


Slide 12 — Fork as a template

On screen: Fork it as a template for a brand-new MCP

Cue: ~55s

Beyond adding a service, you can fork the whole repo as the seed for your own MCP product. Four moves: rename the package and fix imports; update the project name and SERVER_NAME; delete the APOD sample and its tests; then build your first real service with the same 8-step process. Everything reusable — base classes, registry, server wiring, entry point, and the test harness — you inherit for free. The pattern travels: a Weather MCP wrapping OpenWeather, or a database MCP over Postgres where you add a sibling BaseQueryClient. And don't assume it's only for REST — Code Guardian, the second bundled service, scans local files with no external API at all. Same plugin-and-registry shape, different guts.


Slide 13 — Reference services

On screen: Two worked examples in the box

Cue: ~45s

The best documentation is the two services that ship with it. NASA APOD is the canonical reference — a clean REST plugin with three tools (today's photo, by-date, random) and one resource, that curated list of famous space dates. It's the thing you copy when your API looks like a normal REST call. Code Guardian is deliberately different — five tools that scan a local codebase for secrets, OWASP-style vulnerabilities, quality and style problems, and known CVEs through an analyzer registry backed by OSV.dev. No external REST call at its core. Having both in the box is intentional: one proves the HTTP path, the other proves local logic, and together they show the plugin pattern generalizes well past "wrap an API."


Slide 14 — Recap

On screen: Copy · fill 5 files · add 1 line · test · tools appear

Cue: ~50s · close

Let me collapse the whole thing into one sentence: copy the template, fill in five files, add one line, run the tests, and your tools go live in every MCP client. That loop is the product. Three things to take with you. It's SOLID by design — every file has one job, and new work only extends the system, it never rewrites what already works. It's built for AI agents — the CLAUDE.md, the Cursor rules, and the templates mean a coding agent can scaffold a correct service almost unattended. And it's yours to fork — there's a production-ready MCP scaffold hiding inside a NASA photo demo. From here, jump into the docs site: the architecture, the step-by-step guides, and the two reference services in full detail. Thank you.


Estimated speaking time: ~11 min 55s across the 14 slides. Trim slides 5, 6, and 12 first if you need to come in under 10 minutes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment