npm package: @majkapp/majk-chat-mcp
Description: MCP (Model Context Protocol) plugin for majk-chat
Author: Jules White
Latest version: 1.0.32

# @majkapp/majk-chat-mcp

A comprehensive MCP (Model Context Protocol) plugin for majk-chat that enables seamless integration with MCP servers and dynamic shell command execution.

## Table of Contents

- [Installation](#installation)
- [Features](#features)
- [Quick Start](#quick-start)
- [Traditional MCP Servers](#traditional-mcp-servers)
- [Dynamic MCP Servers](#dynamic-mcp-servers)
- [CLI Tool](#cli-tool)
- [Permission System](#permission-system)
- [Tool Filtering](#tool-filtering)
- [Configuration Reference](#configuration-reference)
- [API Reference](#api-reference)
- [Examples](#examples)
- [Troubleshooting](#troubleshooting)

## Installation

```bash
npm install @majkapp/majk-chat-mcp
```

## Features

🔌 **Dual MCP Support**
- Traditional stdio MCP servers
- Dynamic shell command execution (no external servers needed)

🛡️ **Advanced Permission System**
- Dynamic input modification before tool execution
- Allow/deny with custom logic
- Parameter filtering and augmentation

🎯 **Smart Tool Filtering**
- Wildcard support (`mcp__*`, `mcp__filesystem__*`)
- Allow/disallow lists with pattern matching
- Fine-grained control over tool availability

📝 **Flexible Configuration**
- File-based or inline JSON configuration
- Environment variable expansion
- Home directory path resolution

🔧 **Template Engine**
- Handlebars-style templating for dynamic commands
- Conditional execution (`{{#if}}`)
- Array iteration (`{{#each}}`)
- Variable substitution (`{{variable}}`)

🏃 **Standalone CLI Tool**
- Run dynamic servers as real stdio MCP servers
- Configuration validation
- Easy deployment and testing

## Quick Start

### Using with majk-chat CLI

```bash
# Simple dynamic server
majk-chat chat \
  --mcp-config '{"mcpServers":{"tools":{"commands":[{"name":"echo_test","description":"Echo test","parameters":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]},"exec":{"path":"echo","args":["{{message}}"],"expect":"text"}}]}}}' \
  -p "Say hello world" \
  --provider anthropic

# Traditional MCP server
majk-chat chat \
  --mcp-config '{"mcpServers":{"filesystem":{"command":"npx","args":["@modelcontextprotocol/server-filesystem","/workspace"]}}}' \
  -p "List files in the workspace" \
  --provider anthropic

# With permissions and filtering
majk-chat chat \
  --mcp-config ./mcp-config.json \
  --permission-prompt-tool "mcp__permissions__check" \
  --allowed-tools "mcp__filesystem__read*,mcp__tools__safe*" \
  --disallowed-tools "mcp__*__delete*" \
  -p "Analyze the project structure" \
  --provider anthropic
```

## Traditional MCP Servers

Connect to existing MCP servers via stdio transport.

### Configuration

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-filesystem", "/workspace"],
      "env": {
        "LOG_LEVEL": "info"
      }
    },
    "github": {
      "command": "npx", 
      "args": ["@modelcontextprotocol/server-github", "--token", "$GITHUB_TOKEN"],
      "env": {
        "GITHUB_TOKEN": "$GITHUB_TOKEN"
      }
    }
  }
}
```

### CLI Usage

```bash
# From file
majk-chat chat --mcp-config ./mcp-servers.json -p "List files"

# Inline JSON
majk-chat chat --mcp-config '{"mcpServers":{...}}' -p "Query GitHub"

# Legacy option (deprecated)
majk-chat chat --mcp-servers '{"mcpServers":{...}}' -p "Execute task"
```

## Dynamic MCP Servers

Execute shell commands directly without external MCP servers. Perfect for integrating existing CLI tools.

### Basic Example

```json
{
  "mcpServers": {
    "shell_tools": {
      "commands": [
        {
          "name": "get_weather",
          "description": "Get current weather for a city",
          "parameters": {
            "type": "object",
            "properties": {
              "city": {
                "type": "string",
                "description": "City name"
              },
              "unit": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"],
                "default": "celsius"
              }
            },
            "required": ["city"]
          },
          "exec": {
            "path": "curl",
            "args": [
              "-s",
              "http://api.openweathermap.org/data/2.5/weather?q={{city}}&appid=$WEATHER_API_KEY&units={{unit}}"
            ],
            "env": {
              "WEATHER_API_KEY": "$WEATHER_API_KEY"
            },
            "timeoutMs": 10000,
            "expect": "json"
          }
        }
      ]
    }
  }
}
```

### Advanced Templating

```json
{
  "commands": [
    {
      "name": "process_files",
      "description": "Process multiple files with options",
      "parameters": {
        "type": "object",
        "properties": {
          "files": {
            "type": "array",
            "items": {"type": "string"}
          },
          "verbose": {"type": "boolean", "default": false},
          "format": {"type": "string", "default": "json"}
        },
        "required": ["files"]
      },
      "exec": {
        "path": "processor",
        "args": [
          "{{#if verbose}}--verbose{{/if}}",
          "--format={{format}}",
          "{{#each files}}--file={{this}}{{/each}}"
        ],
        "cwd": "~/workspace",
        "env": {
          "PROCESSOR_CONFIG": "$HOME/.processor.conf"
        },
        "timeoutMs": 60000,
        "expect": "json"
      }
    }
  ]
}
```

### Template Syntax

| Syntax | Description | Example |
|--------|-------------|---------|
| `{{var}}` | Variable substitution | `{{city}}` → `"Paris"` |
| `{{#if var}}text{{/if}}` | Conditional inclusion | `{{#if verbose}}--verbose{{/if}}` |
| `{{#each array}}{{this}}{{/each}}` | Array iteration | `{{#each files}}--file={{this}}{{/each}}` |
| `$VAR` | Environment variable | `$API_KEY` → `process.env.API_KEY` |

## CLI Tool

The package includes a standalone CLI tool for running dynamic servers as real stdio MCP servers.

### Installation

```bash
npm install -g @majkapp/majk-chat-mcp
```

### Usage

```bash
# Start server from config file
majk-mcp-server serve --config dynamic-config.json

# Start server from JSON string
majk-mcp-server serve --config-json '{"commands":[...]}'

# Validate configuration
majk-mcp-server validate --config dynamic-config.json

# Get help
majk-mcp-server --help
```

### Example: Weather Service

1. **Create config** (`weather-server.json`):
```json
{
  "commands": [
    {
      "name": "get_weather",
      "description": "Get weather for a city",
      "parameters": {
        "type": "object", 
        "properties": {
          "city": {"type": "string"}
        },
        "required": ["city"]
      },
      "exec": {
        "path": "curl",
        "args": ["-s", "wttr.in/{{city}}?format=3"],
        "timeoutMs": 5000,
        "expect": "text"
      }
    }
  ]
}
```

2. **Run server**:
```bash
majk-mcp-server serve --config weather-server.json
```

3. **Use with majk-chat**:
```bash
majk-chat chat \
  --mcp-config '{"mcpServers":{"weather":{"command":"majk-mcp-server","args":["serve","--config","weather-server.json"]}}}' \
  -p "What's the weather in Tokyo?" \
  --provider anthropic
```

## Permission System

The permission system allows dynamic modification of tool inputs before execution, enabling sophisticated security policies.

### Permission Tool Format

**Request**:
```json
{
  "tool_name": "Bash",
  "input": {"command": "rm file.txt", "description": "Delete file"},
  "tool_use_id": "unique-id-12345",
  "user_id": "user123",
  "request_id": "req456"
}
```

**Response**:
```json
{
  "behavior": "allow",
  "updatedInput": {
    "command": "rm file.txt --dry-run",
    "description": "Delete file (dry run mode)",
    "safety_mode": true
  }
}
```

### Permission Responses

| Response | Behavior |
|----------|----------|
| `{"behavior": "allow"}` | Use original input |
| `{"behavior": "allow", "updatedInput": {...}}` | Use modified input |
| `{"behavior": "allow", "updatedInput": {}}` | Clear all arguments |
| `{"behavior": "deny"}` | Block execution |

### CLI Usage

```bash
majk-chat chat \
  --mcp-config ./config.json \
  --permission-prompt-tool "mcp__permissions__check_permission" \
  -p "Delete all temporary files"
```

## Tool Filtering

Control which tools are available with powerful pattern matching.

### Wildcard Patterns

```bash
# Allow all MCP tools
--allowed-tools "mcp__*"

# Allow filesystem tools only
--allowed-tools "mcp__filesystem__*"

# Block all delete operations
--disallowed-tools "mcp__*__delete*"

# Mixed patterns
--allowed-tools "mcp__filesystem__read*,mcp__tools__safe*,Bash"
```

### CLI Options

```bash
# Comma or space separated
--allowed-tools "tool1,tool2,tool3"
--allowed-tools "tool1 tool2 tool3"

# Wildcard patterns
--disallowed-tools "mcp__*__delete* mcp__*__remove*"

# Both options (disallowed takes precedence)
--allowed-tools "mcp__*" --disallowed-tools "mcp__*__dangerous*"
```

## Configuration Reference

### Traditional MCP Server

```json
{
  "mcpServers": {
    "server_name": {
      "command": "npx",
      "args": ["@package/mcp-server", "--option", "value"],
      "env": {
        "API_KEY": "$API_KEY",
        "CONFIG_PATH": "~/.config/app.conf"
      }
    }
  }
}
```

### Dynamic MCP Server

```json
{
  "mcpServers": {
    "dynamic_tools": {
      "commands": [
        {
          "name": "tool_name",
          "description": "Tool description",
          "parameters": {
            "type": "object",
            "properties": {
              "param1": {"type": "string"},
              "param2": {"type": "number", "default": 42}
            },
            "required": ["param1"]
          },
          "exec": {
            "path": "/usr/bin/command",
            "args": ["--param1", "{{param1}}", "--param2", "{{param2}}"],
            "cwd": "~/workspace",
            "env": {
              "CUSTOM_VAR": "$ENV_VAR"
            },
            "timeoutMs": 30000,
            "expect": "json",
            "stream": false
          }
        }
      ]
    }
  }
}
```

### Configuration Options

| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `path` | string | Command to execute | Required |
| `args` | string[] | Command arguments with templating | Required |
| `cwd` | string | Working directory (`~` expanded) | `process.cwd()` |
| `env` | object | Environment variables | `{}` |
| `timeoutMs` | number | Execution timeout in milliseconds | `30000` |
| `expect` | "text" \| "json" | Expected output format | `"text"` |
| `stream` | boolean | Stream output (future feature) | `false` |

## API Reference

### MCPPlugin

```typescript
import { MCPPlugin } from '@majkapp/majk-chat-mcp';

const plugin = new MCPPlugin({
  configPath: './mcp-config.json',
  allowedTools: ['mcp__*'],
  disallowedTools: ['mcp__*__delete*'],
  permissionPromptTool: 'mcp__permissions__check',
  quiet: true // Suppress console output
});

await plugin.initialize(toolRegistry);
```

### MCPClient

```typescript
import { MCPClient } from '@majkapp/majk-chat-mcp';

const client = new MCPClient(quiet);
const connection = await client.connect('server-name', {
  command: 'npx',
  args: ['@package/mcp-server'],
  env: { API_KEY: 'secret' }
});
```

### DynamicCommandExecutor

```typescript
import { DynamicCommandExecutor } from '@majkapp/majk-chat-mcp';

const executor = new DynamicCommandExecutor('server-name', {
  name: 'my_tool',
  description: 'My custom tool',
  parameters: { type: 'object', properties: {...} },
  exec: {
    path: 'my-command',
    args: ['{{param}}'],
    expect: 'json'
  }
});
```

## Examples

### 1. Weather Service

```bash
majk-chat chat \
  --mcp-config '{
    "mcpServers": {
      "weather": {
        "commands": [{
          "name": "get_weather",
          "description": "Get weather for a city",
          "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"]
          },
          "exec": {
            "path": "curl",
            "args": ["-s", "wttr.in/{{city}}?format=3"],
            "timeoutMs": 5000,
            "expect": "text"
          }
        }]
      }
    }
  }' \
  -p "What's the weather in London?" \
  --provider anthropic
```

### 2. File Processing Pipeline

```bash
majk-chat chat \
  --mcp-config '{
    "mcpServers": {
      "file_tools": {
        "commands": [
          {
            "name": "analyze_files",
            "description": "Analyze files with custom options",
            "parameters": {
              "type": "object",
              "properties": {
                "files": {"type": "array", "items": {"type": "string"}},
                "depth": {"type": "number", "default": 1},
                "include_tests": {"type": "boolean", "default": false}
              },
              "required": ["files"]
            },
            "exec": {
              "path": "analyzer",
              "args": [
                "--depth={{depth}}",
                "{{#if include_tests}}--include-tests{{/if}}",
                "{{#each files}}--file={{this}}{{/each}}"
              ],
              "env": {"ANALYZER_CONFIG": "$HOME/.analyzer.json"},
              "timeoutMs": 60000,
              "expect": "json"
            }
          }
        ]
      }
    }
  }' \
  -p "Analyze main.js and utils.js with tests included" \
  --provider anthropic
```

### 3. Permission-Controlled Operations

```bash
majk-chat chat \
  --mcp-config '{
    "mcpServers": {
      "permissions": {
        "command": "npx",
        "args": ["@majkapp/mcp-permissions-server"]
      },
      "system_tools": {
        "commands": [{
          "name": "system_command",
          "description": "Execute system command",
          "parameters": {
            "type": "object",
            "properties": {"cmd": {"type": "string"}},
            "required": ["cmd"]
          },
          "exec": {
            "path": "sh",
            "args": ["-c", "{{cmd}}"],
            "timeoutMs": 30000,
            "expect": "text"
          }
        }]
      }
    }
  }' \
  --permission-prompt-tool "mcp__permissions__check_system_command" \
  -p "Check disk usage" \
  --provider anthropic
```

### 4. Stream JSON Output

```bash
majk-chat chat \
  --mcp-config ./config.json \
  -p "Process the data pipeline" \
  --output-format stream-json \
  --provider anthropic | jq .
```

### 5. Tool Filtering

```bash
# Allow only read operations
majk-chat chat \
  --mcp-config ./config.json \
  --allowed-tools "mcp__*__read* mcp__*__list* mcp__*__get*" \
  -p "Analyze the project"

# Block dangerous operations
majk-chat chat \
  --mcp-config ./config.json \
  --disallowed-tools "mcp__*__delete* mcp__*__remove* mcp__*__destroy*" \
  -p "Clean up the workspace"
```

## CLI Tool Reference

### majk-mcp-server

Run dynamic MCP servers as standalone stdio servers.

#### Commands

```bash
# Start server
majk-mcp-server serve [options]

# Validate configuration
majk-mcp-server validate [options]

# Show help
majk-mcp-server --help
```

#### Options

| Option | Description | Example |
|--------|-------------|---------|
| `-c, --config <file>` | Configuration file path | `--config weather.json` |
| `--config-json <json>` | Configuration as JSON string | `--config-json '{"commands":[...]}'` |

#### Example Usage

```bash
# Create config
cat > weather-tools.json << 'EOF'
{
  "commands": [
    {
      "name": "weather",
      "description": "Get weather info",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      },
      "exec": {
        "path": "curl",
        "args": ["-s", "wttr.in/{{city}}?format=j1"],
        "expect": "json"
      }
    }
  ]
}
EOF

# Validate config
majk-mcp-server validate --config weather-tools.json

# Run as stdio server
majk-mcp-server serve --config weather-tools.json

# Use with majk-chat
majk-chat chat \
  --mcp-config '{"mcpServers":{"weather":{"command":"majk-mcp-server","args":["serve","--config","weather-tools.json"]}}}' \
  -p "Weather in Seattle?"
```

## Tool Naming Convention

All tools are namespaced to prevent conflicts:

- **Traditional MCP**: `mcp__<server_name>__<tool_name>`
- **Dynamic Commands**: `mcp__<server_name>__<command_name>`

Examples:
- `mcp__filesystem__read_file`
- `mcp__weather__get_current_weather`
- `mcp__permissions__check_permission`

## Output Formats

### Text Format (Default)

Human-readable output with colors, spinners, and formatting:

```
🔧 Calling tool: mcp__weather__get_weather
{
  "city": "Paris"
}

✅ Tool result:
Weather in Paris is 22°C, sunny

📊 Tokens: 45 (prompt: 20, completion: 25)
```

### Stream JSON Format

Structured JSON events for programmatic consumption:

```json
{"type":"system","subtype":"init","session_id":"...","tools":["mcp__weather__get_weather"],...}
{"type":"assistant","message":{"content":[{"type":"tool_use","name":"mcp__weather__get_weather","input":{"city":"Paris"}}],...}}
{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"...","content":"Weather in Paris is 22°C"}],...}}
{"type":"result","subtype":"success","total_cost_usd":0.001234,...}
```

## Troubleshooting

### Common Issues

**1. MCP Server Connection Failed**
```
Failed to connect to MCP server "my-server": Connection closed
```
- Check if the server command/path is correct
- Verify server is installed and accessible
- Check environment variables are set

**2. Dynamic Command Not Found**
```
Command failed with exit code 127: command not found
```
- Verify the command path is correct
- Check if command is in PATH
- Use absolute path if needed

**3. Template Variables Not Resolved**
```
Weather in {{city}} is sunny
```
- Check parameter names match template variables
- Ensure required parameters are provided
- Verify JSON parameter structure

**4. Permission Denied**
```
Permission denied for tool: mcp__tools__dangerous_command
```
- Check permission tool configuration
- Verify permission server is running
- Review tool filtering rules

### Debug Mode

Enable detailed logging in text mode:

```bash
majk-chat chat \
  --mcp-config ./config.json \
  -p "Debug this issue" \
  --output-format text \
  --provider anthropic
```

### Configuration Validation

```bash
# Validate traditional MCP config
majk-chat chat --mcp-config ./config.json --help

# Validate dynamic server config  
majk-mcp-server validate --config dynamic-config.json
```

## Integration Examples

### CI/CD Pipeline

```bash
#!/bin/bash
# Process pull request with AI analysis

majk-chat chat \
  --mcp-config '{
    "mcpServers": {
      "ci_tools": {
        "commands": [
          {
            "name": "run_tests",
            "description": "Run test suite",
            "parameters": {"type": "object", "properties": {}},
            "exec": {"path": "npm", "args": ["test"], "expect": "text"}
          },
          {
            "name": "lint_code", 
            "description": "Run linter",
            "parameters": {"type": "object", "properties": {}},
            "exec": {"path": "npm", "args": ["run", "lint"], "expect": "text"}
          }
        ]
      }
    }
  }' \
  -p "Run tests and linting, then analyze the results" \
  --output-format stream-json \
  --provider anthropic > analysis.json
```

### Development Workflow

```bash
# Interactive development with tools
majk-chat interactive \
  --mcp-config ./dev-tools.json \
  --allowed-tools "mcp__dev__* Read Write Edit" \
  --system "You are a helpful development assistant" \
  --provider anthropic
```

### Automated Analysis

```bash
# Batch file analysis
echo "Analyze main.py" > prompts.txt
echo "Check test coverage" >> prompts.txt  
echo "Suggest improvements" >> prompts.txt

majk-chat chat \
  --prompts prompts.txt \
  --mcp-config ./analysis-tools.json \
  --output-format stream-json \
  --provider anthropic
```

## Security Notes

- 🔒 **Dynamic commands execute with full shell access** - use permission system
- 🛡️ **Template injection protection** - validate inputs carefully
- 🔐 **Environment variables** - avoid exposing secrets in args
- ⚠️ **Timeout protection** - commands are killed after timeout
- 🚫 **Permission system** - implement deny-by-default policies

## License

MIT

## Contributing

Issues and pull requests welcome at [majk-chat repository].

---

*For more examples and advanced usage, see the [majk-chat-cli documentation](../majk-chat-cli/README.md).*