Skip to main content
Run your FrontMCP server locally with hot-reload and verify it with the FrontMCP Inspector (zero setup).

Prerequisites

  • Node.js:
    • Minimum: Version 22 (LTS Maintenance)
    • Recommended: Version 24 (Active LTS)
    • FrontMCP is developed and tested on Node.js 24
  • npm ≥ 10 (pnpm/yarn also supported)

Quick start

Option A — New project

Creates a folder and scaffolds everything for you.
npx frontmcp create my-app
The create command is interactive by default. Use --yes for non-interactive mode with defaults (Docker target, Redis via Docker Compose, GitHub Actions enabled).

Option B — Existing project

Install and initialize in your current repo:
bash universal npm i -D frontmcp @types/node@^24 npx frontmcp init
init adds the required scripts and updates tsconfig.json automatically.

Package scripts

After create or init, your package.json will include:
{
  "scripts": {
    "dev": "frontmcp dev",
    "build": "frontmcp build",
    "inspect": "frontmcp inspector",
    "doctor": "frontmcp doctor"
  }
}
  • frontmcp dev — run in watch mode with type-checks
  • frontmcp build — compile to ./dist (override with --out-dir)
  • frontmcp inspector — launches @modelcontextprotocol/inspector with zero setup
  • frontmcp doctor — verifies Node/npm versions and project configuration

Docker scripts (Docker target only)

If you created your project with the Docker target (--target node), you’ll also have:
{
  "scripts": {
    "docker:up": "docker compose -f ci/docker-compose.yml up",
    "docker:down": "docker compose -f ci/docker-compose.yml down",
    "docker:build": "docker compose -f ci/docker-compose.yml build"
  }
}
# Start the full stack (app + Redis if configured)
npm run docker:up

# Stop containers
npm run docker:down

# Rebuild the Docker image
npm run docker:build

# Rebuild only the app service (selective rebuild — skips Redis)
docker compose -f ci/docker-compose.yml up --build app

init writes this for you, but if you prefer to manage it manually:
tsconfig.json
{
  "compilerOptions": {
    "target": "es2021",
    "module": "esnext",
    "lib": ["es2021"],
    "moduleResolution": "bundler",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["**/*.spec.ts", "**/__tests__/**"]
}

Minimal app

You can import from @frontmcp/sdk directly; no extra install needed.
src/main.ts
import 'reflect-metadata';
import { FrontMcp, LogLevel } from '@frontmcp/sdk';
import HelloApp from './hello.app';

@FrontMcp({
  info: { name: 'Hello MCP', version: '0.1.0' },
  apps: [HelloApp],
  http: { port: Number(process.env.PORT) || 3000 },
  logging: { level: LogLevel.Info },
})
export default class Server {}
src/hello.app.ts
import { App } from '@frontmcp/sdk';
import Greet from './tools/greet.tool';

@App({ id: 'hello', name: 'Hello', tools: [Greet] })
export default class HelloApp {}
src/tools/greet.tool.ts
import { Tool, ToolContext, z } from '@frontmcp/sdk';

@Tool({
  name: 'greet',
  description: 'Greets a user by name',
  inputSchema: { name: z.string() },
})
export default class Greet extends ToolContext {
  async execute({ name }: { name: string }) {
    return `Hello, ${name}!`;
  }
}

Run the dev server

bash universal npm run dev
Your server will start (default http://localhost:3000). The console will print the MCP endpoint.

Port conflict handling

frontmcp dev performs a pre-flight TCP probe before spawning tsx --watch. If the port is already in use the command exits with a one-line message instead of a raw EADDRINUSE stack trace:
[dev] Port 3000 is already in use — refusing to start.
      Retry with one of:
        • frontmcp dev --port <other-port>
        • frontmcp dev --auto-port     (pick the next free port automatically)
        • PORT=<other-port> frontmcp dev
FlagBehaviour
--port <n>Bind the dev server to TCP port <n> (sets PORT=<n> in the child’s env).
--auto-portIf the requested port is busy, walk forward to the next free port.
--show-conflictOn EADDRINUSE, run lsof (POSIX) to print which process is holding the port.
The PORT env var only takes effect when your @FrontMcp metadata reads it — the canonical http: { port: Number(process.env.PORT) || 3000 } pattern shown above. If you hard-code http.port: 4000 in metadata, your server will bind to 4000 regardless of --port or PORT, and the pre-flight probe is advisory only.

Inspect locally (zero setup)

Launch the FrontMCP Inspector to exercise tools and messages in a friendly UI:
bash universal npm run inspect
  • This runs npx @modelcontextprotocol/inspector behind the scenes.
  • Point it at your local server URL printed by dev (e.g., http://localhost:3000).
  • Try calling greet and watch responses stream back in real time.

Troubleshooting

  • Check configuration
npm run doctor
Ensures Node/npm versions, entry detection, and tsconfig.json are correct.
  • Entry detection The CLI looks for package.json.main; if missing, it falls back to src/main.ts. If no entry is found, it will tell you how to create one.
  • Type errors in dev The dev command performs async type-checks while watching your files, so you’ll see issues immediately without stopping the server.