MCP Marionette
The MCP Marionette server provides a bridge for AI agents to interact with humans for decision-making, clarification, and session steering. It implements the Model Context Protocol (MCP) to allow agents to pause their execution and wait for human input through structured forms.
Purpose
This server enables human-in-the-loop workflows where an agent can:
- Ask clarifying questions with predefined options.
- Request confirmation before performing sensitive actions.
- Allow humans to steer or redirect the session goal.
Why Use This with GitHub Copilot?
Cost Savings: Premium Requests vs. Tokens
GitHub Copilot uses a premium request pricing model, not token-based billing. This has important implications for how you interact with Copilot:
| Plan | Premium Requests/Month | Cost per Extra Request |
|---|---|---|
| Copilot Free | 50 | $0.04 |
| Copilot Pro | 300 | $0.04 |
| Copilot Pro+ | 1,500 | $0.04 |
| Copilot Business | 300/user | $0.04 |
| Copilot Enterprise | 1,000/user | $0.04 |
Key insight: Every chat message, agent mode prompt, and complex interaction consumes premium requests. Once you hit your limit, you pay $0.04 per additional request.
How MCP Marionette Saves You Money
Using this MCP server with GitHub Copilot in VS Code provides significant cost benefits:
1. Structured Responses Reduce Back-and-Forth
Without MCP Marionette:
User: "Should I use React or Vue for this project?"
Copilot: "Great question! Both have pros and cons..."
[Multiple chat turns = Multiple premium requests]
With MCP Marionette:
User: "Ask me which framework to use with options React, Vue, Svelte"
Copilot: [Uses askQuestion tool → Single premium request]
Human: [Selects from dropdown: "React - Component-based, large ecosystem"]
Copilot: [Proceeds with React implementation]
Result: 1 premium request instead of 3-5 for clarifying questions.
2. Session Steering Prevents Wasted Requests
Without steering:
Copilot: [Works on wrong task for 10 turns]
User: "Wait, that's not what I wanted"
Copilot: "Sorry, let me restart..."
[All previous requests consumed premium quota]
With steerSession:
User: "Check if the agent is on track"
Copilot: [Uses steerSession → Human sees current goal]
Human: "Redirect to focus on API layer first"
Copilot: [Pivots immediately]
Result: Prevents wasted premium requests on incorrect directions.
3. Agent Mode Efficiency
GitHub Copilot's agent mode is powerful but premium-request intensive. Each autonomous action counts. By adding human checkpoints:
- Agent asks before risky operations
- Human confirms expensive refactors
- Direction changes happen early, not after wasted work
Example: Cost Comparison
Scenario: Implementing a new feature with architecture decisions
| Approach | Premium Requests Used | Cost at $0.04/request |
|---|---|---|
| Unstructured chat | 15-25 turns | $0.60 - $1.00 |
| With MCP Marionette | 5-8 turns + 2 tool calls | $0.28 - $0.40 |
| Savings | ~60-70% fewer requests | $0.30 - $0.60 per task |
For a developer doing 50 complex tasks/month:
- Without MCP: 1,000 premium requests → Exceeds Pro limit, costs $28 extra
- With MCP: 350 premium requests → Well within Pro limit, $0 extra
GitHub Copilot + MCP Setup
GitHub Copilot in VS Code supports MCP servers natively. Here's how to use MCP Marionette:
Step 1: Configure MCP in VS Code
Create or edit .vscode/mcp.json in your project:
{
"servers": {
"marionette": {
"command": "npx",
"args": ["-y", "mcp-marionette"]
}
}
}
Or use the full path for local development:
{
"servers": {
"marionette": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/mcp-marionette/dist/index.js"]
}
}
}
Step 2: Enable MCP in Copilot
- Open VS Code Settings (
Cmd+,/Ctrl+,) - Search for "copilot mcp"
- Enable
github.copilot.chat.mcp.enabled
Or add to your settings.json:
{
"chat.mcp.discovery.enabled": true
}
Step 3: Use in Copilot Chat
- Open Copilot Chat (click the chat icon)
- Select Agent mode from the dropdown
- Click the tools icon (🔧) to see available MCP tools
- Your
askQuestionandsteerSessiontools appear under "MCP"
Step 4: Use Tools in Conversations
You: "I need to implement user authentication. Ask me which auth method to use."
Copilot: [Calls askQuestion tool]
Human sees form: "Which authentication method?"
- OAuth 2.0 - Third-party login (Google, GitHub, etc.)
- Email/Password - Traditional login
- Magic Links - Passwordless email login
[Human selects: "OAuth 2.0 - Third-party login"]
Copilot: "I'll implement OAuth 2.0 authentication..."
When to Use MCP Marionette with Copilot
| Use Case | Benefit |
|---|---|
| Architecture decisions | Get human input before committing to an approach |
| Ambiguous requirements | Clarify with structured options instead of guessing |
| Risky refactors | Ask for confirmation before large changes |
| Long-running tasks | Check in periodically with session steering |
| Multi-step workflows | Human checkpoints prevent wasted work |
Key Takeaway
MCP tools don't consume extra premium requests - they're part of the agent's tool execution. The human response happens in the VS Code UI, not in the chat. This means:
- 1 chat message + 1 tool call = 1 premium request (not 2)
- Structured answers prevent follow-up questions
- Session steering catches wrong directions early
For Copilot users, this MCP server pays for itself by reducing premium request usage by 50-70% on complex tasks.
Installation
Prerequisites
- Node.js 18+ - Required to run the server
- npm - Comes with Node.js
Installation Methods
Method 1: Clone and Build (Recommended for Development)
git clone <repository-url>
cd mcp-marionette
npm install
npm run build
Method 2: Global npm Installation
npm install -g mcp-marionette
mcp-marionette # Run directly
Method 3: Using npx (No Installation Required)
npx -y mcp-marionette
Configuration
The MCP Marionette server must be configured in your MCP client's configuration file. Below are instructions for different MCP clients.
Configuration File Locations
| Client | Configuration File Location |
|---|---|
| Claude Desktop (macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop (Windows) | %APPDATA%\Claude\claude_desktop_config.json |
| Claude Desktop (Linux) | ~/.config/Claude/claude_desktop_config.json |
| Claude Code | .claude/settings.json (project) or ~/.claude.json (global) |
| Cursor (Global) | ~/.cursor/mcp.json |
| Cursor (Project) | .cursor/mcp.json |
| Cline (VS Code) | ~/.vscode/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json |
Claude Desktop Configuration
Step 1: Find the Configuration File
macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Windows:
%APPDATA%\Claude\claude_desktop_config.json
Linux:
~/.config/Claude/claude_desktop_config.json
Step 2: Edit the Configuration
Add the following to your claude_desktop_config.json:
Option A: Direct path (if cloned locally):
{
"mcpServers": {
"marionette": {
"command": "node",
"args": [
"/ABSOLUTE/PATH/TO/mcp-marionette/dist/index.js"
]
}
}
}
Option B: Using npx (no local clone needed):
{
"mcpServers": {
"marionette": {
"command": "npx",
"args": ["-y", "mcp-marionette"]
}
}
}
Option C: Global installation:
{
"mcpServers": {
"marionette": {
"command": "mcp-marionette"
}
}
}
Important Notes:
- Use absolute paths (not relative paths)
- On Windows, use forward slashes
/or double backslashes\\ - Claude Desktop only reads this file at startup
Step 3: Restart Claude Desktop
After saving the configuration file, completely restart Claude Desktop for changes to take effect.
Step 4: Verify Installation
Look for the 🔨 (hammer) icon in Claude Desktop's chat interface. This indicates MCP tools are loaded.
Claude Code Configuration
Option 1: Using CLI Commands
Add the server using Claude Code's CLI:
# For local development
claude mcp add --transport stdio marionette -- node /absolute/path/to/mcp-marionette/dist/index.js
# For global installation
claude mcp add --transport stdio marionette -- mcp-marionette
# For npx
claude mcp add --transport stdio marionette -- npx -y mcp-marionette
Option 2: JSON Configuration
Create or edit .claude/settings.json in your project root:
{
"mcpServers": {
"marionette": {
"command": "node",
"args": [
"/ABSOLUTE/PATH/TO/mcp-marionette/dist/index.js"
]
}
}
}
Or for global configuration, edit ~/.claude.json.
Claude Code supports hot-reloading of MCP servers, so you don't need to restart.
Verify in Claude Code
Run /mcp in Claude Code to see loaded MCP servers.
Cursor Configuration
Cursor uses the same mcpServers format as Claude Desktop.
Global (all projects):
~/.cursor/mcp.json
Project-scoped:
.cursor/mcp.json
Example:
{
"mcpServers": {
"marionette": {
"command": "npx",
"args": ["-y", "mcp-marionette"]
}
}
}
Cline (VS Code) Configuration
File location:
~/.vscode/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json
Example:
{
"mcpServers": {
"marionette": {
"command": "npx",
"args": ["-y", "mcp-marionette"]
}
}
}
How Agents Discover This Server
Once configured, your MCP client will automatically discover and connect to the server:
Discovery Flow
- Server Spawn: MCP client spawns the server process using the configured
commandandargs - Initialize: Client and server perform capability negotiation via JSON-RPC
- Tool Discovery: Client calls
tools/listto discover available tools - Tool Registration: Client registers
askQuestionandsteerSessionwith the agent
Architecture Diagram
┌─────────────┐ ┌──────────────┐ ┌─────────────────────┐
│ Agent │◄───►│ MCP Client │◄───►│ MCP Marionette │
│ (Claude) │ │ (Desktop/ │ │ Server │
│ │ │ Code/etc) │ │ │
└─────────────┘ └──────────────┘ └─────────────────────┘
│
│ 1. Spawn process
│ 2. Initialize connection
│ 3. Discover tools
│ 4. Register tools
▼
[askQuestion, steerSession]
The agent automatically discovers these tools and can invoke them during conversations.
Tool Documentation
askQuestion
Asks a structured question with predefined options and an optional custom response field.
Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
sessionId | string | Yes | Unique identifier for the session. |
question | string | Yes | The question to ask the human. |
header | string | Yes | Header text for the question form (max 30 characters). |
options | array | Yes | List of objects with label and description strings. |
multiple | boolean | No | Allow selecting multiple options. |
allowCustom | boolean | No | Allow providing a custom text response. Defaults to true. |
Output Format
Returns the selected answer or custom response as text and structured data.
Success Response:
{
"content": [{ "type": "text", "text": "Staging" }],
"structuredContent": {
"sessionId": "deploy-task-456",
"action": "accept",
"answer": "Staging"
}
}
Custom Response:
{
"content": [{ "type": "text", "text": "Deploy to canary first" }],
"structuredContent": {
"sessionId": "deploy-task-456",
"action": "accept",
"answer": "Deploy to canary first"
}
}
Example Usage
{
"sessionId": "deploy-task-456",
"header": "Deployment Target",
"question": "Which environment should we deploy the latest changes to?",
"options": [
{ "label": "Staging", "description": "Internal testing environment" },
{ "label": "Production", "description": "Live environment for all users" }
],
"multiple": false
}
steerSession
Allows humans to provide high-level direction to an active agent session.
Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
sessionId | string | Yes | Unique identifier for the session. |
currentGoal | string | No | The current goal being pursued by the agent. |
Output Format
Returns a structured object containing:
directive: One ofcontinue,pause,modify,redirect,terminate, orcustom.newGoal: The updated goal if the directive ismodifyorredirect.customInstructions: Additional details provided by the human.sessionStatus: The resulting status of the session (e.g.,active,paused,terminated).
Example Response:
{
"content": [{
"type": "text",
"text": "{\"directive\":\"modify\",\"newGoal\":\"Focus on MCP server architecture\",\"customInstructions\":\"Include diagrams\",\"sessionStatus\":\"active\"}"
}],
"structuredContent": {
"sessionId": "research-session-789",
"directive": "modify",
"newGoal": "Focus on MCP server architecture",
"customInstructions": "Include diagrams",
"sessionStatus": "active"
}
}
Example Usage
{
"sessionId": "research-session-789",
"currentGoal": "Find all competitors in the MCP ecosystem"
}
Quick Start Examples
Example 1: Ask a Simple Question
Agent Request:
{
"sessionId": "planning-session-001",
"header": "Approach",
"question": "Which approach should we take?",
"options": [
{ "label": "Quick", "description": "Fast but basic implementation" },
{ "label": "Thorough", "description": "Comprehensive with tests" }
]
}
Human Sees:
- Header: "Approach"
- Question: "Which approach should we take?"
- Options: "Quick - Fast but basic implementation" and "Thorough - Comprehensive with tests"
- Custom text input field
Example 2: Steering a Session
Agent Request:
{
"sessionId": "coding-task-123",
"currentGoal": "Refactor the authentication module"
}
Human Sees:
- Session steering form
- Current goal: "Refactor the authentication module"
- Directive options: continue, pause, modify, redirect, terminate, custom
- Fields for new goal and custom instructions
Troubleshooting
Common Issues
Server Not Appearing
Symptoms: The 🔨 icon doesn't show in Claude Desktop.
Solutions:
- Check file paths - Use absolute paths, not relative
- Verify build - Run
npm run buildand ensuredist/index.jsexists - Restart client - Claude Desktop requires a full restart
- Check JSON syntax - Validate your config at https://jsonlint.com/
Permission Denied
Symptoms: EACCES: permission denied
Solution:
# Make the server executable
chmod +x dist/index.js
PATH Issues
Symptoms: command not found or spawn ENOENT
Solutions:
-
Use the full path to node:
{ "command": "/usr/local/bin/node", "args": ["/path/to/mcp-marionette/dist/index.js"] } -
Find node path:
which node # macOS/Linux where node # Windows
npx Issues
Symptoms: npx: command not found or slow startups
Solutions:
-
Clear npx cache:
rm -rf ~/.npm/_npx -
Use global installation instead:
npm install -g mcp-marionette -
Use direct node path instead of npx
"import: command not found"
Symptoms: Server fails with /bin/sh: import: command not found
Cause: Missing shebang in compiled file
Solution: Rebuild with shebang:
npm run build
# Then manually add to top of dist/index.js:
#!/usr/bin/env node
Debugging Steps
-
Test the server directly:
node dist/index.jsIf the server starts without errors, it's working correctly.
-
Check MCP logs:
- Claude Desktop (macOS):
~/Library/Logs/Claude/mcp.log - Cursor: Output panel → MCP server dropdown
- Claude Desktop (macOS):
-
Verify JSON-RPC communication:
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}},"id":1}' | node dist/index.js -
Check for stdout writes: Ensure your server doesn't write to stdout (only stderr). Writing to stdout corrupts JSON-RPC messages.
Client Comparison
| Client | Config File | Hot Reload | Restart Required | Tool Icon |
|---|---|---|---|---|
| Claude Desktop | claude_desktop_config.json | No | Yes | 🔨 |
| Claude Code | .claude/settings.json | Yes | No | /mcp command |
| Cursor | ~/.cursor/mcp.json | Yes | No | Settings panel |
| Cline (VS Code) | cline_mcp_settings.json | Yes | No | Sidebar |
Development
Project Structure
mcp-marionette/
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── README.md # This file
├── src/
│ └── index.ts # Server implementation
└── dist/ # Compiled output
├── index.js
├── index.d.ts
└── index.js.map
Building
npm run build
Testing
# Test the server directly
node dist/index.js
# Or test with npx
npx -y mcp-marionette
Publishing
# Build before publishing
npm run build
# Publish to npm
npm publish
# Or publish as beta
npm publish --tag beta
Security Considerations
- Local Execution: This server runs locally on your machine
- No External Network: No external network connections are made
- User Approval: All tool executions require explicit user approval in MCP clients
- Data Privacy: No data is sent to external services
- Session Isolation: Each session is identified but not persisted
Environment Variables
The server supports the following environment variables:
| Variable | Description | Default |
|---|---|---|
NODE_ENV | Environment mode | production |
Configure in your MCP client config:
{
"mcpServers": {
"marionette": {
"command": "node",
"args": ["/path/to/dist/index.js"],
"env": {
"NODE_ENV": "development"
}
}
}
}
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions:
- GitHub Issues: github.com/yourusername/mcp-marionette/issues
- MCP Documentation: modelcontextprotocol.io