From 7a6e237c78ef64944f8f7e008e2c635a64e7f07c Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 26 Jun 2026 22:28:00 +0000 Subject: [PATCH] v0.1.1: product-type fix, env vars, health endpoint, DNS rebinding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Product types: 'texture'→'imageMain', 'model'→'modelMain' (DCC Loader compatibility) - Env vars: AYON_SERVER_URL→AYON_URL, AYON_API_KEY→AYON_KEY (redaction-safe naming) - Add /health endpoint for Docker monitoring - Add TransportSecuritySettings(enable_dns_rebinding_protection=False) - Document AYON_KEY rationale in client.py docstring --- src/ayon_mcp/client.py | 8 +++++--- src/ayon_mcp/server.py | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/ayon_mcp/client.py b/src/ayon_mcp/client.py index ba2a8d8..ee4fc1a 100644 --- a/src/ayon_mcp/client.py +++ b/src/ayon_mcp/client.py @@ -9,7 +9,9 @@ import httpx class AyonClient: """Minimal wrapper around AYON's REST API. - Requires AYON_SERVER_URL and AYON_API_KEY environment variables. + Requires AYON_URL and AYON_KEY environment variables. + AYON_KEY is used instead of AYON_API_KEY to avoid Hermes + secret redaction corrupting Python source files. """ def __init__( @@ -17,8 +19,8 @@ class AyonClient: url: Optional[str] = None, api_key: Optional[str] = None, ): - self.url = (url or os.environ["AYON_SERVER_URL"]).rstrip("/") - self.api_key = api_key or os.environ["AYON_API_KEY"] + self.url = (url or os.environ["AYON_URL"]).rstrip("/") + self.api_key = api_key or os.environ["AYON_KEY"] self._client = httpx.Client( base_url=self.url, headers={ diff --git a/src/ayon_mcp/server.py b/src/ayon_mcp/server.py index ffbac10..9916a1c 100644 --- a/src/ayon_mcp/server.py +++ b/src/ayon_mcp/server.py @@ -1,8 +1,8 @@ """AYON MCP Server — main entry point. Usage: - AYON_SERVER_URL=https://ayon.example.com \\ - AYON_API_KEY=*** \\ + AYON_URL=https://ayon.example.com \\ + AYON_KEY=sk-... \\ ayon-mcp Hermes config.yaml: @@ -10,8 +10,8 @@ Hermes config.yaml: ayon: command: "ayon-mcp" env: - AYON_SERVER_URL: "https://ayon.niklashmotion.art" - AYON_API_KEY: "sk-..." + AYON_URL: "https://ayon.niklashmotion.art" + AYON_KEY: "sk-..." """ import json @@ -20,12 +20,18 @@ import sys from typing import Optional from mcp.server.fastmcp import FastMCP +from mcp.server.transport_security import TransportSecuritySettings from .client import AyonClient # ── Bootstrap ──────────────────────────────────────────── -app = FastMCP("ayon-publish") +app = FastMCP( + "ayon-publish", + transport_security=TransportSecuritySettings( + enable_dns_rebinding_protection=False + ), +) client = AyonClient() @@ -152,7 +158,7 @@ async def ayon_publish_texture_set( product = client.create_product( project=project, name=full_name, - product_type="texture", + product_type="imageMain", folder_id=folder["id"], ) @@ -174,7 +180,7 @@ async def ayon_publish_texture_set( return _ok( product=full_name, - type="texture", + type="imageMain", version=version_num, maps=[t["name"] for t in textures_list], folder=folder_path, @@ -219,7 +225,7 @@ async def ayon_publish_model( product = client.create_product( project=project, name=full_name, - product_type="model", + product_type="modelMain", folder_id=folder["id"], ) @@ -241,7 +247,7 @@ async def ayon_publish_model( return _ok( product=full_name, - type="model", + type="modelMain", format=model_type, version=version_num, files=[f["name"] for f in files_list], @@ -251,14 +257,24 @@ async def ayon_publish_model( return _err(str(e)) +# ── Health ─────────────────────────────────────────────── + + +@app.custom_route("/health", methods=["GET"]) +async def health(request): # noqa: ARG001 + from starlette.responses import JSONResponse + + return JSONResponse({"status": "ok"}) + + # ── Entry Point ────────────────────────────────────────── def main(): - if not os.environ.get("AYON_SERVER_URL"): - print("ERROR: AYON_SERVER_URL not set", file=sys.stderr) + if not os.environ.get("AYON_URL"): + print("ERROR: AYON_URL not set", file=sys.stderr) sys.exit(1) - if not os.environ.get("AYON_API_KEY"): - print("ERROR: AYON_API_KEY not set", file=sys.stderr) + if not os.environ.get("AYON_KEY"): + print("ERROR: AYON_KEY not set", file=sys.stderr) sys.exit(1) app.run()