Your MCP Codebase Just Hit 50 Files. Here's How to Stop the Chaos.
Here's a scenario you might recognize:
You built an MCP server with FrontMCP. It started clean — a few tools, a resource, maybe an agent. Thirty files. Everything in one project. Life was good.
Then the second team needed tools. Then the third. Someone copy-pasted shared-utils.ts into a new folder. Someone else wrote a duplicate auth provider. You now have:
- 50+ files with no clear boundaries
- Copy-pasted utilities drifting out of sync
- No build caching — every change rebuilds everything
- No dependency graph — breaking changes are discovered in production
- One deployment target — but staging needs different apps than production
You don't need a bigger project. You need a monorepo.
Introducing @frontmcp/nx
@frontmcp/nx is the official Nx plugin for FrontMCP. It brings monorepo-scale development to MCP servers with everything you need to organize, build, and deploy multi-app platforms.
Scaffold workspaces, apps, libraries, servers, and 12 component types — all following FrontMCP conventions.
Build, dev, serve, test, inspect, and deploy — all integrated with Nx caching and dependency ordering.
Servers → Apps → Libs. Clean separation of infrastructure, business logic, and shared code.
Generate deployment shells for Node/Docker, Vercel, Lambda, and Cloudflare — each composing different app combinations.
The Scaling Problem
Every FrontMCP project starts standalone. And for a single server with one team, standalone is perfect. But teams grow, tools multiply, and suddenly you're fighting your own codebase.
| Standalone | Monorepo | |
|---|---|---|
| Projects | 1 | Many (apps, libs, servers) |
| Code sharing | Copy-paste | Import from shared libs |
| Build caching | None | Nx caches unchanged projects |
| Dependency tracking | Manual | Nx dependency graph |
| Affected testing | Run everything | nx affected -t test |
| Deployment targets | 1 | Multiple servers per environment |
| Team boundaries | Conventions | Enforced via tags + module boundaries |
Three-Layer Architecture
The Nx plugin organizes your codebase into three distinct layers, each with a clear responsibility:
| Layer | Directory | Contains | Depends On |
|---|---|---|---|
| Servers | servers/ | Entry points, Docker/Vercel/Lambda config | Apps, Libs |
| Apps | apps/ | Tools, resources, prompts, skills, agents | Libs |
| Libs | libs/ | Shared utilities, plugins, adapters | Other Libs |
5-Minute Quickstart
Go from zero to a running multi-app MCP server inside an Nx monorepo:
Create the workspace
npx frontmcp create my-platform --nx cd my-platformThis scaffolds the full monorepo structure with Nx configuration, TypeScript path aliases, and a sample app.
Generate an app
nx g @frontmcp/nx:app crmCreates
apps/crm/with a main entry point, app class, and sample tool.Add tools and agents
nx g @frontmcp/nx:tool fetch-contacts --project crm nx g @frontmcp/nx:agent lead-qualifier --project crmGenerators follow FrontMCP conventions — decorators, Zod schemas, and proper file placement.
Create a shared library
nx g @frontmcp/nx:lib shared-utilsCreates
libs/shared-utils/— import it from any app via workspace path aliases.Generate a server
nx g @frontmcp/nx:server production --apps crm --deploymentTarget nodeCreates
servers/production/with a Dockerfile, docker-compose.yml, and an entry point that composes the CRM app.Start development
nx dev crmHot-reload development mode. Edit tools, resources, or agents and see changes instantly.
Build and deploy
nx build productionCompiles the production server to
servers/production/dist/— ready for Docker, Vercel, Lambda, or Cloudflare.
What Gets Generated
After the quickstart, your workspace looks like this:
my-platform/
├── apps/
│ └── crm/
│ ├── src/
│ │ ├── main.ts
│ │ ├── crm.app.ts
│ │ ├── tools/
│ │ │ ├── hello.tool.ts
│ │ │ └── fetch-contacts.tool.ts
│ │ └── agents/
│ │ └── lead-qualifier.agent.ts
│ ├── project.json
│ └── tsconfig.json
├── libs/
│ └── shared-utils/
│ ├── src/
│ │ ├── shared-utils.ts
│ │ └── index.ts
│ └── project.json
├── servers/
│ └── production/
│ ├── src/main.ts
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── project.json
├── nx.json
├── tsconfig.base.json
└── package.json
The generated server entry point composes your apps:
import { FrontMcp } from '@frontmcp/sdk';
import { CrmApp } from '@apps/crm';
@FrontMcp({
info: { name: 'Production', version: '1.0.0' },
apps: [CrmApp],
})
export default class Server {}And the generated app registers tools, resources, and agents:
import { App } from '@frontmcp/sdk';
import { HelloTool } from './tools/hello.tool';
import { FetchContactsTool } from './tools/fetch-contacts.tool';
import { LeadQualifierAgent } from './agents/lead-qualifier.agent';
@App({
id: 'crm',
name: 'CRM',
tools: [HelloTool, FetchContactsTool],
agents: [LeadQualifierAgent],
})
export class CrmApp {}16 Generators
Every generator follows FrontMCP conventions and produces code with the correct decorator, Zod schemas, and file placement.
Structural Generators
These create top-level projects in your monorepo:
| Generator | Description | Output |
|---|---|---|
workspace | Scaffold a full Nx monorepo | Root directory |
app | Generate a FrontMCP application | apps/<name>/ |
lib | Generate a shared library | libs/<name>/ |
server | Generate a deployment shell | servers/<name>/ |
Component Generators
These add components to existing projects:
| Generator | Output | Decorator |
|---|---|---|
tool | src/tools/<name>.tool.ts | @Tool |
resource | src/resources/<name>.resource.ts | @Resource |
prompt | src/prompts/<name>.prompt.ts | @Prompt |
skill | src/skills/<name>.skill.ts | @Skill |
agent | src/agents/<name>.agent.ts | @Agent |
provider | src/providers/<name>.provider.ts | @Provider |
plugin | src/plugins/<name>.plugin.ts | @Plugin |
adapter | src/adapters/<name>.adapter.ts | @Adapter |
auth-provider | src/auth/<name>.auth-provider.ts | @AuthProvider |
flow | src/flows/<name>.flow.ts | @Flow |
job | src/jobs/<name>.job.ts | @Job |
workflow | src/workflows/<name>.workflow.ts | @Workflow |
Run any generator with:
nx g @frontmcp/nx:<generator> <name> --project <app>7 Executors
Executors wrap FrontMCP CLI commands as Nx targets, enabling caching, dependency ordering, and nx affected support.
| Executor | CLI Command | Cacheable | Long-Running |
|---|---|---|---|
build | frontmcp build | Yes | No |
build-exec | frontmcp build --exec | Yes | No |
dev | frontmcp dev | No | Yes |
serve | frontmcp start | No | Yes |
test | frontmcp test | Yes | No |
inspector | frontmcp inspector | No | Yes |
deploy | Platform-specific | No | No |
Why Nx Executors Matter
Unchanged projects skip builds entirely. Nx restores cached output in milliseconds.
nx run-many -t build builds projects in correct dependency order automatically.
nx affected -t test only tests projects impacted by your changes. CI goes from 10 minutes to 30 seconds.
Executors are configured in each project's project.json:
{
"name": "crm",
"targets": {
"build": {
"executor": "@frontmcp/nx:build",
"outputs": ["{projectRoot}/dist"],
"options": {
"entry": "{projectRoot}/src/main.ts",
"outputPath": "{projectRoot}/dist"
}
},
"dev": {
"executor": "@frontmcp/nx:dev",
"options": {
"entry": "{projectRoot}/src/main.ts"
}
},
"test": {
"executor": "@frontmcp/nx:test",
"options": {
"runInBand": true
}
}
}
}Multi-Platform Deployment
Generate deployment shells targeting different platforms — each composing different app combinations:
nx g @frontmcp/nx:server production --apps crm,analytics --deploymentTarget nodeGenerates a Dockerfile, docker-compose.yml, and entry point:
servers/production/
├── src/main.ts
├── Dockerfile
├── docker-compose.yml
└── project.json
Build and run:
nx build production
docker compose -f servers/production/docker-compose.yml upReal-World Scenario: 3 Teams, 1 Platform
Imagine you're building an internal AI platform. Three teams contribute tools:
- CRM team — lead management, contact sync, pipeline tools
- Analytics team — dashboards, reports, data queries
- Admin team — user management, billing, configuration
Here's how you'd set it up:
# Create the workspace
npx frontmcp create internal-platform --nx
cd internal-platform
# Generate apps for each team
nx g @frontmcp/nx:app crm --tags "scope:crm,type:app"
nx g @frontmcp/nx:app analytics --tags "scope:analytics,type:app"
nx g @frontmcp/nx:app admin --tags "scope:admin,type:app"
# Generate shared libraries
nx g @frontmcp/nx:lib shared-utils --tags "scope:shared,type:lib"
nx g @frontmcp/nx:lib auth-helpers --tags "scope:shared,type:lib"
# Add tools to each app
nx g @frontmcp/nx:tool fetch-leads --project crm
nx g @frontmcp/nx:tool sync-contacts --project crm
nx g @frontmcp/nx:tool generate-report --project analytics
nx g @frontmcp/nx:tool manage-users --project admin
# Generate servers for different environments
nx g @frontmcp/nx:server production --apps crm,analytics --deploymentTarget node
nx g @frontmcp/nx:server staging --apps crm,analytics,admin --deploymentTarget node
nx g @frontmcp/nx:server edge --apps crm --deploymentTarget vercelNow your CI pipeline can use nx affected to only build and test what changed:
# CI pipeline
nx affected -t test # Only test affected projects
nx affected -t build # Only build affected projects
nx affected -t deploy # Only deploy affected serversOne change to shared-utils triggers tests for all three apps — but only builds the two servers that actually changed. The edge server (which doesn't use shared-utils) is skipped entirely.
Migration from Standalone
Already have a standalone FrontMCP project? Here's how to migrate:
Create the workspace
npx frontmcp create my-platform --nx cd my-platformGenerate an app for your existing code
nx g @frontmcp/nx:app my-appCopy your source files
cp -r ../my-standalone/src/tools/* apps/my-app/src/tools/ cp -r ../my-standalone/src/resources/* apps/my-app/src/resources/ cp -r ../my-standalone/src/prompts/* apps/my-app/src/prompts/Update
apps/my-app/src/my-app.app.tsto import all your components.Extract shared code into libraries
nx g @frontmcp/nx:lib shared-utils nx g @frontmcp/nx:lib data-modelsMove shared utilities into
libs/and update imports.Update imports to workspace aliases
// Before (relative) import { formatDate } from '../../utils/format'; // After (workspace alias) import { formatDate } from '@my-platform/shared-utils';Generate a server
nx g @frontmcp/nx:server production --apps my-app --deploymentTarget nodeVerify everything works
nx dev my-app # Development mode nx build production # Build nx test my-app # Tests nx graph # Visualize dependencies
Standalone vs Monorepo Comparison
| Feature | Standalone | Monorepo with @frontmcp/nx |
|---|---|---|
| Setup | npx frontmcp create | npx frontmcp create --nx |
| Code sharing | Copy-paste between projects | Import from libs/ |
| Build caching | None | Nx caches unchanged projects |
| Dependency graph | Manual tracking | nx graph — visual + enforced |
| Affected testing | Run all tests | nx affected -t test |
| Deployment targets | 1 server config | Multiple servers per environment |
| Team boundaries | Honor system | Tags + module boundary rules |
| Component generators | frontmcp generate | nx g @frontmcp/nx:<generator> |
| Build command | frontmcp build | nx build <project> (cached) |
| Dev mode | frontmcp dev | nx dev <app> |
| CI optimization | Build everything | Build only what changed |
Essential Commands
| Command | Description |
|---|---|
nx g @frontmcp/nx:app <name> | Generate a new app |
nx g @frontmcp/nx:lib <name> | Generate a shared library |
nx g @frontmcp/nx:server <name> | Generate a deployment shell |
nx g @frontmcp/nx:tool <name> --project <app> | Add a tool to an app |
nx dev <app> | Start dev mode with hot-reload |
nx build <project> | Build an app or server |
nx test <project> | Run tests |
nx inspector <app> | Launch MCP Inspector |
nx graph | Visualize dependency graph |
nx affected -t test | Test only affected projects |
nx run-many -t build | Build all projects |
Get Started
@frontmcp/nx is part of the FrontMCP ecosystem. Combine it with CodeCall for code-execution at scale, Tool UI for rich widgets, and deploy to any platform with a single command.
Star us on GitHub to follow development.
Code in this post targets the FrontMCP version current when it was written; see Versions for what changed since.