mcp-skill-framework 0.1.1

A small framework for building MCP (Model Context Protocol) servers as a uniform layer of self-contained tools ("skills"): a typed skill contract, declarative input validation, capability probes, family metadata, and a ready-made dispatcher.
Documentation
//! Family metadata — group related skills and describe them as a unit.
//!
//! A **family** is a cohesive group of [skills](crate::Skill) that share a
//! theme and, often, a host requirement (a binary, a daemon socket, an
//! interpreter). Registering a [`FamilyMeta`] gives an introspection tool,
//! a dashboard, and the startup logs a single source of truth for "what does
//! this group do, what tools does it contribute, and can it run here?"
//!
//! Families are optional: a group of pure, dependency-free skills can simply
//! not register one and inherit the implicit "always ready" behavior.

use crate::capability::SkillCapability;

/// The contract a skill **family** implements. Each family-level module
/// conventionally exports a unit struct (`pub struct Family;`) that impls
/// this trait; an application collects them into a registry that the
/// dispatcher, a dashboard, and the startup logs all read from.
pub trait FamilyMeta: Send + Sync + 'static {
    /// Stable id used in logs, snapshot fields, dashboard groupings, and the
    /// error messages a caller sees when a family's tools are blocked.
    fn family(&self) -> &'static str;

    /// The tool names this family exposes. Conventionally derived from the
    /// family's own skill registry (`skills().iter().map(|s| s.name())`)
    /// rather than maintained as a separate const list, so the two can't
    /// drift apart.
    fn tools(&self) -> Vec<&'static str>;

    /// Short, human-readable summary of what this family does and the host
    /// requirement that makes it interesting (e.g. "Inspect/control the
    /// local Docker daemon via the engine API").
    ///
    /// **Required, no default.** A family that can't surface a useful
    /// one-line description probably shouldn't register `FamilyMeta` at all —
    /// dependency-free families just inherit the implicit-ready path.
    fn description(&self) -> &'static str;

    /// Probe the host for whatever this family depends on (a binary on
    /// `$PATH`, a socket, a config endpoint, …). Runs once at startup; the
    /// result is meant to be cached and consulted by the dispatcher.
    ///
    /// **Required, no default.** Probing the host is the whole reason a
    /// family registers `FamilyMeta`. If a family needs no probe, return
    /// [`SkillCapability::Ready`] explicitly so the choice is visible in the
    /// source.
    fn check_capability(&self) -> SkillCapability;

    /// Multi-tool worked example showing how this family's tools chain in a
    /// representative task. Optional; defaults to `None`. Markdown-friendly —
    /// a short numbered list of `tool_name { arg: value }` calls is the
    /// canonical shape.
    fn example_flow(&self) -> Option<&'static str> {
        None
    }
}