Allow positional inline commands for generate-cli
This commit is contained in:
parent
b5e1c5df84
commit
002cb8cbc8
@ -18,7 +18,7 @@
|
||||
- Generated CLIs now embed their metadata (generator version, resolved server definition, invocation flags) behind a hidden `__mcporter_inspect` command. `mcporter inspect-cli` / `mcporter generate-cli --from <artifact>` read directly from the artifact, while legacy `.metadata.json` sidecars remain as a fallback for older binaries.
|
||||
- Shared the TypeScript signature formatter between `mcporter list` and `mcporter generate-cli`, ensuring command summaries, CLI hints, and generator help stay pixel-perfect and are backed by new snapshot/unit tests.
|
||||
- Introduced `mcporter emit-ts`, a codegen command that emits `.d.ts` tool interfaces or ready-to-run client wrappers (`--mode types|client`, `--include-optional`) using the same doc/comment data that powers the CLI, so agents/tests can consume MCP servers with strong TypeScript types.
|
||||
- `mcporter generate-cli` now accepts inline stdio commands via `--command "npx -y package@latest"`, automatically splits the command/args, infers a friendly name from scripts or package scopes, and documents the chrome-devtools one-liner in the README; additional unit tests cover HTTP, stdio, and scoped package shorthands.
|
||||
- `mcporter generate-cli` now accepts inline stdio commands via `--command "npx -y package@latest"` or by quoting the command as the first positional argument, automatically splits the command/args, infers a friendly name from scripts or package scopes, and documents the chrome-devtools one-liner in the README; additional unit tests cover HTTP, stdio, scoped package, and positional shorthand flows.
|
||||
|
||||
### Documentation & references
|
||||
- Added `docs/tool-calling.md`, `docs/call-syntax.md`, and `docs/call-heuristic.md` to capture every invocation style (flags, function expressions, inferred verbs) plus the typo-correction rules.
|
||||
|
||||
@ -274,6 +274,8 @@ npx mcporter generate-cli \
|
||||
>
|
||||
> `npx mcporter generate-cli --command "npx -y chrome-devtools-mcp@latest"`
|
||||
|
||||
Tip: you can drop `--command` when the inline command is the first positional argument (e.g., `npx mcporter generate-cli "npx -y chrome-devtools-mcp@latest"`).
|
||||
|
||||
- `--name` overrides the inferred CLI name.
|
||||
- Add `--description "..."` if you want a custom summary in the generated help output.
|
||||
- Add `--bundle [path]` to emit an esbuild bundle alongside the template.
|
||||
|
||||
@ -79,6 +79,7 @@ npx mcporter generate-cli --command "npx -y chrome-devtools-mcp@latest"
|
||||
- Omit `--name` to let mcporter infer it from the command URL (for example, `https://mcp.context7.com/mcp` becomes `context7`).
|
||||
- When targeting an existing config entry, you can skip `--server` and pass the name as a positional argument:
|
||||
`npx mcporter generate-cli linear --bundle dist/linear.js`.
|
||||
- When the MCP server is a stdio command, you can also skip `--command` by quoting the inline command as the first positional argument (e.g., `npx mcporter generate-cli "npx -y chrome-devtools-mcp@latest"`).
|
||||
```
|
||||
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ A quick reference for the primary `mcporter` subcommands. Each command inherits
|
||||
compiling with Bun).
|
||||
- Key flags:
|
||||
- `--server <name>` (or inline JSON) – choose the server definition.
|
||||
- `--command <url|command>` – point at an ad-hoc HTTP endpoint or a stdio command (e.g., `"npx -y chrome-devtools-mcp@latest"`); mcporter infers the name when omitted.
|
||||
- `--command <url|command>` – point at an ad-hoc HTTP endpoint or a stdio command (e.g., `"npx -y chrome-devtools-mcp@latest"`); mcporter infers the name when omitted. Quoting the command as the first positional argument works too, so `npx mcporter generate-cli "npx -y chrome-devtools-mcp@latest"` is equivalent.
|
||||
- `--output <path>` – where to write the TypeScript template.
|
||||
- `--bundle <path>` – emit a bundle (Node/Bun) ready for `bun x`.
|
||||
- `--compile <path>` – compile with Bun (implies `--runtime bun`).
|
||||
|
||||
@ -18,7 +18,7 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe
|
||||
- Typed utilities for env/header resolution and stdio command execution.
|
||||
- CLI entry point (`npx mcporter list|call`) built on the same runtime with configurable log levels (`--log-level` flag, `MCPORTER_LOG_LEVEL` env) defaulting to `warn`. Single-server listings must render as TypeScript-style headers: dimmed `/** ... */` doc blocks followed by `function name(...)` signatures, inferred return annotations when schemas expose a `title`, inline enum/format hints, and an optional-parameter summary (`// optional (N): a, b, ...`). Optional fields are hidden by default (unless there are ≤2 of them and <4 required parameters) and the CLI should tell users to run `--all-parameters` whenever anything is suppressed. The CLI should also infer the verb when users omit it: bare server names run `list <server>` (with the same typo-friendly heuristic used by `mcporter list`), while dotted tokens such as `linear.list_issues` dispatch to `call` automatically. Anonymous HTTP MCP servers (e.g., shadcn) must be auto-detected: if an ad-hoc URL returns MCP-shaped JSON even with a non-200 status, mcporter treats it as authenticated instead of launching the OAuth flow. Likewise, `call` must recognise HTTP selectors that inline the tool name (e.g., `https://www.shadcn.io/api/mcp.getComponent(...)`), strip the `.tool` suffix to derive the base server, parse any function-call arguments, and reuse an existing definition when the base URL matches a configured server. Selectors may omit the protocol entirely—we assume HTTPS when no scheme is present and treat hosts that only differ by a leading `www.` as identical for reuse purposes. See [docs/cli-reference.md](./cli-reference.md) for day-to-day usage/flag details.
|
||||
- CLI generator (`npx mcporter generate-cli`) that emits standalone CLIs (plain TypeScript or bundled JS) with embedded schemas and Commander-based subcommands, targeting Node or Bun.
|
||||
- CLI generator (`npx mcporter generate-cli`) that emits standalone CLIs (plain TypeScript or bundled JS) with embedded schemas and Commander-based subcommands, targeting Node or Bun. It must accept server references by name (positional), JSON, HTTP URL (with optional `.tool` suffix / missing scheme), or inline stdio commands (split into `command` + `args` so invocations like `--command "npx -y chrome-devtools-mcp@latest"` work without a config entry) just like the main CLI.
|
||||
- CLI generator (`npx mcporter generate-cli`) that emits standalone CLIs (plain TypeScript or bundled JS) with embedded schemas and Commander-based subcommands, targeting Node or Bun. It must accept server references by name (positional), JSON, HTTP URL (with optional `.tool` suffix / missing scheme), or inline stdio commands (split into `command` + `args` so invocations like `--command "npx -y chrome-devtools-mcp@latest"` or positional equivalents work without a config entry) just like the main CLI.
|
||||
- Test harness using the Sweetistics MCP fixtures to validate every configured server definition.
|
||||
- Documentation: README, usage examples, migration guide for replacing `pnpm mcp:*`.
|
||||
|
||||
@ -47,7 +47,7 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe
|
||||
- Back the proxy with targeted unit tests that cover primitive-only calls, positional tuples + option bags, and error fallbacks when schemas are missing.
|
||||
|
||||
## Standalone CLI Generation
|
||||
- `generate-cli` should accept inline JSON, file paths, inline stdio commands, or existing config names and produce a ready-to-run CLI that maps tools to Commander subcommands.
|
||||
- `generate-cli` should accept inline JSON, file paths, inline stdio commands (either via `--command` or as the first positional argument), or existing config names and produce a ready-to-run CLI that maps tools to Commander subcommands.
|
||||
- Embed schemas (via `listTools { includeSchema: true }`) directly in the generated source so repeat executions avoid additional metadata calls.
|
||||
- Support optional bundling through esbuild, producing Node-friendly `.cjs` files or Bun-ready `.js` binaries with executable shebangs.
|
||||
- Surface flags for output path, runtime target (`node` or `bun`), bundle destination, and per-call timeout (default 30s).
|
||||
|
||||
@ -40,7 +40,9 @@ export async function handleGenerateCli(args: string[], globalFlags: FlagMap): P
|
||||
if (position !== -1) {
|
||||
args.splice(position, 1);
|
||||
}
|
||||
if (looksLikeHttpUrl(positional) || positional.includes('://')) {
|
||||
if (looksLikeInlineCommand(positional)) {
|
||||
parsed.command = normalizeCommandInput(positional);
|
||||
} else if (looksLikeHttpUrl(positional) || positional.includes('://')) {
|
||||
parsed.command = positional;
|
||||
} else {
|
||||
parsed.server = positional;
|
||||
@ -295,6 +297,23 @@ function parseGenerateFlags(args: string[]): GenerateFlags {
|
||||
index += 1;
|
||||
}
|
||||
|
||||
if (!server && !command && !from) {
|
||||
const positional = args.find((token) => token && !token.startsWith('--'));
|
||||
if (positional) {
|
||||
const position = args.indexOf(positional);
|
||||
if (position !== -1) {
|
||||
args.splice(position, 1);
|
||||
}
|
||||
if (looksLikeInlineCommand(positional)) {
|
||||
command = normalizeCommandInput(positional);
|
||||
} else if (looksLikeHttpUrl(positional) || positional.includes('://')) {
|
||||
command = positional;
|
||||
} else {
|
||||
server = positional;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
server,
|
||||
name,
|
||||
@ -395,6 +414,21 @@ function stripExtension(value: string): string {
|
||||
return value.slice(0, index);
|
||||
}
|
||||
|
||||
function looksLikeInlineCommand(value: string): boolean {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
if (!/\s/.test(value)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const parts = splitCommandLine(value.trim());
|
||||
return parts.length > 0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function deriveNameFromUrl(url: URL): string | undefined {
|
||||
const genericHosts = new Set(['www', 'api', 'mcp', 'service', 'services', 'app', 'localhost']);
|
||||
const knownTlds = new Set(['com', 'net', 'org', 'io', 'ai', 'app', 'dev', 'co', 'cloud']);
|
||||
|
||||
@ -69,6 +69,16 @@ describe('generate-cli runner internals', () => {
|
||||
expect(inferred).toBe('shadcn');
|
||||
});
|
||||
|
||||
it('treats positional inline commands as generate-cli targets', () => {
|
||||
const args = ['npx -y chrome-devtools-mcp@latest'];
|
||||
const parsed = generateInternals.parseGenerateFlags([...args]);
|
||||
expect(parsed.command).toBeDefined();
|
||||
expect(parsed.server).toBeUndefined();
|
||||
const spec = parsed.command as { command: string; args?: string[] };
|
||||
expect(spec.command).toBe('npx');
|
||||
expect(spec.args).toEqual(['-y', 'chrome-devtools-mcp@latest']);
|
||||
});
|
||||
|
||||
it('builds regenerate commands honoring global flags and invocation overrides', () => {
|
||||
const definition: SerializedServerDefinition = {
|
||||
name: 'demo',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user