# How to Set Up CyberStrikeAI for Stdio MCP Mode

> Learn how to set up CyberStrikeAI for Stdio MCP mode. Configure external tools via stdin stdout and JSON-RPC messages using external_mcp in config.yaml.

- Repository: [公明/CyberStrikeAI](https://github.com/Ed1s0nZ/CyberStrikeAI)
- Tags: how-to-guide
- Published: 2026-03-09

---

**CyberStrikeAI supports stdio MCP mode by running external tools as child processes and exchanging JSON-RPC messages over stdin/stdout streams, configured via `external_mcp` in [`config.yaml`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/config.yaml) and managed through the `mcp-stdio` binary.**

CyberStrikeAI implements the **Model Context Protocol (MCP)** to communicate with external security tools. When operating in **stdio mode**, the framework spawns configured executables as subprocesses and routes JSON-RPC requests through standard input and output pipes. This setup enables seamless integration with command-line tools and scripts without requiring network sockets.

## Understanding Stdio MCP Mode Architecture

The stdio implementation consists of three core components that handle message routing, process management, and configuration parsing.

### MCP Server Core

In [`internal/mcp/server.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/mcp/server.go), the `HandleStdio` method implements the stdio transport logic. This function reads newline-delimited JSON-RPC messages from **stdin**, processes the requests, and writes compact JSON responses to **stdout**. The implementation explicitly flushes the writer after each response to prevent client blocking and ensure real-time communication. ([source line 1171‑1185](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/mcp/server.go#L1171-L1185))

### Stdio Mode Entrypoint

The [`cmd/mcp-stdio/main.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/cmd/mcp-stdio/main.go) file provides the dedicated entrypoint for stdio operation. This executable loads the global configuration, initializes a logger that writes to **stderr** (preventing corruption of the JSON stream), instantiates the MCP server, registers all security-tool executors via `security.NewExecutor` from [`internal/security/executor.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/security/executor.go), and invokes `HandleStdio` to begin processing. ([source line 15‑43](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/cmd/mcp-stdio/main.go#L15-L43))

### External MCP Configuration

Configuration definitions reside in [`internal/config/config.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/config/config.go), specifically within the `ExternalMCPServerConfig` struct. For stdio mode, critical fields include `Command`, `Args`, `Env`, and `ExternalMCPEnable`. When `Transport` is omitted or set to `"stdio"`, the system automatically selects the stdio transport mechanism. ([source line 27‑42](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/config/config.go#L27-L42))

## Step-by-Step Setup Instructions

Follow these steps to configure and launch CyberStrikeAI in stdio MCP mode.

### 1. Configure the External MCP Entry

Add a stdio server definition under `external_mcp.servers` in your [`config.yaml`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/config.yaml). Set `external_mcp_enable: true` to activate the entry. The `command` field specifies the executable, while `args` accepts a list of command-line arguments.

```yaml
external_mcp:
  servers:
    hexstrike-ai:
      command: python3
      args:
        - /opt/hexstrike/bridge.py
        - --listen
        - http://0.0.0.0:9000
      description: "HexStrike AI stdio bridge"
      timeout: 300
      external_mcp_enable: true

```

### 2. Build the Stdio Binary

Compile the dedicated stdio MCP server binary from the repository root:

```bash
go build -o mcp-stdio ./cmd/mcp-stdio

```

This produces an `mcp-stdio` executable that encapsulates the stdio transport logic and tool registry.

### 3. Launch the MCP Server

Start the binary with your configuration file. The process maintains JSON-RPC communication on stdout while writing operational logs to stderr:

```bash
./mcp-stdio -config config.yaml

```

### 4. Verify Tool Registration

The `mcp-stdio` binary automatically loads tool definitions from the `tools/` directory and registers them with the MCP server through the security executor. No manual registration steps are required after initial configuration.

### 5. Validate the Configuration

The repository includes the unit test `TestExternalMCPHandler_AddOrUpdateExternalMCP_Stdio` in [`internal/handler/external_mcp_test.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/handler/external_mcp_test.go). This test verifies that stdio configurations are correctly parsed and stored via the HTTP API. Run the test suite to confirm your setup:

```bash
go test ./internal/handler -run TestExternalMCPHandler_AddOrUpdateExternalMCP_Stdio

```

([source line 63‑70](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/handler/external_mcp_test.go#L63-L70))

## Configuration Reference and UI Integration

The web interface provides a reference template for stdio configuration. In [`web/static/i18n/en-US.json`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/web/static/i18n/en-US.json), the `exampleStdio` field contains a valid JSON schema that mirrors the [`config.yaml`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/config.yaml) structure, useful for copy-paste validation. ([source line 849‑860](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/web/static/i18n/en-US.json#L849-L860))

When integrating programmatically, clients send JSON-RPC requests to the stdio process using standard encoding:

```go
type Request struct {
    JSONRPC string      `json:"jsonrpc"`
    Method  string      `json:"method"`
    Params  interface{} `json:"params"`
    ID      int         `json:"id"`
}

// Send request to stdio MCP
func sendStdIO(req Request) (Response, error) {
    enc := json.NewEncoder(os.Stdout)
    dec := json.NewDecoder(os.Stdin)
    
    if err := enc.Encode(req); err != nil {
        return Response{}, err
    }
    
    var resp Response
    if err := dec.Decode(&resp); err != nil {
        return Response{}, err
    }
    return resp, nil
}

```

## Summary

- **Core implementation**: `HandleStdio` in [`internal/mcp/server.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/mcp/server.go) manages the stdin/stdout JSON-RPC loop with explicit writer flushing
- **Entrypoint**: [`cmd/mcp-stdio/main.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/cmd/mcp-stdio/main.go) initializes the stdio server, configures stderr logging, and registers security executors
- **Configuration**: Define stdio servers in [`config.yaml`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/config.yaml) under `external_mcp.servers` using `command`, `args`, and `external_mcp_enable` fields as defined in [`internal/config/config.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/config/config.go)
- **Build process**: Compile with `go build -o mcp-stdio ./cmd/mcp-stdio` and run via `./mcp-stdio -config config.yaml`
- **Tool loading**: The `tools/` directory contents are automatically registered through `security.NewExecutor` without manual intervention

## Frequently Asked Questions

### What is the difference between stdio and other MCP transport modes in CyberStrikeAI?

Stdio mode spawns the external tool as a child process and communicates via stdin/stdout pipes, while other transports may use HTTP or WebSocket connections. According to the source code in [`internal/config/config.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/config/config.go), when the `Transport` field is omitted or explicitly set to `"stdio"`, the system defaults to the subprocess-based stdio implementation handled by `HandleStdio` in [`internal/mcp/server.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/mcp/server.go).

### How do I prevent log messages from corrupting the JSON-RPC stream?

The stdio entrypoint in [`cmd/mcp-stdio/main.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/cmd/mcp-stdio/main.go) explicitly configures the logger to write to **stderr** only. This design ensures that all diagnostic and operational output is separated from the JSON-RPC message stream on stdout, preventing parsing errors on the client side.

### Can I use environment variables with stdio MCP servers?

Yes. The `ExternalMCPServerConfig` struct in [`internal/config/config.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/config/config.go) includes an `Env` field that accepts a map of environment variables. These variables are injected into the subprocess environment when the MCP server spawns the configured command, allowing you to pass secrets or configuration values securely.

### Where can I find a working example of the stdio configuration?

The repository provides a reference example in [`web/static/i18n/en-US.json`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/web/static/i18n/en-US.json) under the `exampleStdio` key, which demonstrates the expected JSON schema for stdio configurations. Additionally, the unit test `TestExternalMCPHandler_AddOrUpdateExternalMCP_Stdio` in [`internal/handler/external_mcp_test.go`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/internal/handler/external_mcp_test.go) shows a programmatically valid stdio configuration structure that can be adapted for your [`config.yaml`](https://github.com/Ed1s0nZ/CyberStrikeAI/blob/main/config.yaml) file.