/mcpfusion-development
How to build production MCP servers with MCP Fusion using the MVA (Model-View-Agent) pattern. Use this skill whenever writing, modifying, or reviewing MCP Fusion code — including tools, Presenters, Models, middleware, prompts, routers, tests, or server configuration. Activate
$ npx -y skills add vinkius-labs/mcpfusion --skill mcpfusion-development --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/mcpfusion-development
Context preview
The summary Claude sees to decide when to auto-load this skill.
How to build production MCP servers with MCP Fusion using the MVA (Model-View-Agent) pattern. Use this skill whenever writing, modifying, or reviewing MCP Fusion code — including tools, Presenters, Models, middleware, prompts, routers, tests, or server configuration. Activate
SKILL.md
mcpfusion-development.SKILL.mdname: mcpfusion-development
description: >
How to build production MCP servers with MCP Fusion using the MVA (Model-View-Agent) pattern.
Use this skill whenever writing, modifying, or reviewing MCP Fusion code — including tools,
Presenters, Models, middleware, prompts, routers, tests, or server configuration.
Activate even when the user just says "create a tool", "add an endpoint", "write a Presenter",
or mentions @mcpfusion/core, defineModel, definePresenter, initMCPFusion, FluentToolBuilder, or any
MCP Fusion API. This skill covers the entire framework surface.
license: Apache-2.0
compatibility: Requires Node.js >= 18, TypeScript 5.7+
metadata:
author: vinkius-labs
version: "3.0"
tags: mcp, typescript, framework, mva
mcpfusion development Guide
MCP Fusion is a TypeScript framework for MCP servers built on the **MVA (Model-View-Agent)** pattern. The Model validates data, the Presenter (View) shapes what the AI perceives, and Tools (Agent layer) wire it all together.
> For the complete API reference with all type signatures, read [llms.txt](../../../llms.txt) at the root of the repository. This skill covers the essential patterns and rules.
Reference Examples
Complete, runnable examples are available in `references/`. Read them for concrete implementation patterns:
| Example | Domain | Patterns Shown | |---|---|---| | [example-complete-crud.ts](references/example-complete-crud.ts) | Product Catalog | Full MVA lifecycle: Model → Presenter → Router → Query/Mutation/Action, ErrorBuilder, State Sync | | [example-proxy-api.ts](references/example-proxy-api.ts) | Blog Platform | `.proxy()` API pass-through, `.fromModel()`, field aliases, path params (`:id`), `.handle()` vs `.proxy()` decision tree | | [example-server-setup.ts](references/example-server-setup.ts) | Generic App | Full server bootstrap: context, `initMCPFusion()`, middleware, `autoDiscover()`, prompts, State Sync policies, `startServer()` | | [example-testing.ts](references/example-testing.ts) | Customer Service | `@mcpfusion/testing`: Egress Firewall assertions, JIT System Rules, RBAC middleware, error handling, Symbol Invisibility |
Project Structure
src/
├── models/ ← M — defineModel() declarations
│ ├── InvoiceModel.ts
│ └── UserModel.ts
├── views/ ← V — Presenters
│ ├── invoice.presenter.ts
│ └── user.presenter.ts
├── agents/ ← A — Tool definitions
│ ├── billing.tool.ts
│ └── users.tool.ts
├── index.ts ← ToolRegistry + registerAll()
└── server.ts ← attachToServer() bootstrap
**Layer import rule:** `agents/` → `views/` → `models/` → `@mcpfusion/core`. Never import backwards.
The Golden Rules
1. **ALWAYS use `defineModel()` for domain entity schemas** — never raw `z.object()`. Models go in `models/`. 2. **Presenters receive Models via `.schema(MyModel)`** — the Presenter is the egress firewall. 3. **`with*()` methods are for tool INPUT parameters only** (filters, IDs, pagination) — NOT for domain schemas. 4. **Handlers return raw data** — the framework wraps with `success()` automatically. No boilerplate. 5. **One Model + one Presenter per entity**, reused across every tool and prompt. 6. **Use semantic verbs**: `f.query()` = readOnly, `f.mutation()` = destructive, `f.action()` = neutral.
defineModel() — The "M" in MVA
Every domain entity starts here. Produces a `Model` with a compiled Zod `.schema`.
import { defineModel } from '@mcpfusion/core';
export const InvoiceModel = defineModel('Invoice', m => {
m.casts({
id: m.string(),
amount_cents: m.number('CRITICAL: in CENTS. Divide by 100 for display.'),
status: m.enum('Status', ['paid', 'pending', 'overdue']),
client_name: m.string('Client name'),
});
});
export const UserModel = defineModel('User', m => {
m.casts({
id: m.string(),
name: m.string('Full name'),
email: m.string('Email address'),
role: m.enum('Role', ['admin', 'member', 'guest']),
});
m.hidden(['password_hash', 'stripe_token']); // Never exposed
m.timestamps(); // created_at + updated_at
m.fillable({
create: ['name', 'email', 'role'],
update: ['name', 'email'],
});
});Type Helpers
| Method | Produces | Use | |---|---|---| | `m.string(label?)` | `z.string()` | General text | | `m.text(label?)` | `z.string()` | Markdown / long content | | `m.number(label?)` | `z.number()` | Numeric | | `m.boolean(label?)` | `z.boolean()` | Flags | | `m.date(label?)` | `z.string()` | YYYY-MM-DD | | `m.timestamp(label?)` | `z.string()` | ISO datetime | | `m.uuid(label?)` | `z.string()` | UUID | | `m.id(label?)` | `z.number()` | Always required | | `m.enum(label, values)` | `z.enum()` | Valid values |
FieldDef Chaining
m.enum('Status', ['open', 'done']).default('open')
m.string('Display name').alias('displayName') // agent says 'name', API gets 'displayName'
m.number('Score').examples([85, 92, 100])Model.toApi() — Alias Resolution
Strips undefined values and renames aliased fields. Used automatically by `.proxy()`, call explicitly in `.handle()`:
const data = TaskModel.toApi(input);
// { title: 'X', body: 'Y' } ← alias applied, undefined strippedPresenter — The "V" in MVA
The Presenter is the egress firewall between your handler and the wire. Schema MUST come from `defineModel()`.
definePresenter() — Object Config (Recommended)
import { definePresenter, ui } from '@mcpfusion/core';
export const InvoicePresenter = definePresenter({
name: 'Invoice',
schema: InvoiceModel, // ← Model, never z.object()
// autoRules: true (default) — .describe() annotations become system rules
ui: (inv) => [ui.echarts({ series: [{ type: 'gauge', data: [{ value: inv.amount_cents / 100 }] }] })],
agentLimit: { max: 5Read more
name: mcpfusion-development description: > How to build production MCP servers with MCP Fusion using the MVA (Model-View-Agent) pattern. Use this skill whenever writing, modifying, or reviewing MCP Fusion code — including tools, Presenters, Models, middleware, prompts, routers, tests, or server configuration. Activate even when the user just says "create a tool", "add an endpoint", "write a Presenter", or mentions @mcpfusion/core, defineModel, definePresenter, initMCPFusion, FluentToolBuilder, or any MCP Fusion API. This skill covers the entire framework surface. license: Apache-2.0 compatibility: Requires Node.js >= 18, TypeScript 5.7+ metadata: author: vinkius-labs version: "3.0" tags: mcp, typescript, framework, mva
mcpfusion development Guide
MCP Fusion is a TypeScript framework for MCP servers built on the **MVA (Model-View-Agent)** pattern. The Model validates data, the Presenter (View) shapes what the AI perceives, and Tools (Agent layer) wire it all together.
> For the complete API reference with all type signatures, read [llms.txt](../../../llms.txt) at the root of the repository. This skill covers the essential patterns and rules.
Reference Examples
Complete, runnable examples are available in `references/`. Read them for concrete implementation patterns:
| Example | Domain | Patterns Shown | |---|---|---| | [example-complete-crud.ts](references/example-complete-crud.ts) | Product Catalog | Full MVA lifecycle: Model → Presenter → Router → Query/Mutation/Action, ErrorBuilder, State Sync | | [example-proxy-api.ts](references/example-proxy-api.ts) | Blog Platform | `.proxy()` API pass-through, `.fromModel()`, field aliases, path params (`:id`), `.handle()` vs `.proxy()` decision tree | | [example-server-setup.ts](references/example-server-setup.ts) | Generic App | Full server bootstrap: context, `initMCPFusion()`, middleware, `autoDiscover()`, prompts, State Sync policies, `startServer()` | | [example-testing.ts](references/example-testing.ts) | Customer Service | `@mcpfusion/testing`: Egress Firewall assertions, JIT System Rules, RBAC middleware, error handling, Symbol Invisibility |
Project Structure
src/ ├── models/ ← M — defineModel() declarations │ ├── InvoiceModel.ts │ └── UserModel.ts ├── views/ ← V — Presenters │ ├── invoice.presenter.ts │ └── user.presenter.ts ├── agents/ ← A — Tool definitions │ ├── billing.tool.ts │ └── users.tool.ts ├── index.ts ← ToolRegistry + registerAll() └── server.ts ← attachToServer() bootstrap
**Layer import rule:** `agents/` → `views/` → `models/` → `@mcpfusion/core`. Never import backwards.
The Golden Rules
1. **ALWAYS use `defineModel()` for domain entity schemas** — never raw `z.object()`. Models go in `models/`. 2. **Presenters receive Models via `.schema(MyModel)`** — the Presenter is the egress firewall. 3. **`with*()` methods are for tool INPUT parameters only** (filters, IDs, pagination) — NOT for domain schemas. 4. **Handlers return raw data** — the framework wraps with `success()` automatically. No boilerplate. 5. **One Model + one Presenter per entity**, reused across every tool and prompt. 6. **Use semantic verbs**: `f.query()` = readOnly, `f.mutation()` = destructive, `f.action()` = neutral.
defineModel() — The "M" in MVA
Every domain entity starts here. Produces a `Model` with a compiled Zod `.schema`.
import { defineModel } from '@mcpfusion/core';
export const InvoiceModel = defineModel('Invoice', m => {
m.casts({
id: m.string(),
amount_cents: m.number('CRITICAL: in CENTS. Divide by 100 for display.'),
status: m.enum('Status', ['paid', 'pending', 'overdue']),
client_name: m.string('Client name'),
});
});
export const UserModel = defineModel('User', m => {
m.casts({
id: m.string(),
name: m.string('Full name'),
email: m.string('Email address'),
role: m.enum('Role', ['admin', 'member', 'guest']),
});
m.hidden(['password_hash', 'stripe_token']); // Never exposed
m.timestamps(); // created_at + updated_at
m.fillable({
create: ['name', 'email', 'role'],
update: ['name', 'email'],
});
});Type Helpers
| Method | Produces | Use | |---|---|---| | `m.string(label?)` | `z.string()` | General text | | `m.text(label?)` | `z.string()` | Markdown / long content | | `m.number(label?)` | `z.number()` | Numeric | | `m.boolean(label?)` | `z.boolean()` | Flags | | `m.date(label?)` | `z.string()` | YYYY-MM-DD | | `m.timestamp(label?)` | `z.string()` | ISO datetime | | `m.uuid(label?)` | `z.string()` | UUID | | `m.id(label?)` | `z.number()` | Always required | | `m.enum(label, values)` | `z.enum()` | Valid values |
FieldDef Chaining
m.enum('Status', ['open', 'done']).default('open')
m.string('Display name').alias('displayName') // agent says 'name', API gets 'displayName'
m.number('Score').examples([85, 92, 100])Model.toApi() — Alias Resolution
Strips undefined values and renames aliased fields. Used automatically by `.proxy()`, call explicitly in `.handle()`:
const data = TaskModel.toApi(input);
// { title: 'X', body: 'Y' } ← alias applied, undefined strippedPresenter — The "V" in MVA
The Presenter is the egress firewall between your handler and the wire. Schema MUST come from `defineModel()`.
definePresenter() — Object Config (Recommended)
import { definePresenter, ui } from '@mcpfusion/core';
export const InvoicePresenter = definePresenter({
name: 'Invoice',
schema: InvoiceModel, // ← Model, never z.object()
// autoRules: true (default) — .describe() annotations become system rules
ui: (inv) => [ui.echarts({ series: [{ type: 'gauge', data: [{ value: inv.amount_cents / 100 }] }] })],
agentLimit: { max: 5The TypeScript framework for secure, MCP 2.0-native servers. MCP Fusion is a TypeScript framework that enforces security at the architectural level of every MCP server. Raw data never reaches the LLM without passing through a typed egress firewall.
Repo: vinkius-labs/mcpfusion

