Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Huawei Cloud Open MCP

English | 中文

PyPI

Huawei Cloud Open MCP

Open Connect. Explore What's Next.

One open, local Model Context Protocol server connects code agents — opencode, Codex, Cursor, and any other MCP-capable client — to Huawei Cloud in natural language. No per-service wrappers: the agent explores the full catalog (300+ products, 17,000+ APIs) step by step, narrowing it down to one concrete API call, executed with locally signed requests. This is a personal, local deployment: the gateway runs entirely on your machine — your AK/SK never leave it.

Three composable modes via --mode (comma-separated, e.g. openapi,data): openapi (default) talks to Huawei Cloud OpenAPI, discover connects to cloud-hosted Huawei Cloud MCP servers (experimental, not documented yet), and data runs read-only SQL analytics and transformations over inline/local data with DataFusion — local compute tools that need no credentials and are not governed by the safety policy. The typical closed loop (openapi,data): pull a large dataset via execute_api, save it to a file, aggregate with query_data or reshape it to a new dataset with transform_data — only aggregated results or artifact metadata enter the model context.

How it works

  • Progressive workflow — the agent explores step by step: list_products → get_product → list_apis → get_api → (get_api_examples) → execute_api, narrowing 17,000+ APIs to one concrete call. Each step keeps the LLM context bounded; the full guide is baked into the server instructions.
  • Metadata-driven, zero SDK — API metadata is fetched live from Huawei Cloud API Explorer and cached in memory; requests are signed locally (SDK-HMAC-SHA256, self-implemented) and sent straight to Huawei Cloud.
  • Secure by default — every execute_api must pass a safety policy (allowlist/denylist); with no policy configured, everything is denied. Rules hot-reload, and the agent can request minimal grants via manage_policy.

Quick start

Connect once — your agent explores the rest.

Prerequisites

  • Python 3.10+ and uv on your PATH (or pip)
  • A code agent: opencode or Codex — any MCP-capable client works
  • A Huawei Cloud Access Key (AK/SK) from a minimal-privilege IAM sub-user (recommended: read-only permissions for what you plan to query)
  • Network access to apiexplorer.cn-north-4.myhuaweicloud.com

Install

The quick start runs the gateway via uvx — no install step: the first invocation fetches the package automatically. For a persistent install:

pip install huaweicloud-open-mcp                  # or: uv tool install / pipx install — then replace `uvx huaweicloud-open-mcp` with `huaweicloud-open-mcp` in Step 3
pip install "huaweicloud-open-mcp[datafusion]"    # optional extra: data-mode SQL engine

Step 1 — Provide credentials

The gateway reads your AK/SK from ~/.huaweicloud/credentials (INI format, [basic] section) — on Windows that is %USERPROFILE%\.huaweicloud\credentials. See Credentials for the alternative inline-environment-variable way.

Create a .huaweicloud directory in your home directory, then a credentials file inside it with the following content:

[basic]
ak = your-access-key-id
sk = your-secret-access-key

# optional — uncomment as needed:
# security_token = <temporary-security-token>
# project_id = <project-id>
# domain_id = <domain-id>

Optional keys (uncomment as needed): security_token (temporary credentials), project_id (auto-resolved when unset), domain_id (global-level services; full support in progress). Keep the file private — it holds your secret: run chmod 600 ~/.huaweicloud/credentials on macOS/Linux; on Windows a file in your user profile is only readable by your account by default. The server reads this file at startup; the log line server start: ... credentials=configured (see --log-file) confirms it was picked up.

Step 2 — Create a read-only safety policy

The gateway refuses every execute_api call unless a policy file explicitly allows it; with no policy configured, everything is denied.

Create a policy file — e.g. hwc-policy.json in your home directory — with the following content:

[
  "ECS:*List*=allow",
  "*=deny"
]

Each rule reads product:apiPattern=allow|deny — fnmatch-style wildcards, case-insensitive, # lines are comments. Rules are evaluated top-down and the first match wins, so this file allows every ECS API whose name contains List and denies everything else. Clients need the absolute path to this file — e.g. /home/you/hwc-policy.json on macOS/Linux or C:\Users\you\hwc-policy.json on Windows — because they spawn the server with their own working directory.

Step 3 — Register the gateway with your code agent

opencode — add to opencode.json (project-level, works on every OS) or the global config (~/.config/opencode/opencode.json on macOS/Linux; on Windows, prefer the project-level file or the OPENCODE_CONFIG environment variable pointing to an absolute path):

{
  "mcp": {
    "huaweicloud": {
      "type": "local",
      "command": [
        "uvx", "huaweicloud-open-mcp",
        "--policy", "/home/you/hwc-policy.json"
      ],
      "enabled": true
    }
  }
}

Codex — add to ~/.codex/config.toml (on Windows: %USERPROFILE%\.codex\config.toml) or run (single line, works in any shell):

codex mcp add huaweicloud -- uvx huaweicloud-open-mcp --policy /home/you/hwc-policy.json
[mcp_servers.huaweicloud]
command = "uvx"
args = ["huaweicloud-open-mcp", "--policy", "/home/you/hwc-policy.json"]

Replace the example path with your own absolute path from Step 2 (on Windows, e.g. C:\Users\you\hwc-policy.json; inside JSON/TOML strings write it with escaped backslashes: "C:\\Users\\you\\hwc-policy.json").

Output: start your agent — the seven gateway tools appear, prefixed with your server name (huaweicloud_list_products, huaweicloud_get_product, huaweicloud_list_apis, huaweicloud_get_api, huaweicloud_get_api_examples, huaweicloud_execute_api, huaweicloud_manage_policy). In Codex, codex mcp list shows the server and /mcp in the TUI confirms it is connected.

Credentials come from Step 1 — no secrets in the client config. If you prefer inline environment variables instead, see Credentials.

Step 4 — Browse the catalog (first real call)

Input (say to your agent):

List the available Huawei Cloud products.

The agent calls list_products, which fetches live metadata from Huawei Cloud API Explorer.

Output (abridged):

{
  "ok": true,
  "total": 310,
  "products": [
    { "product": "ECS", "name": "弹性云服务器", "category": "计算",
      "link": "https://www.huaweicloud.com/product/ecs.html" },
    { "product": "EVS", "name": "云硬盘", "category": "存储",
      "link": "https://www.huaweicloud.com/product/evs.html" }
  ]
}

Step 5 — Execute a real read-only API

Input (say to your agent):

List my ECS servers in cn-north-4.

The agent runs the progressive workflow — list_apis(ECS) to find the API, get_api to read its parameters, then execute_api, which signs the request with your AK/SK and sends it to real Huawei Cloud.

Output (abridged):

{
  "ok": true,
  "product": "ECS",
  "api": "ListServersDetails",
  "status": 200,
  "body": {
    "servers": [
      { "name": "ecs-01", "status": "ACTIVE", "id": "1d4e…" }
    ],
    "count": 2
  }
}

"count": 0 with an empty servers list is also a success — your account simply has no instances in that region; ask again with another region (for example cn-east-3).

On security: requests are signed locally and your SK never leaves your machine; the policy file confines the agent to read-only ECS List* APIs. Widen it deliberately, one pattern at a time — see Safety policy.

No account yet? Mock mode

Run the same flow without credentials: skip Step 1, and add --mock to the server command in Step 3 (uvx huaweicloud-open-mcp --mock --policy <policy-path>, e.g. /home/you/hwc-policy.json or C:\Users\you\hwc-policy.json).

Output: Step 4 works identically — the product catalog is real metadata. Step 5 returns simulated server data shaped exactly like the real response (mock endpoint, no Huawei Cloud account involved).

OBS uploads & downloads

OBS object APIs (PutObject / GetObject / AppendObject / UploadPart) never stream data through the gateway. In real mode, execute_api always answers with a presigned-URL envelope — no flag needed — and the client moves the bytes directly to/from OBS, with no size limit:

{
  "ok": true,
  "presign": {
    "url": "https://<bucket>.obs.<region>.myhuaweicloud.com/<key>?AccessKeyId=...&Expires=...&Signature=...",
    "method": "PUT",
    "expires_in": 900,
    "signed_content_type": "application/octet-stream",
    "headers": { "Content-Type": "application/octet-stream" }
  }
}

Pick up the URL with any HTTP client — the gateway never sees the data:

curl -X PUT --upload-file big.dat '<url>' -H 'Content-Type: application/octet-stream'

Rules that matter:

  • Content-Type is part of the signature. For uploads, pass _presign_content_type to lock it and send exactly the headers listed in headers; if you don't lock it, the signature assumes no Content-Type — the direct request must not send one (curl -H 'Content-Type:'). The envelope's note field warns about this case.
  • _presign_expires tunes validity in seconds (default 900).
  • All other OBS APIs (bucket management, tagging, ACL, …) execute through the gateway as usual; pass _presign=true explicitly if you want a URL for one of them. Non-OBS products reject _presign. Mock mode keeps hitting the mock endpoint.

Tools (openapi mode)

Tool Purpose
list_products Full Huawei Cloud product catalog — identifier, display name, category, product link; keyword/category filter
get_product One product's details (classification, API count, global vs regional)
list_apis A product's API directory with tag_groups overview; tag/search/limit/offset to narrow
get_api One API's full documentation (parameters, required fields, enums, constraints) — read before executing. Oversized docs (>200k chars) spill the full envelope to disk and stub the heaviest fields in the response
get_api_examples Official request examples for one API
execute_api Execute one API: path/query params flattened, request body under body; errors come back structured, 429 retried with backoff. Oversized responses (>200k chars) are spilled to disk automatically: the result carries a spill envelope (path/format/bytes/note) and body keeps a truncated preview; _spill=false opts out per call
manage_policy Read/add/remove safety-policy rules at runtime (hot effect, no restart)

Tools (data mode)

Local analytics and transformation on DataFusion (optional extra: pip install "huaweicloud-open-mcp[datafusion]"; the tools return a friendly install hint when missing).

Tool Purpose
query_data Read-only SQL over named tables: {"name": {"data": [objects]}} (inline) or {"name": {"path": "file"}} (local csv/parquet/jsonl/json-array, format auto-detected by extension); returns column schema + JSON-safe rows with row-count/char-budget truncation
transform_data Persist a read-only SQL transformation to a new data file: out = {"path", "format"?} (csv/parquet/jsonl), atomic write, refuse-overwrite by default (overwrite=true to allow); returns artifact metadata (path/format/rows/bytes) + a small preview

Strictly read-only SQL: only SELECT/WITH/EXPLAIN/SHOW/DESCRIBE statements pass the guard; multi-statement and write statements (INSERT/CREATE/COPY TO/…) are rejected — in transform_data the write is applied by the engine after the guard, via the structured out parameter (audit NDJSON records the write path), never via SQL. Both tools touch no cloud APIs, need no credentials and are not subject to the safety policy — deploy them only where the agent session is trusted to read (and, for transform_data, write) local files.

Safety policy

A policy file is a JSON array (or plain text) of rules, evaluated top-down, first match wins:

[
  "ECS:*List*=allow",
  "VPC:*Show*=allow",
  "*=deny"
]
  • Rule format product:apiPattern=allow|deny — fnmatch-style wildcards, case-insensitive product/API, # lines are comments.
  • No --policy configured → every execution denied.
  • Grant scopes (via manage_policy add): once (single execution, burned after use) · session (default; this agent session only) · temporary (TTL) · permanent (written to the policy file).
  • Hot everywhere: external edits to the file apply immediately; add/remove via manage_policy too. Grant minimal rules first (once/session), product-wide only when justified.
  • Denials return an actionable reason; with --elicitation auto|required the server proposes a grant over MCP elicitation (four choices: api = minimal rule, one-shot / api_session = minimal rule, session-scoped / product = product-wide, session-scoped / none). Default is off for predictable cross-client behavior.

A richer example ships with the package: configs/safety-policy.example.json.

Custom hints (optional)

A hints file lets a deployment inject its own guidance into the discovery chain: a global instructions block appended to the server instructions, plus per-product notes and per-API texts attached to discovery results (list_products / get_product / list_apis / get_api).

{
  "instructions": "This deployment targets ops inspection: prefer List*/Show* APIs for batch lookups.",
  "products": {
    "ECS": {
      "notes": "Prefer ListServersDetails for listing servers.",
      "apis": {
        "ResizeServer": "Check flavor availability with ListFlavors first."
      }
    },
    "OBS": "Object upload/download always returns a presign envelope; the gateway never moves bytes."
  }
}
  • Official metadata is never replaced — hints ride along in an extra hints field (product + API notes are merged, product first).
  • Injected only on successful discovery results, never on denials (gate/policy rejections stay untouched); get_api_examples and execute_api are never annotated.
  • Product keys and apis keys are case-insensitive; a product value may be a plain string (product note only) or an object with notes / apis.
  • Loaded at startup (no hot reload); invalid configs fail fast at startup. Without --hints, behavior is byte-for-byte unchanged.

Example: configs/openapi-hints.example.json.

Configuration

CLI flags

Flag Default Description
--mode <modes> openapi Run mode(s), comma-separated (openapi/discover/data, e.g. openapi,data; env HUAWEICLOUD_MCP_MODE)
--mock off Point execute_api at the API Explorer mock endpoint (no credentials needed)
--mock-base <url> Mock endpoint base URL override (env HUAWEICLOUD_MCP_MOCK_BASE)
--mock-passthrough off Mock mode: forward execute business params to the mock endpoint (env HUAWEICLOUD_MCP_MOCK_PASSTHROUGH)
--policy <file> Safety policy file; missing → all executions denied
--region <id> cn-north-4 Default region
--gate <file> Optional product gate (allowlist; unlisted products are hidden from the agent)
--hints <file> Optional custom-hints file (deploy-side guidance injected into instructions and discovery results)
--elicitation auto|required|off off MCP-elicitation confirmation for policy changes
--spill-dir <dir> system temp dir (hwc-mcp-spill) Where oversized responses/envelopes are spilled (empty or off disables spilling; pure truncation returns)
--audit-file <file> disabled Audit trail (NDJSON): one {ts, tool, input, ok} line per tool call
--log-level / --log-file INFO / logs/huaweicloud-open-mcp.log Logging (rotating file; stderr mirrors WARNING+)

Environment variables

Variable Purpose
HUAWEICLOUD_SDK_AK / HUAWEICLOUD_SDK_SK Access key / secret key (real mode); see Credentials for the profile-file alternative
HUAWEICLOUD_SDK_SECURITY_TOKEN Optional temporary-security-credential token
HUAWEICLOUD_SDK_PROJECT_ID Optional; resolved automatically when unset
HUAWEICLOUD_SDK_DOMAIN_ID Optional; loaded for global-level services (full support in progress)
HUAWEICLOUD_MCP_MODE Same as --mode
HUAWEICLOUD_MCP_REGION Same as --region
HUAWEICLOUD_MCP_MOCK Same as --mock (1/true/yes)
HUAWEICLOUD_MCP_MOCK_BASE Mock endpoint base URL override
HUAWEICLOUD_MCP_MOCK_PASSTHROUGH Same as --mock-passthrough
HUAWEICLOUD_MCP_POLICY_FILE Same as --policy
HUAWEICLOUD_MCP_OPENAPI_GATE Same as --gate
HUAWEICLOUD_MCP_OPENAPI_HINTS Same as --hints
HUAWEICLOUD_MCP_AUDIT_FILE Same as --audit-file
HUAWEICLOUD_MCP_SPILL_DIR Same as --spill-dir
HUAWEICLOUD_MCP_ELICIT Same as --elicitation
HUAWEICLOUD_MCP_LOG_LEVEL / HUAWEICLOUD_MCP_LOG_FILE Same as --log-level / --log-file

Credentials

The gateway loads AK/SK from two sources, checked in order: environment variables → ~/.huaweicloud/credentials (on Windows: %USERPROFILE%\.huaweicloud\credentials). When both are configured, environment variables win.

Option A — Profile file (quick-start main path)

~/.huaweicloud/credentials — exactly what Step 1 creates:

[basic]
ak = your-access-key-id
sk = your-secret-access-key

# optional — uncomment as needed:
# security_token = <temporary-security-token>
# project_id = <project-id>
# domain_id = <domain-id>
  • [basic] section with ak and sk is required; the three optional keys mirror the environment variables below.
  • A missing file is silently skipped — the server simply runs without credentials (metadata tools keep working; see below).
  • Keep it private — the file holds your secret: run chmod 600 ~/.huaweicloud/credentials on macOS/Linux; on Windows a file in your user profile is only readable by your account by default.

Option B — Environment variables (inline in client registration)

Set them in the client registration instead of the profile file:

opencode — add an environment block next to command:

"environment": {
  "HUAWEICLOUD_SDK_AK": "your-access-key-id",
  "HUAWEICLOUD_SDK_SK": "your-secret-access-key"
}

Codex — add --env flags before -- (single line, works in any shell):

codex mcp add huaweicloud --env HUAWEICLOUD_SDK_AK=your-access-key-id --env HUAWEICLOUD_SDK_SK=your-secret-access-key -- uvx huaweicloud-open-mcp --policy /home/you/hwc-policy.json
Variable Purpose
HUAWEICLOUD_SDK_AK / HUAWEICLOUD_SDK_SK Required pair
HUAWEICLOUD_SDK_SECURITY_TOKEN Optional temporary-security-credential token
HUAWEICLOUD_SDK_PROJECT_ID Optional; resolved automatically when unset
HUAWEICLOUD_SDK_DOMAIN_ID Optional; loaded for global-level services (full support in progress)

Behavior notes

  • Without credentials, metadata tools (list_products, list_apis, get_api, …) keep working — their data comes from the public API Explorer. Only execute_api needs credentials.
  • Use a dedicated minimal-privilege IAM sub-user's AK/SK — the gateway can then only do what that user could do anyway.
  • Signing happens locally; the SK never leaves your machine, and credentials never appear in logs.

Troubleshooting

Symptom Likely cause Fix
Client shows "failed to connect" or the server exits immediately --policy path is relative or the file is missing — the server fails fast on a bad policy file Use an absolute path to a file that exists
The seven tools never appear in the agent uvx is not on the client's PATH Find it with which uvx (macOS/Linux) or where uvx (Windows) and use the absolute path in place of uvx in the command
Metadata tools work but execute_api fails Credentials not loaded (empty [basic] section, or env vars shadow an empty file) Fix ~/.huaweicloud/credentials (see Credentials) or set the HUAWEICLOUD_SDK_* environment variables
execute_api returns {"ok": false, "reason": ...} mentioning policy The API is not allowed by the policy file (the quick-start file allows only ECS:*List*) Edit the policy file — changes hot-reload without restarting the server — or, after confirming with the user, have the agent add a rule via manage_policy
401 / SignatureDoesNotMatch Wrong AK or SK Recheck the credentials source in use (env wins over profile file)
403 from Huawei Cloud with a permission error The IAM user lacks the permission Grant the minimal IAM policy needed for that API
"count": 0 but you have servers Resources live in another region Ask again with an explicit region, e.g. cn-east-3
Mock calls hang or time out No network route to the API Explorer endpoint Check proxy/firewall access to apiexplorer.cn-north-4.myhuaweicloud.com

For deeper diagnosis, add --log-level DEBUG --log-file <log> to the registration command — e.g. /tmp/hwc-mcp.log on macOS/Linux or %TEMP%\hwc-mcp.log on Windows — and inspect the log file.

Documentation

Explore the design behind the gateway:

Document Type Language
docs/architecture.md Design overview (layers, modules, logging, tests) 中文
docs/mcp-openapi.md openapi-mode design (workflow, signing, OBS lane) 中文
AGENTS.md Contributor conventions (TDD seams, release flow) 中文
benchmarks/README.md Workflow-benchmark design 中文

Development

uv sync                                  # deps (incl. dev)
uv run huaweicloud-open-mcp              # run from source
uv run pytest                            # unit + integration (e2e skipped by default)
uv run pytest -m e2e                     # real-credential E2E
uv run ruff check src tests              # lint
uv run mypy src                          # type check

Companion CLIs: api-refresh (offline APIE pipeline: fetch API Explorer → OpenAPI 2.0 docs) and api-docs (metadata queries from the terminal). Details in AGENTS.md.

Publishing

Releases distinguish TestPyPI from the production PyPI index; both upload URLs are pinned as named indexes in pyproject.toml ([[tool.uv.index]]):

scripts/publish test                      # TestPyPI (token: UV_PUBLISH_TOKEN_TEST)
scripts/publish prod                      # PyPI (token: UV_PUBLISH_TOKEN_PROD, confirmation gate; --yes for CI)
scripts/publish <test|prod> --skip-build  # republish existing dist/ artifacts

Notes:

  • TestPyPI and PyPI accounts/API tokens are independent — request each token from the corresponding site's Account Settings; the script strictly uses the target-specific env var with no fallback, so credentials can never be mixed up.
  • Each build clears dist/ first (uv build + uvx twine check), so no stale artifacts can be uploaded.
  • prod prints the target URL, project version, and artifact list, then requires typing yes.
  • Version numbers are unique per index: never reuse a version already uploaded (verify on TestPyPI, bump the version, then publish to PyPI).

License

Apache-2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

huaweicloud_open_mcp-0.1.0a2.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

huaweicloud_open_mcp-0.1.0a2-py3-none-any.whl (170.8 kB view details)

Uploaded Python 3

File details

Details for the file huaweicloud_open_mcp-0.1.0a2.tar.gz.

File metadata

  • Download URL: huaweicloud_open_mcp-0.1.0a2.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Manjaro Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for huaweicloud_open_mcp-0.1.0a2.tar.gz
Algorithm Hash digest
SHA256 b5fea62363aaf01242723eb813eff54477350c5c7790ae443db504ecc86d8685
MD5 ef5ac0387a1b70b251da52b4b9a908d9
BLAKE2b-256 8719c25d2ef6ef52f9629e469a0c8b978281bf4e217ce07fdf1f2c0333ae2c8a

See more details on using hashes here.

File details

Details for the file huaweicloud_open_mcp-0.1.0a2-py3-none-any.whl.

File metadata

  • Download URL: huaweicloud_open_mcp-0.1.0a2-py3-none-any.whl
  • Upload date:
  • Size: 170.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Manjaro Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for huaweicloud_open_mcp-0.1.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 6fbbd06459bc47c29d0852e1472a3fdbe4e012f34ecffb4a288941b4eb11a910
MD5 db7225659e5503a0911473464329ad70
BLAKE2b-256 e103836b0c6a011e232907d12f22c01ec4983eaf6daf6530a62bba10c925ce05

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0a2 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page