infrastructure-mcp v1.3 — Plugin Architecture Design¶
Date: 2026-03-30 Status: Draft Author: Matt Hesketh
Overview¶
v1.3 transforms infrastructure-mcp from a monolithic Java server into a TypeScript orchestrator that proxies tools from child MCP servers (plugins). Fleet becomes optional. Providers are mix-and-match. Community members can publish plugins for any platform (Wix, Vercel, GoDaddy, etc.) in any language.
Goals¶
- Fleet optional — not everyone runs their own servers
- Provider-agnostic — swap Namecheap for GoDaddy, Cloudflare for Route 53, Fleet for Vercel
- Plugin ecosystem — third parties publish
infrastructure-mcp-plugin-*packages - Language-agnostic plugins — anything that speaks MCP over stdio is a plugin
- Backwards compatible — existing v1.2 configs auto-migrate
Architecture¶
Claude Code / AI Client TUI (Ink/React)
\ /
\ /
Orchestrator (TypeScript, npm)
/ | | \
/ | | \
Cloudflare Namecheap Fleet Wix Plugin
(Java) (Java) (opt) (any lang)
The orchestrator is a TypeScript MCP server published as infrastructure-mcp on npm. It reads a config file, spawns child MCP servers as subprocesses, connects to each via stdio, and proxies their tools to the parent client.
The TUI connects to the orchestrator — not to providers directly. The orchestrator is the single entry point for all clients.
Monorepo structure¶
infrastructure-mcp/
packages/
orchestrator/ # Published as `infrastructure-mcp`
src/
proxy.ts # Spawns/connects to provider MCP servers
router.ts # Tool namespacing, role aliasing, request routing
workflows/
onboard.ts # onboard_domain workflow
migrate.ts # migrate_dns workflow
protect.ts # apply_protection workflow
config.ts # Config loading, validation, v1.2 migration
server.ts # MCP server entry point (stdio)
cli.ts # CLI: --setup, --validate, etc.
package.json
tui/ # Published as `infrastructure-tui`
src/
screens/
dashboard.tsx
providers.tsx # New: manage providers
add-provider.tsx # New: add provider wizard
zone-detail.tsx
onboard.tsx
audit.tsx
settings.tsx
hooks/
use-mcp.ts
use-config.ts
components/ # Existing reusable components
constants/
index.ts # All constants from single barrel
types/
index.ts # All types/interfaces from single barrel
app.tsx
package.json
shared/ # Published as `@infrastructure-mcp/shared`
src/
types.ts # Provider, Role, Config, Workflow types
roles.ts # Role definitions, capability patterns
config-schema.ts # Config validation, v1.2 migration
constants.ts # Shared constants
package.json
docs/
README.md
package.json # Workspace root (npm workspaces)
tsconfig.base.json
What gets removed from this repo¶
src/main/java/— entire Java serverpom.xml— no more Maven buildtui/src/mcp-client.ts— replaced by orchestrator proxy
What moves to other repos¶
cloudflare-mcpandnamecheap-mcpJava repos get amain()to run as standalone MCP servers (currently libraries only)- Fleet becomes
infrastructure-mcp-plugin-fleet(separate repo, reference plugin)
Role System¶
Five roles for v1.3¶
| Role | Responsibility | Default Provider |
|---|---|---|
dns_registrar |
Domain registration, nameserver management | Namecheap |
dns_host |
DNS zones, records | Cloudflare |
cdn |
Caching, performance, edge config | Cloudflare |
security |
WAF, SSL/TLS, bot mgmt, hardening | Cloudflare |
app_platform |
App deployment, services | Fleet (optional) |
Rules¶
- A provider can fill multiple roles (Cloudflare fills
dns_host,cdn,security) - A role can only be filled by one provider at a time
app_platformis optional — the other four are required for orchestrator startup- If a provider is marked
optional: trueand fails to start, the orchestrator logs a warning and continues
Tool namespacing¶
Tools are exposed in two ways:
- Provider-namespaced:
{provider_name}.{original_tool_name}(e.g.,cloudflare.list_zones) - Role-aliased:
{role}.{capability}(e.g.,dns_host.list_zones) — routes to whatever provider fills that role
This means AI agents can write provider-agnostic prompts: "call dns_registrar.list_domains" works whether the registrar is Namecheap or GoDaddy.
Capability patterns per role¶
Used by the TUI for auto-suggesting roles, and by the orchestrator for validating providers at startup.
| Role | Required tool patterns |
|---|---|
dns_registrar |
*list_domains*, *get_nameservers*, *set_nameservers* |
dns_host |
*list_zones*, *create_zone*, *get_dns*, *create_dns* |
cdn |
*cache*, *performance*, *speed* |
security |
*waf*, *ssl*, *protection*, *firewall* |
app_platform |
*list_apps*, *deploy*, *list_domains* |
If a provider claims a role but doesn't expose tools matching the expected patterns, the orchestrator warns at startup (not a fatal error — plugin authors may use different naming).
Configuration¶
Config file format¶
Location: ~/.infrastructure-mcp.json (same path as v1.2, auto-migrated).
{
"providers": [
{
"name": "cloudflare",
"command": "java",
"args": ["-jar", "/path/to/cloudflare-mcp.jar"],
"env": {
"CLOUDFLARE_API_KEY": "...",
"CLOUDFLARE_EMAIL": "...",
"CLOUDFLARE_ACCOUNT_ID": "..."
},
"roles": ["dns_host", "cdn", "security"]
},
{
"name": "namecheap",
"command": "java",
"args": ["-jar", "/path/to/namecheap-mcp.jar"],
"env": {
"NAMECHEAP_API_USER": "...",
"NAMECHEAP_API_KEY": "...",
"NAMECHEAP_CLIENT_IP": "..."
},
"roles": ["dns_registrar"]
},
{
"name": "fleet",
"command": "fleet-mcp",
"roles": ["app_platform"],
"optional": true
}
],
"workflows": {
"onboard_domain": { "enabled": true },
"migrate_dns": { "enabled": true },
"apply_protection": { "enabled": true }
},
"tui": {
"experienceLevel": "professional"
}
}
Config rules¶
- Each provider has a
name(unique),command, optionalargs, optionalenv,rolesarray, and optionaloptionalflag timeout(optional, per-provider): seconds to wait for MCP handshake (default 30)- Credentials are stored with
0600file permissions (matching v1.2 behavior)
v1.2 config migration¶
On first run, the orchestrator detects the old format (has jarPath + flat env with CLOUDFLARE_*/NAMECHEAP_*) and converts:
| Old env vars | New provider | Roles |
|---|---|---|
CLOUDFLARE_* present |
cloudflare |
dns_host, cdn, security |
NAMECHEAP_* present |
namecheap |
dns_registrar |
FLEET_* present |
fleet |
app_platform (optional) |
The orchestrator prints a one-time migration message and writes the new format.
Built-in Workflows¶
Workflows are composite operations that call tools across providers based on roles. They reference capabilities, not provider-specific tool names.
v1.3 workflows¶
| Workflow | Steps | Roles Used |
|---|---|---|
onboard_domain |
Create zone at dns_host -> fetch records from dns_registrar -> migrate records -> update nameservers at dns_registrar -> apply security settings -> apply cdn settings | dns_registrar, dns_host, security, cdn |
migrate_dns |
Fetch records from dns_registrar -> create at dns_host | dns_registrar, dns_host |
apply_protection |
Apply security settings -> apply cdn settings | security, cdn |
Capability resolution¶
Each workflow step references a capability that resolves to an actual tool at runtime:
onboard_domain:
1. dns_host.create_zone(domain)
2. dns_registrar.get_dns(domain)
3. dns_host.create_dns(records)
4. dns_registrar.set_nameservers(domain, ns)
5. security.apply_settings(zone)
6. cdn.apply_settings(zone)
The orchestrator maps capabilities to actual tool names by matching against the provider's tools/list response at startup. If multiple tools match a pattern, the first match is used. If no tools match a required capability for a workflow step, that workflow is disabled with a warning at startup (e.g., "onboard_domain disabled: dns_host provider has no tool matching create_zone").
Workflow configuration¶
Workflows are toggle-able ("enabled": true/false) but not user-editable in v1.3. Custom workflow authoring is out of scope.
Plugin System¶
What is a plugin¶
Any executable that speaks MCP over stdio. Plugin authors:
- Write an MCP server in any language
- Expose tools (following naming conventions for auto-discovery of roles)
- Optionally publish to npm as
infrastructure-mcp-plugin-*
npm package convention¶
{
"name": "infrastructure-mcp-plugin-wix",
"bin": { "infrastructure-mcp-plugin-wix": "./dist/server.js" },
"infrastructure-mcp": {
"roles": ["dns_host", "app_platform"],
"description": "Wix DNS and site management"
}
}
The infrastructure-mcp field in package.json provides metadata for ecosystem discovery.
Non-npm plugins¶
Any command works. Specify the command in config — Python script, Go binary, shell script. No npm required.
Plugin lifecycle¶
- Orchestrator reads config
- Spawns each provider's command as a child process
- Sends MCP
initializehandshake - Calls
tools/listto discover tools - Validates tools against declared roles (warn if expected capabilities missing)
- Proxies tools with namespacing
TUI Changes¶
New screens¶
- Providers screen — list configured providers with status (connected/disconnected/error), roles, tool count. Add/remove/edit providers.
- Add Provider wizard — prompts for command, env vars, then connects to provider, introspects tools, suggests roles. User confirms, writes to config.
Dynamic dashboard¶
- Fleet section only shows if an
app_platformprovider is configured - CDN/security sections appear based on configured roles
- Key hints are dynamic:
f fleetonly appears ifapp_platformis configured p providersadded to key hints
Setup wizard changes¶
- First run no longer asks for Cloudflare/Namecheap/Fleet credentials directly
- Instead: "Add your first provider" flow
- Suggests starting with default stack (Cloudflare + Namecheap) for new users
- Source code review encouragement retained
Code conventions (matching existing TUI patterns)¶
- All types/interfaces exported from
types/index.ts(single barrel file) - All constants exported from
constants/index.ts - Props interfaces defined in types file, not inline in components
- Column definitions and menu items as
constarrays at module top-level - Components are default exports, small and focused
- Hooks in
hooks/withuse-prefix - Screens in
screens/
Error Handling & Resilience¶
Provider startup¶
- Required providers: orchestrator fails to start with clear error naming the provider
- Optional providers (
optional: true): log warning, continue without - Missing required role: fail at config validation before spawning anything
Runtime crashes¶
- Crashed provider is marked disconnected
- Tool calls return:
"Provider 'cloudflare' is disconnected: process exited with code 1" - Workflow steps fail gracefully with context about which step failed and why
- TUI providers screen shows real-time connection status
Config validation¶
At startup, before spawning anything:
- All required roles filled
- No role filled by two providers
- Commands exist / are executable
- infrastructure-mcp --validate flag for dry-run validation
Timeouts¶
- MCP handshake: 30 seconds default (configurable per-provider with
timeout) - Tool calls: inherit parent client timeout
- Java JARs can be slow to start — the default 30s accommodates this
Testing Strategy¶
Orchestrator tests¶
- Config validation: malformed configs, missing roles, duplicate roles, v1.2 migration
- Proxy/router: tool namespacing, role aliasing, routing to correct provider
- Provider lifecycle: spawn, connect, disconnect, crash recovery, timeout
- Workflows: each workflow with mock providers, correct tools called in correct order
- Capability matching: tool name patterns, warnings for missing capabilities
Mock provider¶
Ship a lightweight mock MCP server in the test suite. Configurable to expose arbitrary tools, simulate failures, track calls. Also serves as a reference for plugin authors.
TUI tests¶
- Provider management screens (add, remove, status)
- Dynamic dashboard (sections appear/disappear based on roles)
- Setup wizard with provider addition
- Config migration prompts
Integration tests¶
- Orchestrator spawns real mock provider, proxies tools end-to-end
- Workflow executes across two mock providers filling different roles
Test counts¶
Existing 126 tests (73 Java + 53 TypeScript) are replaced by the new TypeScript test suite. Java tests remain in cloudflare-mcp and namecheap-mcp repos.
Migration Path¶
For existing v1.2 users¶
- Config auto-migrated on first run (one-time message)
- Update
~/.claude.jsonto point to new npm command instead ofjava -jar - TUI setup wizard can do the
claude.jsonupdate automatically
For cloudflare-mcp and namecheap-mcp repos¶
- Add
main()that runs them as standalone MCP servers - Existing tool implementations unchanged
- Published as standalone JARs the orchestrator spawns
Breaking changes¶
- Java 21 no longer required unless using Cloudflare/Namecheap providers
- Tool names change:
cloudflare_list_zones->cloudflare.list_zones(dot namespace) - Fat JAR no longer published
- Old
~/.infrastructure-mcp.jsonformat auto-migrated (old format no longer written)
Documentation¶
Docs site update¶
infrastructure-mcp.hesketh.pro currently shows v1.1. Update mkdocs content for v1.3:
| Page | Content |
|---|---|
| Getting Started | npm-based install, no Java prerequisite for orchestrator |
| Configuration | Config file format, all options, example stacks |
| Providers | How providers work, role system, built-in providers |
| Plugin Authoring Guide | Build a plugin in any language, npm conventions, role capabilities |
| Workflows | Built-in workflows, how they adapt, toggling |
| Migration from v1.2 | Step-by-step for existing users |
| TUI Guide | Provider management, dynamic dashboard |
README¶
Complete rewrite. Plugin ecosystem as headline feature.
Plugin author docs¶
- "Hello world" plugin in ~50 lines (Node.js)
- Reference plugin:
infrastructure-mcp-plugin-fleet - Tool naming conventions per role
- Testing locally with the orchestrator
- Publishing to npm with correct metadata
Out of Scope for v1.3¶
- Custom user-defined workflows (v1.4)
- Plugin marketplace / registry UI
- Hot-reload of providers (restart required)
- Provider-to-provider communication (plugins are isolated)
- Automatic plugin updates