Azure / Azure/containerization-assist

Skill conversion: convert tools to portable Claude skills with slim MCP primitives (3 phases)

Open
#661 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
41
Forks
19
Avg merge
1d 9h
Merged PRs (30d)
2

Description

## Goal

Convert the bulk of the containerization-assist MCP tools into portable skills (markdown) backed by a slim layer of MCP primitives, while preserving the full SDK interface for non-MCP consumers.

**Three motivations:**
1. **Reduce maintenance burden** — ~7000 LOC of tool code, much of it orchestration and prompt shaping rather than integration logic.
2. **Better UX in LLM Harness** — Skills are transparent markdown; users can read and edit them without an \`npm install\`.
3. **Portability** — Skills run in any harness (Claude Code, Copilot, Gemini, custom). MCP tools are tied to MCP-speaking clients.

**Constraint:** Skills must be usable standalone. When the MCP server isn't available, skills should still produce reasonable output — with reduced capability (no org-specific knowledge or policy validation), but functional.

## Architecture

Three layers with clean dependency rules:

\`\`\`
┌─────────────────────────────────────────────────────────┐
│ Skills (markdown, portable) │
│ analyze-repo · generate-dockerfile · fix-dockerfile │
│ build-image · tag-image · push-image │
│ generate-k8s-manifests · ops · containerize (meta) │
└────────────────┬────────────────────────────────────────┘
│ uses generic tools (Bash/Read/Write/Glob)
│ optionally calls ↓ when MCP is available
┌────────────────▼────────────────────────────────────────┐
│ MCP primitives (slim server, opt-in enhancers) │
│ query-knowledge │
│ validate-dockerfile · validate-k8s-manifest │
│ validate-compose │
└────────────────┬────────────────────────────────────────┘

┌────────────────▼────────────────────────────────────────┐
│ MCP tools that stay as code (real SDK work) │
│ scan-image (OSV+Dockerode) · prepare-cluster (kind) │
│ verify-deploy (K8s polling) │
└─────────────────────────────────────────────────────────┘
\`\`\`

**Dependency rules:**
- Skills never *require* MCP. They work in any harness with Bash/Read/Write/Glob.
- MCP primitives never require skills. SDK consumers use them directly.
- \`scan-image\`, \`prepare-cluster\`, \`verify-deploy\` stay as MCP tools because skills can't replicate them reliably (OSV+Dockerode integration, stateful kind/registry/networking, K8s SDK rollout polling).

## Tool classification

| Tool | Disposition |
|------|-------------|
| \`analyze-repo\` | → skill (filesystem walk) |
| \`generate-dockerfile\` | → skill + uses \`query-knowledge\` + \`validate-dockerfile\` primitives |
| \`fix-dockerfile\` | → skill + uses \`validate-dockerfile\` + \`hadolint\` |
| \`build-image\` (currently \`build-image-context\`) | → skill (\`docker build\`) |
| \`tag-image\` | → skill (\`docker tag\`) |
| \`push-image\` | → skill (\`docker push\`); drop the TS credential-helper reimpl |
| \`generate-k8s-manifests\` | → skill + \`query-knowledge\` + \`validate-k8s-manifest\` |
| \`ops\` | → skill (config introspection) |
| \`scan-image\` | **stays as MCP tool** (OSV+Dockerode integration) |
| \`prepare-cluster\` | **stays as MCP tool** (1593 LOC kind/registry orchestration) |
| \`verify-deploy\` | **stays as MCP tool** (K8s SDK polling) |
| \`containerize\` (new) | → meta-skill running the journey end-to-end; replaces \`chain-hints.ts\` |

## Implementation phases

### ✅ Phase 1 — Foundation (PR #660, in review)

Extract 4 typed MCP primitives wrapping existing knowledge + policy library code:
- \`query-knowledge\` — wraps \`findKnowledgeMatches\`
- \`validate-dockerfile\`, \`validate-k8s-manifest\`, \`validate-compose\` — typed wrappers over \`applyPolicy\` returning \`{ passed, violations[], warnings[], suggestions[] }\` with graceful no-policy degrade

Each primitive conforms to the \`Tool\` interface via \`tool({ ... handler })\`. Registered in \`ALL_TOOLS\`. Exposed via the SDK (\`queryKnowledge\`, \`validateDockerfile\`, etc.) and the \`tools\` registry.

**Deferred to Phase 2:** Refactor of \`generate-dockerfile\` / \`fix-dockerfile\` / \`generate-k8s-manifests\` to call primitives. Those tools use \`createKnowledgeTool\` + \`validateContentAgainstPolicy\` patterns whose shapes don't line up with the new primitives' shapes. Restructuring exceeds Phase 1's \"additive + low-risk\" scope.

**Phase 1 stats:** +877 / -7 LOC, 33 files, 2097 unit tests passing.

### Phase 2 — Skills + SDK thinning

- Add \`skills/\` directory with 9 skill markdown files (8 operational + \`containerize\` meta-skill).
- Each skill has a baseline mode (works with generic Bash/Read/Write) and an enhanced mode (calls \`mcp__ca__query-knowledge\` / \`mcp__ca__validate-*\` when available, with try-and-fall-through detection).
- Default \`maxRetries=3\` for policy-violation retry loops; configurable per invocation.
- Inline baseline guidance in each skill so standalone runs still beat \"model winging it.\"
- Rewrite SDK implementations to thin versions; keep all current SDK exports working.
- Remove \`tools/shared/knowledge-tool-pattern.ts\`, \`chain-hints.ts\`, per-tool natural-language formatters.
- Refactor \`generate-dockerfile\`, \`fix-dockerfile\`, \`generate-k8s-manifests\` to use primitives (the work deferred from Phase 1 happens here as part of the wholesale migration).

**Phase 2 ships skills and tools side-by-side** so users can opt in by skill name; existing MCP tools remain callable.

### Phase 3 — Remove deprecated MCP tools (major version)

Delete the 8 skill-replaceable tools from \`src/tools/\`:
- \`analyze-repo\`, \`generate-dockerfile\`, \`fix-dockerfile\`, \`build-image-context\`
- \`tag-image\`, \`push-image\`, \`generate-k8s-manifests\`, \`ops\`

Final MCP server exposes **7 tools**: \`scan-image\`, \`prepare-cluster\`, \`verify-deploy\`, plus the 4 primitives.

**One intentional breaking change:** \`pushImage\` no longer re-implements Docker credential helpers — relies on \`docker\`'s native handling.

## Skill template

Each skill has a uniform shape:

\`\`\`markdown
---
name: generate-dockerfile
description: Use when you need to create a Dockerfile for a repository.
Produces a multi-stage, production-ready Dockerfile tailored
to the detected language/framework. Enhanced with
org-specific knowledge and policy validation when the
containerization-assist MCP server is available.
---

# Generate Dockerfile

## When to use ...
## Inputs ...
## Process
### 1. Analyze the repository
### 2. Gather guidance (enhanced mode) — try mcp__ca__query-knowledge, fall through if unavailable
### 3. Draft the Dockerfile
### 4. Validate (enhanced mode) — try mcp__ca__validate-dockerfile, retry on violations (max maxRetries)
### 5. Write the file
## Baseline guidance (used when MCP unavailable)
[Inline cheatsheet of top ~10 rules]
## Output ...
\`\`\`

## Net code delta (estimated)

| | Before | After Phase 3 |
|---|---|---|
| MCP tool code (\`src/tools/\`) | ~7000 LOC | ~2500 LOC |
| Primitives (\`src/primitives/\`) | 0 | ~600 LOC |
| Skills (markdown) | 0 | 9 files, ~2000 lines |
| SDK impl | ~3000 LOC | ~600 LOC |
| Library (knowledge/policy/validation/infra) | unchanged | unchanged |

**Net:** ~6500 LOC of TypeScript deleted, ~2000 lines of markdown added. MCP surface shrinks from 11 tools to 7.

## SDK preservation

The SDK interface (\`containerization-assist-mcp/sdk\`) is a consumer-facing contract. Every exported name is preserved across all phases; implementations get progressively thinner.

Phase 1 already added \`queryKnowledge\`, \`validateDockerfile\`, \`validateK8sManifest\`, \`validateCompose\` as new SDK exports. Phase 2 thins existing exports to ~10–60 LOC each.

## Why \`scan-image\`, \`prepare-cluster\`, \`verify-deploy\` stay as code

- \`scan-image\` — OSV TypeScript scanner with Dockerode image inspection, REST rate limiting, CVSS normalization. Real SDK integration value a skill can't reliably replicate.
- \`prepare-cluster\` — 1593 LOC of stateful kind/registry/networking orchestration with error recovery, containerd config patching, kind binary management.
- \`verify-deploy\` — K8s SDK rollout polling with structured pod/condition output that downstream tools consume.

## Tracking

- [x] **Phase 1** — PR #660
- [ ] **Phase 2** — issue/PR TBD after Phase 1 merges and stabilizes
- [ ] **Phase 3** — issue/PR TBD; major version bump

## Related

- Phase 1 PR: #660

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.