Skip to content

Muppy Minimum MCP Specification

Overview

This document specifies the minimum viable MCP (Model Context Protocol) server for interacting with Muppy package management. The MCP provides structured APIs for AI assistants and CLI tools to manage m2p (mpy-metapackage) deployments.

Objectives

  • Enable AI assistants to manage Muppy packages without GUI interaction
  • Provide structured data responses (JSON) for reliable parsing
  • Support async operations with proper job tracking
  • Maintain compatibility with existing Muppy workflows

Core Functions

1. Get Package Status

Retrieves the current status and metadata of a package.

get_package_status(package_name: string, namespace: string) 
 {
    status: "Running" | "Error" | "Pending" | "Installing" | "Unknown",
    message: string,
    active_job?: {
      id: string,
      type: "install" | "upgrade" | "sync",
      status: "pending" | "running" | "completed" | "failed"
    },
    last_sync: string,  // ISO timestamp
    version: string,
    helm_release_name?: string
  }

2. Update Parts Config

Updates the parts configuration YAML for a package without triggering sync.

update_parts_config(package_name: string, namespace: string, yaml_content: string)
 {
    success: boolean,
    validation_errors?: string[],
    message: string
  }

Notes: - Validates YAML syntax - Does NOT automatically sync to cluster - Returns specific validation errors if any

3. Sync Parts Config

Synchronizes the updated parts configuration with the cluster.

sync_parts_config(package_name: string, namespace: string)
 {
    job_id: string,
    message: string
  }

Notes: - Returns immediately with job ID - Actual sync happens asynchronously

4. Install Package

Triggers Helm installation or upgrade of the package.

install_package(package_name: string, namespace: string)
 {
    job_id: string,
    message: string
  }

Notes: - Returns immediately with job ID - Installation happens asynchronously via Muppy's job queue

5. Get Job Status

Checks the status of an asynchronous job.

get_job_status(job_id: string)
 {
    status: "pending" | "running" | "completed" | "failed",
    progress?: string,  // Human-readable progress message
    started_at?: string,  // ISO timestamp
    completed_at?: string,  // ISO timestamp
    result?: {
      success: boolean,
      output?: string,  // Helm output or sync logs
      errors?: string[]
    }
  }

6. Get Config Journal

Retrieves the configuration journal entries for a package.

get_config_journal(package_name: string, namespace: string, limit?: number = 10)
 {
    entries: [{
      id: string,
      timestamp: string,  // ISO timestamp
      type: "error" | "warning" | "info" | "success",
      summary: string,
      has_details: boolean
    }]
  }

7. Get Journal Entry Details

Retrieves detailed information for a specific journal entry.

get_journal_entry(package_name: string, namespace: string, entry_id: string)
 {
    id: string,
    timestamp: string,
    type: "error" | "warning" | "info" | "success",
    summary: string,
    full_message: string,
    helm_output?: string,
    k8s_events?: [{
      type: string,
      reason: string,
      message: string,
      timestamp: string
    }],
    debug_info?: object
  }

Usage Patterns

Installing a Package

// 1. Update configuration
const update = await update_parts_config("checkmate", "default", yamlContent);
if (!update.success) {
  // Handle validation errors
  return;
}

// 2. Sync configuration
const syncJob = await sync_parts_config("checkmate", "default");

// 3. Wait for sync to complete
await waitForJob(syncJob.job_id);

// 4. Install package
const installJob = await install_package("checkmate", "default");

// 5. Monitor installation
await waitForJob(installJob.job_id);

// 6. Check final status
const status = await get_package_status("checkmate", "default");

Monitoring Async Operations

async function waitForJob(jobId: string, timeoutMs: number = 300000) {
  const startTime = Date.now();

  while (Date.now() - startTime < timeoutMs) {
    const job = await get_job_status(jobId);

    if (job.status === "completed" || job.status === "failed") {
      return job;
    }

    // Log progress if available
    if (job.progress) {
      console.log(`Job ${jobId}: ${job.progress}`);
    }

    // Wait 2 seconds before next poll
    await sleep(2000);
  }

  throw new Error(`Job ${jobId} timed out after ${timeoutMs}ms`);
}

Error Handling

All functions should return errors in a consistent format:

// On error
 {
    error: {
      code: string,  // e.g., "PACKAGE_NOT_FOUND", "INVALID_YAML"
      message: string,
      details?: object
    }
  }

Common error codes: - PACKAGE_NOT_FOUND: Package doesn't exist - INVALID_YAML: YAML syntax error in parts config - PERMISSION_DENIED: Insufficient permissions - CLUSTER_UNREACHABLE: Cannot connect to Kubernetes cluster - JOB_NOT_FOUND: Job ID doesn't exist - TIMEOUT: Operation timed out

Authentication

The MCP should support authentication methods used by Muppy: - API token via header: Authorization: Bearer <token> - Session-based auth for web UI integration - Certificate-based auth for cluster access

Future Enhancements

This MVP spec can be extended with: - Package creation and deletion - Namespace management - Log streaming for running pods - Resource usage metrics - Package backup/restore - Git integration for config management - Webhook support for job completion

Implementation Notes

  1. The MCP server should maintain minimal state
  2. All package data should be fetched from Muppy's backend
  3. Job polling should be handled by the client, not the MCP server
  4. Response format should always be JSON, even for errors
  5. All timestamps should be ISO 8601 format