Token-efficient MCP client: TypeScript schemas instead of JSON, LLM-friendly syntax, batch calls, TOON output. Built for Claude/GPT automations.
git clone https://github.com/AIGC-Hackers/mcpx ~/.claude/skills/mcpx# MCPX 🧳
_Token-efficient MCP client built for LLMs and humans._
**Why MCPX?** Other MCP clients dump giant JSON schemas that waste tokens and confuse humans. MCPX returns **TypeScript signatures** instead—Claude and developers instantly understand tool signatures. Call tools with **LLM-native syntax** (`server.func({ args })`), run **batch operations** via stdin, and get **TOON output** (90% fewer tokens than JSON).
MCPX helps you lean into the "code execution" workflows highlighted in Anthropic's **Code Execution with MCP** guidance: discover the MCP servers already configured on your system, call them directly, and compose richer automations in TypeScript. All of that works out of the box -- no boilerplate, no schema spelunking.
## Installation
### Homebrew
```bash
# Add the tap
brew tap AIGC-Hackers/mcpx
# Install mcpx
brew install mcpx
# Or install in one command
brew install AIGC-Hackers/mcpx/mcpx
```
### Run without installing
```bash
bunx mcpx list
```
### Alternate tap (steipete)
```bash
brew tap steipete/tap
brew install steipete/tap/mcpx
```
> The steipete tap publishes alongside MCPX 0.3.2. Run `brew update` before reinstalling if you see an older build.
## MCPX vs Other MCP Clients
| Feature | MCPX | Typical MCP Client |
|---------|------|-------------------|
| **Schema output** | TypeScript (readable, token-efficient) | JSON Schema (verbose, token-heavy) |
| **Call syntax** | `linear.createIssue({ title: "Bug" })` | Manual JSON construction |
| **Batch calls** | ✅ Multi-line, stdin, comments | ❌ One call at a time |
| **Output format** | TOON (90% fewer tokens) | Raw JSON |
| **OAuth flow** | ✅ Auto-triggered, bug-free | Manual or buggy |
| **LLM-ready** | ✅ Designed for Claude/GPT workflows | ⚠️ Requires token budget |
## Key Capabilities
- **Zero-config discovery.** `createRuntime()` merges `./mcp.json` with `~/.mcpx/mcp.json`, expands `${ENV}` placeholders, and pools connections so you can reuse transports across multiple calls. First run migrates Cursor/Claude/Codex/Windsurf/VS Code configs into `~/.mcpx/mcp.json` automatically.
- **Flexible data formats.** Call tools with function syntax or structured JSON/JSON5/YAML/TOML data. Output defaults to TOON (LLM-friendly), with `--output` flags for raw/JSON/text formats.
- **Friendly composable API.** `createServerProxy()` exposes tools as ergonomic camelCase methods, automatically applies JSON-schema defaults, validates required arguments, and hands back a `CallResult` with `.text()`, `.json()`, and `.content()` helpers.
- **OAuth and stdio ergonomics.** Built-in OAuth caching, log tailing, and stdio wrappers let you work with HTTP, SSE, and stdio transports from the same interface.
- **Ad-hoc connections.** Point the CLI at *any* MCP endpoint (HTTP or stdio) without touching config, then persist it later if you want. Hosted MCPs that expect a browser login (Supabase, Vercel, etc.) are auto-detected and OAuth is triggered automatically when needed. See [docs/adhoc.md](docs/adhoc.md).
## Quick Start
MCPX auto-discovers the MCP servers you already configured in Cursor, Claude Code/Desktop, Codex, or local overrides. Install via Homebrew or run instantly with `bunx mcpx`. Need a full command reference (flags, modes, return types)? Check out [docs/cli-reference.md](docs/cli-reference.md).
### Call MCP tools
```bash
# Function syntax - natural for agents and interactive use
mcpx call 'linear.create_comment({ issueId: "ENG-123", body: "Great!" })'
# Data format - explicit and structured (JSON5/YAML/TOML also supported)
mcpx call '{ tool: "linear.create_comment", args: { issueId: "ENG-123", body: "Great!" } }'
```
### List your MCP servers
```bash
mcpx list
mcpx list context7
mcpx list https://mcp.linear.app/mcp --all-parameters
mcpx list shadcn.io/api/mcp.getComponents # URL + tool suffix auto-resolves
mcpx list --stdio "bun run ./local-server.ts" --env TOKEN=xyz
```
- Add `--output json` to emit a machine-readable summary with per-server statuses (auth/offline/http/error counts) and, for single-server runs, the full tool schema payload.
You can now point `mcpx list` at ad-hoc servers: provide a URL directly or use the new `--http-url/--stdio` flags (plus `--env`, `--cwd`, `--name`, or `--persist`) to describe any MCP endpoint. Until you persist that definition, you still need to repeat the same URL/stdio flags for `mcpx call`—the printed slug only becomes reusable once you merge it into a config via `--persist` or `mcpx config add`. OAuth is triggered automatically when servers require authentication. Full details live in [docs/adhoc.md](docs/adhoc.md).
Single-server listings now show TypeScript Spec format so you can copy/paste the signature straight into `mcpx call`:
```ts
linear - Hosted Linear MCP
23 tools · 1654ms · HTTP https://mcp.linear.app/mcp
/**
* Create a comment on a specific Linear issue
*/
type CreateCommentSpec = {
tool: 'create_comment'
args: {
issueId: string
body: string
parentId?: string
notifySubscribers?: boolean
labelIds?: string[]
mentionIds?: string[]
}
}
/**
* List documents in the user's Linear workspace
*/
type ListDocumentsSpec = {
tool: 'list_documents'
args: {
query?: string
limit?: number
before?: string
after?: string
orderBy?: 'createdAt' | 'updatedAt'
projectId?: string
initiativeId?: string
creatorId?: string
includeArchived?: boolean
}
}
```
Here's what that looks like for Vercel when you run `mcpx list vercel`:
```ts
vercel - Vercel MCP (requires OAuth)
/**
* Search the Vercel documentation.
* Use this tool to answer any questions about Vercel's platform, features, and best practices.
*/
type SearchVercelDocumentationSpec = {
tool: 'search_vercel_documentation'
args: {
topic: string
tokens?: number
}
}
/**
* Deploy the current project to Vercel
*/
type DeployToVercelSpec = {
tool: 'deploy_to_vercel'
args: Record<string, unknown>
}
```
### Context7: fetch docs (no auth required)
```bash
mcpx call 'context7.resolve-library-id({ libraryName: "react" })'
mcpx call 'context7.get-library-docs({ path: "/websites/react_dev", topic: "hooks" })'
```
### Linear: search documentation (requires `LINEAR_API_KEY`)
```bash
LINEAR_API_KEY=sk_linear_example mcpx call 'linear.search_documentation({ query: "automations" })'
```
### Chrome DevTools: snapshot the current tab
```bash
mcpx call 'chrome-devtools.take_snapshot()'
mcpx call 'linear.create_comment({ issueId: "LNR-123", body: "Hello world" })'
```
> **Call Syntax:** Function syntax `server.tool({ args })` or data format `{ tool: "server.tool", args: {...} }`. Both are parsed (not executed as JS). Supports JSON5/YAML/TOML.
Helpful flags:
- `--config <path>` -- custom config file (overrides the default `./mcp.json` + `~/.mcpx/mcp.json` merge).
- `--root <path>` -- working directory for stdio commands.
- `--log-level <debug|info|warn|error>` -- adjust verbosity (respects `MCPX_LOG_LEVEL`).
- `--oauth-timeout <ms>` -- shorten/extend the OAuth browser wait; same as `MCPX_OAUTH_TIMEOUT_MS` / `MCPX_OAUTH_TIMEOUT`.
- `--tail-log` -- stream the last 20 lines of any log files referenced by the tool response.
- `--output <format>` -- control output format: `toon` (default, LLM-friendly), `json`, `text`, or `raw`.
- `--http-url <https://…>` / `--stdio "command …"` -- describe an ad-hoc MCP server inline (pair with `--env KEY=value`, `--cwd`, `--name`, and `--persist <config.json>` as needed).
- OAuth-protected servers trigger authentication automatically on first use.
> Tip: You can skip the verb entirely—`mcpx firecrawl` automatically runs `mcpx list firecrawl`, and dotted tokens like `mcpx linear.list_issues` dispatch to the call command (typo fixes included).
Timeouts default to 30 s; override with `MCPX_LIST_TIMEOUT` or `MCPX_CALL_TIMEOUT` when you expect slow startups. OAuth browser handshakes get a separate 60 s grace period; pass `--oauth-timeout <ms>` (or export `MCPX_OAUTH_TIMEOUT_MS`) when you need the CLI to bail out faster while you diagnose stubborn auth flows.
### Try an MCP without editing config
```bash
# Point at an HTTPS MCP server directly
mcpx list --http-url https://mcp.linear.app/mcp --name linear
# Run a local stdio MCP server via Bun
mcpx call --stdio "bun run ./local-server.ts" --name local-tools
```
- Add `--persist ~/.mcpx/mcp.json` (or any path) to save the inferred definition for future runs.
- Use `--allow-http` if you truly need to hit a cleartext endpoint.
- See [docs/adhoc.md](docs/adhoc.md) for a deep dive (env overrides, cwd, OAuth).
## Call Syntax
Two formats, both parsed (not executed as JavaScript):
**Function syntax** (natural for agents):
```bash
mcpx call 'linear.create_issue({ title: "Bug", priority: 2, labels: ["urgent"] })'
```
**Data format** (explicit, supports JSON5/YAML/TOML):
```bash
mcpx call '{ tool: "linear.create_issue", args: { title: "Bug", priority: 2 } }'
```
**Features:**
- **Auto-correct.** Typo `listIssue`? MCPX suggests `list_issues` automatically.
- **Type specs.** `mcpx list <server>` prints TypeScript specs—copy/paste directly into calls.
## Batch Calling
Execute multiple MCP tool calls in one shot from stdin or a file. Perfect for LLM-driven workflows, automation scripts, and data migrations.
```bash
# From file
cat batch-calls.txt | mcpx call
# From heredoc (function syntax)
mcpx call << 'EOF'
linear.list_issues({ limit: 5 })
github.search_repos({ query: "mcp" })
EOF
# Data format also works
mcpx call << 'EOF'
[
{ tool: "linear.list_issues", args: { limit: 5 } },
{ tool: "github.search_repos", args: { query: "mcp" } }
]
EOF
```
**Input format** supports function syntax and structured data:
```javascript
// Function syntax (one per line, natural for agents)
linear.create_issue({ title: "Fix bug", priority: 2, labels: ["bug", "urgent"] })
github.search_repos({ query: "mcp" })
// Data format (explicit structure)
[
{ tool: "linear.create_issue", args: { title: "Fix bug", priority: 2, labels: ["bug", "urgent"] } },
{ tool: "github.search_repos", args: { query: "mcp" } }
]
```
**Output** is in **TOON format** (compact, LLM-friendly):
```toon
[2]:
- tool: linear.create_issue
output:
id: ISS-123
title: Fix bug
- tool: github.search_repos
output:
items[1]{name,stars}: repo1,42
```
Override with `--output json` for standard JSON:
```json5
[
{ tool: 'linear.create_issue', output: { id: 'ISS-123', title: 'Fix bug' } },
{ tool: 'github.search_repos', output: { items: [...] } },
]
```
**Error handling**: If any call fails, the error is captured in the output and the exit code is `1`:
```json5
{
tool: 'linear.bad_tool',
output: "Parameter validation failed:\n- Field 'id': Required (expected string, got undefined)",
}
```
Use cases:
- **LLM tool calling**: Generate batch files and pipe to mcpx
- **Automation scripts**: Daily standups, status reports
- **Data migration**: Export from one system, import to another
See [examples/README.md](examples/README.md) and [examples/batch-calls.txt](examples/batch-calls.txt) for complete examples.
Need runtime or automation samples? Head to [docs/tool-calling.md](docs/tool-calling.md) and [docs/cli-reference.md](docs/cli-reference.md). Call `mcpx list <server>` any time you need the TypeScript-style signature, optional parameter hints, and sample invocations that match the CLI's function-call syntax.
## Configuration Reference
`mcp.json` (project) and `~/.mcpx/mcp.json` (user) share the Cursor/Claude schema:
```json5
{
mcpServers: {
context7: {
description: 'Context7 docs MCP',
baseUrl: 'https://mcp.context7.com/mcp',
headers: {
Authorization: '$env:CONTEXT7_API_KEY',
},
},
'chrome-devtools': {
command: 'bunx',
args: ['chrome-devtools-mcp@latest'],
},
},
}
```
What MCPX handles for you:
- `${VAR}`, `${VAR:-fallback}`, and `$env:VAR` interpolation for headers and env entries across both files. Entries defined in `./mcp.json` override duplicates from `~/.mcpx/mcp.json`.
- Automatic OAuth token caching under `~/.mcpx/<server>/` unless you override `tokenCacheDir`.
- Stdio commands inherit the directory of the file that defined them (imports or local config).
- First run populates `~/.mcpx/mcp.json` by migrating Cursor/Claude/Codex/Windsurf/VS Code configs; legacy `imports` arrays are only read during that migration helper.
Provide `configPath` or `rootDir` to CLI/runtime calls when you juggle multiple config files side by side.
## Debug Hanging Servers Quickly
Use `tmux` to keep long-running CLI sessions visible while you investigate lingering MCP transports:
```bash
tmux new-session -- bun run mcpx:list
```
Let it run in the background, then inspect the pane (`tmux capture-pane -pt <session>`), tail stdio logs, or kill the session once the command exits. Pair this with `MCPX_DEBUG_HANG=1` when you need verbose handle diagnostics. More detail: [docs/tmux.md](docs/tmux.md) and [docs/hang-debug.md](docs/hang-debug.md).
## Credits
MCPX was inspired by [mcporter](https://github.com/steipete/mcporter) but rebuilt from scratch with token-efficiency and LLM workflows as first-class design goals.
## License
MIT -- see [LICENSE](LICENSE).
Further reading: [docs/tool-calling.md](docs/tool-calling.md), [docs/adhoc.md](docs/adhoc.md), [docs/tmux.md](docs/tmux.md).