Skill conversion: convert tools to portable Claude skills with slim MCP primitives (3 phases)
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- markdown, typescript
- Domain
- developer-experience, tooling
Research direction
Start with the Phase 1 changes in src/primitives/, the tool registry and SDK exports, then review PR #660 before working on Phase 2. Map the replaceable implementations under src/tools/ to the planned skills/ directory and preserve every SDK export. Done means the skills work standalone, optionally use the primitives, and the retained MCP tools remain available as specified.
Written by the indexing model from the issue text.
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:
- Reduce maintenance burden — ~7000 LOC of tool code, much of it orchestration and prompt shaping rather than integration logic.
- Better UX in LLM Harness — Skills are transparent markdown; users can read and edit them without an `npm install`.
- 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<TSchema, TOut>` 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
- 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
- Dominant language
- TypeScript
- Stars
- 43
- Forks
- 20
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 1
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Azure/containerization-assist
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
Azure/containerization-assist#678 ·
-
question
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Azure/containerization-assist#671 ·
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 30/100
Azure/containerization-assist#215 · 1 comment ·
All issues in Azure/containerization-assist
Similar issues
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 88/100
StabilityNexus/Fate-EVM-Frontend#153 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
code-yeongyu/oh-my-openagent#9039 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Tencent/teamai-cli#862 ·
Maintainers usually reply within 1 day
-
bug good first issue hacktoberfest redis
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
libredb/libredb-studio#1164 ·
Maintainers usually reply within 1 day
-
flake
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day