MCP server for the Garage (deuxfleurs) S3-compatible storage Admin API - bucket, key and permission management as MCP tools.
Strong foundation with 23 well-named tools, comprehensive descriptions (avg 180 chars), and complete input schemas. All tools follow verb_noun naming convention. Descriptions clearly state WHAT the tool does and WHEN to use it. Parameters are well-typed with clear descriptions. Key strengths: destructive operations (delete_bucket, delete_key) include confirmation patterns; permission tools (allow_bucket_key, deny_bucket_key) document Garage's additive/subtractive semantics; S3 object tools include max_bytes truncation guidance. Gaps: output schemas not documented in source; no explicit error recovery guidance in descriptions; some parameter descriptions could be more prescriptive about constraints (e.g., max_keys default/range).
Give a bucket an additional global alias/name. A bucket can have several aliases at once.
Grant a key permissions on a bucket. Garage's own semantics (not a simplification made here): only the flags you set to true are granted. Flags left false are NOT revoked - they simply keep whatever permission they already had. This call can only add permissions; use deny_bucket_key to remove one.
Create a new bucket in Garage.
Create a new S3 access key. The response includes the new key's secret access key in cleartext exactly once - Garage never returns it again after this call, so make sure the caller captures it. The new key starts with no bucket permissions; use allow_bucket_key to grant access to specific buckets.
Permanently delete a bucket. THIS CANNOT BE UNDONE. Garage refuses the request if the bucket still contains objects. To prevent an LLM from deleting the wrong bucket based on an ambiguous instruction, confirm_id is required and must be byte-for-byte identical to id - the call is rejected locally, before any request reaches Garage, if they don't match.
Output schemas not documented in source code. Tool descriptions state WHAT is returned (e.g., 'aliases, website configuration, quotas') but JSON Schema output structure is not visible in provided code. LLMs cannot plan downstream tool calls without knowing response field names and types.
Parameter constraints not fully specified. list_s3_objects max_keys has no documented range (default 1000 stated, but min/max bounds missing). get_s3_object max_bytes default 100000 stated but no range. Unbounded numeric parameters risk LLM passing absurd values.
Error recovery guidance missing. Descriptions state what tools do but lack actionable error guidance (e.g., 'If bucket not found, try list_buckets() to find the correct ID'). Agents cannot self-correct on failures.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 69 | 2026-07-28+ | v2 |
Permanently delete an S3 access key, revoking all its access immediately. THIS CANNOT BE UNDONE. To prevent an LLM from deleting the wrong key based on an ambiguous instruction, confirm_id is required and must be byte-for-byte identical to id - the call is rejected locally, before any request reaches Garage, if they don't match.
Revoke a key's permissions on a bucket. Garage's own semantics (not a simplification made here): only the flags you set to true are revoked. Flags left false are NOT granted - they simply keep whatever permission they already had. This call can only remove permissions; use allow_bucket_key to add one.
Get full detail on a single bucket: aliases, website configuration, quotas, storage usage, object count, and which keys have which permissions on it. Exactly one of the arguments should normally be given.
Get the health of the Garage cluster (connected/known nodes, storage node quorum, partition status). Use this to check whether the cluster is able to serve reads/writes right now.
Get the current cluster layout: how storage capacity is assigned to each node/zone, and any staged (not-yet-applied) layout changes.
Get freeform, human-readable cluster statistics (the same text the `garage stats` CLI command prints), including per-node storage usage and object counts.
Get the current status of the Garage cluster: member nodes, their roles/zones/capacities, and whether each node is currently connected. Use this to get a quick overview of the whole cluster.
Get full detail on a single S3 access key: its name, which buckets it has read/write/owner permissions on, and quotas. Never returns the secret access key value (deliberately not exposed by this tool, see module docstring). Exactly one of the arguments should normally be given.
Get detailed information about a single cluster node (identified by its node ID, as seen in get_cluster_status), such as its Garage version and configuration.
Get statistics for a single cluster node (identified by its node ID, as seen in get_cluster_status), such as storage usage and block counts.
Read the text content of an object in an S3 bucket. Only text (UTF-8 decodable) objects are supported - binary files raise an error rather than returning garbled or base64 output. Content longer than max_bytes is truncated with a note appended.
Register an existing S3 access key pair (e.g. one generated outside Garage's admin API) with the cluster, so it can be granted bucket permissions like any other key. Security note: this tool's arguments include a real credential (secret_access_key). Only import keys you already control. The secret is sent to Garage as part of this call; be aware that it will also appear in this MCP call's arguments/conversation history wherever that is logged or stored by the client.
List all buckets in the Garage cluster, with their IDs, global/local aliases, and a few key flags (e.g. whether a website is configured). Use get_bucket_info for full detail on one bucket.
List all S3 access keys registered in the Garage cluster, with their IDs and names (no secrets). Use get_key_info for full detail on one key, including which buckets it can access.
List objects in an S3 bucket via Garage's S3 API (not the admin API - use list_buckets/get_bucket_info for bucket-level metadata instead). Only buckets the configured S3 credentials have read access to are reachable; this call fails for any other bucket.
Remove a global alias from a bucket. Garage refuses if this would leave the bucket with no aliases and no local aliases either (a bucket must remain reachable by at least one name).
Update a bucket's storage quotas and/or static-website configuration. Only the arguments you pass are changed; the rest of the bucket's configuration is left as-is. Quota note (Garage requirement, not a limitation of this tool): the two quota fields cannot be changed independently. If you set only quotas_max_size, quotas_max_objects is reset to "no limit" (and vice versa) - pass both together if you want to keep an existing limit. Website note: website_index_document is required when enabling the website (website_enabled=True); when disabling it (website_enabled=False), neither index nor error document should be set. Out of scope for this tool (use the garage CLI or web UI instead): CORS rules, lifecycle rules.
Rename a key and/or clear its expiration date. Only the arguments you pass are changed.
Mutually exclusive parameters not explicitly documented. get_bucket_info accepts id, global_alias, or search, description says 'Exactly one...should normally be given' but does not state what happens if multiple are passed. LLMs may pass all three.
Pagination not implemented for list tools. list_buckets, list_keys, list_s3_objects return all results without limit/offset/cursor. Large clusters could return thousands of items, exhausting context window and degrading LLM reasoning.