MCP Server Integration in dcg: How to Run Destructive Command Guard as an MCP Server

Destructive Command Guard (dcg) can run as an MCP (Model Context Protocol) server via STDIO-based RPC, exposing three tools—check_command, scan_file, and explain_pattern—that let AI agents and external tools query its command safety engine without CLI overhead.

The Dicklesworthstone/destructive_command_guard repository provides a robust MCP server integration that transforms dcg from a standalone CLI tool into a queryable service. By implementing the Model Context Protocol, dcg exposes its destructive command detection engine through a standardized interface, enabling seamless integration with AI agents, editors, and automated pipelines. This mode eliminates the need to spawn full CLI processes or parse terminal output, offering direct programmatic access to command evaluation and file scanning capabilities.

What is the dcg MCP Server?

The MCP server implementation in src/mcp.rs wraps dcg’s core evaluation logic in an asynchronous RPC interface. When started via run_mcp_server(), the server initializes a Tokio runtime and creates a DcgMcpServer instance that advertises its capabilities through the MCP initialize payload. Unlike the standard CLI hook protocol designed for Claude Code, this integration targets direct programmatic access, allowing clients to send JSON-RPC requests over standard input/output streams.

The architecture uses StdioTransport for communication and offloads expensive operations to a dedicated blocking worker thread. This design ensures that lightweight operations remain responsive even during intensive file system analysis, as validated by the test blocking_scan_worker_does_not_starve_lightweight_checks.

Available MCP Tools and Capabilities

The server registers three primary tools that map directly to dcg’s core functionality:

check_command

The check_command tool evaluates a single shell command against dcg’s policy engine. It accepts a JSON payload with a "command" string and returns a CheckCommandResponse containing:

  • allowed: Boolean indicating policy compliance
  • decision: Either "allow" or "deny"
  • reason, rule_id, pack_id, severity: Metadata for denied commands
  • allowlist: Optional details when an allow-list override applies

Behind the scenes, this tool invokes evaluate_command from src/evaluator.rs, running the same analysis pipeline used by the CLI.

scan_file

The scan_file tool performs recursive scanning of files or directories for destructive commands. It accepts a "path" parameter and executes the scanning logic from src/scan.rs (scan_paths) on a blocking thread via run_blocking_scan. The tool returns a complete ScanReport JSON object, making it suitable for CI pipelines or pre-commit hooks that need to validate entire codebases.

explain_pattern

The explain_pattern tool provides human-readable documentation for specific rule IDs. By querying the global REGISTRY defined in src/packs/mod.rs, it extracts the stored reason, severity, and optional explanation for patterns like core.git:reset-hard, returning an ExplainPatternResponse that helps users understand why certain commands trigger safety violations.

Starting the MCP Server

To launch the server programmatically, call the run_mcp_server entry point. This function builds a multi-threaded Tokio runtime and blocks until the server terminates:

use dcg::mcp;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Blocks the current process and listens on stdin/stdout
    mcp::run_mcp_server()
}

The underlying run_mcp_server_async function constructs the transport layer using server_runtime::create_server and manages the async event loop. Configuration and allow-list data are loaded from src/config.rs, ensuring the server respects the same policies as the CLI version.

Client Integration Examples

You can interact with the dcg MCP server using any MCP-compatible client. The following example uses the rust-mcp-sdk to query the server:

use rust_mcp_sdk::client::McpClient;
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Connect via stdio – server must already be running
    let client = McpClient::connect_stdio().await?;

    // Check a single command
    let check = client
        .call_tool("check_command", json!({ "command": "git reset --hard" }))
        .await?;
    println!("Safety check: {}", check);

    // Scan a directory
    let scan = client
        .call_tool("scan_file", json!({ "path": "./src" }))
        .await?;
    println!("Scan results: {}", scan);

    // Explain a rule
    let explain = client
        .call_tool("explain_pattern", json!({ "rule_id": "core.git:reset-hard" }))
        .await?;
    println!("Rule explanation: {}", explain);

    Ok(())
}

For AI agent integration, query the check_command tool before executing user-provided shell commands:

// Pseudo-code for AI agent integration
let command = get_user_command();
let result = mcp_client
    .call_tool("check_command", json!({ "command": command }))
    .await?;

if result["allowed"].as_bool().unwrap_or(false) {
    execute_shell(command);
} else {
    display_warning(result["reason"], result["explanation"]);
}

Summary

  • MCP server mode transforms dcg into a queryable service via STDIO-based RPC, implemented in src/mcp.rs.
  • Three core tools expose dcg’s functionality: check_command for single-command evaluation, scan_file for recursive directory scanning, and explain_pattern for rule documentation.
  • Async architecture uses Tokio for request handling with blocking worker threads for expensive scans, ensuring responsive lightweight checks.
  • Direct integration allows AI agents and automation tools to check command safety without spawning CLI processes or parsing text output.

Frequently Asked Questions

How do I start the dcg MCP server from my application?

Import the dcg::mcp module and call run_mcp_server(). This function creates a multi-threaded Tokio runtime and blocks on run_mcp_server_async(), which initializes the StdioTransport and begins listening for MCP requests on standard input/output.

What is the difference between check_command and scan_file?

check_command evaluates a single shell command string against dcg’s policy using evaluate_command, returning an immediate allow/deny decision. scan_file recursively analyzes a filesystem path using scan_paths, running on a blocking thread to prevent starvation of lightweight requests, and returns a comprehensive ScanReport.

Can I use the MCP server with AI agents like Claude or custom LLM tools?

Yes. The MCP protocol enables any compatible client—including AI agents—to call dcg’s tools directly. Agents can invoke check_command before executing user code, or use explain_pattern to provide human-readable safety explanations when blocking dangerous operations.

Where does the MCP server load its destructive pattern rules?

The server consults the global REGISTRY defined in src/packs/mod.rs, which contains all loaded rule packs. Configuration and allow-list overrides are handled by the logic in src/config.rs, ensuring the MCP server respects the same policies as the command-line interface.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →