From Experiment to Framework: The Road to xmcp 0.8

Development

August 20, 2026 Valentina Bearzotti


What started as a simpler way to build MCP servers has grown into a production framework. With xmcp 0.8, we’re making its runtime lighter, its architecture clearer, and its deployment story stronger.

When we started building xmcp, the Model Context Protocol was already opening up a new way for applications and models to work together. The protocol was exciting. The process of building with it? A little less so.

Creating a TypeScript MCP server still meant spending time on registration, transports, bundling, configuration, and deployment before getting to the part that actually mattered: the tools you wanted to build.

At basement, this situation tends to trigger the same response. If a workflow repeatedly gets in the way of the work, we start looking for a better one. Sometimes that becomes an internal convention. Sometimes it becomes a small tool. And sometimes, after enough use and a few conversations that start with “wait, you built what?”, it becomes an open-source project.

xmcp started there: as an attempt to make building an MCP server feel natural to a TypeScript developer.

More than a year later, it has grown into something much broader. Nearly half a million downloads, more than 1,300 GitHub stars, dozens of integrations and examples, and—most importantly—a community building things with it that we never could have planned ourselves.

Version 0.8 is the latest step in that journey. It is not about adding the longest list of features. It is about giving the framework a clearer architecture for everything that comes next.

Starting with the obvious things

Our first goal was straightforward: remove setup without removing control.

A tool should be a file. Its filename should give it a name. Its schema, metadata, and handler should live together. Adding it to a server should not require jumping into a central registry and wiring up another chain of imports.

That became xmcp’s file-system routing.

Project structure
src/
├── tools/
│   └── search.ts
├── prompts/
│   └── summarize.ts
└── resources/
    └── (docs)/
        └── [slug].ts

The framework discovers these files, registers them, watches them during development, and builds the server around them. You can bootstrap a project with one command, add a tool, and see it running without first becoming an expert in xmcp’s internals.

That last part has always mattered to us. A framework can expose powerful abstractions, but the best development experience is often the one that lets you postpone learning them.

We began with tools because they were the most immediate part of MCP. As the protocol and its clients evolved, xmcp expanded to support prompts and resources using the same conventions. The concepts were different, but the mental model stayed familiar: clear files, typed schemas, colocated metadata, and sensible defaults.

By version 0.3, xmcp covered the complete set of core MCP server primitives. That was the moment it started feeling less like a useful shortcut and more like a framework.

From building tools to shipping products

Supporting the protocol was only one part of the problem.

A local server can be simple. A production server has users, authentication, infrastructure, failure modes, and, if things go well, a business model. It needs to connect to existing applications and deploy somewhere other than a developer’s laptop.

Over time, xmcp added adapters for Next.js, Express, Fastify, and NestJS. We built authentication paths for providers including Better Auth, WorkOS, Clerk, Auth0, Descope, and Scalekit. HTTP and STDIO transports became part of the same workflow. Deployment expanded across Vercel, Cloudflare, Replit, Alpic, and any environment capable of running the generated server.

Then MCP moved beyond invisible tool calls.

With MCP Apps, a tool can return an interactive interface instead of stopping at text or structured data. xmcp can build those interfaces with React, package their resources, and connect them to compatible hosts. Integrations with Polar, Commet, Stripe, and x402 have also made it possible to experiment with subscriptions, usage-based access, and agent-native payments.

None of these capabilities were in the first sketch of xmcp. They came from using the framework, listening to what people were trying to ship, and finding the next piece of friction.

That is the good side of growth. The other side is weight.

When development tooling follows you to production

By version 0.7.1, xmcp contained two different kinds of software inside the same package.

The first was the runtime: the code required by a built MCP server to receive requests, run tools, expose resources, and communicate through HTTP or STDIO.

The second was the compiler: the development machinery responsible for discovering files, validating configuration, watching changes, invoking Rspack and TypeScript, and producing the final server.

Both were necessary. They were not necessary at the same time.

Once an xmcp server had been built, its compiler had finished its job. The generated HTTP and STDIO artifacts were already self-contained and capable of running without the project’s node_modules. Yet installing xmcp in production still brought the build toolchain along for the ride.

The framework was doing the right thing at runtime, but the package boundary no longer represented that reality.

One thing I keep learning while working on developer tools is that an abstraction has to earn its weight more than once. It has to make sense when you introduce it, and it has to keep making sense as the system around it grows.

For xmcp 0.8, this one no longer did.

Splitting the compiler from the runtime

Version 0.8 moves the development compiler into a dedicated package: @xmcp-dev/compiler.

The main xmcp package now focuses on the production runtime. The compiler owns file discovery, development mode, configuration processing, bundling, and code generation.

Runtime and compiler
Development
xmcp + @xmcp-dev/compiler

         xmcp build

Self-contained HTTP or STDIO server

Production runtime

This is an architectural change, but we wanted it to feel intentionally boring for existing users.

The commands remain the same:

Commands
xmcp dev
xmcp build
xmcp create

A small shim in the runtime package loads the compiler when one of those commands is used. The generated output remains self-contained, so an HTTP or STDIO build can still be deployed without shipping the project’s dependencies beside it.

We also added an xmcp/config export. This gives the compiler access to the configuration schema supplied by the installed runtime, keeping validation aligned across matching versions instead of duplicating that contract between packages.

The visible workflow barely changes. The boundary underneath it is much healthier.

Lighter where it matters

The package split makes a measurable difference.

In our reproducible comparison against xmcp 0.7.1, the published runtime package went from 11.82 MiB unpacked to 5.77 MiB.

The larger improvement appears in a fresh production installation. That footprint moved from 100.60 MiB across 168 dependency entries to 9.62 MiB across two entries.

Those figures describe the installed production runtime, not a magically compressed server. The generated deployment artifacts remain close to their previous sizes because they were already self-contained. An HTTP build is still roughly 1.1 MiB, while a STDIO build remains under half a MiB in the measured fixture.

That distinction is important. We did not move dependencies around until a benchmark looked impressive. We removed development infrastructure from an environment where it had no work left to do.

The compiler still uses the tools it needs. They now live where they belong: in development.

You can review the complete methodology and results in the xmcp benchmark report.

Upgrading to 0.8

Once both stable packages are publicly available, existing projects will be able to upgrade with:

npm
npm install xmcp@0.8.0
npm install --save-dev @xmcp-dev/compiler@0.8.0

Keep the runtime and compiler on matching versions. Your existing tools, prompts, resources, configuration, and package scripts should continue to work without application-level changes.

For new projects, create-xmcp-app will install and configure both sides of the split automatically:

New project
npx create-xmcp-app@latest

The compiler is a development dependency. Production installations can omit it, and the output created by xmcp build remains deployable on its own.

The installation documentation includes equivalent commands for pnpm, Yarn, and Bun, along with troubleshooting guidance.

Building less into more

It is tempting to measure a framework’s progress by counting everything it can do.

Tools. Prompts. Resources. Authentication. Apps. Payments. Adapters. Deployments. Each new capability expands what people can build, and we are excited to keep pushing those boundaries.

But maturity is also knowing what to separate, what to remove, and what a production server should no longer have to carry.

xmcp 0.8 is a smaller runtime because the framework has become a bigger system. The package split gives each part a clearer responsibility while preserving the workflow that brought people to xmcp in the first place.

We are genuinely grateful to everyone who has tried the framework, opened an issue, built an integration, submitted a pull request, or shipped something unexpected with it. That feedback continues to shape where xmcp goes next.

Explore the framework at xmcp.dev, dive into the documentation, or come build with us on GitHub.

There is plenty left to do. At least now, production will carry a little less of it.


August 20, 2026 Valentina Bearzotti