MCP tools and Copilot Skills solve different problems. For the template engine, MCP is the right choice because templates need live engine access — searching NuGet, reading parameters, validating constraints, writing files. Skills are great for teaching Copilot how to think, but they can't do things on their own.
| MCP Tools | Copilot Skills | |
|---|---|---|
| What they are | Server-side tools with typed inputs/outputs | Markdown instructions + scripts |
| Where they live | Standalone server process (stdio/SSE) | .github/skills/ or ~/.copilot/skills/ |
| What they do | Execute code, call APIs, read/write files | Teach Copilot patterns and workflows |
| Runtime | The server runs your code directly | Copilot interprets instructions and generates code |
| State | Server holds state (template cache, installed packages) | Stateless — loaded into context per-task |
| Discovery | MCP protocol — tools/list returns schemas |
Copilot loads relevant SKILL.md files |
| Cross-client | Any MCP client (VS Code, Claude, Cursor, etc.) | VS Code + Copilot CLI + coding agent only |
A skill could say "to create a web API, run dotnet new webapi --auth Individual" — but it's just text. The model still has to shell out, parse output, handle errors.
An MCP tool is the runtime. template_instantiate calls the template engine API directly, validates parameters, checks constraints, applies smart defaults, and returns structured JSON. No shell, no parsing, no guessing.
Skills can't validate. If a skill tells Copilot to run dotnet new webapi --framework net3.0, it'll fail at the shell level with a cryptic error.
MCP tools validate before creation:
- Invalid choice? → "'net3.0' is not valid for Framework. Options: net8.0, net9.0"
- Bad type? → "Expected true/false for EnableAot, got 'yes'"
- Unknown param? → "Available: Framework, auth, UseControllers..."
Ask a skill-based Copilot to use a template that isn't installed? It'll fail, then suggest dotnet new install, then retry. Multiple steps, multiple opportunities for error.
MCP: template_instantiate("maui-blazor") → not installed → searches NuGet → installs best match → creates. One call, done.
Skills can document rules like "if you enable AOT, use the latest framework" — but the model might forget, or apply them inconsistently.
MCP tools enforce them deterministically:
EnableAot=true→ auto-suggests latest frameworkauth=Individual→ keeps HTTPS enabledUseControllers=true→ setsUseMinimalAPIs=false
These are code, not suggestions.
Skills produce whatever the model generates. MCP tools return typed JSON:
{
"status": "Success",
"templateName": "webapi",
"filesCreated": ["Program.cs", "Controllers/WeatherController.cs", ...],
"appliedSmartDefaults": { "UseHttps": "true" },
"validationWarnings": [],
"constraintResults": []
}The model can reliably extract status, file lists, warnings — no regex on shell output.
Skills only work in GitHub Copilot (VS Code, CLI, coding agent). MCP tools work with:
- VS Code / GitHub Copilot
- Claude Desktop
- Cursor
- Any custom MCP client
Build once, works everywhere.
The MCP server maintains a persistent template cache — installed packages, NuGet search index, template metadata. This means:
- First call to
template_searchis slow (builds cache), subsequent calls are instant - Installed templates persist across sessions
- SDK templates auto-discover on first use
Skills are stateless — every session starts from scratch.
The MCP server has a built-in intent resolver with 70+ keyword mappings. "web API with auth and controllers" → webapi + auth=Individual + UseControllers=true. This runs locally, offline, deterministically.
A skill would have to rely on the LLM to figure out the mapping every time, and might get it wrong.
Skills aren't wrong — they complement MCP:
| Use case | Better fit |
|---|---|
| "Always use xUnit for tests in this repo" | Skill |
| "Create a web API with auth" | MCP tool |
| "Follow our team's project structure conventions" | Skill |
| "Search NuGet for Blazor templates" | MCP tool |
| "When creating APIs, always add health checks" | Skill |
| "Validate template parameters before creation" | MCP tool |
The sweet spot: Use MCP tools for the doing (search, validate, create) and skills for the policy (team conventions, post-creation setup, project-specific rules).
SKILL.md says: "To create a web API, run dotnet new webapi with these flags..."
→ Model reads instructions
→ Model generates shell command
→ Shell runs dotnet new
→ Model parses stdout/stderr (free text)
→ If error → model guesses what went wrong
→ If template missing → model suggests install → retries
Model calls template_from_intent("web API with auth and controllers")
→ Server returns: webapi, confidence 0.85, params: {auth: Individual, UseControllers: true}
→ Model calls template_instantiate with those params
→ Server validates → applies smart defaults → checks constraints → creates
→ Returns structured JSON: status, files, warnings
Fewer steps, deterministic validation, structured output, no shell parsing.
Skills are a markdown file. MCP tools are a full .NET project — build, pack, publish, version, maintain. That's a real cost. If all you need is "remind Copilot to use these flags", a skill is 10 minutes; an MCP server is weeks.
Users need to install the tool (dotnet tool install, dnx, or build from source). Skills just exist in the repo — clone and go. MCP requires NuGet publishing, version management, and users might hit PATH issues, SDK version mismatches, or ENOENT errors.
MCP runs a separate process that stays alive. It consumes memory (template cache, NuGet search index), takes a few seconds to cold-start, and can crash independently. Skills add zero runtime overhead — they're just text loaded into context.
When a skill misbehaves, you read the SKILL.md and fix the instructions. When an MCP tool misbehaves, you're debugging a .NET server — logs, telemetry, stepping through ClassificationBasedIntentResolver scoring logic. The feedback loop is longer.
MCP is well-supported in VS Code, Claude Desktop, and Cursor — but not everywhere. Some clients have quirks (VS Code lazy-connects, Claude needs full paths). Skills work consistently wherever Copilot runs, including the coding agent and GitHub.com.
Even with good descriptions and copilot-instructions, the model might ignore MCP tools and shell out to dotnet new anyway. Skills influence the model's reasoning directly (they're in-context instructions). MCP tools are external capabilities the model has to choose to use.
MCP tools create the project and return. They don't know about your team's conventions — "always add a health check endpoint", "wire up our internal NuGet feed", "add the standard CI pipeline". Skills can encode all of that. MCP would need a separate tool for each post-creation step.
The MCP server depends on specific Microsoft.TemplateEngine.* NuGet packages. When the template engine ships breaking changes (new parameter types, changed APIs), the MCP server needs an update. Skills reference dotnet new CLI, which is always in sync with the SDK.
108 tests and counting. Template engine behavior changes across SDK versions, NuGet availability varies, E2E tests need real SDK installs. Skills need no tests — they're instructions, not code.
If your team just needs "create a console app with our standard setup", a 3-line skill beats a 9-tool MCP server. MCP shines when you need validation, NuGet resolution, cross-parameter logic — but not every team does.
| Capability | MCP | Skills |
|---|---|---|
| Execute template engine APIs | ✅ Direct | ❌ Via shell |
| Parameter validation | ✅ Pre-creation | ❌ Post-failure |
| Auto-resolve from NuGet | ✅ One call | ❌ Multi-step |
| Smart defaults | ✅ Deterministic | |
| Structured output | ✅ Typed JSON | ❌ Free text |
| Cross-client support | ✅ Any MCP client | ❌ Copilot only |
| Stateful cache | ✅ Persistent | ❌ Stateless |
| Intent resolution | ✅ Offline/local | ❌ LLM-dependent |
| Setup effort | ❌ Build + publish + install | ✅ Drop a markdown file |
| Runtime overhead | ❌ Separate process | ✅ Zero |
| Debugging | ❌ Server logs + telemetry | ✅ Read the markdown |
| Post-creation conventions | ❌ Not its job | ✅ Perfect fit |
| Team policies | ❌ Not its job | ✅ Perfect fit |
| Maintenance burden | ❌ Versioning, NuGet deps, tests | ✅ Minimal |
| Works on GitHub.com | ❌ Needs local server | ✅ Coding agent loads skills |