MCP服务器命令行工具

mcpx 是一款将注册的 MCP 服务器转换为智能体友好命令面的命令行工具,支持工具模式发现、OAuth 认证以及通过结构化输入调用工具,适用于 AI 代理使用 MCP 服务。

  • by celados
  • TypeScript
  • 本地部署
  • 18 星标
  • 更新于
在 GitHub 查看 AIGC-Hackers/mcpx

使用说明

mcpx

mcpx is a command line tool that turns registered MCP servers into an agent-friendly command surface.

It keeps MCP server registrations in a global user registry, discovers tool schemas, handles OAuth where possible, and exposes each MCP server as a root command:

mcpx posthog.projects-get
mcpx sentry.search-issues '{"query":"is:unresolved"}'

mcpx is designed for agents. The command surface is intentionally schema-first, stable, and explicit: commands use dotted paths and receive one structured input token, while mcpx's own control commands live under the @ namespace.

Requirements

  • Bun
  • macOS, Linux, or any environment that can run Bun executables

Install

Install the latest release:

curl -fsSL https://raw.githubusercontent.com/celados/mcpx/main/install.sh | bash

By default, the installer downloads the executable JS bundle from GitHub Releases and installs it to ~/.local/bin/mcpx.

Set MCPX_INSTALL_DIR to choose another install directory.

Add MCP Servers

Register MCP servers globally:

mcpx @add "{ name: 'posthog', url: 'https://mcp.posthog.com/mcp' }"
mcpx @add "{ name: 'sentry', url: 'https://mcp.sentry.dev/mcp' }"
mcpx @add "{ name: 'cf-docs', url: 'https://docs.mcp.cloudflare.com/mcp' }"
mcpx @add "{ name: 'cf-bindings', url: 'https://bindings.mcp.cloudflare.com/mcp' }"
mcpx @add "{ name: 'cf-observability', url: 'https://observability.mcp.cloudflare.com/mcp' }"
mcpx @add "{ name: 'browser', url: 'http://127.0.0.1:9000/mcp' }"

browser-os is an agent-native browser built on Chrome. It exposes a local MCP server that lets agents control the browser directly — navigating pages, extracting content, and interacting with web UIs.

mcpx keeps its state under ~/.agents/mcpx/state-v2/: server declarations in registry.json, credentials (OAuth grants, bearer values, secret headers) in credentials.json, and observed tool schemas in schema-cache.json. The MCP Runtime is the only writer.

Project directories do not need MCP config files. A project should decide which global servers are relevant by using schema selectors or a generated skill.

Call Tools

Call tools through the server command:

mcpx <server>.<tool> '<json-or-json5>'

Examples:

mcpx posthog.projects-get '{}'
mcpx sentry.whoami '{}'

For complex payloads, use stdin to keep the input readable:

mcpx cf-graphql.graphql_query - <<'JSON'
{
  "query": "query GetWorkerAnalytics($accountTag: String!, $scriptName: String!, $since: Time!, $until: Time!) { viewer { accounts(filter: {accountTag: $accountTag}) { workersInvocationsAdaptive(limit: 1000, filter: {scriptName: $scriptName, datetime_geq: $since, datetime_leq: $until}, orderBy: [datetimeHour_ASC]) { dimensions { datetimeHour scriptName status } sum { requests subrequests errors duration } quantiles { cpuTimeP50 cpuTimeP99 } } } } }",
  "operationName": "GetWorkerAnalytics",
  "variables": {
    "accountTag": "abc123def456",
    "scriptName": "my-worker",
    "since": "2026-04-20T00:00:00Z",
    "until": "2026-04-27T00:00:00Z"
  }
}
JSON

The command accepts exactly one input object. Pass it inline, as @file, or through - stdin.

Discover Schemas

Print the command schema for agents:

mcpx @schema

Focus on one server:

mcpx @schema .posthog

Focus on a set of servers:

mcpx @schema '.{posthog,sentry}'

Focus on an internal mcpx command:

mcpx @schema '.["@add"]'

mcpx caches discovered tool schemas in the global registry. Cached schemas older than one day are refreshed opportunistically in a single background worker when mcpx starts, so normal commands do not block on schema discovery. Servers that have not discovered any tools yet are still retried synchronously during startup.

Control Commands

mcpx control commands use the @ namespace so they do not collide with server names:

mcpx @add "{ name: '<server>', url: '<mcp-url>' }"
mcpx @add "{ name: '<server>', url: '<mcp-url>', bearer: 'env:<TOKEN_ENV>' }"
mcpx @add "{ name: '<server>', transport: 'stdio', command: '<command>', args: ['<arg>'] }"
mcpx @remove "{ name: '<server>' }"
mcpx @refresh
mcpx @daemon.status
mcpx @daemon.stop
mcpx @daemon.server
mcpx @skill
mcpx @skill-install

Server names cannot start with @.

HTTP is the default transport. Pass bearer credentials as a string or array. env:NAME reads a token from an environment variable at runtime; literal values are accepted but are stored in the registry:

mcpx @add "{ name: 'posthog', url: 'https://mcp.posthog.com/mcp', bearer: 'env:POSTHOG_TOKEN' }"
mcpx @add "{ name: 'posthog', url: 'https://mcp.posthog.com/mcp', bearer: ['env:POSTHOG_TOKEN_A', 'env:POSTHOG_TOKEN_B'] }"

Multiple bearer credentials use round-robin selection by default. Stdio servers are local process registrations with structured args and env:

mcpx @add '{
  "name": "open-design",
  "transport": "stdio",
  "command": "node",
  "args": ["/path/to/open-design/apps/daemon/dist/cli.js", "mcp"],
  "env": { "OPEN_DESIGN_TOKEN": "..." }
}'

@refresh checks registered MCP servers concurrently: it makes each server's credentials usable, then refreshes its cached tool schemas. Progress for every server (token refresh, browser authorization URL, tool listing, result) is printed to stderr as it happens; stdout carries only the final report. A failing server is reported by name and does not prevent the others from being checked.

Stdio servers are called through mcpxd, a user-local daemon that reuses stdio MCP sessions across CLI invocations. mcpxd starts on demand, keeps idle stdio servers warm, and can be inspected or stopped with mcpx @daemon.status and mcpx @daemon.stop. The daemon process is started through the explicit mcpx @daemon.server subcommand. HTTP servers continue to use the direct client path.

Authentication

Bearer auth is configured explicitly in the @add input. Prefer env:NAME references so secrets stay out of the registry. ${NAME} is also accepted when passed through the shell literally. When several bearer credentials are registered, mcpx advances a local round-robin cursor before each HTTP request.

OAuth follows the MCP authorization spec through the official MCP SDK. A server does not need to declare OAuth up front: whenever it answers a request with 401 and a WWW-Authenticate: Bearer resource_metadata=… challenge, mcpx discovers its authorization server from that challenge, authorizes, records the server as OAuth, and retries the request. This covers servers whose tools are partly anonymous — @add lists their tools without credentials, and the first call to a protected tool starts sign-in. A 403 insufficient_scope challenge re-authorizes with the additional scope the same way. @add itself never opens a browser; it reports auth-required when listing tools was challenged.

For OAuth servers that support dynamic client registration, mcpx registers a client automatically for each browser sign-in.

For OAuth servers that do not support dynamic client registration, mcpx prompts for a manual client_id and client_secret. These providers usually require a preconfigured redirect URL. mcpx uses:

http://127.0.0.1:65245/callback

Add and save that exact Redirect URL in the provider app settings before continuing the prompt.

OAuth credentials repair themselves during ordinary tool calls:

  • When a token is close to expiry, mcpx refreshes it silently before the call.
  • When the server rejects a token with 401, mcpx refreshes it and retries the call once. Another call that already replaced the token is not undone.
  • When no refresh is possible (no token yet, or the refresh grant was revoked), the call opens browser authorization, prints the authorization URL to stderr, and waits up to 5 minutes for it to complete before continuing. Concurrent calls for the same server share one authorization.

Providers that need a manual OAuth client can only prompt in an interactive terminal; without one, the call fails immediately with reauth-required and mcpx @refresh must be run in a terminal.

Tool calls use a 5 minute request timeout by default. Set MCPX_TOOL_CALL_TIMEOUT_MS when a remote MCP server legitimately needs longer.

mcpx buffers MCP subscription notifications and returns them with the next daemon tool-call result by default. Set MCPX_NOTIFICATION_MODE=discard to ignore those notifications for a command; accepted values are buffer and discard.

Output

mcpx optimizes output for humans and agents by default:

  • text MCP content is printed directly
  • JSON text content is rendered as YAML
  • non-text content is saved to a temporary file and printed as file saved <path>
  • supplemental MCP structuredContent is printed as $structured only when it is not already represented by the primary content

Use argc context to preserve raw server output:

mcpx posthog.projects-get --context "{ output: 'raw' }"

Project Skills

Generate a project-local skill that tells agents which global MCP servers to use:

mcpx @skill-install "{ servers: 'posthog,sentry' }"

This writes:

.agents/skills/mcpx/SKILL.md
.agents/skills/mcpx/references/install.md
.agents/skills/mcpx/references/servers.md

The generated skill instructs agents to discover tools with focused schema selectors and call MCP tools through mcpx. A Troubleshooting section at the bottom points collaborators at install and server-setup references so their agent can recover when mcpx is missing or a listed server is not registered.

For temporary agent guidance without writing .agents/skills, print a one-server skill to stdout:

mcpx @skill-install "{ show: 'sentry' }"

Skill

General mcpx skill definition lives at src/index.md (served by mcpx @skill).

License

MIT