README.md•5.29 kB
# MCP CLI Wrapper
A flexible MCP (Model Context Protocol) server that wraps any CLI tool and exposes its subcommands as individual MCP tools with typed parameters.
## Features
- **Config-driven tools**: Define CLI subcommands as MCP tools via JSON configuration
- **Fallback mode**: Single `run_cli` tool when no config provided
- **Type-safe parameters**: Zod validation for all inputs before execution
- **Flexible parameter types**: Supports positional args, flags, and boolean switches
- **Preserved parameter order**: Flags and positionals stay interleaved as defined
- **Nested subcommands**: Supports `git remote add` style commands
- **Safe execution**: Uses `spawnSync` to prevent command injection
- **Full output capture**: Returns stdout, stderr, and exit code
## Installation
```bash
npm install
npm run build
```
## Usage
### Basic (Fallback Mode)
Run without a config file to get a single `run_cli` tool that accepts raw arguments:
```bash
node dist/index.js git
```
This exposes one tool:
- `run_cli` - Accepts `args: string[]` and executes `git <args...>`
### With Configuration
Run with a config file to expose multiple typed tools:
```bash
node dist/index.js git ./config.example.json
```
This exposes tools like:
- `git_status` - Show working tree status
- `git_commit` - Commit with typed `message` and optional `all` flag
- `git_add` - Stage files with `pathspec` parameter
- `git_log` - Show logs with `oneline` and `max_count` options
- And more...
## Configuration Format
Create a JSON file with tool definitions:
```json
{
"tools": [
{
"name": "git_commit",
"description": "Record changes to the repository with a commit message.",
"subcommand": "commit",
"parameters": [
{
"name": "message",
"type": "string",
"description": "The commit message.",
"flag": "-m",
"required": true
},
{
"name": "all",
"type": "boolean",
"description": "Automatically stage all modified files.",
"flag": "--all",
"required": false
}
]
}
]
}
```
### Parameter Configuration
Each parameter supports:
| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Parameter name (used in schema) |
| `type` | `"string"` \| `"number"` \| `"boolean"` | Parameter type |
| `description` | string | Description shown to AI agents |
| `flag` | string (optional) | CLI flag (e.g., `-m`, `--force`). If omitted, parameter is positional |
| `required` | boolean | Whether the parameter is required |
### Parameter Order
Parameters are processed in **declaration order**. This allows you to define tools where flags must precede positional arguments:
```json
{
"name": "docker_run",
"subcommand": "run",
"parameters": [
{ "name": "interactive", "flag": "-it", "type": "boolean", "required": false },
{ "name": "image", "type": "string", "required": true },
{ "name": "command", "type": "string", "required": false }
]
}
```
This produces: `docker run -it ubuntu bash` (flags before positionals)
### Nested Subcommands
Use spaces in `subcommand` for nested commands:
```json
{
"name": "git_remote_add",
"subcommand": "remote add",
"parameters": [
{ "name": "name", "type": "string", "required": true },
{ "name": "url", "type": "string", "required": true }
]
}
```
## MCP Client Configuration
### Claude Desktop
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"git": {
"command": "node",
"args": ["/path/to/mcp-cli-wrapper/dist/index.js", "git", "/path/to/config.json"]
}
}
}
```
### Claude Code
Add to your MCP settings:
```json
{
"mcpServers": {
"git": {
"command": "node",
"args": ["./dist/index.js", "git", "./config.example.json"]
}
}
}
```
## Example Configs
### Git (included)
See `config.example.json` for a complete Git configuration with 8 tools.
### Docker (example)
```json
{
"tools": [
{
"name": "docker_ps",
"description": "List running containers",
"subcommand": "ps",
"parameters": [
{ "name": "all", "type": "boolean", "flag": "-a", "description": "Show all containers", "required": false }
]
},
{
"name": "docker_run",
"description": "Run a container",
"subcommand": "run",
"parameters": [
{ "name": "detach", "type": "boolean", "flag": "-d", "description": "Run in background", "required": false },
{ "name": "name", "type": "string", "flag": "--name", "description": "Container name", "required": false },
{ "name": "image", "type": "string", "description": "Image to run", "required": true }
]
}
]
}
```
## Security
- **No shell interpolation**: Arguments are passed directly via `spawnSync`, preventing command injection
- **Input validation**: All parameters validated with Zod schemas before execution
- **Local execution only**: Commands run on the local machine with the user's permissions
## Development
```bash
# Install dependencies
npm install
# Build
npm run build
# Run in development
npm run dev git ./config.example.json
```
## License
MIT