zeph_plugins/manifest.rs
1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! `plugin.toml` manifest schema.
5
6use serde::{Deserialize, Serialize};
7
8fn default_config_table() -> toml::Value {
9 toml::Value::Table(toml::map::Map::new())
10}
11
12/// Top-level `plugin.toml` manifest.
13///
14/// # Example
15///
16/// ```toml
17/// [plugin]
18/// name = "git-workflows"
19/// version = "0.1.0"
20/// description = "Git workflow skills and MCP git server"
21/// zeph-version = ">=0.19"
22///
23/// [[skills]]
24/// path = "skills/git-commit"
25///
26/// [[mcp.servers]]
27/// id = "git"
28/// command = "mcp-git"
29/// args = ["--repo", "."]
30///
31/// [config.tools]
32/// blocked_commands = ["git push --force"]
33/// ```
34#[derive(Debug, Clone, Deserialize, Serialize)]
35pub struct PluginManifest {
36 /// Plugin metadata.
37 pub plugin: PluginMeta,
38 /// Skill entries bundled by this plugin.
39 #[serde(default)]
40 pub skills: Vec<SkillEntry>,
41 /// MCP server declarations.
42 #[serde(default)]
43 pub mcp: McpSection,
44 /// Tighten-only config overlay applied at startup.
45 #[serde(default = "default_config_table")]
46 pub config: toml::Value,
47}
48
49/// Plugin metadata from the `[plugin]` table.
50#[derive(Debug, Clone, Deserialize, Serialize)]
51pub struct PluginMeta {
52 /// Canonical plugin name. Must be a valid identifier: `[a-z0-9][a-z0-9-]*`.
53 pub name: String,
54 /// Plugin version (informational).
55 pub version: String,
56 /// Short description shown in `zeph plugin list`.
57 #[serde(default)]
58 pub description: String,
59 // zeph-version field intentionally omitted: version-gating is deferred to a future release
60 // when the semver crate is added as a workspace dependency.
61}
62
63/// A single skill entry in `[[skills]]`.
64#[derive(Debug, Clone, Deserialize, Serialize)]
65pub struct SkillEntry {
66 /// Relative path from the plugin root to the skill directory containing `SKILL.md`.
67 pub path: String,
68}
69
70/// The `[mcp]` section.
71#[derive(Debug, Clone, Default, Deserialize, Serialize)]
72pub struct McpSection {
73 /// MCP server declarations in `[[mcp.servers]]`.
74 #[serde(default)]
75 pub servers: Vec<PluginMcpServer>,
76}
77
78/// A single MCP server declaration in `[[mcp.servers]]`.
79#[derive(Debug, Clone, Deserialize, Serialize)]
80pub struct PluginMcpServer {
81 /// Unique server ID. Used to de-duplicate across plugins.
82 pub id: String,
83 /// Command to spawn (stdio transport). Must be in `mcp.allowed_commands`.
84 #[serde(default)]
85 pub command: Option<String>,
86 /// Arguments passed to `command`.
87 #[serde(default)]
88 pub args: Vec<String>,
89}