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:

  1. --config <path> flag (explicit)
  2. MCPORTER_CONFIG environment variable
  3. <project>/config/mcporter.json (project)
  4. ~/.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 (takeSnapshottake_snapshot)
  • Positional arguments: Map to schema-required fields automatically
  • JSON-schema defaults: Respected without explicit declaration
  • Result wrapper: CallResult provides 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,c or --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 linting
  • pnpm build - TypeScript compilation to dist/
  • pnpm test - Vitest unit/integration tests with HTTP fixtures
  • GitHub Actions CI runs identically to local testing

Comparison to Alternatives

AspectMCPorterDirect MCP SDKShell Scripts
DiscoveryAutoManualManual
Call syntaxMultipleProgrammaticNone
CLI generationBuilt-inNot providedManual
TypeScript supportFirst-classNativeNone
ConfigurationMergedPer-appPer-script
Context managementPooledManualNot applicable
Token cachingAutomaticManualManual

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.md as evolving instructions for AI agents

Resources