Skip to content
mcp-bridge logo

MCP Bridge

mcp-bridge

MCP detection and unified state operations. Provides seamless integration with Control Tower MCP when available, with file-based fallback.

SKILL.md

Full skill instructions

MCP Bridge

// Project Autopilot - MCP Bridge Skill // Copyright (c) 2026 Jeremy McSpadden [email protected]

Core Principle: Detect MCP availability once at command start, use unified interfaces throughout execution.


MCP Configuration Detection

Configuration File Locations

MCP configuration is checked in order of precedence:

ScopePathDescription
Project.mcp.jsonProject-scoped, shared with team
User~/​.claude.jsonUser-scoped, all projects
User Local~/​.claude/​settings.local.jsonUser local settings

Detection Function

FUNCTION detectControlTower():
    """
    Detect whether Control Tower MCP is configured and available.
    Returns detection result for use throughout command execution.
    """

    # Configuration file locations (checked in order)
    configPaths = [
        "{cwd}/​.mcp.json",                    # Project scope
        "~/​.claude.json",                     # User scope
        "~/​.claude/​settings.local.json"       # User local
    ]

    FOR each configPath IN configPaths:
        IF fileExists(configPath):
            TRY:
                config = parseJSON(readFile(configPath))

                # Check for control-tower or autopilot server entry
                IF config.mcpServers:
                    IF "control-tower" IN config.mcpServers:
                        RETURN {
                            available: true,
                            source: 'mcp',
                            serverName: 'control-tower',
                            configPath: configPath
                        }
                    IF "autopilot" IN config.mcpServers:
                        RETURN {
                            available: true,
                            source: 'mcp',
                            serverName: 'autopilot',
                            configPath: configPath
                        }
            CATCH:
                # Ignore parse errors, try next config
                CONTINUE

    # No MCP configuration found
    RETURN {
        available: false,
        source: 'local'
    }

Example Detection Result

// MCP Available
{
  "available": true,
  "source": "mcp",
  "serverName": "control-tower",
  "configPath": "/​Users/​dev/​.claude.json"
}

// Local Mode
{
  "available": false,
  "source": "local"
}

Unified State Operations

Save Checkpoint

FUNCTION saveCheckpoint(state, context):
    """
    Save checkpoint via MCP if available, otherwise file-based.

    Parameters:
        state: {
            phase: string,
            task: string,
            decisions: array,
            todos: array,
            blockers: array
        }
        context: detection result from detectControlTower()
    """

    IF context.available:
        TRY:
            result = CALL_MCP "checkpoint_save" {
                project_id: context.projectId,
                execution_id: context.executionId,
                state: state,
                phase: state.phase,
                task: state.task,
                context_usage_pct: getContextUsage(),
                name: "Auto-checkpoint"
            }

            LOG "Checkpoint saved via Control Tower"
            RETURN {source: 'mcp', id: result.checkpoint_id}

        CATCH error:
            # MCP configured but failed - show clear error, don't silently fallback
            handleMCPError(error)
            THROW error
    ELSE:
        # MCP not configured - use file-based (no warning, this is expected)
        formatted = formatTransponderState(state)
        writeFile(".autopilot/​TRANSPONDER.md", formatted)
        LOG "State saved locally"
        RETURN {source: 'local', path: '.autopilot/​TRANSPONDER.md'}

Load Checkpoint

FUNCTION loadCheckpoint(projectId, context):
    """
    Load latest checkpoint via MCP if available, otherwise file-based.

    Parameters:
        projectId: string (UUID for MCP, ignored for local)
        context: detection result from detectControlTower()

    Returns:
        Checkpoint state object
    """

    IF context.available:
        TRY:
            result = CALL_MCP "checkpoint_load" {
                project_id: projectId
                # checkpoint_id omitted for latest
            }

            LOG "Checkpoint loaded from Control Tower"
            RETURN {
                source: 'mcp',
                state: result.state,
                checkpoint_id: result.checkpoint_id,
                created_at: result.created_at
            }

        CATCH error:
            handleMCPError(error)
            THROW error
    ELSE:
        # Local state
        IF fileExists(".autopilot/​TRANSPONDER.md"):
            content = readFile(".autopilot/​TRANSPONDER.md")
            state = parseTransponderState(content)
            RETURN {source: 'local', state: state}
        ELSE:
            RETURN {source: 'local', state: null}

Update Progress

FUNCTION updateProgress(projectId, executionId, phase, task, status, message, context):
    """
    Update progress via MCP if available, otherwise file-based.

    Parameters:
        projectId: string (UUID)
        executionId: string (UUID)
        phase: string (e.g., "03-api")
        task: string (e.g., "03.2")
        status: "pending" | "in_progress" | "completed" | "failed" | "skipped"
        message: string (description of progress)
        context: detection result from detectControlTower()
    """

    IF context.available:
        TRY:
            result = CALL_MCP "progress_update" {
                project_id: projectId,
                execution_id: executionId,
                phase: phase,
                task: task,
                status: status,
                message: message
            }

            # Progress update is silent (no log spam)
            RETURN {source: 'mcp', id: result.id}

        CATCH error:
            handleMCPError(error)
            THROW error
    ELSE:
        # Append to progress.md
        entry = formatProgressEntry(phase, task, status, message)
        appendFile(".autopilot/​progress.md", entry)
        RETURN {source: 'local', path: '.autopilot/​progress.md'}

Record Activity

FUNCTION recordActivity(projectId, executionId, message, context):
    """
    Record activity log entry via MCP if available, otherwise file-based.

    Parameters:
        projectId: string (UUID)
        executionId: string (UUID)
        message: string (activity description)
        context: detection result from detectControlTower()
    """

    IF context.available:
        TRY:
            result = CALL_MCP "activity_log" {
                project_id: projectId,
                execution_id: executionId,
                message: message
            }

            RETURN {source: 'mcp', id: result.id}

        CATCH error:
            handleMCPError(error)
            THROW error
    ELSE:
        # Append to progress.md with timestamp
        timestamp = formatTimestamp(now())
        entry = "{timestamp} | {message}\n"
        appendFile(".autopilot/​progress.md", entry)
        RETURN {source: 'local', path: '.autopilot/​progress.md'}

Record Cost

FUNCTION recordCost(projectId, executionId, model, inputTokens, outputTokens, cost, context):
    """
    Record token/​cost usage via MCP if available, otherwise file-based.

    Parameters:
        projectId: string (UUID)
        executionId: string (UUID)
        model: string (e.g., "claude-sonnet-4-20250514")
        inputTokens: number
        outputTokens: number
        cost: number (USD)
        context: detection result from detectControlTower()
    """

    IF context.available:
        TRY:
            result = CALL_MCP "cost_record" {
                project_id: projectId,
                execution_id: executionId,
                model: model,
                input_tokens: inputTokens,
                output_tokens: outputTokens,
                cost: cost
            }

            RETURN {source: 'mcp', id: result.id}

        CATCH error:
            handleMCPError(error)
            THROW error
    ELSE:
        # Append to token-usage.md
        entry = formatCostEntry(model, inputTokens, outputTokens, cost)
        appendFile(".autopilot/​token-usage.md", entry)
        RETURN {source: 'local', path: '.autopilot/​token-usage.md'}

Error Handling

MCP Error Handler

FUNCTION handleMCPError(error):
    """
    Handle MCP errors with clear troubleshooting steps.
    Do NOT silently fallback - if MCP is configured but fails, user needs to know.
    """

    LOG ""
    LOG "Control Tower MCP unavailable."
    LOG ""
    LOG "Troubleshooting steps:"
    LOG "  1) Verify MCP server running:"
    LOG "     cd control-tower && npm run start:mcp"
    LOG ""
    LOG "  2) Check Claude Code MCP config:"
    LOG "     Run /​mcp to verify control-tower server listed"
    LOG ""
    LOG "  3) Verify database connection:"
    LOG "     Ensure PostgreSQL is running"
    LOG ""
    LOG "  4) Check server logs:"
    LOG "     Look for connection errors in MCP server output"
    LOG ""

    IF error.message:
        LOG "Error details: {error.message}"

Error Categories

Error TypeBehaviorUser Action
MCP not configuredUse local files silentlyNone - expected
MCP configured, server unreachableShow error, haltStart MCP server
MCP configured, auth failedShow error, haltCheck API key
MCP configured, database errorShow error, haltCheck PostgreSQL

Output Formatting

Source Indicator

FUNCTION getSourceIndicator(context):
    """
    Returns indicator text for command banner.
    """

    IF context.available:
        RETURN "Control Tower"
    ELSE:
        RETURN "Local"

Banner Format

# With Control Tower MCP:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AUTOPILOT: TAKEOFF                               Control Tower
   Execute flight plan with wave-based parallelization
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

# With local file-based state:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AUTOPILOT: TAKEOFF                                      Local
   Execute flight plan with wave-based parallelization
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Dashboard Link

FUNCTION showDashboardLink(projectId, context):
    """
    Show dashboard link only when Control Tower is active and projectId valid.
    """

    IF context.available AND projectId:
        # Get dashboard URL from config or use default
        dashboardUrl = context.dashboardUrl OR "http://localhost:3000"

        LOG ""
        LOG "View in dashboard: {dashboardUrl}/​projects/​{projectId}"

Dashboard Link Display Rules

ConditionShow Link?Reason
MCP available, valid projectIdYesFull functionality
MCP available, no projectIdNoProject not registered
Local modeNoNo dashboard in local mode
--local flagNoExplicitly local mode

Flag Handling

--local Flag

FUNCTION initializeStateBackend(arguments):
    """
    Initialize state backend based on MCP availability and flags.
    Called at command startup.
    """

    # Check for --local flag first
    IF "--local" IN arguments:
        LOG "Using local file-based state (--local flag)"
        RETURN {
            available: false,
            source: 'local',
            forced: true
        }

    # Detect Control Tower
    detection = detectControlTower()

    IF detection.available:
        LOG "Control Tower MCP detected"

        # Auto-register project if needed
        projectId = ensureProjectRegistered(detection)
        detection.projectId = projectId

        # Get or create execution
        executionId = getOrCreateExecution(projectId)
        detection.executionId = executionId
    ELSE:
        LOG "Using local file-based state"

    RETURN detection

Ensure Project Registered

FUNCTION ensureProjectRegistered(context):
    """
    Ensure current project is registered with Control Tower.
    Returns projectId (existing or newly created).
    """

    # Check for existing project by path
    result = CALL_MCP "project_lookup" {
        path: getCurrentDirectory()
    }

    IF result.project_id:
        RETURN result.project_id

    # Register new project
    projectName = getProjectName()  # From package.json or directory name

    result = CALL_MCP "project_register" {
        name: projectName,
        path: getCurrentDirectory(),
        description: getProjectDescription()  # From clearance.md if exists
    }

    RETURN result.project_id

Integration Examples

Takeoff Command Integration

# At command start (Phase 0)
context = initializeStateBackend(arguments)
sourceIndicator = getSourceIndicator(context)

# Display banner with source indicator
LOG "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
LOG "AUTOPILOT: TAKEOFF                               {sourceIndicator}"
LOG "   Execute flight plan with wave-based parallelization"
LOG "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

# During execution - save checkpoint
saveCheckpoint({
    phase: currentPhase,
    task: currentTask,
    decisions: recentDecisions,
    todos: pendingTodos,
    blockers: currentBlockers
}, context)

# During execution - update progress
updateProgress(
    context.projectId,
    context.executionId,
    "03-api",
    "03.2",
    "completed",
    "Created user endpoints with validation",
    context
)

# During execution - record cost
recordCost(
    context.projectId,
    context.executionId,
    "claude-sonnet-4-20250514",
    15000,
    8500,
    0.12,
    context
)

# At completion
showDashboardLink(context.projectId, context)

Cockpit Command Integration

# At command start
context = initializeStateBackend(arguments)
sourceIndicator = getSourceIndicator(context)

# Display banner with source indicator
LOG "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
LOG "AUTOPILOT: COCKPIT                              {sourceIndicator}"
LOG "   Return to cockpit - resume flight from waypoint"
LOG "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

# Load checkpoint
checkpoint = loadCheckpoint(context.projectId, context)

IF checkpoint.state:
    LOG "Checkpoint loaded: Phase {checkpoint.state.phase}, Task {checkpoint.state.task}"
ELSE:
    LOG "No checkpoint found - starting fresh"

# At resume
showDashboardLink(context.projectId, context)

State File Paths

Local Mode Files

FilePurpose
.autopilot/​TRANSPONDER.mdSession state bridge
.autopilot/​progress.mdActivity log
.autopilot/​token-usage.mdCost tracking
.autopilot/​holding-pattern.mdMid-phase resume

MCP Mode Storage

ToolData Stored
checkpoint_saveState snapshots with full context
progress_updatePhase/​task progress entries
activity_logActivity timeline
cost_recordToken/​cost records

Testing Checklist

Before deploying MCP integration:

[ ] Test with MCP not configured → uses local files silently
[ ] Test with MCP configured and working → uses MCP
[ ] Test with MCP configured but server down → shows error, does not fallback
[ ] Test with --local flag → forces local even when MCP configured
[ ] Test dashboard link only shows when MCP active
[ ] Test source indicator displays correctly in banner
[ ] Test all commands maintain identical output format except indicator

Quick Reference

Detection Priority

  1. --local flag (force local)
  2. .mcp.json (project scope)
  3. ~/​.claude.json (user scope)
  4. ~/​.claude/​settings.local.json (user local)
  5. Fallback to local

Operation Priority

  1. If MCP available: Use MCP tools
  2. If MCP fails: Show error, halt (no silent fallback)
  3. If MCP not configured: Use local files (no warning)

Source Indicators

ModeIndicator
Control Tower MCPControl Tower
Local filesLocal
Forced local (--local)Local

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View