Read-only Exoscale advisor MCP server — docs search plus list-only live catalogue queries, structurally incapable of mutation.
Project description
exoscale-mcp-advisor
A read-only Model Context Protocol server that lets an MCP-capable agent learn about Exoscale: search the verified connector documentation and run list-only live catalogue queries (zones, instance types, templates, managed-database plans, SKS versions). It is, by construction, incapable of mutating any cloud resource.
Status: released. Eight read-only tools, the stdio server, and the four-layer test suite (structural no-mutation, mocked-connector, protocol-level, gated live smoke) are in place and green; published to PyPI as
exoscale-mcp-advisor. The full design is indocs/mcp-advisor-design.md; release history is inCHANGELOG.md.
It builds on exoscale-connector:
the knowledge it serves is read from that package's bundled reference, and the
live queries reuse the connector's read-only list clients. Nothing about
Exoscale is hardcoded or duplicated here.
General description
The advisor targets the learning path, not the execution path. An agent can ask
"what instance types exist in at-vie-1 right now?" or "how do I create a
security group with the connector?" and get live data plus verified docs, while
the server stays structurally unable to create, change, or delete anything.
Infrastructure changes stay the human's job, performed with reviewed, idempotent
code.
Tool surface (see design §3):
| Tool | Credentials | Purpose |
|---|---|---|
search_docs(query) |
— | Ranked sections from the connector's reference bundle. |
get_asset_page(asset_type) |
— | Full reference page for one asset type. |
list_asset_types() |
— | The asset-type index (slug + heading) for discovery. |
list_zones() |
✔ | Live list of zones. |
list_instance_types(zone) |
✔ | Live list of instance types (with derived memory_gib). |
list_templates(zone, visibility) |
✔ | Live list of templates (with derived size_gib). |
list_dbaas_plans(zone=None) |
✔ | Live managed-database (DBaaS) service types and plans. |
list_sks_versions(zone=None) |
✔ | Live list of Kubernetes versions a new SKS cluster may use. |
The three docs tools need no credentials; the five live tools read Exoscale API credentials from the server's environment (see the User guide). No mutation tools — ever, by design.
User guide
The server runs with no clone or install step:
uvx exoscale-mcp-advisor
Or from a source checkout (for development):
pip install -e .
exoscale-mcp-advisor # or: python -m exoscale_mcp_advisor
It speaks MCP over stdio, so it is configured like any other stdio MCP server in your client. The five live catalogue tools require Exoscale API credentials in the server's launch environment. They are never passed on the command line and never read from a file by the app:
EXOSCALE_API_KEY=...
EXOSCALE_API_SECRET=...
EXOSCALE_ZONE=at-vie-1
Getting them into the server's environment, two common ways:
# 1) Pass them to the MCP client as it launches the server (Claude Code shown):
claude mcp add exoscale-advisor \
-e EXOSCALE_API_KEY=... -e EXOSCALE_API_SECRET=... -e EXOSCALE_ZONE=at-vie-1 \
-- uvx exoscale-mcp-advisor
# 2) Inject from a vault at launch, so no secret is typed or stored in config:
claude mcp add exoscale-advisor -- \
infisical run --domain http://localhost:8080 -- uvx exoscale-mcp-advisor
Use a least-privilege, read-only API key (see the Admin guide). The three docs
tools (search_docs, get_asset_page, list_asset_types) need no credentials;
if the live tools run without credentials they return a clear, actionable error
while the docs tools keep working. The catalogue exposes no pricing, so use
Exoscale's calculator for cost estimates.
Example use cases
What the advisor is for, from trivial to advanced. Every example is read-only: the server produces explanations and reviewable code, never a side effect (design D1). Each rung notes the tools it uses and whether credentials are needed.
-
Docs lookup, no credentials. "Search the Exoscale docs for how to create a security group, then show me the full security-group reference page." Uses
search_docsandget_asset_page, withlist_asset_typesto discover slugs first. -
A single live query. "What instance types are available in
at-vie-1right now?" Uses one live tool such aslist_instance_typesorlist_templates;memory_gibandsize_gibcome pre-derived, so no manual byte math. -
Live and docs synthesis. "Compare the instance types in
at-vie-1and recommend one suitable as an SKS worker, citing the sizing constraints." Combines a live tool withget_asset_pageand reasoning; it has no pricing data, so cost questions defer to Exoscale's calculator. -
Multi-asset design, read-only. "Design an HA web-app stack in
at-vie-1(load balancer, web tier, managed database), cite the docs for each asset, and don't provision anything." Uses manyget_asset_pagecalls pluslist_dbaas_plansandlist_zones, returning a design and citations rather than a side effect. -
Reviewable code generation. "Generate an
exoscale-connectorscript that provisions the stack above, with secrets side-loaded from the environment, and I'll run it." The advisor-not-operator pattern: read-only advice plus a script you review and run, with the server unable to apply changes itself.
The ladder is the point: a credential-free entry for learning at rung 1, and a ceiling at rung 5 where the advisor writes the infrastructure code while a human keeps the keys and the final apply.
Admin guide
Least-privilege credentials (defense in depth). Although the server can only
issue list calls, the API key it runs with should also be restricted to
read-only operations, so the key itself cannot mutate anything. Build the IAM
policy with the connector's own iam_expr / IAMPolicy helpers (default-deny,
then allow only list/get catalogue operations) — see the connector's IAM
policy cookbook and design §7.
Credential injection. Credentials come from the environment, injected at
startup by a vault CLI (e.g. infisical run -- uvx exoscale-mcp-advisor in
development; a production vault agent in production). The application never reads
secrets from files and is not coupled to any specific vault provider.
Security model. Read-only is enforced on two independent layers: the code registers only read-only tools (a CI test fails the build if a mutation tool is ever added), and the credentials are scoped to read-only operations. See design §6–§7.
Developer guide
Setup
python -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
Requires Python ≥3.10 (the mcp SDK floor).
Checks
ruff check src tests # lint
mypy src # type-check
pytest tests/unit -q # unit tests
The gated live smoke test (under tests/integration) talks to a real account
using only list, and is opt-in behind EXOSCALE_RUN_LIVE_TESTS=1 — default-
skipped, and never run in CI. Run it with credentials injected from the
environment (never hardcoded):
EXOSCALE_RUN_LIVE_TESTS=1 \
infisical run --domain http://localhost:8080 -- \
pytest tests/integration -q
It is read-only, so safe to run against any account.
Architecture & contribution. Read
docs/mcp-advisor-design.md first — it defines the
tool surface, the zero-duplication knowledge source, the read-only-by-
construction guarantee, and the four-layer test strategy. Conventional commits;
keep this README current with behavior changes in the same commit; no untested
code lands.
Stability & compatibility. The public API is the tool surface (tool names
and their contracts) — everything else is internal and may change. Pre-1.0,
minor versions may introduce breaking changes. The full policy, including the
deprecation procedure and the exoscale-connector floor guarantee, is
design §16.
Releasing. The version is single-sourced from __version__ in
src/exoscale_mcp_advisor/__init__.py. There is no credential to manage —
publishing uses PyPI Trusted Publishing (OIDC), so no API token is stored or
rotated. To cut a release:
- Bump
__version__and add aCHANGELOG.mdentry; merge tomain. - Create a GitHub Release with tag
vX.Y.Z(matching the version). - Publishing the Release triggers
.github/workflows/release.yml, which builds the sdist + wheel, runstwine check, and uploads to PyPI via OIDC with PEP 740 build attestations attached.
The PyPI trusted publisher is bound to owner ralle-lang, repo
exoscale-mcp-advisor, workflow release.yml, and the pypi environment; every
action in all workflows is pinned to a commit SHA.
License
MIT © 2026 Raphael Lang
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file exoscale_mcp_advisor-0.4.0.tar.gz.
File metadata
- Download URL: exoscale_mcp_advisor-0.4.0.tar.gz
- Upload date:
- Size: 33.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cab04471fa14f6bd71df9f1259f25616ef6c4f4394b279dcd21f19fc29ab8372
|
|
| MD5 |
ea7b6ceb808b718697023924132993f0
|
|
| BLAKE2b-256 |
20b0840af6c29c0521a594af256db4b1dae26854fbd90de0a4ddd3d3d4710d55
|
Provenance
The following attestation bundles were made for exoscale_mcp_advisor-0.4.0.tar.gz:
Publisher:
release.yml on ralle-lang/exoscale-mcp-advisor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
exoscale_mcp_advisor-0.4.0.tar.gz -
Subject digest:
cab04471fa14f6bd71df9f1259f25616ef6c4f4394b279dcd21f19fc29ab8372 - Sigstore transparency entry: 1805609944
- Sigstore integration time:
-
Permalink:
ralle-lang/exoscale-mcp-advisor@a8b3b678ab78b1e54740368b9a191efb73f04af1 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ralle-lang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a8b3b678ab78b1e54740368b9a191efb73f04af1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file exoscale_mcp_advisor-0.4.0-py3-none-any.whl.
File metadata
- Download URL: exoscale_mcp_advisor-0.4.0-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71d9f1b98383d8be9df52747b9a231a6600783111b00ca98a3bfdd11cb9b4925
|
|
| MD5 |
ab4f98536f45ce1b40348f9965cd1b42
|
|
| BLAKE2b-256 |
ee0875a52ddba4c1e3aa2356be82d170c9ebba6492baf7da04a90bf34d405e75
|
Provenance
The following attestation bundles were made for exoscale_mcp_advisor-0.4.0-py3-none-any.whl:
Publisher:
release.yml on ralle-lang/exoscale-mcp-advisor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
exoscale_mcp_advisor-0.4.0-py3-none-any.whl -
Subject digest:
71d9f1b98383d8be9df52747b9a231a6600783111b00ca98a3bfdd11cb9b4925 - Sigstore transparency entry: 1805609983
- Sigstore integration time:
-
Permalink:
ralle-lang/exoscale-mcp-advisor@a8b3b678ab78b1e54740368b9a191efb73f04af1 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ralle-lang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a8b3b678ab78b1e54740368b9a191efb73f04af1 -
Trigger Event:
release
-
Statement type: