Converts the CredentialsNotConfiguredError sentinel to a user-facing ToolError
in tool_error_handler, including the exact CREDENTIALS_ENV_PATH so users know
where to create the .env file. Removes the now-invalid per-tool elicitation
test (replaced by 2 new tests for the handler conversion behavior).
- _write_env now creates CREDENTIALS_DIR (mode 700) and writes credentials
to CREDENTIALS_ENV_PATH (mode 600) instead of PROJECT_ROOT/.env
- On first run (no .env yet), seeds file content from .env.example to
preserve comments and structure
- elicit_and_configure catches NotImplementedError from ctx.elicit() so
clients that don't support elicitation return False gracefully instead
of propagating the exception
- Updated test_elicit_and_configure_writes_env_file to patch CREDENTIALS_DIR
and CREDENTIALS_ENV_PATH instead of PROJECT_ROOT
- Added 5 new tests covering dir/file permissions, .env.example seeding,
in-place credential update, and NotImplementedError guard
Introduce a version-agnostic credential directory (~/.unraid-mcp, overridable
via UNRAID_CREDENTIALS_DIR env var) and surface it as CREDENTIALS_DIR and
CREDENTIALS_ENV_PATH module-level constants. Prepend the canonical .env path to
dotenv_paths so all runtimes (plugin, uv, Docker) resolve credentials from the
same stable location without relying on versioned plugin cache paths.
make_graphql_request now reads credentials from the settings module at call
time (via a local import) instead of relying on module-level names captured at
import time. When either credential is missing it raises CredentialsNotConfiguredError
(not ToolError), allowing callers to trigger elicitation rather than surfacing a
generic error to the MCP client.
Updated tests/test_client.py and tests/http_layer/test_request_construction.py
to patch unraid_mcp.config.settings.* instead of the now-removed client-module
attrs, and to expect CredentialsNotConfiguredError on missing credentials.
Always update both pyproject.toml and .claude-plugin/plugin.json
when bumping versions — missed in 0.4.4→0.4.5 bump.
Co-Authored-By: Claude <noreply@anthropic.com>
- Move scripts/test-tools.sh and scripts/test-actions.sh → tests/mcporter/
- Fix PROJECT_DIR path in test-tools.sh (SCRIPT_DIR/.. → SCRIPT_DIR/../..)
- Add tests/mcporter/test-destructive.sh: 2 live + 13 skipped destructive tests
- stdio transport (no running server required)
- notifications:delete (create→list→delete), keys:delete (create→delete→verify)
- 3 new skips: createDockerFolder/updateSshSettings/createRCloneRemote not in API
- Requires --confirm flag; dry-run by default
- Add tests/mcporter/README.md documenting both scripts and coverage
- Rewrite docs/DESTRUCTIVE_ACTIONS.md: merge test guide, all 15 actions with commands
- Delete docs/test-actions.md (merged into tests/mcporter/README.md)
- Fix rclone.py create_remote: send "parameters" not "config" (API field name)
- Update README.md and CLAUDE.md: 11 tools/~104 actions, new script paths
- Add AGENTS.md and GEMINI.md symlinks to CLAUDE.md
- Bump version 0.4.3 → 0.4.4
Co-authored-by: Claude <noreply@anthropic.com>
Adds scripts/test-actions.sh — a mcporter-based smoke test that exercises
all 42 non-destructive MCP actions across 10 tools. Two-phase design:
phase 1 runs param-free reads; phase 2 extracts resource IDs from those
responses to test the ID-required reads (container details/logs, network
details, disk details, log content, VM details, API key get).
Also adds docs/test-actions.md with full usage, coverage table, skip
rationale, and cleanup notes.
Fixed three bugs discovered during test run:
- Connectivity check used curl -f which treats 406 (correct MCP response
to plain GET) as failure
- run_test_capture wrote status lines to stdout causing captured $() to
contain mixed text+JSON, breaking all Phase 2 ID extraction
- run_test echoed full JSON response to terminal on every call
Co-Authored-By: Claude <noreply@anthropic.com>