Commit Graph

15 Commits

Author SHA1 Message Date
Jacob Magar
efaab031ae fix: address all 17 PR review comments
Resolves review threads:
- PRRT_kwDOO6Hdxs50fewG (setup.py): non-eliciting clients now return True
  from elicit_reset_confirmation so they can reconfigure without being blocked
- PRRT_kwDOO6Hdxs50fewM (test-tools.sh): add notification/recalculate smoke test
- PRRT_kwDOO6Hdxs50fewP (test-tools.sh): add system/array smoke test
- PRRT_kwDOO6Hdxs50fewT (resources.py): surface manager error state instead of
  reporting 'connecting' for permanently failed subscriptions
- PRRT_kwDOO6Hdxs50feAj (resources.py): use is not None check for empty cached dicts
- PRRT_kwDOO6Hdxs50fewY (integration tests): remove duplicate snapshot-registration
  tests already covered in test_resources.py
- PRRT_kwDOO6Hdxs50fewe (test_resources.py): replace brittle import-detail test
  with behavior tests for connecting/error states
- PRRT_kwDOO6Hdxs50fewh (test_customization.py): strengthen public_theme assertion
- PRRT_kwDOO6Hdxs50fewk (test_customization.py): strengthen theme assertion
- PRRT_kwDOO6Hdxs50fewo (__init__.py): correct subaction count ~88 -> ~107
- PRRT_kwDOO6Hdxs50fewx (test_oidc.py): assert providers list value directly
- PRRT_kwDOO6Hdxs50fewz (unraid.py): remove unreachable raise after vm handler
- PRRT_kwDOO6Hdxs50few2 (unraid.py): remove unreachable raise after docker handler
- PRRT_kwDOO6Hdxs50fev8 (CLAUDE.md): replace legacy 15-tool table with unified
  unraid action/subaction table
- PRRT_kwDOO6Hdxs50fev_ (test_oidc.py): assert providers + defaultAllowedOrigins
- PRRT_kwDOO6Hdxs50feAz (CLAUDE.md): update tool categories to unified API shape
- PRRT_kwDOO6Hdxs50feBE (CLAUDE.md/setup.py): update unraid_health refs to
  unraid(action=health, subaction=setup)
2026-03-16 02:58:54 -04:00
Jacob Magar
dab1cd6995 refactor(tools)!: consolidate 15 individual tools into single unified unraid tool
BREAKING CHANGE: Replaces 15 separate MCP tools (unraid_info, unraid_array,
unraid_storage, unraid_docker, unraid_vm, unraid_notifications, unraid_rclone,
unraid_users, unraid_keys, unraid_health, unraid_settings, unraid_customization,
unraid_plugins, unraid_oidc, unraid_live) with a single `unraid` tool using
action (domain) + subaction (operation) routing.

New interface: unraid(action="system", subaction="overview") replaces
unraid_info(action="overview"). All 15 domains and ~108 subactions preserved.

- Add unraid_mcp/tools/unraid.py (1891 lines, all domains consolidated)
- Remove 15 individual tool files
- Update tools/__init__.py to register single unified tool
- Update server.py for new tool registration pattern
- Update subscriptions/manager.py and resources.py for new tool names
- Update all 25 test files + integration/contract/safety/schema/property tests
- Update mcporter smoke-test script for new tool interface
- Bump version 0.6.0 → 1.0.0

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-16 02:29:57 -04:00
Jacob Magar
c4f1b2eb00 test(creds): add replacement test for credentials propagation through tool_error_handler 2026-03-14 14:21:21 -04:00
Jacob Magar
81f1fe174d feat(creds): tool_error_handler converts CredentialsNotConfiguredError to ToolError with path
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).
2026-03-14 14:05:59 -04:00
Jacob Magar
e930b868e4 feat(creds): write to ~/.unraid-mcp/.env with 700/600 permissions, seed from .env.example
- _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
2026-03-14 14:00:57 -04:00
Jacob Magar
d8ce45c0fc feat(creds): add CREDENTIALS_DIR and CREDENTIALS_ENV_PATH to settings
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.
2026-03-14 13:54:14 -04:00
Jacob Magar
49264550b1 feat(elicitation): auto-elicit credentials on CredentialsNotConfiguredError in unraid_info 2026-03-14 04:07:51 -04:00
Jacob Magar
8a986a84c2 feat(elicitation): raise CredentialsNotConfiguredError in client when creds absent
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.
2026-03-14 03:55:57 -04:00
Jacob Magar
e73f791fd3 feat(elicitation): add elicit_and_configure() with .env persistence 2026-03-14 03:49:11 -04:00
Jacob Magar
7458409147 test(elicitation): assert warning is logged when creds missing at startup 2026-03-14 03:47:29 -04:00
Jacob Magar
42bfcc1998 feat(elicitation): degrade gracefully when credentials are missing at startup 2026-03-14 03:45:42 -04:00
Jacob Magar
a7988e1eae test(elicitation): fix os.environ leak in apply_runtime_config test 2026-03-14 03:44:34 -04:00
Jacob Magar
520d92af57 feat(elicitation): add is_configured() and apply_runtime_config() to settings 2026-03-14 03:43:20 -04:00
Jacob Magar
1952720ef9 test(elicitation): fix test_setup.py style and add ToolError contract test 2026-03-14 03:41:24 -04:00
Jacob Magar
ea839ec09c feat(elicitation): add CredentialsNotConfiguredError sentinel 2026-03-14 03:39:49 -04:00