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

@intentface/just-mcp-to-cli

v0.2.0

Published

Turn any MCP server into native bash commands for just-bash

Readme

@intentface/just-mcp-to-cli

Turn any MCP server into native bash commands for just-bash.

An agent types slack send-message --channel "#dev" --text "deployed" and it just works. No SDK. No MCP knowledge. Just bash.

Install

npm install @intentface/just-mcp-to-cli just-bash

Quick Start

import { Bash } from "just-bash";
import { mcpCommand } from "@intentface/just-mcp-to-cli";

const bash = new Bash({
  customCommands: [
    await mcpCommand("slack", "https://mcp.slack.com/mcp"),
  ],
});

await bash.exec('slack send-message --channel "#general" --text "hello world"');

How It Works

mcpCommand() connects to an MCP server, discovers its tools, and registers them as a just-bash custom command. Each MCP tool becomes a subcommand with auto-generated CLI flags from the tool's JSON Schema.

mcpCommand("slack", url)
  → connects to MCP server
  → discovers tools via tools/list
  → returns a just-bash Command

bash.exec("slack send-message --channel '#dev' --text 'hi'")
  → parses subcommand + flags
  → calls tools/call on the MCP server
  → formats result to stdout

Discovery & Help

Every registered server and tool gets auto-generated --help:

# List all tools on a server
slack --help
# slack — MCP tools
#
# Available commands:
#   send_message       Send a message to a channel
#   list_channels      List available channels
#
# Run `slack <command> --help` for details on each command.

# Tool-specific help with full type info
slack send_message --help
# Usage: slack send_message [options]
#
# Send a message to a channel
#
# Required:
#   --channel <string>        Channel name or ID
#   --text <string>           Message content [maxLength: 4000]
#
# Optional:
#   --thread-ts <string>      Reply to a specific thread
#   --unfurl-links            Unfurl links in the message
#
# Flags:
#   --help              Show this help message
#   --json              Read arguments from stdin as JSON
#   --raw               Output raw MCP result
#   --verbose           Show request/response details

Help output includes type hints (<string>, <number>, <string[]>), enum values, defaults, format hints (<email>, <date-time>), and constraints (min, max, pattern, etc.).

Nested Parameters

Object parameters can be passed two ways:

# Dot-notation flags
linear create-issue --title "Bug" --assignee.id "user-123" --assignee.role "owner"

# Or as a JSON string
linear create-issue --title "Bug" --assignee '{"id":"user-123","role":"owner"}'

Help output shows nested properties inline:

Optional:
  --assignee <json>         Assignee details
    Pass as JSON string, or use dot-notation flags:
      --assignee.id <uuid>          User ID (required)
      --assignee.role <string>      Team role [one of: owner, reviewer, member]

Unix Pipes

Output goes to stdout, so piping works naturally:

# Pipe between MCP servers
github list-issues --repo "acme/app" --state open \
  | jq '.[] | .title' \
  | xargs -I{} slack send-message --channel "#bugs" --text "Open: {}"

# Read args from stdin as JSON
echo '{"channel":"#general","text":"hi"}' | slack send-message --json

# Output to file
linear list-issues --team ENG > /tmp/issues.json

Multiple Servers

import { Bash } from "just-bash";
import { mcpCommands } from "@intentface/just-mcp-to-cli";

const commands = await mcpCommands({
  slack: "https://mcp.slack.com/mcp",
  gmail: {
    url: "https://gmail.mcp.claude.com/mcp",
    headers: { Authorization: "Bearer ..." },
  },
  linear: "https://mcp.linear.app/mcp",
});

const bash = new Bash({ customCommands: commands });

Configuration

await mcpCommand("slack", "https://mcp.slack.com/mcp", {
  // Auth
  headers: { Authorization: "Bearer xoxb-..." },

  // Rename tools for shorter commands
  aliases: {
    send_message: "send",      // slack send --channel ...
    list_channels: "channels", // slack channels
  },

  // Filter which tools are exposed
  include: ["send_message", "list_channels"],
  // or: exclude: ["admin_*"],

  // Output format
  defaultOutput: "json", // "json" | "text" | "raw"

  // Connection
  timeout: 30000,
  retries: 2,
});

API

mcpCommand(name, url, options?)

Connect to an MCP server and return a just-bash Command.

| Param | Type | Description | |-------|------|-------------| | name | string | Command name (e.g. "slack") | | url | string | MCP server endpoint URL | | options | McpCommandOptions | Optional configuration (see above) |

Returns Promise<Command> — pass to Bash({ customCommands: [...] }).

mcpCommands(servers)

Register multiple servers at once.

| Param | Type | Description | |-------|------|-------------| | servers | Record<string, string \| ServerConfig> | Map of name → URL or config |

Returns Promise<Command[]>.

MCPTransport

Low-level MCP client if you need direct access:

import { MCPTransport } from "@intentface/just-mcp-to-cli";

const transport = new MCPTransport("https://mcp.slack.com/mcp", {
  headers: { Authorization: "Bearer ..." },
  timeout: 30000,
  retries: 2,
});

await transport.initialize();
const tools = await transport.listTools();
const result = await transport.callTool("send_message", { channel: "#dev", text: "hi" });
await transport.close();

Utility Exports

For advanced use cases, the internals are also exported:

import {
  schemaToArgs,    // JSON Schema → CliArg[]
  parseArgs,       // argv string[] → parsed object
  generateServerHelp, // tool list → help text
  generateToolHelp,   // single tool → help text
  formatResult,       // MCP result → formatted string
} from "@intentface/just-mcp-to-cli";

Reserved Flags

These flags are available on every tool:

| Flag | Description | |------|-------------| | --help, -h | Show help for the server or tool | | --json | Read arguments from stdin as JSON instead of flags | | --raw | Output the raw MCP result envelope | | --verbose | Show request/response details |

Error Handling

Follows standard Unix conventions:

| Exit Code | Meaning | |-----------|---------| | 0 | Success | | 1 | MCP error or connection error | | 2 | Invalid arguments (missing required, bad type, unknown flag) |

Errors go to stderr, output goes to stdout.


Developing

Prerequisites

Setup

git clone https://github.com/intentface/just-mcp-to-cli.git
cd just-mcp-to-cli
bun install

Commands

# Run tests
bun test

# Run tests in watch mode
bun test --watch

# Type-check
bunx tsc --noEmit

# Build (ESM + CJS + types)
bun run build

# Inspect the package before publishing
npm pack --dry-run

Project Structure

src/
  index.ts              Public API — mcpCommand(), mcpCommands()
  transport.ts          MCP HTTP/SSE client (thin JSON-RPC, no SDK)
  schema-to-args.ts     JSON Schema ↔ CLI flags + arg parser
  help-generator.ts     --help text formatting with rich type info
  output.ts             MCP result → stdout formatting (text/json/raw)
  command-factory.ts    Glue — wires everything into defineCommand()
  types.ts              Shared TypeScript types

tests/
  schema-to-args.test.ts
  help-generator.test.ts
  output.test.ts
  transport.test.ts
  command-factory.test.ts

examples/
  basic.ts              Connect to one MCP server
  multi-server.ts       Connect to multiple servers
  custom-commands.ts    Mix MCP tools with your own commands (runs standalone)
  interactive.ts        Interactive REPL

Architecture

The library has a simple pipeline:

  1. Transport — thin JSON-RPC client using fetch(). Supports Streamable HTTP (primary) and SSE (fallback). No @modelcontextprotocol/sdk dependency.
  2. Schema-to-args — converts each tool's inputSchema (JSON Schema) into CLI flag definitions. Flattens nested objects into dot-notation (--filter.status). Maps between kebab-case, snake_case, and camelCase.
  3. Help generator — produces GNU-style --help output from the arg definitions, showing types, constraints, enums, defaults, and nested object structure.
  4. Output formatter — transforms MCP tools/call results into text, JSON, or raw format for stdout.
  5. Command factory — ties it all together into a defineCommand() handler that routes subcommands, parses args, calls the MCP server, and formats output.

Running Examples

# Run without MCP server (uses only custom commands)
bun run examples/custom-commands.ts

# Connect to an MCP server
MCP_URL=https://your-server.com/mcp MCP_NAME=mytools bun run examples/basic.ts

# Interactive REPL
MCP_URL=https://your-server.com/mcp MCP_NAME=mytools bun run examples/interactive.ts

Publishing

npm login --scope=@intentface
npm publish --access public

License

MIT