MCPorter
MCPorter is a TypeScript runtime, CLI, and code-generation toolkit for the Model Context Protocol (MCP) that discovers configured MCP servers, calls them directly with friendly syntax, composes automations in TypeScript, and generates standalone CLIs—all without boilerplate or schema spelunking.
Core Philosophy
MCPorter implements Anthropic’s “code execution” workflow: call MCP servers directly from TypeScript rather than embedding MCPs in agent context, keeping context clean and lean. Built by Peter Steinberger (@steipete) to enable practical, no-friction MCP integration.
Three Core Capabilities
1. Discovery and Configuration
Auto-discovers MCP servers already configured in:
- Cursor, Claude Code, Claude Desktop
- Codex, Windsurf, VS Code
- Local
config/mcporter.json(project-level) ~/.mcporter/mcporter.json(system-level)
Merges all sources automatically with configuration precedence:
--config <path>flag (explicit)MCPORTER_CONFIGenvironment variable<project>/config/mcporter.json(project)~/.mcporter/mcporter.json(system)
Pools connections for efficient reuse across multiple tool calls.
Handles configuration:
- Variable interpolation:
${VAR},${VAR:-default},$env:VAR - OAuth token caching under
~/.mcporter/<server>/ - Per-server logging configuration
2. Calling MCP Tools - Multiple Syntaxes
Function-call syntax (most elegant and readable):
mcporter call 'linear.create_issue(title: "Bug", team: "ENG")'
mcporter call 'context7.resolve-library-id("react")' Flag-style syntax (traditional CLI):
mcporter linear.create_issue title=value team=value
mcporter linear.create_issue title:value team:value
mcporter linear.create_issue title: value team: value All three syntaxes normalize automatically; CLI supports:
- Positional arguments mapping to required fields
- Named parameters with -:` separator
- JSON objects and arrays in nested structures
Auto-correction: Typos like sshadcn auto-correct to shadcn with dimmed notice; ambiguous names surface “Did you mean?” hints.
Ad-hoc targets (no config needed):
mcporter --stdio "command"
mcporter --http-url "http://endpoint"
mcporter --stdio "…" --http-url "…" 3. TypeScript Runtime for Agents and Scripts
import { createRuntime } from 'mcporter';
const runtime = await createRuntime();
const result = await runtime.callTool('server_name', 'tool_name', {
param: 'value'
});
// Multiple result formats
await result.text() // Plain text
await result.markdown() // Markdown formatted
await result.json() // Parsed JSON object
result.raw // Full MCP envelope Smart type handling:
- Property names: camelCase ↔ kebab-case automatic mapping (
takeSnapshot→take_snapshot) - Positional arguments: Map to schema-required fields automatically
- JSON-schema defaults: Respected without explicit declaration
- Result wrapper:
CallResultprovides flexible consumption
Code Generation: Create Standalone CLIs
Transform any MCP server into a distributable command-line tool:
mcporter generate-cli linear --bundle dist/linear.js
mcporter generate-cli 'shadcn.io/api/mcp.getComponents' --output shadcn-cli Options:
--name <name>- Override inferred CLI name--description "..."- Custom help text (queries server if omitted)--runtime bun|node- Choose runtime (default: inferred)--compile- Emit Bun-compiled binary--bundle [path]- Emit bundle alongside template--bundler rolldown|bun- Override bundler choice--include-tools a,b,cor--exclude-tools x,y,z- Tool subset--from <artifact> --dry-run- Regenerate from existing CLI
Generated CLIs:
- Inherit MCPorter’s color-aware help layout
- Show embedded tool list + quick-start when invoked with no arguments
- Bold titles + dimmed descriptions on TTYs (smart formatting)
- Full help pages for each tool
- Compact output on pipes/non-TTY environments
Configuration Management Commands
Interactive configuration:
mcporter config list # Show local entries; summarize imports
mcporter config list --source import # Inspect imported entries from editors
mcporter config list --json # Scripting-friendly JSON output
mcporter config get <server> # Fuzzy match with auto-correction
mcporter config add <url> # Add new MCP server
mcporter config add <name> <url> <cmd> # Explicit name + command
mcporter config remove <server> # Remove entry
mcporter config logout <server> # Clear cached OAuth tokens
mcporter config import cursor --copy # Copy Cursor MCPs to local config
mcporter config import claude --copy # Copy Claude MCPs to local config All subcommands honor:
--config <path>- Use specific config file--root <dir>- Set project root for config lookup- TTY-aware output formatting
Daemon Mode (Advanced)
Keep MCP servers warm in background with persistent connections:
mcporter daemon start # Start daemon
mcporter daemon start --log # Start with stdout/stderr logging
mcporter daemon start --log-file /tmp/daemon.log # Log to file
mcporter daemon start --log-servers chrome-devtools # Single server only Per-server daemon logging in config:
{
"servers": {
"myserver": {
"logging": { "daemon": { "enabled": true } }
}
}
} Ad-hoc STDIO/HTTP targets persist when added to config/mcporter.json or via --persist flag.
Installation Options
Instant execution (no install needed):
npx mcporter list
npx mcporter call 'server.tool(arg: "value")' Project integration:
pnpm add mcporter
npm install mcporter System-wide (Homebrew):
brew tap steipete/tap
brew install steipete/tap/mcporter Set system default config:
export MCPORTER_CONFIG=~/.mcporter/mcporter.json Configuration Schema
Location: ~/.mcporter/mcporter.json or config/mcporter.json
Format (mirrors Cursor/Claude shape):
{
"servers": {
"linear": {
"command": "node",
"args": ["linear-mcp/dist/index.js"],
"env": { "LINEAR_API_KEY": "${LINEAR_KEY}" },
"logging": { "daemon": { "enabled": true } }
},
"shadcn": {
"url": "http://localhost:3000/api/mcp"
}
}
} MCPorter handles:
- Environment variable expansion with fallback syntax
- OAuth token storage (transparent caching)
- Connection pooling across calls
- Per-server configuration overrides
Key Strengths
Zero boilerplate: Auto-discovers configs; no manual schema management
Property mapping: camelCase ↔ kebab-case conversion automatic
Smart typing: TypeScript integration with strong types without manual plumbing
Terminal-aware: Detects TTY for intelligent color/formatting (bold on terminals, plain on pipes)
Friendly errors: Schema validation errors, typo auto-correction, “Did you mean?” hints
Multiple transports: Supports STDIO, HTTP, WebSocket to MCP servers
Streaming support: Full streaming results for long-running operations
Flexible results: CallResult wrapper supports .text(), .markdown(), .json(), .raw access patterns
Use Cases
Direct MCP calling from CLI:
- Quick tool invocations without context switching
- Ad-hoc testing of MCP servers
- Integration into shell scripts and automation
Agent/Script integration:
- TypeScript code that calls MCP tools with full typing
- Custom automations composing multiple MCP calls
- Clean context management for AI agents
Tool distribution:
- Convert internal MCPs into standalone CLIs
- Share tools with teams without MCP infrastructure
- Single-purpose command-line tools from complex servers
Code generation:
- Generate TypeScript interfaces (
.d.ts) from MCP servers - Create ready-to-run client wrappers
- Emit Bun-compiled binaries for distribution
Developer Experience
- Low learning curve: Simple record-and-call workflow
- Immediate feedback: TTY-aware output, clear error messages
- Discoverability:
mcporter list <server>shows signatures and sample invocations - Fuzzy matching: Typos forgiven with auto-correct
- IDE-friendly: Generated TypeScript interfaces enable editor autocomplete
Architecture
- Language: TypeScript/Node.js
- Transports: STDIO (subprocess), HTTP, WebSocket
- Configuration: JSON with environment variable interpolation
- Caching: OAuth tokens and connection pooling
- Dependencies: Minimal (biome, oxlint, vitest for tooling)
Testing and CI
pnpm check- Biome formatting + Oxlint/tsgolint lintingpnpm build- TypeScript compilation todist/pnpm test- Vitest unit/integration tests with HTTP fixtures- GitHub Actions CI runs identically to local testing
Comparison to Alternatives
| Aspect | MCPorter | Direct MCP SDK | Shell Scripts |
|---|---|---|---|
| Discovery | Auto | Manual | Manual |
| Call syntax | Multiple | Programmatic | None |
| CLI generation | Built-in | Not provided | Manual |
| TypeScript support | First-class | Native | None |
| Configuration | Merged | Per-app | Per-script |
| Context management | Pooled | Manual | Not applicable |
| Token caching | Automatic | Manual | Manual |
Creator and Philosophy
Created by Peter Steinberger (@steipete), who emphasizes:
- Clean context management - Use MCPs without bloating agent context
- Practical defaults - Auto-discovery and zero-config approach
- Code execution paradigm - Call MCPs as tools, not as context providers
- Living documentation -
CLAUDE.mdas evolving instructions for AI agents
Related Technologies
- Model Context Protocol - MCP specification and ecosystem
- Claude Code - IDE integration using MCPs
- Cursor - MCP-aware code editor
- Anthropic - Creator of MCP standard
Resources
- GitHub: https://github.com/steipete/mcporter
- NPM: https://www.npmjs.com/package/mcporter
- Documentation: docs/ folder in repository
- CLI reference:
docs/cli-reference.md - Configuration guide:
docs/config.md - Tool calling:
docs/tool-calling.md