Skip to content

PederHP/skillsdotnet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SkillsDotNet

NuGet NuGet

Agent skills (agentskills.io) for the C# MCP SDK.

Experimental: This package is under active development and its API is subject to change.

Skills provide "context-as-progressive-disclosure" via SKILL.md files. This library uses a skill:// URI convention to distribute skills as MCP resources -- clients can load frontmatter for discovery (~50-100 tokens), full SKILL.md on demand, and supporting files as needed.

Installation

dotnet add package SkillsDotNet.Mcp

Requires the official C# MCP SDK (ModelContextProtocol package).

If you only need the core skill types (parsing, validation, scanning) without the MCP transport layer:

dotnet add package SkillsDotNet

Server-Side Usage

Register a single skill directory

builder.Services
    .AddMcpServer()
    .WithSkill("/path/to/my-skill");

Register all skills from a directory

Each subdirectory containing a SKILL.md is registered as a skill:

builder.Services
    .AddMcpServer()
    .WithSkillsDirectory("/path/to/skills");

Vendor shortcuts

Register skills from well-known agent directories:

builder.Services
    .AddMcpServer()
    .WithClaudeSkills()    // ~/.claude/skills/
    .WithCursorSkills()    // ~/.cursor/skills/
    .WithCopilotSkills()   // ~/.copilot/skills/
    .WithCodexSkills()     // /etc/codex/skills/ + ~/.codex/skills/
    .WithGeminiSkills()    // ~/.gemini/skills/
    .WithGooseSkills()     // ~/.config/agents/skills/
    .WithOpenCodeSkills(); // ~/.config/opencode/skills/

Options

builder.Services
    .AddMcpServer()
    .WithSkillsDirectory("/path/to/skills", new SkillOptions
    {
        // List every file as a separate resource (default: Template)
        SupportingFiles = SkillFileMode.Resources,

        // Custom main file name (default: "SKILL.md")
        MainFileName = "SKILL.md"
    });

Client-Side Usage

Discover skills on a server

var skills = await client.ListSkillsAsync();
foreach (var skill in skills)
{
    Console.WriteLine($"{skill.Name}: {skill.Description}");
}

Read a skill's manifest

var manifest = await client.GetSkillManifestAsync("code-review");
foreach (var file in manifest.Files)
{
    Console.WriteLine($"  {file.Path} ({file.Size} bytes, {file.Hash})");
}

Download a skill locally

var path = await client.DownloadSkillAsync("code-review", targetDirectory: "./skills");

Sync all skills from a server

var paths = await client.SyncSkillsAsync(targetDirectory: "./skills");

Using skills with IChatClient

SkillCatalog discovers skills from one or more MCP servers and provides two things for use with Microsoft.Extensions.AI: context blocks (frontmatter summaries for the system prompt) and a load_skill tool the model can call to load a skill's full content on demand.

// Build a catalog from one or more MCP servers
var catalog = new SkillCatalog();
await catalog.AddClientAsync(mcpClient1);
await catalog.AddClientAsync(mcpClient2);

// Get frontmatter context blocks — add to the system message so the
// model knows what skills are available (~50-100 tokens each)
var contexts = catalog.GetSkillContexts(); // IReadOnlyList<TextContent>

var messages = new List<ChatMessage>
{
    new(ChatRole.System, [
        new TextContent("You are a helpful assistant. The following skills are available:"),
        .. contexts
    ]),
    new(ChatRole.User, "Help me review this pull request"),
};

// Get the load_skill tool — add to ChatOptions.Tools so the model
// can load a skill's full SKILL.md content when it decides to use one
var options = new ChatOptions
{
    Tools = [catalog.LoadSkillTool],
};

var response = await chatClient.GetResponseAsync(messages, options);

If a server disconnects, remove its skills from the catalog:

catalog.RemoveClient(mcpClient1);

Handling skill dependencies

Skills can declare MCP server dependencies in their frontmatter:

---
name: explore-everything
description: Explores an MCP server
dependencies: [everything-server]
---

When a skill with dependencies is loaded via the load_skill tool, the OnDependenciesRequired callback fires so the client host can connect to the required servers on demand:

catalog.OnDependenciesRequired = async (request, cancellationToken) =>
{
    Console.WriteLine($"Skill '{request.SkillName}' requires: {string.Join(", ", request.ServerNames)}");

    foreach (var serverName in request.ServerNames)
    {
        // Look up and connect to the server using your own configuration
        var client = await ConnectToServerAsync(serverName, cancellationToken);
        if (client is null)
            return false; // Signal failure — LoadSkillAsync will throw
    }

    return true; // All dependencies satisfied
};

The callback receives a SkillDependencyRequest with the skill name and the list of required server names. Return true when all servers are connected, or false to abort (which causes LoadSkillAsync to throw InvalidOperationException). If the callback is not set, skills with dependencies load silently without notification.

See the DynamicMcpServers sample for a complete example.

URI Convention

Each skill exposes three resources following the FastMCP convention:

URI Type Content
skill://{name}/SKILL.md Resource (listed) Full SKILL.md content
skill://{name}/_manifest Resource (listed) JSON manifest with file listing
skill://{name}/{+path} ResourceTemplate Supporting files on demand

Manifest format

{
  "skill": "code-review",
  "files": [
    { "path": "SKILL.md", "size": 512, "hash": "sha256:abc123..." },
    { "path": "references/checklist.md", "size": 256, "hash": "sha256:def456..." }
  ]
}

Writing a Skill

A skill is a directory containing a SKILL.md file with YAML frontmatter:

my-skill/
  SKILL.md
  references/
    example.md
---
name: my-skill
description: What this skill does
license: MIT
compatibility: claude, cursor
metadata:
  author: your-name
  version: "1.0"
---

# My Skill

Instructions for the agent go here.

Frontmatter fields

Field Required Description
name Yes 1-64 chars, lowercase alphanumeric + hyphens, must match directory name
description Yes 1-1024 chars
license No License identifier
compatibility No Comma-separated list of compatible agents (max 500 chars)
dependencies No List of required MCP server names (connected on demand via OnDependenciesRequired)
allowed-tools No Experimental tool restrictions
metadata No Arbitrary key-value pairs for client-specific data

Name rules

Per the agentskills.io spec:

  • Lowercase letters, digits, and hyphens only
  • No leading, trailing, or consecutive hyphens
  • NFKC normalized, max 64 characters
  • Must match the directory name

Packages

Package Description
SkillsDotNet Core library: FrontmatterParser, SkillValidator, SkillDirectoryScanner, SkillInfo, SkillFileInfo, SkillContextExtensions. Depends on Microsoft.Extensions.AI.Abstractions.
SkillsDotNet.Mcp MCP transport layer: SkillResourceFactory, SkillCatalog, builder extensions, client extensions. Depends on SkillsDotNet and ModelContextProtocol.

Target Frameworks

  • .NET 10
  • .NET 9
  • .NET 8

Acknowledgements

Many conventions and especially the server-side resource implementations in this library are inspired by FastMCP 3.0. We've tried to align with FastMCP whenever possible.

License

MIT

About

C# implementation of agent skills (agentskills.io) with MCP integration and convenience.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages