Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,33 @@ mcpx posthog.projects-get '{}'
mcpx sentry.whoami '{}'
```

For complex payloads, use stdin to keep the input readable:
For complex payloads, put the whole object on stdin as YAML — block scalars need
no escaping:

```bash
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"
mcpx cf-graphql.graphql_query - <<'EOF'
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 }
}
} }
}
}
JSON
operationName: GetWorkerAnalytics
variables:
accountTag: abc123def456
scriptName: my-worker
since: "2026-04-20T00:00:00Z"
until: "2026-04-27T00:00:00Z"
EOF
```

The command accepts exactly one input object. Pass it inline, as `@file`, or
through `-` stdin.
The command accepts exactly one input object: inline JSON5, or the whole object
from `@file` / `-` stdin as YAML (JSON5 when it starts with `{`). Field values
are literal; there is no per-field `-` / `@path`.

## Discover Schemas

Expand Down
6 changes: 4 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mcpx",
"version": "0.16.1",
"version": "0.17.0",
"license": "MIT",
"bin": {
"mcpx": "./src/main.ts"
Expand All @@ -16,7 +16,7 @@
"test": "bun test"
},
"dependencies": {
"@celados/argc": "^9.0.0",
"@celados/argc": "^10.2.0",
"@clack/prompts": "^1.2.0",
"@modelcontextprotocol/client": "^2.4.0",
"@valibot/to-json-schema": "^1.6.0",
Expand Down
24 changes: 15 additions & 9 deletions src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ or another server registered in the user's global mcpx registry.
- Run `mcpx` directly.
- Start with the server inventory instead of dumping every registered schema.
- Call MCP tools as `mcpx <server>.<tool> "<object>"`.
- Pass one quoted object token, `@file`, or stdin as the complete tool input.
- Pass one quoted object token, or the whole object as YAML/JSON5 via `@file` / stdin (`-`), as the complete tool input.
- Use focused schema selectors before calling tools on large MCP surfaces.
- Do not hand-edit `~/.agents/mcpx/servers.json` or token cache files unless the user explicitly asks for registry surgery.
- Treat MCP server registration and OAuth setup as human-owned configuration. If a required server is missing or unauthenticated, stop and ask the user to configure it.
Expand Down Expand Up @@ -50,18 +50,24 @@ mcpx posthog.projects-get '{}'
mcpx sentry.search-issues '{"query":"is:unresolved"}'
```

For non-trivial payloads, prefer `@file` or heredoc input:
For non-trivial payloads, put the whole input object in a quoted heredoc (or an
`@file`) as YAML — nothing to escape, multi-line text goes in `|` block scalars:

```bash
mcpx <server>.<tool> @payload.json

mcpx <server>.<tool> - <<'JSON'
{
"query": "is:unresolved"
}
JSON
mcpx <server>.<tool> - <<'EOF'
query: is:unresolved
note: |
multi-line text
stays verbatim
EOF

mcpx <server>.<tool> @payload.yaml
```

Field values are always literal: never pass `-` or `@path` as a field value, and
never mix the object with `--flag`s. Quote scalars YAML would type (`'1.10'`,
`'012'`, `'true'`). A file or stdin starting with `{` is read as JSON5 instead.

Default output is optimized for agents (YAML for structured content,
direct text passthrough, media saved as `file saved <path>`). Pass
`--context "{ output: 'raw' }"` when exact server output is required. Raw output
Expand Down
3 changes: 1 addition & 2 deletions src/json-schema-standard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ export function jsonSchemaToStandardSchema(
},
jsonSchema: {
input: () => inputSchema,
// argc derives CLI parameter help from output schemas; MCP tool ingress
// and handler-facing input are the same contract here.
// MCP tool ingress and handler-facing input are the same contract here.
output: () => inputSchema,
},
},
Expand Down
15 changes: 8 additions & 7 deletions src/skill-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,17 @@ Call MCP tools through dotted command paths and pass one object input token.
mcpx <server>.<tool> '{ }'
\`\`\`

For larger payloads, prefer file or heredoc input:
For larger payloads, put the whole object in a quoted heredoc or file as YAML
(multi-line text as \`|\` block scalars; field values are always literal):

\`\`\`bash
mcpx <server>.<tool> @payload.json
mcpx <server>.<tool> - <<'EOF'
example: true
text: |
multi-line text
EOF

mcpx <server>.<tool> - <<'JSON'
{
"example": true
}
JSON
mcpx <server>.<tool> @payload.yaml
\`\`\`

## Notifications
Expand Down
4 changes: 2 additions & 2 deletions tests/skill-template.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ describe('mcpx skill template', () => {
`mcpx @schema '.posthog.{"projects-get","alerts-list","alert-create"}'`,
)
expect(content).toContain("mcpx <server>.<tool> '{ }'")
expect(content).toContain('mcpx <server>.<tool> @payload.json')
expect(content).toContain("mcpx <server>.<tool> - <<'JSON'")
expect(content).toContain('mcpx <server>.<tool> @payload.yaml')
expect(content).toContain("mcpx <server>.<tool> - <<'EOF'")
expect(content).toContain('## Troubleshooting')
expect(content).toContain('references/install.md')
expect(content).toContain('references/servers.md')
Expand Down
Loading