Pre-alpha documentation
Publish and activate manifest-bound Agent Skills over MCP.
Use the Final SEP-2640 static Server and Client/Host profiles with immutable manifests, origin-scoped approval, lazy verified reads, and explicit execution gates.
One immutable snapshot drives every response
The server freezes each SKILL.md and supporting file at startup.
skills/list, skills/get, and
resources/read use those same bytes, so a manifest cannot drift
away from the content returned later.
| Boundary | Guarantee |
|---|---|
| Discovery | Bounded pagination, deterministic order, TTL and cache scope. |
| Manifest | Every file appears once with exact raw-byte SHA-256 and size. |
| Reads | Text or Base64 content from the retained immutable snapshot. |
| Policy | Authentication, exact scopes and dynamic authorization before disclosure. |
| Limits | 512 files and 16 MiB per Skill, plus aggregate catalog ceilings. |
| Host | Origin + URI identity, approval before reads, exact digest/size/ frontmatter verification, durable scoped acting windows, exact restart resume, immutable revocation, and manifest-only lazy access. |
| Execution | Exact owner/version/descriptor binding plus a fresh, acting-window-bound policy permit before every execution and recovery probe, with exact durable correlation and bounded schema-bound input. Each fresh payload-redacted receipt serializes with revocation and validates its active window before provider I/O; later revocation does not recall an authorization already committed. |
Activate through the verification-first Host
let client = McpClient::connect(
endpoint,
McpClientIdentity::new("orders-agent", env!("CARGO_PKG_VERSION"))?,
authorization,
McpClientOptions::for_skills(),
).await?;
let host = McpSkillHost::new(
client,
McpSkillOrigin::new("production/orders-mcp")?,
SkillActivationScope::new(tenant_id, run_id, thread_id),
Arc::new(application_skill_policy),
Arc::new(postgres_store.clone()),
McpSkillHostOptions::default(),
)?;
let catalog = host.list_skills().await?;
let selected = catalog.find_uri("skill://code-review/SKILL.md")
.ok_or(AppError::SkillUnavailable)?;
let activation = McpSkillActivationAttempt::generate();
let active = Arc::new(host.activate(selected, activation).await?);
let file = active.read_file("references/checklist.md").await?;
model_context.push_untrusted_skill_file(file.identity(), file.bytes())?;
let guarded = Arc::new(McpSkillBoundTool::new(
Arc::clone(&active),
ticket_create_tool,
Arc::new(postgres_store.clone()),
McpSkillHostCodeExecution::NotPossible,
)?);
tool_registry.register(guarded)?;
let tools = tool_registry.build();
Listing never prefetches Skill files. Preserve each verified file's origin
identity in model-visible context. Register McpSkillBoundTool
instead of the raw provider so the ordinary durable Tool runtime enforces an
exact policy decision before execution and reconciliation. Frontmatter
allowed-tools is review input, never an authorization grant. Policy
returns version-pinned activation and per-operation grant evidence. The durable
window store and receipt sink fail closed before dispatch when evidence is expired,
revoked, crossed, or unavailable.
Reject ambiguous or unsafe packages at startup
The registry rejects duplicate YAML keys at any depth, malformed Agent Skills fields, alias expansion beyond the materialized-value budget, name/URI mismatch, traversal and non-canonical paths, overlapping resource URIs, incomplete packages, and oversized catalogs. Unknown frontmatter fields remain data and are preserved without becoming authority.
Build the static server surface
let skill = McpServerSkillDefinition::new(
"skill://code-review/SKILL.md",
[
McpServerSkillFile::text(
"SKILL.md",
"text/markdown",
include_str!("skills/code-review/SKILL.md"),
)?,
McpServerSkillFile::text(
"references/checklist.md",
"text/markdown",
include_str!("skills/code-review/references/checklist.md"),
)?,
],
)?;
let mut skills = McpServerSkillCatalogBuilder::default();
skills.register(skill)?;
let app = McpServerApplicationBuilder::new(options)
.with_skills(skills.build()?, skill_authorization)?
.build()?; Keep the bytes in reviewed deployment inputs. Do not rebuild Skill registries on the request path.
Reproduce both profile gates
cargo test -p stateknot-integrations mcp_server_skill --locked
cargo test -p stateknot-integrations --test mcp_skills_server --locked
cargo test -p stateknot-integrations mcp_skill_host --locked
cargo test -p stateknot-integrations --test mcp_skills_host --locked
cargo test -p stateknot-store-postgres --test postgres --locked tool_authorization_receipts_are_exact_immutable_and_page_verifiable Read the complete implementation and non-claim boundaries in the Server guide and Client/Host guide.