Add hidden aliases and README artwork

This commit is contained in:
Peter Steinberger 2025-11-26 00:32:36 +01:00
parent 298685f937
commit 69926e91cd
10 changed files with 50 additions and 3 deletions

View File

@ -3,6 +3,8 @@
## [Unreleased]
### CLI
- `mcporter call|auth|list help/--help` now print the command-specific usage text instead of attempting to run a server, matching the footers “mcporter <command> --help” hint.
- Added a hidden `list-tools` alias for `mcporter list` to preserve older muscle memory and avoid “Unknown MCP server” errors when copied from legacy docs.
- Ad-hoc HTTP flows now accept `--insecure` as a hidden synonym for `--allow-http`, making plain-HTTP testing flags match common intuition. `--sse` also aliases `--http-url` to keep older examples working.
### Security / Dependencies
- Override transitive `body-parser` to 2.2.1 (CVE-2025-13466) via pnpm overrides.

View File

@ -1,4 +1,15 @@
# MCPorter 🧳 - Call MCPs from TypeScript or package them as a CLI
<p align="center">
<img src="./mcporter.png" alt="MCPorter header banner" width="1100">
</p>
<p align="center">
<a href="https://www.npmjs.com/package/mcporter"><img src="https://img.shields.io/npm/v/mcporter?style=for-the-badge&logo=npm&logoColor=white" alt="npm version"></a>
<a href="https://github.com/steipete/mcporter/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/steipete/mcporter/ci.yml?branch=main&style=for-the-badge&label=tests" alt="CI Status"></a>
<a href="https://github.com/steipete/mcporter"><img src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20Windows-blue?style=for-the-badge" alt="Platforms"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=for-the-badge" alt="MIT License"></a>
</p>
_TypeScript runtime, CLI, and code-generation toolkit for the Model Context Protocol._
MCPorter 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, compose richer automations in TypeScript, and mint single-purpose CLIs when you need to share a tool. All of that works out of the box -- no boilerplate, no schema spelunking.

View File

@ -32,7 +32,7 @@ Notice that the second command repeats the URL. Ad-hoc definitions are ephemeral
## Transport Detection
- **HTTP(S)**: Providing a URL defaults to the streamable HTTP transport. `https://` works out of the box; `http://` requires `--allow-http` to acknowledge cleartext traffic.
- **HTTP(S)**: Providing a URL defaults to the streamable HTTP transport. `https://` works out of the box; `http://` requires `--allow-http` (or the hidden alias `--insecure`) to acknowledge cleartext traffic. The `--sse` flag is a hidden alias for `--http-url` to match older examples.
- **STDIO**: Supplying `--stdio` (with a command string) or `--stdio-bin` (binary + args) selects the stdio transport. Your current shell environment is inherited automatically; use `--env KEY=value` only when you need to inject/override specific variables (and `--cwd` to change directories).
- **Conflict guard**: Passing both URL and stdio flags errors out so we dont guess.

View File

@ -14,6 +14,8 @@ A quick reference for the primary `mcporter` subcommands. Each command inherits
status).
- With a server name, prints TypeScript-style signatures for each tool, doc
comments, and optional summaries.
- Hidden alias: `list-tools` (kept for muscle memory; not advertised in help output).
- Hidden ad-hoc flag aliases: `--sse` for `--http-url`, `--insecure` for `--allow-http` (for plain HTTP testing).
- Flags:
- `--all-parameters` include every optional parameter in the signature.
- `--schema` pretty-print the JSON schema for each tool.

BIN
mcporter.png Normal file

Binary file not shown.

View File

@ -20,6 +20,11 @@ export function inferCommandRouting(
return { kind: 'command', command: 'list', args };
}
// Hidden alias kept for muscle memory / older docs.
if (token === 'list-tools') {
return { kind: 'command', command: 'list', args };
}
if (isExplicitCommand(token)) {
return { kind: 'command', command: token, args };
}

View File

@ -27,7 +27,7 @@ export function extractEphemeralServerFlags(
continue;
}
if (token === '--http-url') {
if (token === '--http-url' || token === '--sse') {
const value = args[index + 1];
if (!value) {
throw new Error("Flag '--http-url' requires a value.");
@ -37,7 +37,7 @@ export function extractEphemeralServerFlags(
continue;
}
if (token === '--allow-http') {
if (token === '--allow-http' || token === '--insecure') {
ensureSpec().allowInsecureHttp = true;
args.splice(index, 1);
continue;

View File

@ -23,6 +23,11 @@ describe('command inference', () => {
expect(result).toEqual({ kind: 'command', command: 'list', args: ['chrome-devtools'] });
});
it('treats list-tools as a hidden list alias', () => {
const result = inferCommandRouting('list-tools', ['linear'], definitions);
expect(result).toEqual({ kind: 'command', command: 'list', args: ['linear'] });
});
it('auto-corrects close server names', () => {
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
const result = inferCommandRouting('vercek', [], definitions);

View File

@ -37,4 +37,18 @@ describe('extractEphemeralServerFlags', () => {
});
expect(args).toEqual([]);
});
it('accepts --insecure as a hidden alias for --allow-http', () => {
const args = ['--http-url', 'http://mcp.example.com/mcp', '--insecure'];
const spec = extractEphemeralServerFlags(args);
expect(spec).toEqual({ httpUrl: 'http://mcp.example.com/mcp', allowInsecureHttp: true });
expect(args).toEqual([]);
});
it('accepts --sse as a hidden alias for --http-url', () => {
const args = ['--sse', 'https://mcp.example.com/sse'];
const spec = extractEphemeralServerFlags(args);
expect(spec).toEqual({ httpUrl: 'https://mcp.example.com/sse' });
expect(args).toEqual([]);
});
});

View File

@ -43,6 +43,14 @@ describe('CLI list flag parsing', () => {
expect(args).toEqual(['server']);
});
it('treats --sse as a hidden alias for --http-url in ad-hoc mode', async () => {
const { extractListFlags } = await cliModulePromise;
const args = ['--sse', 'https://mcp.example.com/sse', 'list'];
const flags = extractListFlags(args);
expect(flags.ephemeral).toEqual({ httpUrl: 'https://mcp.example.com/sse' });
expect(args).toEqual(['list']);
});
it('honors --timeout when listing a single server', async () => {
const { handleList } = await cliModulePromise;
const definition: ServerDefinition = {