diff --git a/AGENTS.md b/AGENTS.md index 5db5664..89b889e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,15 +6,18 @@ Shared guardrails distilled from the various `~/Projects/*/AGENTS.md` files (sta Usage: In repo copies, the shared content lives inside `` and the tool list inside ``. Keep those tagged blocks identical across repos; anything outside them is repo-local and can be customized freely. ## Codex Global Instructions + - Keep the system-wide Codex guidance at `~/.codex/AGENTS.md` (the Codex home; override via `CODEX_HOME` if needed) so every task inherits these rules by default. ## General Guardrails ### Intake & Scoping + - Open the local agent instructions plus any `docs:list` summaries at the start of every session. Re-run those helpers whenever you suspect the docs may have changed. - Review any referenced tmux panes, CI logs, or failing command transcripts so you understand the most recent context before writing code. ### Tooling & Command Wrappers + - Use the command wrappers provided by the workspace (`./runner …`, `scripts/committer`, `pnpm mcp:*`, etc.). Skip them only for trivial read-only shell commands if that’s explicitly allowed. - Stick to the package manager and runtime mandated by the repo (pnpm-only, bun-only, swift-only, go-only, etc.). Never swap in alternatives without approval. - When editing shared guardrail scripts (runners, committer helpers, browser tools, etc.), mirror the same change back into the `agent-scripts` folder so the canonical copy stays current. @@ -23,29 +26,34 @@ Usage: In repo copies, the shared content lives inside `` an - Keep the project’s `AGENTS.md` `` block in sync with the full tool list from `TOOLS.md` so downstream repos get the latest tool descriptions. ### tmux & Long Tasks + - Run any command that could hang (tests, servers, log streams, browser automation) inside tmux using the repository’s preferred entry point. - Do not wrap tmux commands in infinite polling loops. Run the job, sleep briefly (≤30 s), capture output, and surface status at least once per minute. - Document which sessions you create and clean them up when they are no longer needed unless the workflow explicitly calls for persistent watchers. ### Build, Test & Verification + - Before handing off work, run the full “green gate” for that repo (lint, type-check, tests, doc scripts, etc.). Follow the same command set humans run—no ad-hoc shortcuts. - Leave existing watchers running unless the owner tells you to stop them; keep their tmux panes healthy if you started them. - Treat every bug fix as a chance to add or extend automated tests that prove the behavior. - When someone asks to “fix CI,” use the GitHub CLI (`gh`) to inspect, rerun, and unblock failing workflows on GitHub until they are green. ### Code Quality & Naming + - Refactor in place. Never create duplicate files with suffixes such as “V2”, “New”, or “Fixed”; update the canonical file and remove obsolete paths entirely. - Favor strict typing: avoid `any`, untyped dictionaries, or generic type erasure unless absolutely required. Prefer concrete structs/enums and mark public concurrency surfaces appropriately. - Keep files at a manageable size. When a file grows unwieldy, extract helpers or new modules instead of letting it bloat. - Match the repo’s established style (commit conventions, formatting tools, component patterns, etc.) by studying existing code before introducing new patterns. ### Git, Commits & Releases + - Invoke git through the provided wrappers, especially for status, diffs, and commits. Only commit or push when the user asks you to do so. - To resolve a rebase, `git add`/`git commit` is allowed. - Follow the documented release or deployment checklists instead of inventing new steps. - Do not delete or rename unfamiliar files without double-checking with the user or the repo instructions. ### Documentation & Knowledge Capture + - Update existing docs whenever your change affects them, including front-matter metadata if the repo’s `docs:list` tooling depends on it. - Whenever doing a large refactor, track work in `docs/refactor/<date>.md`, update it as you go, and delete it when the work is finished. - Only create new documentation when the user or local instructions explicitly request it; otherwise, edit the canonical file in place. @@ -53,16 +61,19 @@ Usage: In repo copies, the shared content lives inside `<shared>…</shared>` an - Routine test additions don’t require changelog entries; reserve changelog lines for user-visible behavior changes. ### Troubleshooting & Observability + - Design workflows so they are observable without constant babysitting: use tmux panes, CI logs, log-tail scripts, MCP/browser helpers, and similar tooling to surface progress. - If you get stuck, consult external references (web search, official docs, Stack Overflow, etc.) before escalating, and record any insights you find for the next agent. - Keep any polling or progress loops bounded to protect hang detectors and make it obvious when something stalls. ### Stack-Specific Reminders + - Start background builders or watchers using the automation provided by the repo (daemon scripts, tmux-based dev servers, etc.) instead of running binaries directly. - Use the official CLI wrappers for browser automation, screenshotting, or MCP interactions rather than crafting new ad-hoc scripts. - Respect each workspace’s testing cadence (e.g., always running the main `check` script after edits, never launching forbidden dev servers, keeping replies concise when requested). ## Swift Projects + - Kick off the workspace’s build daemon or helper before running any Swift CLI or app; rely on the provided wrapper to rebuild targets automatically instead of launching stale binaries. - Validate changes with `swift build` and the relevant filtered test suites, documenting any compiler crashes and rewriting problematic constructs immediately so the suite can keep running. - Keep concurrency annotations (`Sendable`, actors, structured tasks) accurate and prefer static imports over dynamic runtime lookups that break ahead-of-time compilation. @@ -70,6 +81,7 @@ Usage: In repo copies, the shared content lives inside `<shared>…</shared>` an - When encountering toolchain instability, capture the repro steps in the designated troubleshooting doc and note any required cache cleans (DerivedData, SwiftPM caches) you perform. ## TypeScript Projects + - Use the package manager declared by the workspace (often `pnpm` or `bun`) and run every command through the same wrapper humans use; do not substitute `npm`/`yarn` or bypass the runner. - Start each session by running the repo’s doc-index script (commonly a `docs:list` helper), then keep required watchers (`lint:watch`, `test:watch`, dev servers) running inside tmux unless told otherwise. - Treat `lint`, `typecheck`, and `test` commands (e.g., `pnpm run check`, `bun run typecheck`) as mandatory gates before handing off work; surface any failures with their exact command output. @@ -101,7 +113,7 @@ Edit guidance: keep the actual tool list inside this `<tools></tools>` block so - `firecrawl`: MCP-powered site fetcher to Markdown; run `npx mcporter firecrawl`. - `XcodeBuildMCP`: MCP wrapper around Xcode tooling; run `npx mcporter XcodeBuildMCP`. - `gh`: GitHub CLI for PRs, CI logs, releases, repo queries; run `gh help`. -</tools> + </tools> # Repo Notes diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e06fd6..4869ff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,22 +3,27 @@ ## [0.8.2] - Unreleased ### CLI + - Respect schema-declared string parameters when coercing numeric-looking `mcporter call` key=value arguments, so Slack timestamps like `thread_ts` stay strings. (PR #141, thanks @Hamzaa6296) ## [0.8.1] - 2026-03-29 ### CLI + - Bun-compiled/Homebrew binaries now embed the package version before boot, so `mcporter --version` reports the real release (for example `0.8.1`) instead of falling back to `0.0.0-dev`. ### Tests + - Added regression coverage for the Bun compile wrapper so future release builds keep the embedded runtime version intact. ### Tooling / Dependencies + - npm publishes now use an explicit package allowlist, so local release tarballs/checksum files do not get bundled into the published package. ## [0.8.0] - 2026-03-29 ### CLI + - Preserve OAuth flow vs post-auth transport failures so invalid OAuth/provider errors surface directly, while real legacy 404/405 transport mismatches still fall back to SSE correctly. (PR #97, thanks @mavam) - Ignore static `Authorization` headers once OAuth is active so imported editor configs cannot override fresh OAuth tokens. (PR #123, thanks @ahonn) - Keep `mcporter call --output json` parseable by emitting valid JSON even when the command falls back to raw output. (PR #128, thanks @armanddp) @@ -39,31 +44,39 @@ - Added generated `mcporter.schema.json` plus `pnpm generate:schema` for IDE autocomplete/validation, including `$schema` and `oauthScope`/`oauth_scope` coverage. (PR #43, thanks @aryasaatvik) ### Tooling / Dependencies + - Updated dependencies to latest releases (including MCP SDK, Rolldown RC, Zod, Biome, Oxlint, Vitest, Bun types). - Synced `biome.json` schema URL to Biome `2.4.5`. ## [0.7.3] - 2025-12-29 ### CLI + - Fixed generated CLIs to read Commander.js option values via camelCased properties so snake_case tool schemas map correctly. (Thanks @rawwerks, PR #28) - Coerce generated CLI array arguments based on JSON Schema item types (including integer arrays). (Thanks @rawwerks, PR #27) - `mcporter generate-cli` supports `--include-tools` / `--exclude-tools` to generate CLIs for a subset of server tools. (Thanks @zackleman, PR #24) ### Tests + - Added regression coverage for typed array parsing in generated CLIs. - - Added regression coverage for snake_case, camelCase, and numeric option names in generated CLIs. - - Increased the Bun bundler integration-test timeout to reduce flakes on slower runners. +- Added regression coverage for snake_case, camelCase, and numeric option names in generated CLIs. +- Increased the Bun bundler integration-test timeout to reduce flakes on slower runners. ### Tooling / Dependencies + - Updated dependency set (SDK, Rolldown, Zod, Biome, Oxlint, Bun types). - Synced the Biome schema URL to the current CLI version. ## [0.7.1] - 2025-12-08 + ### Daemon + - Track config file mtimes for every loaded layer (home + project or explicit) in daemon metadata and auto-restart when any layer changes, so newly added keep-alive servers are picked up without manual restarts. Includes regression tests for stale-daemon detection. ## [0.7.0] - 2025-12-06 + ### CLI + - Centralized OAuth credentials in a shared vault (`~/.mcporter/credentials.json`) while still honoring per-server `tokenCacheDir` when present; legacy per-server caches are migrated automatically. - `mcporter auth --reset` now clears the vault and legacy caches without crashing on corrupted credential files, making re-auth reliable for servers like Gmail. - StdIO servers that expose a separate auth subcommand (e.g., Gmail MCP) can now declare `oauthCommand.args`; `mcporter auth <server>` will spawn that helper and wait for browser completion, so Gmail auth now works without running npx manually. @@ -71,68 +84,89 @@ - Added regression coverage to ensure future raw output changes cannot reintroduce truncation. ## [0.6.6] - 2025-11-28 + ### CLI + - Prevented ENOENT crashes when no config file exists anywhere by only passing an explicit `--config`/`MCPORTER_CONFIG` path to the runtime; implicit defaults now fall back cleanly across list/config/daemon flows. ## [0.6.5] - 2025-11-26 + ### CLI + - `mcporter call|auth|list help/--help` now print the command-specific usage text instead of attempting to run a server, matching the footer’s “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. ## [0.6.4] - 2025-11-25 + ### CLI + - `mcporter list` now uses cached OAuth access tokens (if present) for the all-servers view without opening browser windows, so previously authorized servers no longer show spurious “auth required” in non-interactive listings. - `pnpm test --filter <pattern>` now works by translating to a Vitest file pattern, avoiding the prior “Unknown option --filter” error. ## [0.6.3] - 2025-11-22 + ### Runtime & CLI + - Updated to `@modelcontextprotocol/sdk` 1.22.0; inline stdio test server now uses Zod schemas to remain compatible with the SDK’s JSON Schema conversion path. ### Runtime + - `listTools` now follows SDK pagination, looping through `nextCursor` so long catalogs return complete tool lists. ### Configuration + - Claude imports now preserve root-fallback parsing for legacy `.claude.json` and `.claude/mcp.json` files while treating `.claude/settings*.json` as container-only configs, preventing metadata fields like `statusLine` from being misdetected as MCP servers. - Added regression coverage for Claude settings and mcp.json imports to guard the root-fallback behavior. ## [0.6.2] - 2025-11-18 ### Runtime + - Propagate `--timeout` / `MCPORTER_CALL_TIMEOUT` into MCP tool calls (SDK `timeout`, `resetTimeoutOnProgress`, `maxTotalTimeout`) so long-running requests are no longer capped by the SDK’s 60s default. ### CLI + - `mcporter generate-cli` once again treats single-token `--command` values (e.g., `./scripts/server.ts`) as STDIO transports instead of trying to coerce them into HTTP URLs, restoring the pre-0.6.1 behavior for ad-hoc scripts. - Global flag parsing moved into `cli-factory` for consistent log-level/oauth-timeout handling across commands. - `daemon` host/client hardened and covered with new tests; idle eviction and restart paths verified. ### Configuration + - Reintroduced support for `OPENCODE_CONFIG_DIR` so OpenCode imports continue to honor the documented directory override alongside `OPENCODE_CONFIG`. - Platform-aware defaults for Cursor/Claude/Windsurf/VS Code/OpenCode configs now dedupe paths and include Windows-specific locations. ### Platform resilience (Windows/WSL) + - Added `fs-helpers` that treat chmod/copy failures on NTFS/DrvFs as best-effort so CLI generation keeps working on WSL mounts. - Documented Windows/WSL workflows: install/test from ext4 copies, remount guidance for /mnt/c, and syncing tips. ### StdIO MCP coverage + - Added stdio e2e tests using in-repo filesystem & memory MCP fixtures to ensure list/call works via execPath. ### Content extraction + - `createCallResult` now reads nested `raw.content`/`raw.structuredContent` so tools that wrap responses render text/markdown/json correctly; new unit tests cover text joining, markdown, and JSON. ## [0.6.1] - 2025-11-17 ### CLI + - `mcporter list --verbose` now surfaces every config path that registers the target server (primary first, then duplicates) in both text and JSON output, making it easier to trace where a name is coming from. - JSON list payloads include a new `sources` array when `--verbose` is set, mirroring the on-screen path list for programmatic consumers. - Verbose source listings now tag the import kind (cursor/vscode/codex, etc.) and explicitly label the primary entry vs. shadowed duplicates. ### Runtime + ## [0.6.0] - 2025-11-16 ### Configuration + - Default config resolution now layers the system config (`~/.mcporter/mcporter.json[c]`) before the project config (`config/mcporter.json`), so globally installed MCP servers remain available inside repos while allowing per-project overrides. - `--config` and `MCPORTER_CONFIG` continue to select a single file without merging for explicit workflows. - `mcporter config add --scope home|project` lets you choose the write target explicitly (project remains the default; `--persist <path>` still wins when provided). @@ -140,16 +174,19 @@ ## [0.5.11] - 2025-11-16 ### Code generation & metadata + - Quick start examples in generated CLIs now derive from actual embedded tools (up to three), showing real command names/flags instead of generic placeholders. ## [0.5.10] - 2025-11-16 ### Code generation & metadata + - Generated CLIs now present the canonical kebab-cased tool names in help while accepting underscore aliases at runtime, eliminating the “unknown command” errors when copying names directly from server tool lists. ## [0.5.9] - 2025-11-15 ### CLI + - `mcporter list` suppresses raw STDIO stderr dumps when enumerating all configured servers, keeping the summary output readable while still surfacing per-server health statuses. - `mcporter config <subcommand> --help` (and `mcporter config help <subcommand>`) now display detailed usage, flags, and examples for every config subcommand instead of returning a placeholder message. Inline `--help` tokens are intercepted before executing the command, so flows like `mcporter config add --help` no longer throw usage errors. - `mcporter config doctor` prints the project and system config paths before reporting diagnostics, making it obvious which files were inspected when tracking down configuration issues. @@ -157,17 +194,20 @@ ## [0.5.8] - 2025-11-15 ### CLI & runtime + - STDIO transports now interpolate `${VAR}`/`$env:VAR` tokens in the configured command and arguments before spawning child processes, so chrome-devtools inherits the live `CHROME_DEVTOOLS_URL` value instead of receiving the literal placeholder. - Keep-alive detection skips any STDIO server whose command/args reference `CHROME_DEVTOOLS_URL`, ensuring daemon mode relaunches chrome-devtools for each Oracle browser session instead of pinning a stale port. - Command arguments that escape placeholders as `\${VAR}` (common when using `String.raw` in TypeScript config helpers) now trim the backslash after interpolation so downstream servers receive clean URLs. ### CLI + - Ad-hoc STDIO invocations that start with `npx -y <package>` now infer the npm package name (stripping versions and ignoring arguments after `--`) instead of producing slugs like `npx-y`, so repeated `mcporter list|call` runs automatically reuse a readable server key without passing `--name`. - Quoted inline commands such as `mcporter list "npx -y xcodebuildmcp"` now auto-detect the ad-hoc STDIO transport, so you can skip `--stdio` entirely when probing MCP packages via `npx`. ## [0.5.7] - 2025-11-14 ### CLI + - Added `mcporter daemon restart`, a stop+start convenience that reuses logging flags so agents can bounce the keep-alive daemon with a single command. - Added `list_tools` as a hidden shortcut for `mcporter list <server>`, so `chrome-devtools.list_tools` (and similar selectors) print the tool catalog instantly without requiring a real MCP tool. - Warn when colon-style arguments omit a value (e.g., `command:`) and suggest quoting/`--args` JSON so agents don’t accidentally send `undefined` to STDIO servers. @@ -175,53 +215,63 @@ ## [0.5.6] - 2025-11-11 ### CLI & runtime + - Reset cached keep-alive connections whenever STDIO transports hit fatal errors (timeouts, closed pipes, daemon restarts, etc.), so chrome-devtools automatically recovers after you close Chrome instead of requiring `mcporter daemon stop`. - Daemon-routed calls now log a restart notice and automatically retry once after closing the stale transport, providing self-healing behavior when Chrome or other keep-alive servers crash mid-call. ## [0.5.5] - 2025-11-11 ### CLI & runtime + - Added hidden agent shortcuts: `mcporter describe <server>` now aliases `mcporter list`, and calling `<server>.help` automatically falls back to the list output when a server lacks a `help` tool (also wired into the legacy `pnpm mcp call` path) so agents always get a readable summary. ## [0.5.4] - 2025-11-10 ### CLI & runtime + - Propagate the CLI’s per-call timeout (defaults to 60s or `--timeout`) through the keep-alive daemon, so chrome-devtools and other persistent STDIO servers stop as soon as the caller times out. - `Runtime.callTool` now honors `timeoutMs` directly, ensuring TanStack MCP clients and the CLI share a single source of truth for cancellation even outside the daemon. - Ad-hoc STDIO servers launched via `mcporter call "npx …"` (or `--stdio`) inherit the same keep-alive heuristics and canonical names as config-defined entries, so `MCPORTER_DISABLE_KEEPALIVE=chrome-devtools` and similar overrides work without passing `--name`. ### Tests + - Added regression coverage (`tests/daemon-client-timeout.test.ts`, `tests/runtime-call-timeout.test.ts`, and updated keep-alive suites) to guard timeout propagation and canonical keep-alive detection. ## [0.5.3] - 2025-11-10 ### CLI & runtime + - Fixed Claude imports so `mcporter list` merges project-scoped servers from `.claude.json` (matching the current workspace) and ignores metadata-only keys like `tipsHistory`/`cachedStatsigGates`, resolving GitHub issues #6 and #7. - OpenCode imports now read only the documented `mcp` container (no root-level fallback), matching the current OpenCode schema and preventing stray metadata from being misinterpreted as servers. ## [0.5.2] - 2025-11-10 ### CLI & runtime + - `mcporter call "<stdio command>" ...` now auto-detects ad-hoc STDIO servers, so you can skip `--stdio/--stdio-arg` entirely and just quote the command you want to run. - When a server exposes exactly one tool, `mcporter call` infers it automatically (and prints a dim log), letting one-tool servers like Vercel Domains run with only their arguments. - STDIO transports now inherit your current shell environment by default, so ad-hoc commands see the same variables as your terminal; keep `--env KEY=value` for explicit overrides. ### Fixes + - `mcporter config list` and `mcporter config doctor` no longer crash when the project config is missing or contains malformed JSON; we log a single warning and keep going, matching the behavior of the top-level `mcporter list`. ## [0.5.1] - 2025-11-10 ### CLI & runtime + - Added a per-login daemon that auto-starts when keep-alive MCP servers (e.g., Chrome DevTools, Mobile MCP, Playwright) are invoked. The daemon keeps STDIO transports alive across agents, exposes `mcporter daemon <start|status|stop>`, and supports idle shutdown plus manual restarts. - Keep-alive detection now honors the `lifecycle` config flag/env overrides and also inspects STDIO command signatures, so renaming `chrome-devtools` (or other stateful servers) no longer disables the daemon accidentally. - Introduced daemon logging controls (`mcporter daemon start --log|--log-file`, `--log-servers`, `MCPORTER_DAEMON_LOG*` env vars, and per-server `logging.daemon.enabled`). `mcporter daemon status` reports the active log path, and a new `tests/daemon.integration.test.ts` suite keeps the end-to-end flow covered. ### Fixes + - `mcporter list` (and every CLI entry point) once again treats missing project configs as empty instead of throwing ENOENT, matching the 0.4.x behavior when you run the CLI outside a repo. ## [0.5.0] - 2025-11-10 ### CLI & runtime + - **Daemonized keep-alive servers.** A new per-login daemon automatically spins up whenever keep-alive MCP servers (Chrome DevTools, Mobile MCP, Playwright, etc.) are invoked. It keeps STDIO transports warm across agents, exposes `mcporter daemon <start|status|stop>`, supports idle shutdowns/manual restarts, and respects the `lifecycle` config flag plus STDIO command metadata so renamed servers stay eligible. - Fixed `createKeepAliveRuntime` so the daemon wrapper’s `listTools` implementation matches the base `Runtime` signature; `pnpm build` (and any command that shells out to `pnpm build`) succeeds again. - Cursor imports now cover both workspace and user `.cursor/mcp.json` files plus the platform-specific `Cursor/User/mcp.json` directories, and the VS Code/Windsurf walkers dedupe paths so editor-managed MCP servers are auto-discovered consistently across macOS, Linux, and Windows. @@ -230,63 +280,76 @@ ## [0.4.5] - 2025-11-10 ### CLI & runtime + - Fixed the npm `bin` entry so it points to `dist/cli.js` without a leading `./`, keeping the executable in the published tarball and restoring `npx mcporter` functionality. Also bumped the embedded runtime version to 0.4.4 so the CLI reports the correct release. - Added `MCPORTER_CONFIG` plus a home-directory fallback (`~/.mcporter/mcporter.json[c]`) so the CLI automatically finds your system-wide config when a project file is missing. ### Docs + - Consolidated the external MCP import matrix into `docs/import.md`, removing the short-lived `docs/mcp-import.md` duplication, and clarified the release checklist to stop immediately on failing tests or lint warnings. ## [0.4.3] - 2025-11-10 ### CLI & runtime + - Added OpenCode imports (project `opencode.json[c]`, `OPENCODE_CONFIG_DIR`, user config, and the `OPENCODE_CONFIG` override) plus JSONC parsing so `mcporter list/config` can auto-discover servers defined in OpenCode. - Claude Code imports now honor `.claude/settings.local.json` and `.claude/settings.json` ahead of the legacy `mcp.json`, and we skip entries that lack a URL/command (e.g., permissions blocks) so malformed settings no longer break the merge. ### Docs + - Documented the full import matrix (including OpenCode + Claude settings hierarchy) directly in `docs/import.md` and `docs/config.md`. ## [0.4.2] - 2025-11-09 ### CLI & runtime + - `mcporter list` (and other commands that load imports) now skip empty or malformed Claude Desktop / Cursor / Codex config files instead of throwing, so a blank `claude_desktop_config.json` no longer blocks the rest of the imports. - Bundled sample config adds the Mobile Next MCP definition, making it available out of the box when you run `mcporter list` before customizing your own config. ## [0.4.1] - 2025-11-08 ### CLI & runtime + - Fixed the fallback when `config/mcporter.json` is missing so `mcporter list` continues to import Cursor/Claude/Codex/etc. configs even when you run the CLI outside a repo that defines its own config, matching the 0.3.x behavior. - Added regression coverage that exercises the “no config file” path to ensure future changes keep importing user-level MCP servers. ## [0.4.0] - 2025-11-08 ### CLI & runtime + - `mcporter config list` now displays only local entries by default, appends a color-aware summary of every imported config (path, counts, sample names), and still lets you pass `--source import`/`--json` for the merged view. - `mcporter config get`, `remove`, and `logout` now use the same fuzzy matching/suggestion logic as `mcporter list`/`call`, auto-correcting near-miss names and emitting “Did you mean …?” hints when ambiguity remains. ## [0.3.6] - 2025-11-08 ### CLI & runtime + - `mcporter list` now prints copy/pasteable examples for ad-hoc servers by repeating the HTTP URL (with quoting) so the commands shown under `Examples:` actually work before you persist the definition. ### Code generation + - Staged the actual dependency directories (`commander`, `mcporter`) directly into the Bun bundler workspace so `npx mcporter generate-cli "npx -y chrome-devtools-mcp" --compile` succeeds even when npm hoists dependencies outside the package (fixes the regression some users still saw with 0.3.5). ## [0.3.5] - 2025-11-08 ### Code generation + - Ensure the Bun bundler resolves `commander`/`mcporter` even when `npx mcporter generate-cli … --compile` runs inside an empty temp directory by symlinking mcporter’s own `node_modules` into the staging workspace before invoking `bun build`. This keeps the “one weird trick” workflow working post-0.3.4 without requiring extra installs. ## [0.3.4] - 2025-11-08 ### CLI & runtime + - Added a global `--oauth-timeout <ms>` flag (and the matching `MCPORTER_OAUTH_TIMEOUT_MS` override) so long-running OAuth handshakes can be shortened during debugging; the runtime now logs a clear warning and tears down the flow once the limit is reached, ensuring `mcporter list/call/auth` always exit. ### Docs + - Documented the new OAuth timeout flag/env var across the README and tmux/hang-debug guides so release checklists and manual repro steps call out the faster escape hatch. ## [0.3.3] - 2025-11-07 ### Code generation + - When a server definition omits `description`, `mcporter generate-cli` now asks the MCP server for its own `instructions`/`serverInfo.title` during tool discovery and embeds that value, so generated CLIs introduce themselves with the real server description instead of the generic “Standalone CLI…” fallback. - Embedded tool listings inside generated CLIs now show each command’s flag signature (no `usage:` prefix) separated by blank lines, and per-command `--help` output inherits the same colorized usage/option styling as the main `mcporter` binary for readability on rich TTYs. - Added a `--bundler rolldown|bun` flag to `mcporter generate-cli`, defaulting to Rolldown but allowing Bun’s bundler (when paired with `--runtime bun`) for teams that want to stay entirely inside the Bun toolchain. The generator now records the chosen bundler in artifact metadata and enforces the Bun-only constraint so reproduction via `--from` stays deterministic. @@ -296,50 +359,58 @@ ## [0.3.2] - 2025-11-07 ### CLI + - Embedded the CLI version so Homebrew/Bun builds respond to `mcporter --version` even when `package.json` is unavailable. - Revamped `mcporter --help` to mirror the richer list/call formatting (name + summary rows, grouped sections, quick-start examples, and ANSI colors when TTYs are detected). - Fixed `mcporter list` so it no longer errors when `config/mcporter.json` is absent—fresh installs now run without creating config files, and a regression test guards the optional-config flow. - Generated standalone CLIs now print the full help menu (same grouped layout as the main CLI) when invoked without arguments, matching the behavior of `mcporter` itself. ### Code generation + - Generated binaries now default to the current working directory (using the inferred server name) when `--compile` is provided without a path, and automatically append a numeric suffix when the target already exists. - Standalone CLIs inherit the improved help layout (color-aware title, grouped command summaries, embedded tool listings, and quick-start snippets) so generated artifacts read the same way as the main CLI. - Swapped the bundler from esbuild to Rolldown for both JS and Bun targets, removing the fragile per-architecture esbuild binaries while keeping aliasing for local dependencies and honoring `--minify` via Rolldown’s native minifier. - Improved `generate-cli` so inline stdio commands (e.g., `"npx chrome-devtools-mcp"`) parse correctly even when invoked from empty directories. ### Code generation + - `readPackageMetadata()` now tolerates missing `package.json` files; when invoked from a directory without a manifest it falls back to mcporter’s own version string, so `generate-cli` works even when you call it via `npx` in an empty folder. ## [0.3.1] - 2025-11-07 ### CLI & runtime + - Short-circuited global `--help` / `--version` handling so these flags no longer fall through command inference and always print immediately, regardless of which command the user typed first. - Added regression coverage for the new shortcuts and kept the existing `runCli` helper exported so tests (and downstream tools) can exercise argument parsing without forking the entire process. ### Code generation & metadata + - Fixed `mcporter generate-cli --bundle/--compile` in empty directories by aliasing `commander`/`mcporter` imports to the CLI’s own installation so esbuild always resolves dependencies. Verified with a new fixture that bundles from temp dirs without `node_modules` (fixes #1). - Added an end-to-end integration test that runs `node dist/cli.js generate-cli` twice—once for bundling and once for `--compile`—as well as a GitHub Actions step that installs Bun so CI exercises the compiled binary path on every PR. - ## [0.3.0] - 2025-11-06 ### CLI & runtime + - Added configurable log levels (`--log-level` / `MCPORTER_LOG_LEVEL`) that default to `warn`, promoting noisy transport fallbacks to warnings so critical issues still surface. - Forced the CLI to exit cleanly after shutdown (opt out with `MCPORTER_NO_FORCE_EXIT`) and patched `StdioClientTransport` so stdio MCP servers no longer leave Node handles hanging; stderr from stdio servers is buffered and replayed via `MCPORTER_STDIO_LOGS=1` or whenever a server exits with a non-zero status. ### Discovery, calling, and ad-hoc workflows + - Rebuilt `mcporter list`: spinner updates stream live, summaries print only after discovery completes, and single-server views now render TypeScript-style doc blocks, inline examples, inferred return hints, and compact `// optional (N): …` summaries. The CLI guarantees at least five parameters before truncating, introduced a single `--all-parameters` switch (replacing the `--required-only` / `--include-optional` pair), and shares its formatter with `mcporter generate-cli` so signatures are consistent everywhere. - Verb inference and parser upgrades let bare server names dispatch to `list`, dotted invocations jump straight to `call`, colon-delimited flags (`key:value` / `key: value`) sit alongside `key=value`, and the JavaScript-like call syntax now supports unlabeled positional arguments plus typo correction heuristics when tool names are close but not exact. - Ad-hoc workflows are significantly safer: `--http-url` / `--stdio` definitions (with `--env`, `--cwd`, `--name`, `--persist`) work across `list`, `call`, and `auth`, mcporter reuses existing config entries when a URL matches (preserving OAuth tokens / redirect URIs), and `mcporter auth <url>` piggybacks on the same resolver to persist entries or retry when a server flips modes mid-flight. - Hardened OAuth detection automatically promotes ad-hoc HTTP servers that return 401/403 to `auth: "oauth"`, broadens the unauthorized heuristic for Supabase/Vercel/GitHub-style responses, and performs a one-time retry whenever a server switches into OAuth mode while you are connecting. ### Code generation & metadata + - 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"` 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. - Expanded the ad-hoc/OAuth story across `README.md`, `docs/adhoc.md`, `docs/local.md`, `docs/known-issues.md`, and `docs/supabase-auth-issue.md`, detailing when servers auto-promote to OAuth, how retries behave, and how to persist generated definitions safely. - Updated the README, CLI reference, and generator docs to cover the new `--all-parameters` flag, list formatter, metadata embedding, the `mcporter emit-ts` workflow, and refreshed branding so the CLI and docs consistently introduce the project as **MCPorter**. @@ -365,22 +436,28 @@ ## [0.1.0] - Initial release. + ## [0.6.2] - 2025-11-18 ### Platform resilience (Windows/WSL) + - Added `fs-helpers` that treat chmod/copy failures on NTFS/DrvFs as best-effort so CLI generation keeps working on WSL mounts. - Documented Windows/WSL workflows: install/test from ext4 copies, remount guidance for /mnt/c, and syncing tips. ### CLI/runtime + - Global flag parsing moved into `cli-factory` for consistent log-level/oauth-timeout handling across commands. - `daemon` host/client hardened and covered with new tests; idle eviction and restart paths verified. - Imports now include platform-aware defaults for Cursor/Claude/Windsurf/VS Code/OpenCode configs with path dedupe. ### StdIO MCP coverage + - Added stdio e2e tests using in-repo filesystem & memory MCP fixtures to ensure list/call works via execPath. ### Content extraction + - `createCallResult` now reads nested `raw.content`/`raw.structuredContent` so tools that wrap responses render text/markdown/json correctly; new unit tests cover text joining, markdown, and JSON. ### Docs + - New `docs/windows.md` with WSL/NTFS tips; added to docs index. diff --git a/config/mcporter.json b/config/mcporter.json index 7272fc3..77971a6 100644 --- a/config/mcporter.json +++ b/config/mcporter.json @@ -3,10 +3,7 @@ "chrome-devtools": { "description": "Chrome DevTools protocol bridge for driving local tabs during debugging or automation.", "command": "npx", - "args": [ - "-y", - "chrome-devtools-mcp@latest" - ], + "args": ["-y", "chrome-devtools-mcp@latest"], "env": { "npm_config_loglevel": "error" } @@ -14,10 +11,7 @@ "mobile-mcp": { "description": "Mobile Next MCP server for automating iOS/Android simulators and devices.", "command": "npx", - "args": [ - "-y", - "@mobilenext/mobile-mcp@latest" - ], + "args": ["-y", "@mobilenext/mobile-mcp@latest"], "env": { "npm_config_loglevel": "error" } @@ -47,10 +41,7 @@ "obsidian": { "description": "Local Obsidian vault access via obsidian-mcp-server.", "command": "npx", - "args": [ - "-y", - "obsidian-mcp-server@latest" - ], + "args": ["-y", "obsidian-mcp-server@latest"], "env": { "OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}", "OBSIDIAN_BASE_URL": "${OBSIDIAN_BASE_URL:-https://127.0.0.1:27124}", @@ -84,10 +75,7 @@ "signoz": { "description": "SigNoz Query MCP server (logs, traces, metrics).", "command": "npx", - "args": [ - "-y", - "signoz-mcp-server@latest" - ], + "args": ["-y", "signoz-mcp-server@latest"], "env": { "SIGNOZ_URL": "${SIGNOZ_URL:-http://localhost:3301}", "SIGNOZ_TOKEN": "${SIGNOZ_TOKEN:-}", @@ -102,13 +90,7 @@ "iterm": { "description": "iTerm2 terminal bridge via local iterm-mcp", "command": "pnpm", - "args": [ - "--dir", - "/Users/steipete/Projects/iterm-mcp", - "exec", - "node", - "build/index.js" - ], + "args": ["--dir", "/Users/steipete/Projects/iterm-mcp", "exec", "node", "build/index.js"], "env": { "npm_config_loglevel": "error" } @@ -116,19 +98,11 @@ "XcodeBuildMCP": { "description": "XcodeBuild MCP server for building, testing, and inspecting Xcode projects and simulators.", "command": "npx", - "args": [ - "-y", - "xcodebuildmcp@latest" - ], + "args": ["-y", "xcodebuildmcp@latest"], "env": { "npm_config_loglevel": "error" } } }, - "imports": [ - "cursor", - "claude-code", - "claude-desktop", - "codex" - ] + "imports": ["cursor", "claude-code", "claude-desktop", "codex"] } diff --git a/docs/adhoc.md b/docs/adhoc.md index c04d0f9..e1050f0 100644 --- a/docs/adhoc.md +++ b/docs/adhoc.md @@ -16,6 +16,7 @@ Two new flag sets let you describe a server on the command line: - `mcporter call --stdio "bun run ./server.ts" --name local-tools` You can also pass a bare URL as the selector (`mcporter list https://mcp.linear.app/mcp`) or embed the URL in a `call` expression (`mcporter call 'https://mcp.example.com/tools.generate({ topic: "release" })'`). + - Add `--json` to `mcporter list …` when you need a machine-readable summary of status counts and per-server failures, use `--output json`/`--output raw` with `mcporter call` to receive structured `{ server, tool, issue }` envelopes whenever a transport error occurs, and run `mcporter auth … --json` to capture the same envelope if OAuth or transport setup fails. ### Example: HTTP ad-hoc workflow diff --git a/docs/call-heuristic.md b/docs/call-heuristic.md index 759a42d..98b3286 100644 --- a/docs/call-heuristic.md +++ b/docs/call-heuristic.md @@ -6,19 +6,22 @@ read_when: # Call Command Auto-Correction -`mcporter call` aims to help when a tool name is *almost* correct without hiding real mistakes. +`mcporter call` aims to help when a tool name is _almost_ correct without hiding real mistakes. ## Confident Matches → Auto-Correct + - We normalise tool names (strip punctuation, lowercase) and compute a Levenshtein distance. - If the distance is ≤ `max(2, floor(length × 0.3))`, or the names only differ by case/punctuation, we retry automatically. - A dim informational line explains the correction: `[mcporter] Auto-corrected tool call to linear.list_issues (input: linear.listIssues).` ## Low-Confidence Matches → Suggest + - When the best candidate falls outside the threshold we keep the original failure. - We still print a hint so the user learns the canonical name: `[mcporter] Did you mean linear.list_issue_statuses?` - No second call is attempted in this case. ## Edge Cases + - We only inspect the tool catalog if the server explicitly replied with “Tool … not found”. Other MCP errors surface untouched. - If listing tools itself fails (auth, offline, etc.) we skip both auto-correct and hints. - Behaviour is covered by `tests/cli-call.test.ts`. diff --git a/docs/call-syntax.md b/docs/call-syntax.md index 6e3dfee..734f21d 100644 --- a/docs/call-syntax.md +++ b/docs/call-syntax.md @@ -8,11 +8,11 @@ read_when: `mcporter call` now understands two complementary styles: -| Style | Example | Notes | -|-------|---------|-------| -| Flag-based (compatible) | `mcporter call linear.create_comment --issue-id LNR-123 --body "Hi"` | Use `key=value`, `key:value`, or `key: value` pairs—ideal for shell scripts. | -| Function-call (expressive) | `mcporter call 'linear.create_comment(issueId: "LNR-123", body: "Hi")'` | Mirrors the pseudo-TypeScript signature shown by `mcporter list`; unlabeled values map to schema order. | -| Structured output | `mcporter call 'linear.create_comment(...)' --output json` | Successful calls emit JSON bodies; failures emit `{ server, tool, issue }` envelopes so automation can react to auth/offline/http errors. | +| Style | Example | Notes | +| -------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| Flag-based (compatible) | `mcporter call linear.create_comment --issue-id LNR-123 --body "Hi"` | Use `key=value`, `key:value`, or `key: value` pairs—ideal for shell scripts. | +| Function-call (expressive) | `mcporter call 'linear.create_comment(issueId: "LNR-123", body: "Hi")'` | Mirrors the pseudo-TypeScript signature shown by `mcporter list`; unlabeled values map to schema order. | +| Structured output | `mcporter call 'linear.create_comment(...)' --output json` | Successful calls emit JSON bodies; failures emit `{ server, tool, issue }` envelopes so automation can react to auth/offline/http errors. | Both forms share the same validation pipeline, so required parameters, enums, and formats behave identically. diff --git a/docs/cli-generator.md b/docs/cli-generator.md index e0db864..ad963d8 100644 --- a/docs/cli-generator.md +++ b/docs/cli-generator.md @@ -9,9 +9,11 @@ read_when: Default behavior: generating `<server>.ts` in the working directory if no output path is provided. Bundling is opt-in via `--bundle` and produces a single JS file with shebang; otherwise we emit TypeScript targeting Node.js. Rolldown handles bundling by default unless the runtime resolves to Bun—in that case Bun’s native bundler is selected automatically (still requires `--runtime bun` or Bun auto-detection); `--bundler` lets you override either choice. ## Goal + Create an `mcporter generate-cli` command that produces a standalone CLI for a single MCP server. The generated CLI should feel like a Unix tool: subcommands map to MCP tools, arguments translate to schema fields, and output can be piped/redirected easily. ## High-Level Requirements + - **Input**: Identify the target server either by shorthand name or by providing an explicit MCP server definition. - **Output**: Emit a TypeScript file (ESM) targeting Node.js by default (`<server>.ts` unless `--output` overrides). Bundling to a standalone JS file happens only when `--bundle` is passed. - **Runtime Selection**: Prefer Bun when it is available (`bun --version` succeeds); otherwise fall back to Node.js. Callers can force either runtime via `--runtime bun|node`. @@ -21,6 +23,7 @@ Create an `mcporter generate-cli` command that produces a standalone CLI for a s - **Documentation**: Update README (or similar) to show how to generate and use the CLI. ## Steps + 1. **Command Scaffolding** - Add `generate-cli` subcommand to the existing CLI. - Parse flags: `--server`, `--name`, `--command`, optional `--description`, plus `--output`, `--runtime=node|bun`, `--bundle`, `--bundler=rolldown|bun`, `--minify`, `--compile`, `--include-tools`, `--exclude-tools`, etc. Runtime auto-detects Bun when available, and the bundler inherits that choice unless overridden. @@ -53,6 +56,7 @@ Create an `mcporter generate-cli` command that produces a standalone CLI for a s - Provide an example generated CLI under `examples/generated/<server>.ts` (if we keep an examples directory). ## Notes + - Generated CLI depends on the latest `commander` for argument parsing. - Default timeout for tool calls is 30 seconds, overridable via `--timeout`. - Runtime flag remains (`--runtime bun`) to tailor shebang/usage instructions, but Node.js is the default. @@ -94,8 +98,6 @@ npx mcporter generate-cli --command "npx -y chrome-devtools-mcp@latest" `npx mcporter generate-cli linear --exclude-tools debug_tool,admin_reset`. ``` - - ## Artifact Metadata & Regeneration - Every generated artifact embeds its metadata (generator version, resolved server definition, invocation flags). A hidden `__mcporter_inspect` subcommand prints the payload without contacting the MCP server, so binaries remain self-describing even after being copied to another machine. @@ -103,14 +105,14 @@ npx mcporter generate-cli --command "npx -y chrome-devtools-mcp@latest" - `mcporter generate-cli --from <artifact>` replays the stored invocation against the latest mcporter build. `--server`, `--runtime`, `--timeout`, `--minify/--no-minify`, `--bundle`, `--compile`, `--output`, and `--dry-run` let you override specific pieces of the stored metadata when necessary. - Because the metadata lives inside the artifact, any template, bundle, or compiled binary can be refreshed after a generator upgrade without juggling sidecar files. - - ## Status + - ✅ `generate-cli` subcommand implemented with schema-aware proxy generation. - ✅ Inline JSON / file / shorthand server resolution wired up. - ✅ Bundling via Rolldown by default (or Bun automatically when the runtime is Bun, with `--bundler` available for overrides) plus optional minification and Bun bytecode compilation. - ✅ Integration tests cover bundling, minification, compiled binaries, and metadata/regeneration flows against the mock MCP server. Next steps: + 1. Add optional shell completion scaffolding if demand arises. 2. Explore templated TypeScript definitions for generated CLIs to improve editor tooling. diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 3384ec4..ff8cbc3 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -10,6 +10,7 @@ A quick reference for the primary `mcporter` subcommands. Each command inherits `--config <file>` and `--root <dir>` to override where servers are loaded from. ## `mcporter list [server]` + - Without arguments, lists every configured server (with live discovery + brief status). - With a server name, prints TypeScript-style signatures for each tool, doc @@ -22,6 +23,7 @@ A quick reference for the primary `mcporter` subcommands. Each command inherits - `--timeout <ms>` – per-server timeout when enumerating all servers. ## `mcporter call <server.tool>` + - Invokes a tool once and prints the response; supports positional arguments via pseudo-TS syntax and `--arg` flags. - Useful flags: @@ -35,6 +37,7 @@ A quick reference for the primary `mcporter` subcommands. Each command inherits - `--tail-log` – stream tail output when the tool returns log handles. ## `mcporter generate-cli` + - Produces a standalone CLI for a single MCP server (optionally bundling or compiling with Bun). - Key flags: @@ -58,6 +61,7 @@ A quick reference for the primary `mcporter` subcommands. Each command inherits treats the URL as an ad-hoc server definition. ## `mcporter emit-ts <server>` + - Emits TypeScript definitions (and optionally a ready-to-use client) describing a server’s tools. This reuses the same formatter as `mcporter list` so doc comments, signatures, and examples stay in sync. diff --git a/docs/config.md b/docs/config.md index ddc22a6..faf354d 100644 --- a/docs/config.md +++ b/docs/config.md @@ -5,6 +5,7 @@ read_when: --- # CLI Help Menu Snapshot + ``` mcporter config Usage: mcporter config [options] <command> @@ -35,9 +36,11 @@ See https://github.com/sweetistics/mcporter/blob/main/docs/config.md for config # Configuration Guide ## Overview + mcporter keeps three configuration buckets in sync: repository-scoped JSON (`config/mcporter.json`), imported editor configs (Cursor, Claude, Codex, Windsurf, OpenCode, VS Code), and ad-hoc definitions supplied on the CLI. This guide explains how those sources merge, how to mutate them with `mcporter config ...`, and the safety rails around OAuth, env interpolation, and persistence. ## Quick Start + 1. Create `config/mcporter.json` at the repo root: ```jsonc { @@ -46,10 +49,10 @@ mcporter keeps three configuration buckets in sync: repository-scoped JSON (`con "linear": { "description": "Linear issues", "baseUrl": "https://mcp.linear.app/mcp", - "headers": { "Authorization": "Bearer ${LINEAR_API_KEY}" } - } + "headers": { "Authorization": "Bearer ${LINEAR_API_KEY}" }, + }, }, - "imports": ["cursor", "claude-code", "claude-desktop", "codex", "windsurf", "opencode", "vscode"] + "imports": ["cursor", "claude-code", "claude-desktop", "codex", "windsurf", "opencode", "vscode"], } ``` The `$schema` property enables IDE autocomplete and validation. Use the raw GitHub URL for the latest schema, or copy `mcporter.schema.json` locally. @@ -66,41 +69,47 @@ mcporter now merges home and project config files by default so global servers s 3. Otherwise, mcporter loads both of these layers (when present): - `~/.mcporter/mcporter.json` or `~/.mcporter/mcporter.jsonc` - `<root>/config/mcporter.json` - Entries from the project file override entries with the same name from the home file. Each layer still pulls in its own imports before merging. + Entries from the project file override entries with the same name from the home file. Each layer still pulls in its own imports before merging. All `mcporter config …` mutations still write back to a single file: the explicit path when provided; otherwise the project config path (`<root>/config/mcporter.json`). To edit the home file explicitly, run commands like `mcporter config --config ~/.mcporter/mcporter.json add <name> …` or set `MCPORTER_CONFIG` in your shell profile. ## Discovery & Precedence + mcporter builds a merged view of all known servers before executing any command. The sources load in this order: -| Priority | Source | Notes | -| --- | --- | --- | -| 1 | Explicit `--http-url`, `--stdio`, or bare URL passed to commands | Highest priority, never cached unless `--persist` is supplied. Requires `--allow-http` for plain HTTP URLs. | -| 2 | `config/mcporter.json` (or the file passed via `--config`) | Default path is `<root>/config/mcporter.json`; missing file returns an empty config so commands continue to work. | -| 3 | Imports listed in `"imports"` | When you omit `imports`, mcporter loads `['cursor','claude-code','claude-desktop','codex','windsurf','opencode','vscode']`. When you specify a non-empty array, mcporter appends any omitted defaults after your list so shared presets remain available. | +| Priority | Source | Notes | +| -------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Explicit `--http-url`, `--stdio`, or bare URL passed to commands | Highest priority, never cached unless `--persist` is supplied. Requires `--allow-http` for plain HTTP URLs. | +| 2 | `config/mcporter.json` (or the file passed via `--config`) | Default path is `<root>/config/mcporter.json`; missing file returns an empty config so commands continue to work. | +| 3 | Imports listed in `"imports"` | When you omit `imports`, mcporter loads `['cursor','claude-code','claude-desktop','codex','windsurf','opencode','vscode']`. When you specify a non-empty array, mcporter appends any omitted defaults after your list so shared presets remain available. | Rules: + - Later sources never override earlier ones. Local config always wins over imports; ad-hoc descriptors override both for the duration of a command. - Each merged server tracks its origin (local path vs. import path), so `mcporter config get <name>` can show you the path before you edit or remove the local copy with `mcporter config remove <name>`. - Imports remain read-only until you explicitly copy an entry via `mcporter config import <kind> --copy` or run `mcporter config add --copy-from claude-code:linear` (feature planned alongside the CLI work). ## CLI Workflows + `mcporter config` is the entry point for reading and writing configuration files. Use the existing ad-hoc flags on `mcporter list|call|auth` when you want ephemeral definitions; once you’re ready to persist them, switch back to `mcporter config add`. Use `--scope home|project` with `mcporter config add` to pick the write target explicitly. `project` is always the default (creating `config/mcporter.json` if needed); `home` writes to `~/.mcporter/mcporter.json` even when a project config is present. `--persist <path>` still takes precedence when you need a custom file. ### `mcporter config list [filter]` + - Shows **local** entries by default. Pass `--source import` to list imported editor configs, or `--json` for machine output. - Always appends a summary of other config files (paths, counts, sample names) so you know where imported entries live. - `filter` accepts a name, glob fragment, or `source:cursor` selector. - Adds informational notes when we auto-correct names (same machinery as `mcporter list`). ### `mcporter config get <name>` + - Prints the resolved definition for a single server, including the on-disk path, inherited headers/env, and transport details. - Near-miss names are auto-corrected with the same heuristics as `mcporter list`/`call`, and you’ll see suggestions whenever ambiguity remains. - Supports ad-hoc descriptors so you can inspect a URL before persisting it. ### `mcporter config add <name> [target]` + - Persists a server into the writable config file. Accepts both positional shortcuts (`mcporter config add sentry https://mcp.sentry.dev/mcp`) and flag-driven definitions: - `--transport http|sse|stdio` - `--url` or `--command`/`--stdio` @@ -109,9 +118,11 @@ Use `--scope home|project` with `mcporter config add` to pick the write target e - `--dry-run` shows the JSON diff without writing, while `--persist <path>` overrides the destination file. ### `mcporter config remove <name>` + - Removes the local definition. Names sourced exclusively from imports remain untouched until you copy them locally. ### `mcporter config import <kind>` + - Displays (and optionally copies) entries from editor-specific configs: - `cursor`: `.cursor/mcp.json` in the repo, falling back to `~/.config/Cursor/User/mcp.json` (or `%APPDATA%/Cursor/User` on Windows). - `claude-code`: `<root>/.claude/settings.local.json`, `<root>/.claude/settings.json`, `<root>/.claude/mcp.json`, then `~/.claude/settings.json`, `~/.claude/mcp.json`, `~/.claude.json`. `settings.local.json` is meant for untracked per-developer overrides, while `settings.json` is the shared project config. @@ -123,14 +134,17 @@ Use `--scope home|project` with `mcporter config add` to pick the write target e - `--copy` writes selected entries into your local config; `--filter <glob>` narrows the import list; `--path <file>` lets you point at bespoke locations. ### `mcporter config login <name|url>` / `logout` + - Mirrors `mcporter auth`. `login` completes OAuth (or token provisioning) for either a named server or an ad-hoc URL. When a hosted MCP returns 401/403, mcporter automatically promotes that target to OAuth and re-runs the flow, matching the behavior documented in `docs/adhoc.md`. - `--browser none` suppresses automatic browser launch (useful for copying the URL into a remote browser). - `logout` wipes token caches under `~/.mcporter/<name>/` (or the custom `tokenCacheDir`). Pass `--all` to clear everything. ### `mcporter config doctor` + - Early validator that checks for simple issues (e.g., OAuth entries missing cache paths). Future iterations will add fixes for Accept headers, duplicate imports, and more. ## Ad-hoc & Persistence + - `--http-url` and `--stdio` flags live on `mcporter list|call|auth`, keeping `mcporter config` focused on persistent config files. - Names default to slugified hostnames or executable/script combos. Supply `--name` to improve reuse; mcporter uses that slug for OAuth caches even before persistence. - `--allow-http` is mandatory for cleartext endpoints so we never downgrade transport silently. @@ -138,6 +152,7 @@ Use `--scope home|project` with `mcporter config add` to pick the write target e - `--env KEY=VAL` entries merge with existing `env` dictionaries if you later persist the same server; nothing is lost when you alternate between CLI flags and JSON edits. ## JSON Schema for IDE Support + mcporter provides a JSON Schema for config file validation and autocompletion. Add the `$schema` property to your config file: ```jsonc @@ -148,6 +163,7 @@ mcporter provides a JSON Schema for config file validation and autocompletion. A ``` For local development, you can reference the schema from the repo root: + ```jsonc { "$schema": "../mcporter.schema.json", @@ -158,48 +174,53 @@ For local development, you can reference the schema from the repo root: The schema is auto-generated from the Zod validation schemas using `pnpm generate:schema`. ## Schema Reference + Top-level structure: -| Key | Type | Description | -| --- | --- | --- | -| `mcpServers` | object | Map of server names → definitions. Required even if empty. | -| `imports` | string[] | Optional list of import kinds. Empty array disables imports entirely; omitting the key falls back to the default list. | +| Key | Type | Description | +| ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------- | +| `mcpServers` | object | Map of server names → definitions. Required even if empty. | +| `imports` | string[] | Optional list of import kinds. Empty array disables imports entirely; omitting the key falls back to the default list. | Server definition fields (subset of what `RawEntrySchema` accepts): -| Field | Description | -| --- | --- | -| `description` | Free-form summary printed by `mcporter list`/`config list`. | -| `baseUrl` / `url` / `serverUrl` | HTTPS or HTTP endpoint. `http://` requires `--allow-http` in ad-hoc mode but works in config if you explicitly set it. | -| `command` / `args` | Stdio executable definition (string or array). Arrays are preferred because they avoid shell quoting issues. | -| `env` | Key/value pairs applied when launching stdio commands. Supports `${VAR}` interpolation and `${VAR:-fallback}` defaults. Existing process env values win over fallbacks. | -| `headers` | Request headers for HTTP/SSE transports. Values can reference `$env:VAR` or `${VAR}` placeholders, which must be set at runtime or mcporter aborts with a helpful error. -| `auth` | Currently only `oauth` is recognized. Any other string is ignored (treated as undefined) to avoid stale state from other clients. | -| `tokenCacheDir` | Directory for OAuth tokens; still honored, but mcporter now keeps a centralized vault in `~/.mcporter/credentials.json` (legacy per-server caches are auto-migrated). Supports `~` expansion. | -| `clientName` | Optional identifier some servers use for telemetry/audience segmentation. | -| `oauthRedirectUrl` | Override the default localhost callback. Useful when tunneling OAuth through Codespaces or remote dev boxes. | -| `oauthScope` | Optional explicit OAuth scope string. If omitted, mcporter lets the MCP SDK derive scope from server/auth metadata. Use this as an escape hatch for providers that require explicit scopes but don’t publish `scopes_supported`. | -| `oauthCommand.args` | For STDIO servers that ship a custom auth subcommand (e.g., Gmail MCP). mcporter will spawn the stdio command with these args when you run `mcporter auth <name>`, so you don’t need to call `npx ... auth` manually. | +| Field | Description | +| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `description` | Free-form summary printed by `mcporter list`/`config list`. | +| `baseUrl` / `url` / `serverUrl` | HTTPS or HTTP endpoint. `http://` requires `--allow-http` in ad-hoc mode but works in config if you explicitly set it. | +| `command` / `args` | Stdio executable definition (string or array). Arrays are preferred because they avoid shell quoting issues. | +| `env` | Key/value pairs applied when launching stdio commands. Supports `${VAR}` interpolation and `${VAR:-fallback}` defaults. Existing process env values win over fallbacks. | +| `headers` | Request headers for HTTP/SSE transports. Values can reference `$env:VAR` or `${VAR}` placeholders, which must be set at runtime or mcporter aborts with a helpful error. | +| `auth` | Currently only `oauth` is recognized. Any other string is ignored (treated as undefined) to avoid stale state from other clients. | +| `tokenCacheDir` | Directory for OAuth tokens; still honored, but mcporter now keeps a centralized vault in `~/.mcporter/credentials.json` (legacy per-server caches are auto-migrated). Supports `~` expansion. | +| `clientName` | Optional identifier some servers use for telemetry/audience segmentation. | +| `oauthRedirectUrl` | Override the default localhost callback. Useful when tunneling OAuth through Codespaces or remote dev boxes. | +| `oauthScope` | Optional explicit OAuth scope string. If omitted, mcporter lets the MCP SDK derive scope from server/auth metadata. Use this as an escape hatch for providers that require explicit scopes but don’t publish `scopes_supported`. | +| `oauthCommand.args` | For STDIO servers that ship a custom auth subcommand (e.g., Gmail MCP). mcporter will spawn the stdio command with these args when you run `mcporter auth <name>`, so you don’t need to call `npx ... auth` manually. | mcporter normalizes headers to include `Accept: application/json, text/event-stream` automatically, matching the runtime’s streaming expectations. ## Imports & Conflict Resolution + - `pathsForImport(kind, rootDir)` determines every candidate path. mcporter searches the repo first, then user-level directories, and stops at the first file that parses. - Entries pulled from imports are treated as read-only snapshots. The merge process keeps the first definition for each name; later sources with the same name are skipped until you override locally. - To copy an imported entry, either run `mcporter config import <kind> --copy --filter name` or use `mcporter config add name --copy-from kind:name`. The copy operation writes through the same JSON normalization stack, so the resulting file matches our schema even if the source format was TOML (Codex) or legacy JSON shapes (`servers` vs `mcpServers`). ## Project vs. Machine Layers + - Keep `config/mcporter.json` under version control. Encourage contributors to add sensitive data via env vars (`${LINEAR_API_KEY}`) rather than inline secrets. - Machine-specific additions can live in `~/.mcporter/local.json`; point `mcporter config --config ~/.mcporter/local.json add ...` there when you prefer not to touch the repo. Since the runtime only watches one config at a time, CI jobs should always pass `--config config/mcporter.json` (or run from the repo root) for deterministic behavior. - OAuth tokens, cached server metadata, and generated CLIs should remain outside the repo (`~/.mcporter/<name>/`, `dist/`). ## Validation & Troubleshooting + - `mcporter list --http-url ...` refuses to auto-run OAuth to keep listing commands quick; use `mcporter config login ...` or `mcporter auth ...` to finish credential setup. - When env placeholders are missing, commands fail fast with the exact variable name. Add the variable or wrap it in `${VAR:-fallback}` to provide defaults. - Use `mcporter config get <name> --show-source` (planned flag) to confirm whether a server came from an import. If a teammate’s Cursor config keeps overriding your local entry, reorder the `imports` array to move Cursor later or set it to `[]` to disable imports entirely. - `docs/adhoc.md` covers deeper debugging, including tmux workflows and OAuth promotion logs. ## Outstanding Coverage Items + - Describe how `--persist` writes through the same import merge pipeline (especially once `mcporter config add --copy-from` ships) so users know exactly which file changes. - Call out that `--allow-http` remains required for cleartext URLs even in config mutations, and reiterate that `--env KEY=VAL` merges with on-disk env blocks rather than replacing them entirely. - Clarify and illustrate the automatic OAuth promotion path for ad-hoc HTTP entries in both this doc and future `mcporter config login` help output. diff --git a/docs/emit-ts.md b/docs/emit-ts.md index d1ee1d8..fc13a4e 100644 --- a/docs/emit-ts.md +++ b/docs/emit-ts.md @@ -19,14 +19,14 @@ mcporter emit-ts <server> --out linear-client.ts \ ``` - `--mode types` (default) emits a `.d.ts` interface (`LinearTools`) with -docblocks + promisified signatures. Missing output schemas fall back to -`CallResult`. + docblocks + promisified signatures. Missing output schemas fall back to + `CallResult`. - `--mode client` emits both the interface (auto-derived `.d.ts`) **and** an -executable `.ts` helper that wraps `createServerProxy`. Each method returns a -`CallResult`, and the factory exposes a `close()` helper for runtimes the client -creates. + executable `.ts` helper that wraps `createServerProxy`. Each method returns a + `CallResult`, and the factory exposes a `close()` helper for runtimes the client + creates. - `--include-optional` mirrors `mcporter list --all-parameters`, ensuring every -parameter is shown even when optional. + parameter is shown even when optional. Outputs overwrite existing files automatically so you can regenerate artifacts whenever the server schema changes. @@ -81,13 +81,13 @@ returned object’s `close()` becomes a no-op. ## Flags -| Flag | Description | -| --- | --- | -| `--out <path>` | Required. `.d.ts` target for `types`, `.ts` target for `client`. | -| `--mode types|client` | Output kind (defaults to `types`). | +| Flag | Description | +| -------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------- | +| `--out <path>` | Required. `.d.ts` target for `types`, `.ts` target for `client`. | +| `--mode types | client` | Output kind (defaults to `types`). | | `--types-out <path>` | Optional override for the `.d.ts` file when `--mode client`. Default: derive from `--out`. | -| `--include-optional` | Include every parameter (not just the minimum 5 + required). | -| `--json` | Emit a JSON summary describing the emitted file(s) instead of plain-text logs. | +| `--include-optional` | Include every parameter (not just the minimum 5 + required). | +| `--json` | Emit a JSON summary describing the emitted file(s) instead of plain-text logs. | ## Testing diff --git a/docs/hang-debug.md b/docs/hang-debug.md index 76a2c46..cb14fc3 100644 --- a/docs/hang-debug.md +++ b/docs/hang-debug.md @@ -21,7 +21,7 @@ culprit is a child MCP server process that keeps the stdio transport alive. child remains, mcporter will now unref and force-kill it, but the debug list tells you exactly what was keeping the event loop alive. 4. **Capture the pane output** – run `tmux capture-pane -p -t <session> -S - -200` to save the diagnostic log for later review. +-200` to save the diagnostic log for later review. 5. **Retry with `--timeout`** – if the tool itself hangs, use `--timeout <ms>` or `MCPORTER_CALL_TIMEOUT` to fail fast while still gathering diagnostics. @@ -65,7 +65,7 @@ child process, which mcporter will now terminate during shutdown. - Killing residual children is best-effort; if you see repeated `kill-failed` messages, manually terminate the PID listed in the log. - Always keep tmux sessions tidy after debugging: `tmux kill-session -t - <session>`. +<session>`. - The CLI now forces `process.exit(0)` after cleanup by default so Node never lingers on leaked handles. Export `MCPORTER_NO_FORCE_EXIT=1` if you’re debugging and need the process to stay alive. diff --git a/docs/import.md b/docs/import.md index d514822..6a367c1 100644 --- a/docs/import.md +++ b/docs/import.md @@ -28,15 +28,15 @@ Set `"imports": []` when you want to disable auto-merging entirely, or supply a ## Import Support Matrix -| Kind | Typical owner | Format | Project paths | User paths | Notes | -| --- | --- | --- | --- | --- | --- | -| `cursor` | Cursor IDE | JSON (`mcpServers`) | `.cursor/mcp.json` | macOS/Linux: `${XDG_CONFIG_HOME:-~/.config}/Cursor/User/mcp.json`<br>Windows: `%APPDATA%/Cursor/User/mcp.json` | Mirrors Cursor’s “MCP Servers” panel. Per-workspace files override the global file when both exist. | -| `claude-code` | Claude Code (browser) | JSON (`mcpServers`) | `.claude/settings.local.json`, `.claude/settings.json`, `.claude/mcp.json` | `~/.claude/settings.json`, `~/.claude/mcp.json`, `~/.claude.json` | `settings.local.json` (ignored by git) overrides `settings.json`, which is the shared project config; both beat the legacy `mcp.json`. | -| `claude-desktop` | Claude Desktop | JSON (`mcpServers`) | — | macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`<br>Windows: `%APPDATA%/Claude/claude_desktop_config.json`<br>Linux: `~/.config/Claude/claude_desktop_config.json` | Desktop Claude stores all servers per-machine, so there’s no project-relative file. | -| `codex` | Sweetistics Codex | TOML (`[mcp_servers.*]`) | `.codex/config.toml` | `~/.codex/config.toml` | Only `config.toml` is recognized; the deprecated `mcp.toml` filename is ignored. | -| `windsurf` | Codeium Windsurf | JSON (`mcpServers`) | — | Windows: `%APPDATA%/Codeium/windsurf/mcp_config.json`<br>macOS/Linux: `~/.codeium/windsurf/mcp_config.json` | Global-only config managed by Codeium. | -| `opencode` | OpenCode | JSON/JSONC (`mcp`, `mcpServers`, or root map) | `opencode.json`, `opencode.jsonc` | `OPENCODE_CONFIG` override<br>`OPENCODE_CONFIG_DIR/opencode.json(c)`<br>macOS/Linux: `${XDG_CONFIG_HOME:-~/.config}/opencode/opencode.json(c)`<br>Windows: `%APPDATA%/opencode/opencode.json(c)` | Accepts comment-friendly `.jsonc` files and honors OpenCode’s precedence env vars. | -| `vscode` | VS Code MCP extension | JSON (`mcpServers` or `servers`) | — | macOS: `~/Library/Application Support/Code(/Code - Insiders)/User/mcp.json`<br>Windows: `%APPDATA%/Code(/Code - Insiders)/User/mcp.json`<br>Linux: `~/.config/Code(/Code - Insiders)/User/mcp.json` | We probe both Stable and Insiders directories; the first readable file wins. | +| Kind | Typical owner | Format | Project paths | User paths | Notes | +| ---------------- | --------------------- | --------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `cursor` | Cursor IDE | JSON (`mcpServers`) | `.cursor/mcp.json` | macOS/Linux: `${XDG_CONFIG_HOME:-~/.config}/Cursor/User/mcp.json`<br>Windows: `%APPDATA%/Cursor/User/mcp.json` | Mirrors Cursor’s “MCP Servers” panel. Per-workspace files override the global file when both exist. | +| `claude-code` | Claude Code (browser) | JSON (`mcpServers`) | `.claude/settings.local.json`, `.claude/settings.json`, `.claude/mcp.json` | `~/.claude/settings.json`, `~/.claude/mcp.json`, `~/.claude.json` | `settings.local.json` (ignored by git) overrides `settings.json`, which is the shared project config; both beat the legacy `mcp.json`. | +| `claude-desktop` | Claude Desktop | JSON (`mcpServers`) | — | macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`<br>Windows: `%APPDATA%/Claude/claude_desktop_config.json`<br>Linux: `~/.config/Claude/claude_desktop_config.json` | Desktop Claude stores all servers per-machine, so there’s no project-relative file. | +| `codex` | Sweetistics Codex | TOML (`[mcp_servers.*]`) | `.codex/config.toml` | `~/.codex/config.toml` | Only `config.toml` is recognized; the deprecated `mcp.toml` filename is ignored. | +| `windsurf` | Codeium Windsurf | JSON (`mcpServers`) | — | Windows: `%APPDATA%/Codeium/windsurf/mcp_config.json`<br>macOS/Linux: `~/.codeium/windsurf/mcp_config.json` | Global-only config managed by Codeium. | +| `opencode` | OpenCode | JSON/JSONC (`mcp`, `mcpServers`, or root map) | `opencode.json`, `opencode.jsonc` | `OPENCODE_CONFIG` override<br>`OPENCODE_CONFIG_DIR/opencode.json(c)`<br>macOS/Linux: `${XDG_CONFIG_HOME:-~/.config}/opencode/opencode.json(c)`<br>Windows: `%APPDATA%/opencode/opencode.json(c)` | Accepts comment-friendly `.jsonc` files and honors OpenCode’s precedence env vars. | +| `vscode` | VS Code MCP extension | JSON (`mcpServers` or `servers`) | — | macOS: `~/Library/Application Support/Code(/Code - Insiders)/User/mcp.json`<br>Windows: `%APPDATA%/Code(/Code - Insiders)/User/mcp.json`<br>Linux: `~/.config/Code(/Code - Insiders)/User/mcp.json` | We probe both Stable and Insiders directories; the first readable file wins. | > Tip: mcporter resolves `~` and `$XDG_CONFIG_HOME` inside these paths automatically, so you can rely on the same `imports` list across platforms. > diff --git a/docs/known-issues.md b/docs/known-issues.md index 83a1a6e..50feb59 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -9,6 +9,7 @@ read_when: This file tracks limitations that users regularly run into. Most of these require upstream cooperation or larger refactors—feel free to reference this when triaging bugs. ## Hosted OAuth servers (Supabase, GitHub MCP, etc.) + - Supabase’s hosted MCP server rejects the standard `mcp:tools` scope and only accepts Supabase-specific scopes (`projects:read`, `database:write`, ...). Because they do not expose OAuth discovery metadata or scope negotiation, mcporter cannot auto-register or complete the flow. Workarounds: - Use Supabase’s supported clients (Cursor, Windsurf). - Self-host their MCP server and configure PAT headers / custom OAuth. @@ -16,16 +17,19 @@ This file tracks limitations that users regularly run into. Most of these requir - GitHub’s MCP endpoint (`https://api.githubcopilot.com/mcp/`) returns “does not support dynamic client registration” when mcporter attempts to connect. Copilot’s backend expects pre-registered client credentials. Until GitHub publishes a dynamic-registration API (or client secrets), mcporter cannot interact with their hosted server. ## Output schemas missing/buggy on many servers + - The MCP spec allows servers to omit `outputSchema`. In practice, many hosted MCPs return empty or inconsistent schemas, so features that rely on return types (TypeScript signatures, generated CLIs, `createServerProxy` return helpers) may degrade to `unknown`. - Workarounds: inspect the server’s README / manual docs for output details, or wrap the tool via `createServerProxy` and handle the raw envelope manually. - Potential improvement: allow user-provided schema overrides (e.g., `mcporter config patch`, CLI flag to load schema JSON) so we can fill gaps on a per-tool basis. ## MCP SDK 1.22.0 inline-stdio regression + - Upgrading `@modelcontextprotocol/sdk` to 1.22.0 causes `mcporter generate-cli --compile` (and direct runtime `listTools`) to fail against inline STDIO servers with `MCP error -32603: Cannot read properties of undefined (reading 'typeName')`. - Repro: `pnpm mcporter generate-cli "node mock-stdio.mjs" --compile /tmp/inline-cli --runtime bun` using the inline stdio harness in `tests/cli-generate-cli.integration.test.ts`. - Status: reproduced locally; pinned the SDK to `~1.21.2` until upstream ships a fix. ## Next Steps + - Implement true scope negotiation (read discovery metadata, allow `--oauth-scope`). - Keep lobbying providers for spec-compliant OAuth behavior. - Consider adding schema override hooks or auto-caching schema snapshots per tool. diff --git a/docs/livetests.md b/docs/livetests.md index c6763e8..dc68f81 100644 --- a/docs/livetests.md +++ b/docs/livetests.md @@ -9,10 +9,12 @@ read_when: These tests hit real hosted MCP servers and require outbound HTTP. They are **off by default** to keep CI and local runs deterministic. ## When to run + - Before releases when you want end-to-end validation against hosted servers. - When debugging regressions that only repro against real servers (e.g., DeepWiki). ## How to run + ```bash MCP_LIVE_TESTS=1 pnpm test:live ``` @@ -20,6 +22,7 @@ MCP_LIVE_TESTS=1 pnpm test:live This runs the Vitest suite under `tests/live`, in-band, with longer timeouts. ## Current coverage + - **DeepWiki**: - Streamable HTTP success path: `https://mcp.deepwiki.com/mcp` - Deprecated SSE endpoint classification: `https://mcp.deepwiki.com/sse` @@ -28,6 +31,7 @@ This runs the Vitest suite under `tests/live`, in-band, with longer timeouts. - assert the legacy SSE endpoint currently returns a structured HTTP `410` issue envelope ## Notes + - Tests are skipped entirely unless `MCP_LIVE_TESTS=1` is set. - Ensure network egress is allowed. No secrets are required for the current DeepWiki checks. - As of 2026-03-29, DeepWiki's hosted `/sse` endpoint responds with HTTP `410`, so the live suite treats that as a compatibility/error-classification smoke rather than a success-path transport check. diff --git a/docs/manual-testing.md b/docs/manual-testing.md index d716bc7..a753570 100644 --- a/docs/manual-testing.md +++ b/docs/manual-testing.md @@ -40,6 +40,7 @@ cat /tmp/list-SERVER.log ``` Verify: + - Header shows the right name/transport and the new metadata line (`tools · duration · transport`). - Timeouts produce the footer block: `Tools: <timed out after ...>` and `Reason: ...`. @@ -53,6 +54,7 @@ cat /tmp/call-SERVER.log ``` Checks: + - Successful calls print the payload; failures reuse the shared hinting (`SSE error ...`, auto-correct messages, etc.). - For HTTP selectors (`https://.../mcp.tool` or `https://.../mcp.tool(args)`), ensure no OAuth prompt appears and the request hits the configured server. @@ -68,6 +70,7 @@ cat /tmp/auth-SERVER.log ``` Expectations: + - If a token cache exists, log should mention the cleared directory. - Failed auths emit the unified message (`Failed to authorize 'SERVER': ...`). diff --git a/docs/migration.md b/docs/migration.md index 41dc737..b4b3928 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -33,11 +33,11 @@ npm install mcporter ## 4. Programmatic Usage ```ts -import { createRuntime } from "mcporter"; +import { createRuntime } from 'mcporter'; -const runtime = await createRuntime({ configPath: "./config/mcporter.json" }); -const tools = await runtime.listTools("chrome-devtools"); -await runtime.callTool("chrome-devtools", "take_screenshot", { args: { url: "https://x.com" } }); +const runtime = await createRuntime({ configPath: './config/mcporter.json' }); +const tools = await runtime.listTools('chrome-devtools'); +await runtime.callTool('chrome-devtools', 'take_screenshot', { args: { url: 'https://x.com' } }); await runtime.close(); ``` @@ -46,12 +46,12 @@ Prefer `createRuntime` for long-lived agents so connections and OAuth tokens can ## 5. Single Call Helper ```ts -import { callOnce } from "mcporter"; +import { callOnce } from 'mcporter'; await callOnce({ - server: "firecrawl", - toolName: "crawl", - args: { url: "https://anthropic.com" }, + server: 'firecrawl', + toolName: 'crawl', + args: { url: 'https://anthropic.com' }, }); ``` @@ -65,12 +65,12 @@ Use `callOnce` for fire-and-forget invocations. ## 7. Troubleshooting -| Symptom | Fix | -| --- | --- | -| Browser did not open | Copy the printed OAuth URL manually into a browser. | -| Authorization hangs | Ensure the callback URL can bind to `127.0.0.1`; firewalls may block it. | -| Tokens are stale | Delete `~/.mcporter/<server>/tokens.json` and retry. | -| Stdio command fails | Pass `--root` to point at the repo root so relative paths resolve. | +| Symptom | Fix | +| -------------------- | ------------------------------------------------------------------------ | +| Browser did not open | Copy the printed OAuth URL manually into a browser. | +| Authorization hangs | Ensure the callback URL can bind to `127.0.0.1`; firewalls may block it. | +| Tokens are stale | Delete `~/.mcporter/<server>/tokens.json` and retry. | +| Stdio command fails | Pass `--root` to point at the repo root so relative paths resolve. | --- diff --git a/docs/refactor.md b/docs/refactor.md index 3da69b0..330acd9 100644 --- a/docs/refactor.md +++ b/docs/refactor.md @@ -9,7 +9,8 @@ read_when: This doc tracks remaining reuse/refactor work now that the original plan is done. Each section lists the goal, why it matters, and the concrete steps/tests needed. -## 1. Shared Tool Schema Cache *(Completed)* +## 1. Shared Tool Schema Cache _(Completed)_ + - **Problem**: `generate-cli` and `emit-ts` both fetch & serialize tool schemas independently (and `mcporter list` re-parses them too). - **What we did**: @@ -18,7 +19,8 @@ Each section lists the goal, why it matters, and the concrete steps/tests needed 3. Added `tests/tool-cache.test.ts` + updated emit-ts tests to ensure the helper is covered. - **Next**: Consider integrating the cache into `generate-cli` if we ever reuse runtime instances there. -## 2. Unified Flag Parsing for Generator-style Commands *(Completed)* +## 2. Unified Flag Parsing for Generator-style Commands _(Completed)_ + - **Problem**: `generate-cli`, the (now legacy) `regenerate-cli` wrapper, and `emit-ts` each reimplemented `--runtime`, `--timeout`, and `--include-optional` handling. - **What we did**: @@ -29,7 +31,8 @@ Each section lists the goal, why it matters, and the concrete steps/tests needed 3. Added `tests/generator-flag-parser.test.ts` to cover runtime/timeout and optional flags. -## 3. Test Fixture Reuse *(Completed)* +## 3. Test Fixture Reuse _(Completed)_ + - **Problem**: Emit-ts/tool-cache/unit tests each defined their own tool/definition fixtures, leading to divergence. - **What we did**: @@ -39,7 +42,8 @@ Each section lists the goal, why it matters, and the concrete steps/tests needed 3. Ensured the fixture covers required+optional parameters so both suites hit the same edge cases. -## 4. CallResult Helper Extraction *(Completed)* +## 4. CallResult Helper Extraction _(Completed)_ + - **Problem**: `call-command.ts` and the emit-ts client template both wrapped results with `createCallResult`, but there was no shared helper. - **What we did**: @@ -49,7 +53,8 @@ Each section lists the goal, why it matters, and the concrete steps/tests needed they stay in sync. 3. Adjusted emit-ts tests to assert the helper is referenced. -## 5. CLI Docs Consolidation *(Completed)* +## 5. CLI Docs Consolidation _(Completed)_ + - **Problem**: CLI usage guidance was scattered across README, `docs/spec.md`, and various feature docs. - **What we did**: @@ -60,7 +65,8 @@ Each section lists the goal, why it matters, and the concrete steps/tests needed - **Next**: Once the other doc changes land, update README/spec to link to the reference and drop redundant sections. -## 6. Runtime Module Split *(Completed)* +## 6. Runtime Module Split _(Completed)_ + - **Problem**: `src/runtime.ts` had grown bulky (600+ lines) mixing transport setup, OAuth flow control, and small helpers, making tests and reuse harder. - **What we did**: 1. Extracted transport construction/retry logic to `src/runtime/transport.ts`. @@ -72,5 +78,6 @@ Each section lists the goal, why it matters, and the concrete steps/tests needed - **Next**: Keep new helpers in sync as runtime evolves; prefer adding surface to these modules over growing `runtime.ts` again. --- + Tracking the above here keeps future agents aligned. Update this checklist as items ship (mark sections “Completed” when done, or delete the doc once empty). diff --git a/docs/spec.md b/docs/spec.md index 1e367f8..705dcd1 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -7,11 +7,13 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe > Inspired in part by Anthropic’s guidance on MCP code execution agents: https://www.anthropic.com/engineering/code-execution-with-mcp ## Goals + - Provide a TypeScript runtime + CLI that exposes all MCP servers defined in `~/Projects/sweetistics/config/mcporter.json`. - Preserve current one-shot `pnpm mcporter:call` ergonomics while enabling reusable connections for Bun/Node agents. - Keep feature parity with the Python helper (env interpolation, stdio wrapping, OAuth caching) and extend test coverage. ## Deliverables + - `packages/mcporter` (standalone npm package) exporting: - `createRuntime()` for shared connections (list/call tools, resolve resources). - `callOnce()` convenience matching today’s single-call flow. @@ -23,6 +25,7 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe - Documentation: README, usage examples, migration guide for replacing `pnpm mcp:*`. ## Architecture Notes + - Load MCP definitions from JSON (support relative paths + HTTPS). - Reuse `@modelcontextprotocol/sdk` transports; invoke stdio servers directly (e.g., call `npx` with env overrides) without an extra wrapper script. - Automatically detect OAuth requirements for ad-hoc HTTP servers by retrying failed handshakes and promoting the definition to `auth: "oauth"` when a 401/403 is encountered, then launching the browser flow immediately. @@ -35,6 +38,7 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe - Document Cursor-compatible `config/mcporter.json` structure; support env-sourced headers and stdio commands while keeping inline overrides available for scripts. ## Schema-Aware Proxy Strategy + - Cache tool schemas on first access, persist them under `~/.mcporter/<server>/schema.json` for reuse across processes, and tolerate failures by falling back to raw `callTool`. - Allow direct method-style invocations such as `context7.getLibraryDocs("react")` by: - Mapping camelCase properties to kebab-case tool names. @@ -47,6 +51,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 (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. @@ -54,24 +59,28 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe - Add integration tests asserting the generated CLI can list tools, execute with positional/flag arguments, and hydrate cache files without additional list calls. ## Configuration + - Single file `config/mcporter.json` mirrors Cursor/Claude schema: `mcpServers` map with entries containing `baseUrl` or `command`+`args`, optional `headers`, `env`, `description`, `auth`, `tokenCacheDir`, and convenience `bearerToken`/`bearerTokenEnv` fields. - Optional `imports` array (defaulting to ['cursor', 'claude-code', 'claude-desktop', 'codex', 'windsurf', 'vscode']) controls auto-merging of editor configs; entries earlier in the list win conflicts while local definitions can still override. - Provide `configPath` override for scripts/tests; keep inline overrides in examples for completeness but default to file-based configuration. - Add fixtures validating HTTP vs. stdio normalization, header/env behavior, and editor config imports (Cursor, Claude Code/Desktop, Codex, Windsurf, VS Code) to ensure priority ordering matches defaults. ## Work Phases + 1. **Scaffold Package** - Init pnpm workspace config, tsconfig, lint/test scaffolding, build script. 2. **Core Runtime** - Port config parsing + env/header logic. - Implement connection cache, tool invocation, resource helpers. 3. **CLI Surface** + - Implement `list` (with optional schema) and `call` commands. - Render tool metadata as pseudo-TypeScript declarations: blue `function` signatures, grey doc comments using `@param` lines, inferred return names, and compact optional summaries that collapse longer lists until users pass `--all-parameters`. The default view must still surface at least five parameters (even if they’re optional) before summarising the remainder. - Ensure output parity with existing helper. - `call` has to parse both `server.tool` tokens and HTTP selectors like `https://host/path.tool(args)`; in the HTTP case we need to peel off the `.tool` suffix, infer/auto-register the ad-hoc server (respecting `--allow-http`), and hydrate arguments from parentheses or trailing `key=value` pairs. - Add `generate-cli` for standalone/bundled CLIs with embedded schema caching. - Ensure `generate-cli`, `inspect-cli`, and `emit-ts` share the same server-resolution logic as `list/call`, including HTTP URL matching and scheme-less selectors with `.tool` suffixes. + 4. **Testing & Fixtures** - Mock representative MCP servers (stdio + HTTP + OAuth) for integration tests. - Snapshot output for `list` vs. `call`. @@ -80,6 +89,7 @@ summary: 'Plan for the mcporter package replacing the Sweetistics pnpm MCP helpe - Update Sweetistics docs to point to the new package. ## Open Questions + - How aggressively should we parallelize list calls? Current helper serializes to avoid load. - Should we bundle a minimal REPL for ad-hoc debugging, or keep CLI focused on list/call? - Do we expose streaming/async iterator interfaces for tools returning logs? diff --git a/docs/subagent.md b/docs/subagent.md index 0773221..d00eb2b 100644 --- a/docs/subagent.md +++ b/docs/subagent.md @@ -5,6 +5,7 @@ summary: 'Multi-agent system directives and coordination rules. Master reference # Claude Subagent Quickstart ## CLI Basics + - Never invoke subagents through `./runner`—launch them inside tmux directly so the session can persist and bypass the runner timeouts. Example: ```bash @@ -13,6 +14,7 @@ summary: 'Multi-agent system directives and coordination rules. Master reference ``` Once inside the session, run `/model` to confirm the active alias (`haiku` maps to Claude 3.5 Haiku) and switch models if needed. + - Need to queue instructions without attaching? Use `bun scripts/agent-send.ts --session <name> -- "your command"` to inject text into a running agent session (single Enter is sent by default). - Run Claude through the repo wrapper when you just need help (`./runner claude --help`), but for actual delegation launch Claude inside tmux so the work keeps running after you disconnect. - Two modes: @@ -23,16 +25,19 @@ summary: 'Multi-agent system directives and coordination rules. Master reference - Ralph’s supervisor loop launches Claude the same way (`claude --dangerously-skip-permissions "<prompt>"`) to keep the tmux automation flowing. ## One-Shot Prompts + - The CLI accepts the prompt as a trailing argument in one-shot mode. Multi-line prompts can be piped: `echo "..." | ./runner claude --print`. - Add `--output-format json` when you need structured fields (e.g., summary + bullets) for post-processing. - Keep prompts explicit about reading full files: “Read docs/example.md in full and produce a 2–3 sentence summary covering all sections.” ## Bulk Markdown Conversion + - Produce the markdown inventory first (`pnpm run docs:list`) and feed batches of filenames to your Claude session. - For each batch, issue a single instruction like “Rewrite these files with YAML front matter summaries, keep all other content verbatim.” Haiku can loop over multi-file edits when you provide the explicit list. - After Claude reports success, diff each file locally (`./runner git diff docs/<file>.md`) before moving to the next batch. ## Ralph Integration Notes + - Ralph (see `scripts/ralph.ts`) spins up tmux sessions, auto-wakes the worker, and calls Claude as the supervisor via `claude --dangerously-skip-permissions`. - Supervisor responses must end with either `CONTINUE`, `SEND: <message>`, or `RESTART`; Ralph parses these tokens to decide the next action. - To start Ralph manually: `bun scripts/ralph.ts start --goal "…" [--markdown path]`. Progress is tracked in `.ralph/progress.md` by default. diff --git a/docs/supabase-auth-issue.md b/docs/supabase-auth-issue.md index d67fd1b..3098274 100644 --- a/docs/supabase-auth-issue.md +++ b/docs/supabase-auth-issue.md @@ -7,6 +7,7 @@ read_when: # OAuth Notes & Hosted MCP Compatibility ## MCP Spec Expectations + - The June 18 2025 MCP “Authorization” spec (and the linked OAuth flow document) requires OAuth 2.1 dynamic client registration plus RFC 7235 `WWW-Authenticate` challenges for scope negotiation. - Servers SHOULD expose discovery metadata via `/.well-known/oauth-authorization-server` and `/.well-known/oauth-protected-resource`. Those documents list supported scopes and additional OAuth endpoints. - Clients are expected to start with a baseline scope (the spec uses `mcp:tools`) and then re-authenticate with any server-supplied scope hints. @@ -14,6 +15,7 @@ read_when: We currently hard-code `mcp:tools` because it is the only scope guaranteed to exist in the MCP reference implementation. We need richer negotiation to support providers that enforce product-specific scopes. ## Hosted Supabase MCP (~Oct 2025) + Supabase’s hosted MCP server (`https://mcp.supabase.com/mcp`) validates the requested scopes against their management API permissions (`organizations:read`, `projects:read`, `database:write`, `storage:read`, etc.). When mcporter asks for `mcp:tools`, their authorization server rejects the request with HTTP 400 and a body similar to: ``` @@ -21,11 +23,13 @@ Supabase’s hosted MCP server (`https://mcp.supabase.com/mcp`) validates the re ``` Key takeaways from Supabase’s docs: + 1. Hosted installs rely on dynamic client registration and are currently integrated with Cursor/Windsurf (which embed the Supabase scope list). 2. Manual authentication is offered for self-hosted/CI workflows (PAT headers or custom OAuth app), but their hosted server still expects Supabase-specific scopes. 3. There is no public metadata endpoint describing those scopes, so third-party MCP clients cannot opt in automatically. ## mcporter’s Current Behavior + - We auto-promote ad-hoc HTTP servers to OAuth and retry once when we see 401/403 errors. - We surface any server-supplied OAuth error payload so it’s obvious whether the problem is scope-related, a missing token, etc. - After the second failure we stop retrying to avoid infinite loops. @@ -33,6 +37,7 @@ Key takeaways from Supabase’s docs: This works for providers that use standard MCP scopes (e.g., the MCP example server, Vercel’s MCP), but it fails for Supabase because they reject `mcp:tools` outright. ## Roadmap / Proposed Improvements + 1. **Scope discovery & negotiation** - Fetch `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server` when a server advertises OAuth. If `scopes_supported` is present, intersect it with user overrides and use that list instead of `mcp:tools`. - Parse `WWW-Authenticate` challenges on 401/403 responses and restart the authorization flow with the scopes the server demands. @@ -46,6 +51,7 @@ This works for providers that use standard MCP scopes (e.g., the MCP example ser - File upstream issues (e.g., Supabase) requesting support for standard MCP scopes or publication of `scopes_supported` metadata, so we can integrate without custom code. ## Workarounds Today + - Use a supported GUI client (Cursor, Claude Desktop, Windsurf) for Supabase’s hosted MCP—they already ship the necessary scopes. - Self-host Supabase MCP and configure PAT headers or your own OAuth client; you can then relax scope validation to include `mcp:tools`. - For other providers, consult their docs for discovery metadata. If they list scopes, set them via a future `--oauth-scope` flag once we implement it (tracked in #TODO). diff --git a/docs/tmux.md b/docs/tmux.md index 3b984f5..4831a8e 100644 --- a/docs/tmux.md +++ b/docs/tmux.md @@ -13,11 +13,14 @@ Use `tmux` to verify whether a CLI command actually exits or is stalled on open tmux new-session -ds mcporter-check "pnpm exec tsx src/cli.ts list" ``` 2. Wait a few seconds, then ask tmux if the session is still running: + ```bash tmux has-session -t mcporter-check ``` + - Exit status **1** (`can't find session`) means the process exited normally. - Exit status **0** means the command is still running (or hung) inside the session. + 3. Capture the output without attaching: ```bash tmux capture-pane -pt mcporter-check | tail -n 40 diff --git a/docs/tool-calling.md b/docs/tool-calling.md index b3571a1..a476275 100644 --- a/docs/tool-calling.md +++ b/docs/tool-calling.md @@ -69,6 +69,7 @@ mcporter call --http-url https://mcp.example.com/mcp fetch_docs repoName=value --- **Tips** + - Use `mcporter list <server>` to see parameter names, return types, and example invocations. - Optional fields hide by default; add `--all-parameters` when listing a server to reveal everything. - `mcporter auth <server|url>` accepts the same ad-hoc flags, so you can authenticate immediately after a 401 without editing config. diff --git a/docs/windows.md b/docs/windows.md index be164a9..ff17f20 100755 --- a/docs/windows.md +++ b/docs/windows.md @@ -5,21 +5,21 @@ summary: What to do when pnpm/test flows fail on NTFS-backed worktrees. ## Installing dependencies -* `pnpm install` fails on `/mnt/c` because NTFS/DrvFs blocks `futime`. Clone/sync the repo to `$HOME` (ext4 inside WSL) and run `./runner pnpm install` there instead. Example: `rsync -a --delete --exclude node_modules /mnt/c/Projects/mcporter/ ~/mcporter-wsl/`. -* Keep `$HOME/.bun/bin` and `$HOME/.local/share/pnpm` on your PATH before invoking `./runner`. Without Bun and pnpm the runner prints the guardrail error and exits. -* If you *must* work from `/mnt/c`, remount with `metadata` support (`sudo mount -t drvfs C: /mnt/c -o metadata,uid=$(id -u),gid=$(id -g),umask=22,fmask=111`). Otherwise installs, chmods, and copyfile calls will continue to fail. +- `pnpm install` fails on `/mnt/c` because NTFS/DrvFs blocks `futime`. Clone/sync the repo to `$HOME` (ext4 inside WSL) and run `./runner pnpm install` there instead. Example: `rsync -a --delete --exclude node_modules /mnt/c/Projects/mcporter/ ~/mcporter-wsl/`. +- Keep `$HOME/.bun/bin` and `$HOME/.local/share/pnpm` on your PATH before invoking `./runner`. Without Bun and pnpm the runner prints the guardrail error and exits. +- If you _must_ work from `/mnt/c`, remount with `metadata` support (`sudo mount -t drvfs C: /mnt/c -o metadata,uid=$(id -u),gid=$(id -g),umask=22,fmask=111`). Otherwise installs, chmods, and copyfile calls will continue to fail. ## Running tests -* Use the ext4 copy (`~/mcporter-wsl`) for `pnpm lint`, `pnpm typecheck`, and the Vitest suites. All tests pass there (71 files / 280 tests, 1 file and 2 tests skipped). -* Whole-repo `pnpm test` on `/mnt/c` repeatedly times out because Vitest cannot start workers when the node_modules tree belongs to root or sits on NTFS. Copy the repo to ext4 or fix ownership before retrying. -* When working cross-filesystem, remember to sync the edited source files back to the canonical `/mnt/c/Projects/mcporter` tree (e.g., `rsync -a ~/mcporter-wsl/src/cli/generate/{template,artifacts,fs-helpers}.ts /mnt/c/Projects/mcporter/src/cli/generate/`). -* The stdio integration suite now vendors two tiny fixtures under `tests/fixtures/stdio-*.mjs` that spin up filesystem/memory MCP servers via `node`. The tests shell out to `process.execPath`, so make sure your PATH resolves `node` correctly (fnm/nvs setups sometimes expose only `node.exe` on Windows). If you need to debug them manually, run `./runner pnpm exec vitest run tests/stdio-servers.integration.test.ts` so the guardrails apply. +- Use the ext4 copy (`~/mcporter-wsl`) for `pnpm lint`, `pnpm typecheck`, and the Vitest suites. All tests pass there (71 files / 280 tests, 1 file and 2 tests skipped). +- Whole-repo `pnpm test` on `/mnt/c` repeatedly times out because Vitest cannot start workers when the node_modules tree belongs to root or sits on NTFS. Copy the repo to ext4 or fix ownership before retrying. +- When working cross-filesystem, remember to sync the edited source files back to the canonical `/mnt/c/Projects/mcporter` tree (e.g., `rsync -a ~/mcporter-wsl/src/cli/generate/{template,artifacts,fs-helpers}.ts /mnt/c/Projects/mcporter/src/cli/generate/`). +- The stdio integration suite now vendors two tiny fixtures under `tests/fixtures/stdio-*.mjs` that spin up filesystem/memory MCP servers via `node`. The tests shell out to `process.execPath`, so make sure your PATH resolves `node` correctly (fnm/nvs setups sometimes expose only `node.exe` on Windows). If you need to debug them manually, run `./runner pnpm exec vitest run tests/stdio-servers.integration.test.ts` so the guardrails apply. ## Windows-specific fixes in the repo -* CLI generation now uses `src/cli/generate/fs-helpers.ts`: `markExecutable` ignores `EPERM/EINVAL/ENOSYS/EACCES` so NTFS builds no longer fail when setting executable bits. -* `safeCopyFile` falls back to a manual read/write when DrvFs blocks `copyFile`, keeping Bun bundling stable on Windows. -* These helpers only affect Windows/WSL behavior—Linux/macOS paths still perform real `chmod`/`copyFile`. -* Regenerated CLIs (for example `node dist/cli.js generate-cli context7 --config config/mcporter.json --bundle /mnt/c/Temp/context7-cli.js --runtime node`) now complete successfully even when the bundle lives on `/mnt/c`, and the resulting executable runs with `node /mnt/c/Temp/context7-cli.js --help`. -* When running `mcporter generate-cli` with `--command ./relative-script.ts`, the CLI no longer tries to normalize the path into an HTTP URL—relative/bare commands are always treated as STDIO transports now, matching the PowerShell/WSL behavior you expect. +- CLI generation now uses `src/cli/generate/fs-helpers.ts`: `markExecutable` ignores `EPERM/EINVAL/ENOSYS/EACCES` so NTFS builds no longer fail when setting executable bits. +- `safeCopyFile` falls back to a manual read/write when DrvFs blocks `copyFile`, keeping Bun bundling stable on Windows. +- These helpers only affect Windows/WSL behavior—Linux/macOS paths still perform real `chmod`/`copyFile`. +- Regenerated CLIs (for example `node dist/cli.js generate-cli context7 --config config/mcporter.json --bundle /mnt/c/Temp/context7-cli.js --runtime node`) now complete successfully even when the bundle lives on `/mnt/c`, and the resulting executable runs with `node /mnt/c/Temp/context7-cli.js --help`. +- When running `mcporter generate-cli` with `--command ./relative-script.ts`, the CLI no longer tries to normalize the path into an HTTP URL—relative/bare commands are always treated as STDIO transports now, matching the PowerShell/WSL behavior you expect. diff --git a/mcporter.schema.json b/mcporter.schema.json index 2b02d78..0d350ba 100644 --- a/mcporter.schema.json +++ b/mcporter.schema.json @@ -127,9 +127,7 @@ "description": "Arguments for the OAuth command" } }, - "required": [ - "args" - ], + "required": ["args"], "additionalProperties": false }, "oauth_command": { @@ -144,9 +142,7 @@ "description": "Arguments for the OAuth command" } }, - "required": [ - "args" - ], + "required": ["args"], "additionalProperties": false }, "bearerToken": { @@ -200,9 +196,7 @@ "maximum": 9007199254740991 } }, - "required": [ - "mode" - ], + "required": ["mode"], "additionalProperties": false } ], @@ -237,15 +231,7 @@ "type": "array", "items": { "type": "string", - "enum": [ - "cursor", - "claude-code", - "claude-desktop", - "codex", - "windsurf", - "opencode", - "vscode" - ], + "enum": ["cursor", "claude-code", "claude-desktop", "codex", "windsurf", "opencode", "vscode"], "description": "Supported editor/client configurations to import MCP servers from" } }, @@ -254,9 +240,7 @@ "description": "JSON Schema URL for IDE validation and autocomplete" } }, - "required": [ - "mcpServers" - ], + "required": ["mcpServers"], "additionalProperties": false, "description": "mcporter configuration file schema", "$id": "https://raw.githubusercontent.com/steipete/mcporter/main/mcporter.schema.json" diff --git a/tests/fixtures/imports/.config/opencode/opencode.jsonc b/tests/fixtures/imports/.config/opencode/opencode.jsonc index b0d8ea2..2c9942b 100644 --- a/tests/fixtures/imports/.config/opencode/opencode.jsonc +++ b/tests/fixtures/imports/.config/opencode/opencode.jsonc @@ -4,7 +4,7 @@ "opencode-user-only": { "description": "User-level OpenCode server", "command": "opencode-user-cli", - "args": ["--json"] - } - } + "args": ["--json"], + }, + }, } diff --git a/tests/fixtures/imports/opencode.jsonc b/tests/fixtures/imports/opencode.jsonc index ac6121f..ea2ebf0 100644 --- a/tests/fixtures/imports/opencode.jsonc +++ b/tests/fixtures/imports/opencode.jsonc @@ -5,7 +5,7 @@ "description": "Project-level OpenCode server", "type": "stdio", "command": "opencode-cli", - "args": ["serve"] - } - } + "args": ["serve"], + }, + }, }