MCP SDK's StreamableHTTPError/SseError store the HTTP status code in
error.code, but the message text may not contain the numeric status.
analyzeConnectionError now reads error.code (100-599) before falling
back to message-text parsing, so OAuth promotion triggers correctly
for 401 responses on Streamable HTTP transport.
Instead of hardcoding scope 'mcp:tools' during dynamic client
registration, fetch /.well-known/oauth-protected-resource from the
server to discover its supported scopes. This fixes InvalidScopeError
when connecting to servers like Todoist that only accept their own
scopes (e.g. 'data:read_write').
Also includes the fix from #38: remove the ad-hoc source restriction
in maybeEnableOAuth() so config-file servers can be promoted to OAuth.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
HTTP 405 (Method Not Allowed) was included in AUTH_STATUSES, causing it
to be treated as an authentication error. This leads to premature OAuth
session cleanup when StreamableHTTP returns 405, leaving the SSE
fallback without credentials. Remove 405 from AUTH_STATUSES so transport
errors are classified correctly.
Fixes#47
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Values like phone numbers, PINs, or codes with leading zeros (e.g. 000123)
are auto-coerced to numbers by default. The --raw-strings flag (or --no-coerce
alias) preserves them as strings.
Note: Cannot use --raw as the flag name because it conflicts with the
existing --raw output format shortcut in output-format.ts.
Fixes: numeric strings being silently converted to numbers
Previously json() in createCallResult returned early on the first
parseable JSON entry. When an MCP server returned multiple results
in the content array, only the first item was ever surfaced.
Now all parseable entries are collected. A single item still returns
as a single object (backward compatible); multiple items return as
an array.
Also increased inspect depth in printRaw from 2 to null to prevent
truncation of deeply nested list results.
* fix(cli): prevent string truncation in raw output
Node's util.inspect() has a default maxStringLength of 10000 characters,
causing large MCP responses to be truncated with '... N more characters'.
See: https://nodejs.org/api/util.html#utilinspectobject-options
This affects --output raw and the default output format when it falls
back to printRaw().
Fix: set maxStringLength: null to disable string truncation while
preserving depth: 2 for readable nested object summaries.
Verify (before fix shows 10000, after fix shows 15000):
node -e "console.log('x count:', (require('util').inspect({t:'x'.repeat(15000)}, {depth:2}).match(/x/g)||[]).length)"
node -e "console.log('x count:', (require('util').inspect({t:'x'.repeat(15000)}, {depth:2, maxStringLength:null}).match(/x/g)||[]).length)"
* test(cli): ensure raw output not truncated
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Tests cover the scenario where mcporter is run in a completely empty
environment (no config files anywhere - not in project dir, home dir,
or env vars). Before the fix, this would crash with ENOENT.
Unit tests:
- resolveConfigPath returns explicit=false when no config exists anywhere
E2E tests:
- list command succeeds with empty environment
- list --json outputs valid JSON with empty servers array
- config list succeeds
- config doctor succeeds and shows version banner
The resolveContainerDescriptor function was applying root fallback to all
claude-code config files, causing non-MCP fields like statusLine, tipsHistory,
and cachedStatsigGates to be incorrectly detected as MCP server definitions.
This change makes root fallback path-aware for claude-code imports:
- .claude.json (legacy format): root fallback enabled
- .claude/settings.json: root fallback disabled, requires proper containers
- .claude/settings.local.json: root fallback disabled
- .claude/mcp.json: root fallback disabled
Fixes issue where statusLine appears as offline server in mcporter list output.
Tests added to verify metadata fields are ignored while proper mcpServers
containers and legacy .claude.json format continue to work correctly.