Files
2026-04-14 19:33:48 +02:00

3.5 KiB

metin-release-mcp

Thin Model Context Protocol server that wraps the Phase 1 metin-release CLI. Each release … subcommand is exposed as an MCP tool. The server contains no release business logic: it shells out to the real CLI with --json and returns the parsed envelope verbatim.

Install

The server ships as an optional extra alongside the main CLI:

pip install -e '.[mcp]'

This installs the mcp Python SDK and adds a metin-release-mcp console script plus a python -m metin_release_mcp module entry.

Running

The server speaks MCP over stdio, so you wire it into an MCP-capable client (Claude Desktop, Claude Code, etc.) as a stdio command. Example client entry:

{
  "mcpServers": {
    "metin-release": {
      "command": "metin-release-mcp",
      "env": {
        "METIN_RELEASE_BINARY": "/usr/local/bin/metin-release"
      }
    }
  }
}

You can also poke at it directly:

  • metin-release-mcp --help — list registered tools
  • metin-release-mcp --list-tools — dump the full tool JSON schemas
  • metin-release-mcp --version

Tools

Tool CLI subcommand
release_inspect metin-release release inspect
release_build_manifest metin-release release build-manifest
release_sign metin-release release sign
release_diff_remote metin-release release diff-remote
release_upload_blobs metin-release release upload-blobs
release_promote metin-release release promote
release_verify_public metin-release release verify-public
release_publish metin-release release publish

Tool input keys match CLI flag names with _ instead of - (--base-urlbase_url, --dry-rundry_run). Boolean fields correspond to argparse store_true flags: pass true to set the flag, omit or pass false to leave it off.

Example invocation

{
  "name": "release_inspect",
  "arguments": {
    "source": "/srv/metin/client"
  }
}

The server runs metin-release release inspect --json --source /srv/metin/client and returns the full JSON envelope:

{
  "ok": true,
  "command": "release inspect",
  "status": "inspected",
  "stats": {
    "source_path": "/srv/metin/client",
    "file_count": 9166,
    "total_bytes": 3523473920,
    "launcher_present": true,
    "main_exe_present": true
  }
}

CLI resolution

On every tool call the server resolves the metin-release binary in this order:

  1. METIN_RELEASE_BINARY environment variable, if set and non-empty
  2. shutil.which("metin-release") against PATH

If neither resolves, the tool call returns a wrapper-level error envelope (error.code = "cli_not_found").

Error handling

The server never invents its own release-level errors. There are three paths:

  • Success — CLI exits 0 with a valid JSON envelope → envelope returned as-is
  • CLI-level failure — CLI exits non-zero with an {"ok": false, "error": …} envelope → that envelope is returned as-is, plus the CLI's stderr is attached as a diagnostic text block
  • Wrapper failure — binary missing, unparseable stdout, unknown tool, invalid input → synthetic envelope with one of cli_not_found, cli_unparseable_output, unknown_tool, invalid_tool_input

Environment variables

Variable Purpose
METIN_RELEASE_BINARY Override the metin-release binary path.

Any env vars the wrapped CLI honours (METIN_RELEASE_MAKE_MANIFEST, METIN_RELEASE_SIGN_MANIFEST) are inherited by the subprocess unchanged.