Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 10 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,35 +60,28 @@ jobs:
env:
RUSTDOCFLAGS: "-D warnings"

# Security and supply chain audit using cargo-deny
# Security audit using cargo-audit
# Temporary replacement for cargo-deny due to CVSS 4.0 parsing issues
security:
name: Security Audit
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@v5

- name: Install Rust
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable

- name: Install cargo-deny
uses: taiki-e/install-action@v2
- name: Audit dependencies for security vulnerabilities
uses: actions-rust-lang/audit@v1
with:
tool: cargo-deny

- name: Check security advisories
run: cargo deny check advisories

- name: Check licenses
run: cargo deny check licenses

- name: Check banned dependencies
run: cargo deny check bans

- name: Check sources
run: cargo deny check sources
# Ignore advisories that don't apply or are low severity
# RUSTSEC-2024-0436: paste crate is unmaintained (comes from rmcp SDK dependency)
ignore: RUSTSEC-2024-0436
denyWarnings: true

# Cross-platform tests with matrix
test:
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ members = [
"crates/mcp-core",
"crates/mcp-examples",
"crates/mcp-introspector",
"crates/mcp-plugin-store",
"crates/mcp-skill-store",
"crates/mcp-skill-generator",
"crates/mcp-vfs",
"crates/mcp-wasm-runtime",
Expand Down Expand Up @@ -41,7 +41,7 @@ mcp-bridge = { path = "crates/mcp-bridge" }
mcp-codegen = { path = "crates/mcp-codegen" }
mcp-core = { path = "crates/mcp-core" }
mcp-introspector = { path = "crates/mcp-introspector" }
mcp-plugin-store = { path = "crates/mcp-plugin-store" }
mcp-skill-store = { path = "crates/mcp-skill-store" }
mcp-skill-generator = { path = "crates/mcp-skill-generator" }
mcp-vfs = { path = "crates/mcp-vfs" }
mcp-wasm-runtime = { path = "crates/mcp-wasm-runtime" }
Expand Down
2 changes: 1 addition & 1 deletion crates/mcp-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mcp-bridge.workspace = true
mcp-codegen.workspace = true
mcp-core.workspace = true
mcp-introspector.workspace = true
mcp-plugin-store.workspace = true
mcp-skill-store.workspace = true
mcp-vfs.workspace = true
mcp-wasm-runtime.workspace = true
serde = { workspace = true, features = ["derive"] }
Expand Down
56 changes: 28 additions & 28 deletions crates/mcp-cli/src/commands/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use mcp_codegen::CodeGenerator;
use mcp_core::ServerId;
use mcp_core::cli::{ExitCode, OutputFormat, ServerConnectionString};
use mcp_introspector::Introspector;
use mcp_plugin_store::{PluginStore, ServerInfo, ToolInfo};
use mcp_skill_store::{ServerInfo, SkillStore, ToolInfo};
use mcp_vfs::VfsBuilder;
use serde::Serialize;
use std::path::PathBuf;
Expand All @@ -29,8 +29,8 @@ struct GenerationResult {
files_created: usize,
/// Total lines of code generated
total_lines: usize,
/// Plugin saved location (if --save-plugin was used)
plugin_saved: Option<String>,
/// Skill saved location (if --save-skill was used)
skill_saved: Option<String>,
}

/// Runs the generate command.
Expand All @@ -47,8 +47,8 @@ struct GenerationResult {
/// * `output` - Optional output directory (defaults to "./generated")
/// * `feature` - Code generation feature mode ("wasm" or "skills")
/// * `force` - Overwrite existing output directory without prompting
/// * `save_plugin` - Save generated code as a plugin
/// * `plugin_dir` - Plugin directory for save operations
/// * `save_skill` - Save generated code as a skill
/// * `skill_dir` - Plugin directory for save operations
/// * `output_format` - Output format (json, text, pretty)
///
/// # Errors
Expand All @@ -59,7 +59,7 @@ struct GenerationResult {
/// - Server introspection fails
/// - Code generation fails
/// - File system operations fail
/// - Plugin save fails (if --save-plugin is used)
/// - Skill save fails (if --save-skill is used)
///
/// # Examples
///
Expand All @@ -75,7 +75,7 @@ struct GenerationResult {
/// "wasm".to_string(),
/// false,
/// false,
/// PathBuf::from("./plugins"),
/// PathBuf::from("./skills"),
/// OutputFormat::Pretty,
/// ).await?;
/// assert_eq!(result, ExitCode::SUCCESS);
Expand All @@ -87,8 +87,8 @@ pub async fn run(
output: Option<PathBuf>,
feature: String,
force: bool,
save_plugin: bool,
plugin_dir: PathBuf,
save_skill: bool,
skill_dir: PathBuf,
output_format: OutputFormat,
) -> Result<ExitCode> {
// Validate inputs
Expand Down Expand Up @@ -198,16 +198,16 @@ pub async fn run(
info!("Created file: {file_path}");
}

// Step 4: Save plugin if requested
let plugin_saved = if save_plugin {
info!("Saving plugin to: {}", plugin_dir.display());
// Step 4: Save skill if requested
let skill_saved = if save_skill {
info!("Saving skill to: {}", skill_dir.display());

// For MVP, we use mock WASM since we don't have TypeScript compilation
// In production, this would compile the generated TypeScript to WASM
let mock_wasm = create_mock_wasm();

// Create plugin store
let store = PluginStore::new(&plugin_dir).context("failed to initialize plugin store")?;
// Create skill store
let store = SkillStore::new(&skill_dir).context("failed to initialize skill store")?;

// Build VFS from generated code
let mut vfs_builder = VfsBuilder::new();
Expand All @@ -222,7 +222,7 @@ pub async fn run(

// Extract server info from introspection
// Note: Using "2024-11-05" as default protocol version for MVP
let plugin_server_info = ServerInfo {
let skill_server_info = ServerInfo {
name: server.clone(),
version: server_info.version.clone(),
protocol_version: "2024-11-05".to_string(),
Expand All @@ -238,15 +238,15 @@ pub async fn run(
})
.collect();

// Save plugin
// Save skill
store
.save_plugin(&server, &vfs, &mock_wasm, plugin_server_info, tool_info)
.with_context(|| format!("failed to save plugin for server '{server}'"))?;
.save_skill(&server, &vfs, &mock_wasm, skill_server_info, tool_info)
.with_context(|| format!("failed to save skill for server '{server}'"))?;

let plugin_path = store.plugin_path(&server);
info!("Plugin saved to: {}", plugin_path.display());
let skill_path = store.skill_path(&server);
info!("Skill saved to: {}", skill_path.display());

Some(plugin_path.display().to_string())
Some(skill_path.display().to_string())
} else {
None
};
Expand All @@ -258,7 +258,7 @@ pub async fn run(
feature_mode: feature.clone(),
files_created: generated_code.file_count(),
total_lines,
plugin_saved: plugin_saved.clone(),
skill_saved: skill_saved.clone(),
};

// Format and display result
Expand All @@ -270,8 +270,8 @@ pub async fn run(
result.files_created, result.total_lines, result.output_dir
);

if let Some(plugin_path) = plugin_saved {
info!("Plugin saved to: {}", plugin_path);
if let Some(skill_path) = skill_saved {
info!("Skill saved to: {}", skill_path);
}

Ok(ExitCode::SUCCESS)
Expand Down Expand Up @@ -301,7 +301,7 @@ mod tests {
feature_mode: "wasm".to_string(),
files_created: 5,
total_lines: 250,
plugin_saved: None,
skill_saved: None,
};

let json = serde_json::to_string(&result).unwrap();
Expand Down Expand Up @@ -340,15 +340,15 @@ mod tests {
feature_mode: "wasm".to_string(),
files_created: 10,
total_lines: 500,
plugin_saved: Some("./plugins/test".to_string()),
skill_saved: Some("./skills/test".to_string()),
};

assert_eq!(result.server, "test");
assert_eq!(result.output_dir, "/tmp");
assert_eq!(result.feature_mode, "wasm");
assert_eq!(result.files_created, 10);
assert_eq!(result.total_lines, 500);
assert_eq!(result.plugin_saved, Some("./plugins/test".to_string()));
assert_eq!(result.skill_saved, Some("./skills/test".to_string()));
}

#[tokio::test]
Expand Down Expand Up @@ -439,7 +439,7 @@ mod tests {
feature_mode: "wasm".to_string(),
files_created: 8,
total_lines: 400,
plugin_saved: None,
skill_saved: None,
};

// Test that all fields are accessible
Expand Down
2 changes: 1 addition & 1 deletion crates/mcp-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ pub mod debug;
pub mod execute;
pub mod generate;
pub mod introspect;
pub mod plugin;
pub mod server;
pub mod skill;
pub mod stats;
Loading
Loading