README.md•8.93 kB
# MCPMan
A Model Context Protocol (MCP) server manager that acts as a proxy/multiplexer for multiple MCP servers.
## Overview
MCPMan allows you to:
- Connect to multiple MCP servers simultaneously (stdio and HTTP transports)
- Generate and execute code from natural language descriptions using LLMs
- Execute JavaScript code with access to all connected MCP tools
- Invoke tools from multiple servers with batch and parallel execution
- Manage server configurations with OAuth 2.1 support
- Dynamically add new servers without restarting
- Store and access tool results through $results array
## Quick Start
### Installation
```bash
bun install
```
### Initialize Configuration
```bash
mcpman init
```
### Add MCP Servers
```bash
# Add stdio server
mcpman add filesystem --command npx --args @modelcontextprotocol/server-filesystem
# Add HTTP server with OAuth
mcpman add api-server --url https://api.example.com/mcp
```
### Generate and Execute Code from Natural Language
The `code` tool uses LLMs (via Claude Agent SDK or MCP sampling) to generate JavaScript code from natural language descriptions. Generated code is validated with TypeScript compiler before execution.
```bash
# Generate code from description
mcpman code "list all files in the current directory"
# Generate code with custom root directories
mcpman code "read the package.json file and show the dependencies" --roots /path/to/project
```
**Features:**
- **Automatic Code Generation**: LLM writes JavaScript code to accomplish your task
- **TypeScript Validation**: Generated code is validated with TypeScript compiler API (with up to 3 retries if validation fails)
- **Type-Safe API**: Generated TypeScript definitions provide autocomplete and type checking for all MCP tools
- **Server Filtering**: Optional `servers` parameter limits which MCP servers are available to reduce context size and improve code quality
- **$results Integration**: Generated code results are automatically stored in `$results` array
When using as an MCP tool, strongly recommend specifying the `servers` parameter to limit context:
```javascript
// Good - limits context to only playwright tools
{
functionDescription: "navigate to google.com and take a screenshot",
servers: ["playwright"]
}
// Avoid - includes all servers which may result in poor performance
{
functionDescription: "navigate to google.com and take a screenshot"
}
```
### Evaluate Function Expressions with MCP Tools
```bash
# Simple function with no arguments
mcpman eval "() => listServers()"
# Function with argument
mcpman eval "(arg) => filesystem.listFiles({ path: arg.directory })" --arg '{"directory": "."}'
# Specify custom root directories
mcpman eval "(arg) => filesystem.listFiles({ path: arg.path })" --arg '{"path": "/tmp"}' --roots /tmp
# Complex function with console output
mcpman eval "(arg) => { console.log('Processing:', arg.name); return arg.value * 2; }" --arg '{"name": "test", "value": 21}'
```
### Run as MCP Server
```bash
mcpman serve
```
## Architecture
MCPMan operates in two modes:
### Server Mode
- Acts as an MCP server exposing multiple tools:
- `code` - Generate and execute JavaScript code from natural language descriptions using LLMs with TypeScript validation
- `eval` - Execute JavaScript with access to all MCP tools
- `invoke` - Batch invoke tools with parallel/sequential execution
- `list_servers` - List connected servers and their tools
- `help` - Get documentation for specific tools
- `install` - Dynamically add new servers
- Connects to multiple upstream MCP servers
- Transparently forwards root directory information from clients to upstream servers
- Provides unified JavaScript execution environment with $results array
### CLI Mode
- Direct command-line interface for server management
- Execute JavaScript code with MCP tool access
- Configure and test server connections
## Configuration
Configuration is stored in `~/.mcpman/settings.json`:
```json
{
"servers": {
"filesystem": {
"transport": "stdio",
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"env": {},
"disabled": false,
"timeout": 30000
},
"api-server": {
"transport": "http",
"url": "https://api.example.com/mcp",
"headers": {},
"oauth": {
"clientName": "mcpman",
"redirectUrl": "http://localhost:3000/callback",
"scopes": ["mcp:tools"],
"clientId": "optional-client-id",
"clientSecret": "optional-client-secret"
},
"disabled": false,
"timeout": 30000
}
}
}
```
## CLI Commands
```bash
# Server management
mcpman init # Initialize configuration
mcpman add <name> # Add new server
mcpman list # List configured servers
mcpman validate # Validate configuration
mcpman test # Test server connections
# Execution
mcpman code "description" [--roots /path] # Generate and execute code from natural language
mcpman eval "function-expr" [--arg '{}'] [--roots /path] # Execute function expression with MCP tools
mcpman serve # Run as MCP server
# Authentication
mcpman auth <server-name> # Authenticate with OAuth server
```
## JavaScript Execution Environment
> **Inspired by [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/)** - Instead of directly calling MCP tools, LLMs write code that interacts with a JavaScript API. This approach leverages LLMs' strength in writing code and enables more sophisticated tool chaining and composition.
In the eval environment, each configured server is available as a global object. All code must be provided as function expressions:
```javascript
// No argument function - list servers
() => listServers()
// Function with argument - list files
(arg) => filesystem.listFiles({ path: arg.directory })
// Complex function with multiple operations
(arg) => {
console.log("Processing directory:", arg.path);
const files = filesystem.listFiles({ path: arg.path });
return files.filter(f => f.name.endsWith('.js'));
}
// Async function with multiple server calls
async (arg) => {
const servers = listServers();
console.log("Available servers:", servers);
const result = await someServer.someTool({ param: arg.value });
return result;
}
// Access previous results via $results array
() => {
console.log("Previous result:", $results[0]);
return $results[0];
}
```
### $results Array
When using the `eval` or `invoke` tools as an MCP client, results are automatically stored in the `$results` array. Each tool invocation appends its result to this array, and you can access previous results by index:
```javascript
// After calling invoke or eval, results are stored
$results[0] // First result
$results[1] // Second result
```
## Batch Tool Invocation
The `invoke` tool allows you to call multiple MCP tools in batch mode:
```javascript
// Sequential execution (stops on first error)
{
calls: [
{ server: "filesystem", tool: "read_file", parameters: { path: "package.json" } },
{ server: "filesystem", tool: "read_file", parameters: { path: "README.md" } }
],
parallel: false
}
// Parallel execution (all tools execute concurrently)
{
calls: [
{ server: "filesystem", tool: "list_directory", parameters: { path: "." } },
{ server: "git", tool: "status", parameters: {} }
],
parallel: true
}
```
## Logging
When running in server mode, MCPMan redirects console output to log files:
- **Main log**: `~/.mcpman/mcpman.log` - All console.log/error/warn/info output
- **Trace log**: `~/.mcpman/trace.log` - Detailed trace logging (requires `MCPMAN_TRACE=1`)
Logs use synchronous writes to ensure all messages are captured, even during crashes. Error objects are formatted with full stack traces and causes.
```bash
# Enable trace logging
MCPMAN_TRACE=1 mcpman serve
# View logs
tail -f ~/.mcpman/mcpman.log
tail -f ~/.mcpman/trace.log
```
## Development
### Setup
```bash
bun install
pre-commit install # Install git hooks
```
### Available Scripts
```bash
bun dev # Development server with hot reload
bun run build # Build compiled binary
bun run lint # Lint code
bun run format # Format code
bun run typecheck # Type check
bun test # Run tests
```
### Code Style
- TypeScript with strict type checking
- Biome for linting and formatting (100 char line width, 2-space indents)
- Zod schemas for configuration validation
- Pre-commit hooks ensure code quality
## MCP Protocol Support
MCPMan fully supports the MCP protocol including:
- Tool discovery and execution
- Root directory management (transparent proxy)
- Request/response handling
- Error propagation
- OAuth 2.1 authentication for HTTP transports
## License
MIT