npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mcp-layer/cli

v1.3.2

Published

CLI framework for interacting with MCP servers using discovered schemas.

Readme

@mcp-layer/cli

@mcp-layer/cli is a CLI framework that turns MCP server schemas into a usable command line. It discovers a server from configuration, connects with the transport defined for that server (stdio, Streamable HTTP, or SSE), extracts the unified schema from @mcp-layer/schema, and renders commands for tools, prompts, resources, and templates. You can also extend it with custom commands.

Table of Contents

Install

pnpm add @mcp-layer/cli

Quick start

Run the CLI against a configured MCP server:

mcp-layer servers list
mcp-layer tools list
mcp-layer tools echo --text "hello"

Run the same commands against a remote server by selecting a config entry that uses url/endpoint:

mcp-layer tools list --server remote
mcp-layer tools echo --server remote --text "hello"

Command surface

The CLI exposes the same schema items for tools, prompts, resources, and templates.

mcp-layer servers list
mcp-layer tools list
mcp-layer tools <tool>
mcp-layer prompts list
mcp-layer prompts <prompt>
mcp-layer resources list
mcp-layer resources <uri>
mcp-layer templates list
mcp-layer templates <template>

Shorthand form:

mcp-layer tools:echo --text "hello"
mcp-layer prompts:kickoff --json '{"topic":"launch"}'

Input handling

Inputs come from the MCP schema. You can supply them three ways:

  • --json '{"key":"value"}' for inline JSON
  • --input ./payload.json for JSON files
  • --key value for schema properties (flags are generated from input schema fields)

Array and object inputs support a few additional forms:

  • Arrays can be repeated: --items one --items two
  • Arrays can be JSON: --items '["one","two"]'
  • Objects can use dot notation: --meta.tag alpha
  • Objects can be JSON: --meta '{"tag":"alpha"}'
  • Scalar values are coerced using the schema type (e.g., --count 5, --enabled true).

If a parameter clashes with a CLI flag (like --help), pass tool arguments after --:

mcp-layer tools echo -- --help "not a real help flag"

Output formatting

The CLI formats MCP responses for readability by default:

  • Text content prints as plain text.
  • Markdown content renders as ANSI Markdown when stdout is a TTY (pipes receive plain text).
  • Images and audio show a short hint with MIME type and size.
  • Resource links show name, description, and URI.
  • Unsupported content types render as a labeled JSON fallback.

Use --raw to emit raw MCP payloads (plain text or binary bytes when a single payload is returned). If multiple content items are present, --raw returns JSON. This makes piping to files straightforward:

mcp-layer tools <tool> --raw > output.json
mcp-layer tools <tool> --raw > payload.bin

For single resource payloads, --raw emits the unrendered text content (or binary bytes), which makes it easy to pipe markdown or plain text into a file:

mcp-layer resources resource://manual --raw > manual.md

Disable markdown rendering with --no-markdown.

Server-provided text is sanitized to strip ANSI escape sequences by default. If you trust the server and want to preserve ANSI output, pass --allow-ansi.

Example:

mcp-layer tools <tool> --allow-ansi

Color output

Color output is enabled by default when stdout is a TTY. Disable it with --no-color or by setting NO_COLOR=1. You can customize the colors via accent and subtle in cli() options.

Per-command help

Use --help after a command to see its flags and examples:

mcp-layer tools echo --help
mcp-layer prompts kickoff --help

When a server is selected, help output uses the server name/version and lists all discovered tools, prompts, resources, and templates for that server.

Custom commands registered via cli().command() are included in the main help output and have their own --help rendering.

Example:

import { cli } from '@mcp-layer/cli';

await cli({ name: 'acme-mcp' })
  .command(
    {
      name: 'status',
      description: 'Show CLI status.'
    },
    async function statusCommand(argv) {
      process.stdout.write(JSON.stringify({ ok: true }, null, 2));
    }
  )
  .render();

Output formats

List commands support JSON output:

mcp-layer tools list --format json
mcp-layer resources list --format json

Run/read/render commands render formatted output by default. Use --raw for JSON (or binary bytes when a single binary payload is returned).

Configuration and server selection

@mcp-layer/cli uses @mcp-layer/config to discover MCP server definitions. Transport is selected automatically from the chosen server entry through @mcp-layer/connect.

The MCP spec defines available transports, but config keys are host-tool specific. References:

Selection order below is @mcp-layer/connect behavior:

Automatic selection behavior:

  • command entries connect over stdio.
  • url/endpoint entries connect over Streamable HTTP by default.
  • --transport sse (runtime override) forces legacy SSE for URL-based entries.

Use --transport when you need an explicit runtime override (for example, forcing SSE against a legacy endpoint) without adding non-standard keys to shared config files.

When multiple servers are configured, choose one with --server:

mcp-layer tools list --server demo

Control server listing in help output via showServers:

  • showServers: true always renders the Servers section.
  • showServers: false always hides the Servers section. Default: true.

You can also point at a specific config file or directory:

mcp-layer tools list --config ./mcp.json
mcp-layer tools list --config ~/configs

Embedding and custom commands

You can embed the CLI and add custom commands using the same parser and help renderer.

import { cli } from '@mcp-layer/cli';

/**
 * Render the CLI with a custom command.
 * @returns {Promise<void>}
 */
async function main() {
  await cli({ name: 'acme-mcp', description: 'Acme MCP CLI' })
    .command(
      {
        name: 'status',
        description: 'Report CLI configuration state.'
      },
      async function statusCommand(argv, helpers) {
        const verbose = Boolean(argv.verbose);
        const done = helpers.spinner('Loading status');
        process.stdout.write(JSON.stringify({ ok: true, verbose }, null, 2));
        done();
      }
    )
    .render();
}

main();

API

cli(options)

Creates a CLI instance.

Options:

  • name: CLI name displayed in help output.
  • version: CLI version string.
  • description: CLI description for help output.
  • colors: enable or disable color output.
  • accent: hex color for headings (default #FFA500).
  • subtle: hex color for flag names (default #696969).
  • spinner: enable the loading spinner.
  • markdown: enable markdown rendering for text output.
  • ansi: allow ANSI escape sequences in server-provided text.
  • server: default server name.
  • config: default config path.
  • showServers: show or hide the Servers section in help output.
  • timeout: fail if MCP initialization exceeds the timeout in milliseconds (opt-in only).

cli().command(options, handler)

Registers a custom command.

  • options.name: command name.
  • options.description: summary for help output.
  • handler(argv, helpers): async handler invoked with parsed args.
  • helpers.spinner(text): start a spinner and return a stop() function.

cli().render([argv])

Executes the CLI. If argv is omitted, it uses process.argv.

Global flags

  • --server <name>: select a configured server.
  • --config <path>: point at a config file or directory.
  • --transport <mode>: override transport at runtime (stdio, streamable-http, or sse).
  • --timeout <ms>: fail if MCP initialization exceeds the timeout in milliseconds (opt-in).
  • --format <json>: use JSON for list output.
  • --json <string>: supply inline JSON input.
  • --input <path>: supply JSON input from a file.
  • --raw: emit raw JSON (or binary bytes for a single binary payload).
  • --no-markdown: disable markdown rendering.
  • --allow-ansi: preserve ANSI escape sequences from server text.
  • --no-spinner: disable the loading spinner.
  • --no-color: disable color output.

Development

pnpm test --filter @mcp-layer/cli

Runtime Error Reference

This section is written for high-pressure debugging moments. Each entry maps directly to the CLI's MCP discovery and invocation paths.

Unknown "{targetType}" target "{targetName}".

Thrown from: cli.render

This happens when you run contextual help for a specific target (tools <name> --help, prompts <name> --help, resources <uri> --help, templates <uri> --help) and that target is not in the MCP catalog returned by the selected server.

Step-by-step resolution:

  1. Confirm which server the CLI selected: run mcp-layer servers list or pass --server <name> explicitly.
  2. List the available targets from that exact server: mcp-layer tools list, mcp-layer prompts list, mcp-layer resources list, or mcp-layer templates list.
  3. Compare the failing target value character-for-character with list output (case and punctuation must match).
  4. If the target should exist but does not, check the MCP server implementation for that capability and restart/reload the server.
mcp-layer --server dev tools list
mcp-layer --server dev tools weather.get --help

Unknown command "{command}".

Thrown from: cli.render

This happens when the first positional token does not match any built-in CLI surface (tools, prompts, resources, templates, servers, help) and does not match a registered custom command.

Step-by-step resolution:

  1. Run mcp-layer --help and verify the exact command name and shape.
  2. Check for typos or singular/plural mixups (tool vs tools).
  3. If you expected a custom command, confirm it was registered before calling cli().render(...).
  4. Re-run with the exact command shown by help output.
# Wrong: tool list
mcp-layer tools list

Unknown prompt "{promptName}".

Thrown from: cli.render

This happens on prompts <name> exec when the connected MCP server does not expose a prompt with that name in prompts/list.

Step-by-step resolution:

  1. Run mcp-layer prompts list --server <name> and copy the prompt name directly.
  2. Confirm the same --server and --config values are used between list and exec commands.
  3. Verify the MCP server currently loaded the prompt in its handler registry.
  4. Retry prompts <name> exec with the exact listed name.
mcp-layer --server dev prompts list
mcp-layer --server dev prompts summarize.exec exec --topic "release notes"

Unknown resource "{resourceUri}".

Thrown from: cli.render

This happens on resources <uri> exec when no resource with that URI exists in the connected MCP server's resources/list catalog.

Step-by-step resolution:

  1. Run mcp-layer resources list --server <name> to retrieve valid URIs.
  2. Copy the URI exactly; resource URIs are protocol-level identifiers and are strict.
  3. Ensure you are querying the same MCP server/environment where that URI is expected to exist.
  4. Re-run the read command with the exact URI from list output.
mcp-layer --server dev resources list
mcp-layer --server dev resources mcp://docs/changelog exec

Unknown template "{templateUri}".

Thrown from: cli.render

This happens on templates <uriTemplate> exec when the specified URI template is not present in the server's resources/templates/list response.

Step-by-step resolution:

  1. Run mcp-layer templates list --server <name>.
  2. Copy the URI template exactly from output (including placeholder names).
  3. Confirm the template is registered on the server instance you are connected to.
  4. Retry with the exact listed template and required parameters.
mcp-layer --server dev templates list
mcp-layer --server dev templates mcp://docs/{slug} exec --slug release-2026-02

Unknown tool "{toolName}".

Thrown from: cli.render

This happens on tools <name> exec when the name is missing from the server's tools/list response.

Step-by-step resolution:

  1. Run mcp-layer tools list --server <name>.
  2. Use the exact tool name from list output.
  3. If missing unexpectedly, inspect server startup logs to verify tool registration completed.
  4. Re-run execution with the exact name and required arguments.
mcp-layer --server dev tools list
mcp-layer --server dev tools weather.get exec --city London

Invalid integer for "{parameter}": "{value}".

Thrown from: coercenumber

This happens while validating tool/prompt/template arguments against the MCP JSON Schema. The target field is typed as integer, but the CLI received a non-integer value (for example 3.14, 1e2, or text).

Step-by-step resolution:

  1. Inspect the input schema (detail.input.json) for the failing parameter and confirm it is type: "integer".
  2. Check the CLI value source: direct flag (--count), --json, or --input file.
  3. Pass an integer literal only (no decimals, no unit suffixes).
  4. Add a command-level validation test covering both rejected (3.5) and accepted (3) values.
# Wrong
mcp-layer tools batch.run exec --count 2.5

# Correct
mcp-layer tools batch.run exec --count 2

Invalid number for "{parameter}": "{value}".

Thrown from: coercenumber

This happens while coercing CLI argument values for a schema field typed as number or integer; the received string cannot be parsed to a JavaScript number at all (for example ten, 10ms, or an empty string).

Step-by-step resolution:

  1. Identify where the value came from (--json, --input, or CLI flags).
  2. Ensure the payload value is numeric JSON (42, 3.14) and not decorated text ("42ms").
  3. If using shell flags, quote safely so the shell does not alter the token.
  4. Re-run with a pure numeric value and add a regression test for the bad literal.
# Wrong
mcp-layer tools stats.query exec --threshold ten

# Correct
mcp-layer tools stats.query exec --threshold 10

Required parameter "{parameter}" is missing.

Thrown from: inputs

This happens after the CLI loads an MCP item's input schema and sees that a field listed in required is absent from resolved arguments.

Step-by-step resolution:

  1. Inspect the tool/prompt/template schema and locate required fields.
  2. Provide the missing value using the right input channel:
  3. Use --<name> <value> for simple values.
  4. Use --json '{"name":"value"}' or --input payload.json for structured payloads.
  5. Re-run and verify all required keys are present.
# Tool schema requires "city"
mcp-layer tools weather.get exec --city Paris

Invalid JSON for "{parameter}": {reason}

Thrown from: parsejson

This happens when a schema field is an object or array and the CLI attempts to parse the provided string as JSON, but parsing fails. Typical sources are single quotes, trailing commas, or shell-escaped payload corruption.

Step-by-step resolution:

  1. Identify which argument name the error reports in {parameter}.
  2. Validate the raw JSON snippet with node -e 'JSON.parse(...)' before passing it to CLI.
  3. Prefer --input payload.json for complex nested JSON to avoid shell escaping issues.
  4. Re-run and keep payload examples in docs/tests for that command.
# Wrong (single quotes are not valid JSON content)
mcp-layer tools repo.search exec --filters '{tag: "api"}'

# Correct
mcp-layer tools repo.search exec --filters '{"tag":"api"}'

Template parameter "{parameter}" is required but was not provided.

Thrown from: render

This happens when executing a resource template and at least one {placeholder} in uriTemplate has no matching argument in CLI input.

Step-by-step resolution:

  1. Inspect the template string from templates list and enumerate placeholders.
  2. Pass each placeholder as a flag with the exact same parameter name.
  3. If arguments are provided via --json/--input, verify key names exactly match template placeholder names.
  4. Re-run after all placeholders are bound.
# Template: mcp://docs/{team}/{slug}
mcp-layer templates mcp://docs/{team}/{slug} exec --team api --slug auth-flow

Template URI is missing.

Thrown from: render

This happens when template execution reaches URI rendering without a uriTemplate value in the selected catalog item. In practice this indicates malformed/partial template metadata from the server.

Step-by-step resolution:

  1. Run mcp-layer templates list --format json and inspect detail.uriTemplate for the failing entry.
  2. Confirm the server returns a valid MCP resource template object, including uriTemplate.
  3. Fix the server-side template registration payload.
  4. Restart the server and verify template metadata again before exec.
{
  name: 'docs-by-slug',
  description: 'Read docs by slug',
  uriTemplate: 'mcp://docs/{slug}'
}

Multiple servers found. Provide --server .

Thrown from: select

This happens when configuration discovery yields more than one server and no --server flag (or default server setting) is provided, so CLI cannot safely infer which MCP endpoint to use.

Step-by-step resolution:

  1. Run mcp-layer servers list to see discovered server names.
  2. Pick the intended server explicitly with --server <name>.
  3. Optionally set a default server in CLI config to avoid repeating the flag.
  4. Re-run the original command with explicit server selection.
mcp-layer servers list
mcp-layer --server local-dev tools list

Server "{server}" was not found.

Thrown from: select

This happens when --server <name> (or configured default) does not match any server key in the loaded MCP configuration documents.

Step-by-step resolution:

  1. Run mcp-layer servers list and verify the actual configured names.
  2. Check that --config points to the config file/directory you intended.
  3. Update command/config to use an existing server key exactly.
  4. If the server should exist, add it to config and rerun.
mcp-layer --config ./mcp.json servers list
mcp-layer --config ./mcp.json --server integration tools list

License

MIT