fix: correct marketplace.json source field and improve async operations

- Fix marketplace.json: change source from relative path to GitHub URL
  (was "skills/unraid", now "https://github.com/jmagar/unraid-mcp")
  This resolves the "Invalid input" schema validation error when adding
  the marketplace to Claude Code

- Refactor subscriptions autostart to use anyio.Path for async file checks
  (replaces blocking pathlib.Path.exists() with async anyio.Path.exists())

- Update dependencies: anyio 4.11.0→4.12.1, attrs 25.3.0→25.4.0
This commit is contained in:
Jacob Magar
2026-02-16 16:38:43 -05:00
parent 715a79a34d
commit 890bc544a1
4 changed files with 492 additions and 449 deletions

View File

@@ -13,7 +13,7 @@
"plugins": [
{
"name": "unraid",
"source": "skills/unraid",
"source": "https://github.com/jmagar/unraid-mcp",
"description": "Query and monitor Unraid servers via GraphQL API - array status, disk health, containers, VMs, system monitoring",
"version": "0.2.0",
"tags": ["unraid", "monitoring", "homelab", "graphql", "docker", "virtualization"],

View File

@@ -6,8 +6,8 @@ and the MCP protocol, providing fallback queries when subscription data is unava
import json
import os
from pathlib import Path
import anyio
from fastmcp import FastMCP
from ..config.logging import logger
@@ -50,7 +50,7 @@ async def autostart_subscriptions() -> None:
if log_path is None:
# Default to syslog if available
default_path = "/var/log/syslog"
if Path(default_path).exists():
if await anyio.Path(default_path).exists():
log_path = default_path
logger.info(f"[AUTOSTART] Using default log path: {default_path}")

View File

@@ -4,9 +4,9 @@ Provides the `unraid_storage` tool with 6 actions for shares, physical disks,
unassigned devices, log files, and log content retrieval.
"""
from pathlib import Path
from typing import Any, Literal
import anyio
from fastmcp import FastMCP
from ..config.logging import logger
@@ -111,7 +111,7 @@ def register_storage_tool(mcp: FastMCP) -> None:
if not log_path:
raise ToolError("log_path is required for 'logs' action")
# Resolve path to prevent traversal attacks (e.g. /var/log/../../etc/shadow)
normalized = str(Path(log_path).resolve())
normalized = str(await anyio.Path(log_path).resolve())
if not any(normalized.startswith(p) for p in _ALLOWED_LOG_PREFIXES):
raise ToolError(
f"log_path must start with one of: {', '.join(_ALLOWED_LOG_PREFIXES)}. "

931
uv.lock generated

File diff suppressed because it is too large Load Diff