Skip to content

Quickstart — Lightspeed

From zero to a running MCP server in under 30 seconds. The CLI scaffolds a production-ready project with autoDiscover() file-based routing, typed context, Presenters, middleware, testing, and pre-configured connections for Cursor, Claude Desktop, and Claude Code — no boilerplate.

Prerequisites

Node.js 18+ required.

bash
npm install @vinkius-core/mcp-fusion @modelcontextprotocol/sdk zod

Already using a project?

If you're adding MCP Fusion to an existing Node.js project, the install above is all you need — then skip to Building Tools.

Scaffold

The CLI creates a complete project with all dependencies pre-installed:

bash
npx fusion create my-server

The interactive wizard runs:

  Project name?  (my-mcp-server) › my-server
  Transport?     [stdio, sse]    › stdio
  Vector?        [vanilla, prisma, n8n, openapi, oauth] › vanilla
  Include testing?               › yes

  ● Scaffolding project — 14 files (6ms)
  ● Installing dependencies...
  ✔ Done

  $ cd my-server
  $ fusion dev
  $ npm test

Skip the wizard with --yes for defaults, or pass flags directly. For example, if you want to give Claude Desktop or Cursor secure access to your database, you can automatically generate a Postgres SQL Agent MCP through Prisma schemas without risking raw SQL injection vulnerabilities:

bash
npx fusion create my-api --vector prisma --transport sse --yes

Pro-Tip: The --vector prisma command is the absolute fastest way to bridge Prisma to MCP. It leverages the MVA Presenter architecture to build an Egress Firewall, ensuring internal columns (like password_hash or ssn) are stripped from memory before they ever reach the LLM Context Window.

What you get

text
my-server/
├── src/
│   ├── fusion.ts          # initFusion<AppContext>()
│   ├── context.ts         # AppContext type + factory
│   ├── server.ts          # Bootstrap with autoDiscover
│   ├── tools/
│   │   └── system/
│   │       ├── health.ts  # Health check with Presenter
│   │       └── echo.ts    # Echo for connectivity testing
│   ├── presenters/
│   │   └── SystemPresenter.ts
│   ├── prompts/
│   │   └── greet.ts
│   └── middleware/
│       └── auth.ts
├── tests/
│   ├── setup.ts
│   └── system.test.ts
├── .cursor/mcp.json       # Pre-configured for Cursor
├── .env.example
├── package.json
├── tsconfig.json
└── vitest.config.ts

Every file is real code — not stubs. The server boots, the tests pass, Cursor connects.

Run & Connect

bash
cd my-server
fusion dev

The server starts on stdio. Connect it to your MCP client:

Cursor — Zero-Click Integration

Already configured. The CLI generates .cursor/mcp.json automatically — open the project in Cursor and the MCP connection is live. No manual setup, no config editing. This is the fastest path from scaffold to working MCP server.

Claude Desktop

Add to your claude_desktop_config.json:

json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["tsx", "src/server.ts"]
    }
  }
}

Claude Code

bash
claude mcp add my-server npx tsx src/server.ts

Windsurf

Add to your Windsurf MCP config (~/.codeium/windsurf/mcp_config.json):

json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["tsx", "src/server.ts"]
    }
  }
}

Cline (VS Code Extension)

Add via Cline's MCP settings in VS Code — cline_mcp_settings.json:

json
{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["tsx", "src/server.ts"]
    }
  }
}

VS Code + GitHub Copilot

Add to your .vscode/mcp.json:

json
{
  "servers": {
    "my-server": {
      "command": "npx",
      "args": ["tsx", "src/server.ts"]
    }
  }
}

SSE transport

For network-accessible servers (multi-client, remote deployment):

bash
npx fusion create my-api --transport sse
cd my-api
fusion dev
# Server running on http://localhost:3001/sse

autoDiscover — file-based routing

This is the scaffolded project's superpower. No index.ts with 50 imports. No manual registry.register() calls. Drop a file in src/tools/ and it's a live MCP tool.

How it works

The generated server.ts calls autoDiscover() at startup:

typescript
// src/server.ts (scaffolded)
import { ToolRegistry, autoDiscover } from '@vinkius-core/mcp-fusion';

const registry = f.registry();
const discovered = await autoDiscover(registry, new URL('./tools', import.meta.url).pathname);
console.error(`📦 Discovered ${discovered.length} tool file(s)`);

autoDiscover scans the entire src/tools/ tree, imports every .ts/.js file, extracts the tool builder, and registers it. .test.ts, .spec.ts, and .d.ts files are skipped automatically.

Naming convention

The directory structure becomes the tool namespace:

text
src/tools/
├── billing/
│   ├── get_invoice.ts    → billing.get_invoice
│   └── pay.ts            → billing.pay
├── users/
│   ├── list.ts           → users.list
│   └── ban.ts            → users.ban
└── system/
    └── health.ts         → system.health

The tool's name field in the code is the source of truth — the directory just groups related files. Git diffs stay clean because adding a tool never touches a shared import file.

Export resolution

autoDiscover resolves exports in priority order:

PriorityWhat it looks forExample
1export defaultexport default f.query('weather.get').handle(...)
2Named tool exportexport const tool = f.query('weather.get').handle(...)
3Any exported builderScans all exports for objects with getName()

The recommended pattern is export default:

typescript
// src/tools/weather/get.ts
import { f } from '../../fusion.js';

export default f.query('weather.get')
  .describe('Get current weather for a city')
  .withString('city', 'City name')
  .handle(async (input) => {
    return { city: input.city, temp_c: 18, condition: 'Clear' };
  });

Restart the dev server. weather_get is now callable by any MCP client.

Multiple tools in one file

Priority 3 enables exporting multiple tools from a single file:

typescript
// src/tools/billing/crud.ts
import { f } from '../../fusion.js';

export const listInvoices = f.query('billing.list_invoices')
  .describe('List all invoices')
  .handle(async () => ({ invoices: [] }));

export const createInvoice = f.mutation('billing.create_invoice')
  .describe('Create an invoice')
  .withNumber('amount', 'Invoice amount')
  .handle(async (input) => ({ id: 'inv_1', amount: input.amount }));

Both tools are discovered and registered — no extra wiring.

Advanced options

autoDiscover accepts an options object for fine-grained control:

typescript
await autoDiscover(registry, './src/tools', {
  pattern: /\.tool\.ts$/,   // only files ending in .tool.ts
  recursive: true,          // scan subdirectories (default: true)
  loader: 'esm',            // 'esm' (default) or 'cjs'
  resolve: (mod) => {       // custom export resolver
    return mod.myTool as ToolBuilderLike;
  },
});
OptionDefaultDescription
pattern/\.(ts|js|mjs|mts)$/Regex filter for file names
recursivetrueScan subdirectories
loader'esm'Module system — 'esm' uses import(), 'cjs' uses require()
resolvePriority cascade (default → tool → any)Custom function to extract builders from module exports

Test

The scaffolded project includes Vitest with a system test that verifies tool registration:

bash
npm test

The test harness uses MVA_META_SYMBOL to call tools in-memory — no transport layer, no network. Add your own:

typescript
// tests/weather.test.ts
import { describe, it, expect } from 'vitest';
import { ToolRegistry, autoDiscover } from '@vinkius-core/mcp-fusion';

describe('weather.get', () => {
  it('returns temperature for a city', async () => {
    const registry = new ToolRegistry();
    await autoDiscover(registry, new URL('../src/tools', import.meta.url).pathname);

    const result = await registry.callTool('weather_get', { city: 'Tokyo' });
    expect(result.content[0].text).toContain('Tokyo');
  });
});

Vectors

The --vector flag changes what gets scaffolded:

VectorWhat it adds
vanillaautoDiscover() file-based routing. Zero external deps
prismaprisma/schema.prisma + DB tool stubs + @vinkius-core/mcp-fusion-prisma-gen generator
n8nsrc/n8n.tsN8nConnector auto-discovers webhook workflows as MCP tools
openapiopenapi.yaml + SETUP.md — generates Models/Views/Agents from spec
oauthsrc/auth.ts + src/middleware/auth.ts — RFC 8628 Device Flow with requireAuth()
bash
# Database-driven MCP server
npx fusion create inventory-api --vector prisma --transport sse

# n8n workflow bridge
npx fusion create ops-bridge --vector n8n

# Authenticated API
npx fusion create secure-api --vector oauth

Each vector adds its dependencies to package.json and environment variables to .env.example automatically.

Next steps

WhatWhere
Understand tool definitions, annotations, Zod schemasBuilding Tools
Shape what the LLM sees with PresentersPresenter Guide
Add auth, rate limiting, loggingMiddleware
Register prompts and dynamic manifestsPrompt Engine
Run the full test harnessTesting
Lock your capability surfaceCapability Governance
Manual setup without the CLIQuickstart — Traditional

Go Live

Your server runs locally over Stdio. To expose it globally as a stateless HTTP endpoint, deploy to Vercel or Cloudflare Workers. Both adapters bridge the gap between MCP's long-lived process model and serverless runtimes — registry compilation is cached at cold start, warm requests execute with near-zero overhead.

Vercel — Next.js Edge Deployment

Drops into a Next.js App Router route. Edge Runtime for ~0ms cold starts, or Node.js Runtime for @vercel/postgres and heavier computation:

typescript
// app/api/mcp/route.ts
import { vercelAdapter } from '@vinkius-core/mcp-fusion-vercel';

export const POST = vercelAdapter({ registry, contextFactory });
export const runtime = 'edge'; // optional — global edge distribution

Cloudflare Workers — D1 & KV at the Edge

Your tools query D1 (SQLite at the edge) and KV with sub-millisecond latency from 300+ locations:

typescript
// src/worker.ts
import { cloudflareWorkersAdapter } from '@vinkius-core/mcp-fusion-cloudflare';

export default cloudflareWorkersAdapter({ registry, contextFactory });

Full guides: Vercel Adapter · Cloudflare Adapter · Production Server