style: apply oxfmt formatting
This commit is contained in:
parent
9bfc604e01
commit
34fe35e46c
14
AGENTS.md
14
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 `<shared>…</shared>` and the tool list inside `<tools>…</tools>`. 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 `<shared>…</shared>` an
|
||||
- Keep the project’s `AGENTS.md` `<tools></tools>` 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/<title><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
|
||||
|
||||
|
||||
83
CHANGELOG.md
83
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.
|
||||
|
||||
@ -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"]
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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`.
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
>
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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': ...`).
|
||||
|
||||
|
||||
@ -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. |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -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).
|
||||
|
||||
10
docs/spec.md
10
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?
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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).
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"opencode-user-only": {
|
||||
"description": "User-level OpenCode server",
|
||||
"command": "opencode-user-cli",
|
||||
"args": ["--json"]
|
||||
}
|
||||
}
|
||||
"args": ["--json"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
6
tests/fixtures/imports/opencode.jsonc
vendored
6
tests/fixtures/imports/opencode.jsonc
vendored
@ -5,7 +5,7 @@
|
||||
"description": "Project-level OpenCode server",
|
||||
"type": "stdio",
|
||||
"command": "opencode-cli",
|
||||
"args": ["serve"]
|
||||
}
|
||||
}
|
||||
"args": ["serve"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user