Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/TODOs.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ Run "mcpc --help" for usage information.



- mcpc @session --timeout ... / mcpc @session <cmd> --timeout ... has no effect

- createSessionProgram() advertises --header and --profile options for mcpc @session ..., but these values are never applied: withMcpClient()/SessionClient ignore headers/profile overrides and always use the session’s stored config. This is misleading for users and makes it easy to think a command is authenticated/modified when it isn’t. Either wire these options into session execution (e.g. by updating/restarting the session/bridge) or remove them from the session program/help.

- parseServerArg() splits config entries using the first : (arg.indexOf(':')). This breaks Windows paths with drive letters (e.g. C:\Users\me\mcp.json:filesystem), which would be parsed as file=C entry=\Users\.... Consider special-casing ^[A-Za-z]:[\\/] and/or using lastIndexOf(':') for the file/entry delimiter to keep Windows paths working


## x402
- sign -r <b64> Sign payment from PAYMENT-REQUIRED header - why the "-r" is needed?

Expand Down Expand Up @@ -109,7 +116,7 @@ $ mcpc connect
- "login" and "logout" commands could work also with file:entry, just use the remote server URL

- maybe introduce new session status: auth failed or unauthed
- ux: consider forking "alive" session state to "alive" and "diconnected", to indicate the remove server is not responding but bridge
ux: consider forking "alive" session state to "alive" and "disconnected", to indicate the remote server is not responding but bridge
runs fine. We can use lastSeenAt + ping interval info for that, or status of last ping.
- ux: Be even more forgiving with `args:=x`, when we know from tools/prompt schema the text is compatible with `x` even if the exact type is not -
just re-type it dynamically to make it work.
Expand Down
12 changes: 10 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,23 @@ function getOptionsFromCommand(command: Command): HandlerOptions {
// Always convert to array for consistent handling
options.headers = Array.isArray(opts.header) ? opts.header : [opts.header];
}
if (opts.timeout) options.timeout = parseInt(opts.timeout, 10);
if (opts.timeout) {
const timeout = parseInt(opts.timeout as string, 10);
if (isNaN(timeout) || timeout <= 0) {
throw new Error(
`Invalid --timeout value: "${opts.timeout as string}". Must be a positive number (seconds).`
);
}
options.timeout = timeout;
}
if (opts.profile) options.profile = opts.profile;
if (verbose) options.verbose = verbose;
if (opts.x402) options.x402 = true;
if (opts.schema) options.schema = opts.schema;
if (opts.schemaMode) {
const mode = opts.schemaMode as string;
if (mode !== 'strict' && mode !== 'compatible' && mode !== 'ignore') {
throw new Error(`Invalid schema mode: ${mode}. Must be 'strict', 'compatible', or 'ignore'.`);
throw new Error(`Invalid --schema-mode value: "${mode}". Valid modes are: strict, compatible, ignore`);
}
options.schemaMode = mode;
}
Expand Down
30 changes: 10 additions & 20 deletions test/e2e/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,37 +118,27 @@ done
# Suites directory
SUITES_DIR="$SCRIPT_DIR/suites"

# Find all test files matching patterns
# Find all test files matching patterns (outputs newline-separated paths)
find_tests() {
local tests=()

if [[ ${#PATTERNS[@]} -eq 0 ]]; then
# No pattern - find all tests in suites/
while IFS= read -r -d '' test; do
tests+=("$test")
done < <(find "$SUITES_DIR" -name "*.test.sh" -print0 | sort -z)
find "$SUITES_DIR" -name "*.test.sh" | sort
else
for pattern in "${PATTERNS[@]}"; do
if [[ -f "$SUITES_DIR/$pattern" ]]; then
# Specific file
tests+=("$SUITES_DIR/$pattern")
echo "$SUITES_DIR/$pattern"
elif [[ -d "$SUITES_DIR/$pattern" ]]; then
# Directory - find all tests in it
while IFS= read -r -d '' test; do
tests+=("$test")
done < <(find "$SUITES_DIR/$pattern" -name "*.test.sh" -print0 | sort -z)
find "$SUITES_DIR/$pattern" -name "*.test.sh" | sort
elif [[ -d "$SUITES_DIR/${pattern%/}" ]]; then
# Directory without trailing slash
while IFS= read -r -d '' test; do
tests+=("$test")
done < <(find "$SUITES_DIR/${pattern%/}" -name "*.test.sh" -print0 | sort -z)
find "$SUITES_DIR/${pattern%/}" -name "*.test.sh" | sort
else
echo "Warning: No tests match pattern: $pattern" >&2
fi
done
fi

printf '%s\n' "${tests[@]}"
}

# Get test name from path (relative to suites dir, without .test.sh)
Expand All @@ -158,11 +148,11 @@ test_name() {
echo "${rel%.test.sh}"
}

# Collect tests (compatible with bash 3.x on macOS)
# Collect tests
TESTS=()
while IFS= read -r test; do
[[ -n "$test" ]] && TESTS+=("$test")
done < <(find_tests)
done <<< "$(find_tests)"

if [[ ${#TESTS[@]} -eq 0 ]]; then
echo "No tests found" >&2
Expand Down Expand Up @@ -362,9 +352,9 @@ fi

# Check for setup requirements (tests that were skipped due to missing configuration)
SETUP_FILES=()
while IFS= read -r -d '' setup_file; do
SETUP_FILES+=("$setup_file")
done < <(find "$RUN_DIR" -name ".setup_required" -print0 2>/dev/null)
while IFS= read -r setup_file; do
[[ -n "$setup_file" ]] && SETUP_FILES+=("$setup_file")
done <<< "$(find "$RUN_DIR" -name ".setup_required" 2>/dev/null)"

if [[ ${#SETUP_FILES[@]} -gt 0 ]]; then
echo ""
Expand Down
Loading