Skip to main content
Glama

s3-mcp

Minimal Model Context Protocol server for S3-compatible storage — AWS S3, RustFS, MinIO, Cloudflare R2, and similar.

  • Path-style addressing by default (required for many self-hosted endpoints whose TLS cert does not cover bucket.endpoint subdomains)

  • Opt-in self-signed / custom-CA TLS trust, scoped to the S3 client only

  • Read-only by default; writes require an explicit flag

  • Optional bucket allow-list

  • Env vars + CLI flag overrides; secrets stay env-only

Tools

Tool

Access

Description

s3_list_buckets

read

List buckets

s3_list_objects

read

List objects (prefix, delimiter, pagination). Listing does not return user metadata — use s3_head_object.

s3_head_object

read

Size, ETag, content-type, user metadata

s3_read_object

read

Read body via a capped Range request (encoding: auto | utf8 | base64)

s3_put_object

write

Upload text or base64 content

s3_delete_object

write

Delete object (idempotent: missing key → success)

Write tools refuse with a clear error unless S3_ALLOW_WRITE=true (or --allow-write).

Related MCP server: S3 MCP Server

Install / run

{
  "mcpServers": {
    "s3": {
      "command": "npx",
      "args": ["-y", "s3-mcp"],
      "env": {
        "S3_ENDPOINT": "https://rustfs.example.com",
        "S3_ACCESS_KEY_ID": "<key>",
        "S3_SECRET_ACCESS_KEY": "<secret>",
        "S3_REGION": "us-east-1",
        "S3_ALLOW_SELF_SIGNED": "true"
      }
    }
  }
}

A bare --stdio arg is accepted and ignored (drop-in compatible with configs written for s3-mcp-server).

npx straight from GitHub

{
  "mcpServers": {
    "s3": {
      "command": "npx",
      "args": ["-y", "github:tompetk/s3-mcp"],
      "env": {
        "S3_ENDPOINT": "https://rustfs.example.com",
        "S3_ACCESS_KEY_ID": "<key>",
        "S3_SECRET_ACCESS_KEY": "<secret>",
        "S3_REGION": "us-east-1",
        "S3_ALLOW_SELF_SIGNED": "true"
      }
    }
  }
}

Keep -y: without it npx asks for install confirmation on stdin, which is the MCP transport, so the server never starts. The first run takes roughly 40 seconds because npm installs TypeScript and runs the prepare build; later runs use the npx cache. The published npm package ships prebuilt dist/, so ["-y", "s3-mcp"] starts instantly.

From source

git clone https://github.com/tompetk/s3-mcp.git
cd s3-mcp
npm install
npm run build
node dist/index.js --help

Point your MCP client at node + the absolute path to dist/index.js.

Configuration examples

RustFS / MinIO (self-hosted, often self-signed)

{
  "mcpServers": {
    "s3": {
      "command": "npx",
      "args": ["-y", "s3-mcp", "--insecure"],
      "env": {
        "S3_ENDPOINT": "https://rustfs.example.com",
        "S3_ACCESS_KEY_ID": "<key>",
        "S3_SECRET_ACCESS_KEY": "<secret>",
        "S3_REGION": "us-east-1",
        "S3_FORCE_PATH_STYLE": "true",
        "S3_ALLOW_WRITE": "false"
      }
    }
  }
}

Prefer a custom CA when you have one:

S3_CA_BUNDLE=/path/to/ca.pem

--insecure / S3_ALLOW_SELF_SIGNED=true disables certificate verification for this client only (never sets NODE_TLS_REJECT_UNAUTHORIZED). Prefer S3_CA_BUNDLE when possible.

Cloudflare R2

{
  "mcpServers": {
    "s3": {
      "command": "npx",
      "args": ["-y", "s3-mcp", "--no-path-style"],
      "env": {
        "S3_ENDPOINT": "https://<ACCOUNT_ID>.r2.cloudflarestorage.com",
        "S3_ACCESS_KEY_ID": "<key>",
        "S3_SECRET_ACCESS_KEY": "<secret>",
        "S3_REGION": "auto"
      }
    }
  }
}

Environment variables & flags

Env

Flag

Default

Notes

S3_ENDPOINT

--endpoint

(required)

S3 API URL

S3_ACCESS_KEY_ID

(required)

Env only (argv is visible in ps)

S3_SECRET_ACCESS_KEY

(required)

Env only

S3_REGION

--region

us-east-1

Use auto for R2

S3_FORCE_PATH_STYLE

--path-style / --no-path-style

true

Path-style is the safe default for self-hosted

S3_ALLOW_SELF_SIGNED

--insecure

false

Skip TLS verify (logs a stderr warning)

S3_CA_BUNDLE

--ca-bundle

PEM file to trust

S3_ALLOW_WRITE

--allow-write

false

Enable put/delete

S3_ALLOWED_BUCKETS

--bucket (repeatable)

Comma-separated allow-list

S3_MAX_READ_BYTES

--max-read-bytes

262144

Cap for s3_read_object

--stdio

Accepted, ignored

--help / --version

CLI flags override env vars.

Security

  • Read-only by default. Pointing this at production buckets without S3_ALLOW_WRITE cannot mutate data via the MCP tools.

  • Bucket allow-list. Set S3_ALLOWED_BUCKETS=prod-logs,prod-artifacts (or repeat --bucket) so the agent cannot touch other buckets the credentials can see.

  • TLS. Prefer S3_CA_BUNDLE over --insecure. Self-signed mode is convenient for lab endpoints; it is not a substitute for trusting the right CA.

  • Secrets. Keep keys in the MCP client's env block or a secret store — never commit them. .env is gitignored; use .env.example as a template for local smoke tests.

Development

npm install
npm run build
npm run typecheck

# Live round-trip (creates a throwaway bucket unless S3_BUCKET is set)
export S3_ENDPOINT=https://rustfs.example.com
export S3_ACCESS_KEY_ID=...
export S3_SECRET_ACCESS_KEY=...
npm run smoke

# Read-only credentials (list + head + ranged get)
S3_SMOKE_READ_ONLY=true S3_BUCKET=test npm run smoke

Publishing

Tags matching v* trigger GitHub Actions to build and npm publish --provenance --access public. Add an NPM_TOKEN repository secret once.

git tag v1.0.0
git push origin v1.0.0

License

MIT

Available Tools

6 tools
s3_delete_objectDelete S3 objectA
Destructive

Delete an object. Requires S3_ALLOW_WRITE=true. Idempotent: missing keys (NoSuchKey/404) are treated as success.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYesObject key
bucketYesBucket name

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the danger profile is known. The description adds genuinely new behavioral facts beyond them: the S3_ALLOW_WRITE=true gating requirement and idempotent handling of missing keys (NoSuchKey/404 treated as success), which materially affects error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with zero filler, front-loaded with the action, then precondition, then idempotency semantics. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter delete tool with full schema coverage and no output schema, the description covers the action, the authorization precondition, and the error/idempotency semantics. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% ('Object key', 'Bucket name'), so the schema already carries parameter meaning. The description adds nothing about bucket/key formats or constraints, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Delete an object') that an agent can immediately distinguish from the read/list/head/put siblings. The title and name reinforce the same precise meaning with no ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a hard precondition ('Requires S3_ALLOW_WRITE=true'), which is useful context for deciding whether the call will succeed, but it never contrasts when to use this versus siblings like s3_put_object or s3_head_object. Usage is implied rather than explicitly scoped.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s3_head_objectHead S3 objectA
Read-only

Fetch object metadata without downloading the body (size, ETag, content-type, user metadata).

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYesObject key
bucketYesBucket name

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, and destructiveHint=false, so safety is covered. The description goes beyond that by naming the exact payload returned (size, ETag, content-type, user metadata) and confirming no body transfer, though it omits error behavior (e.g., missing key) and permission requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the key constraint ('without downloading the body') and the returned fields both earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully enumerates the returned metadata, which is exactly the gap it should fill. Error/edge-case behavior is the only missing piece, which is minor for a simple two-parameter read operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so bucket and key are already documented in the schema. The description adds no meaning beyond that (e.g., key format, versioning, prefix behavior), so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch object metadata') and immediately differentiates itself from the body-downloading sibling by specifying 'without downloading the body'. An agent can distinguish this from s3_read_object without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the 'without downloading the body' clause, which suggests this is the cheap metadata-check alternative to s3_read_object. However, it never explicitly says when to use this versus alternatives (e.g., for existence checks) or when-not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s3_list_bucketsList S3 bucketsA
Read-only

List all available S3 buckets visible to the configured credentials.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds meaningful context beyond that: results are limited to buckets visible to the configured credentials, which tells the agent why the list may be partial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the resource and its scoping constraint are both stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with full annotation coverage and no output schema, the description is nearly sufficient. It does not state what the response contains (e.g., bucket names) or whether large accounts are truncated, a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so per the baseline this scores 4. The empty schema and the description agree that no filtering or paging inputs are accepted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (S3 buckets) with scope ('visible to the configured credentials'). The bucket-level resource naturally distinguishes it from the object-level siblings such as s3_list_objects and s3_head_object.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use statement, no exclusions, and no named alternatives. Usage is implied by the resource scope — an agent would reasonably call this to discover buckets before listing objects — but the description never says so.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s3_list_objectsList S3 objectsA
Read-only

List objects in a bucket. Optional prefix/delimiter for folder-style browsing. Note: S3 ListObjectsV2 does not return user metadata — use s3_head_object for that.

ParametersJSON Schema
NameRequiredDescriptionDefault
bucketYesBucket name
prefixNoKey prefix filter
maxKeysNoMax keys to return (default 1000)
delimiterNoDelimiter for common prefixes (e.g. "/")
continuationTokenNoPagination token from a previous response

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/openWorldHint/destructiveHint=false, so the safety profile is covered. The description adds a valuable limitation (metadata not returned) but says nothing about pagination behavior despite exposing a continuationToken, so added behavioral context is partial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short, front-loaded sentences with zero filler; purpose first, then the browsing idiom, then the sibling-routing caveat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate for a read-only list tool whose annotations carry safety, but for a paginated list with a continuationToken parameter and no output schema, an agent gets no description of what the response contains or how to page. This is a meaningful gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters are already fully documented. The description's mention of prefix/delimiter semantics and the metadata note adds marginal value but no syntax or format detail beyond the schema; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List objects in a bucket') and names the sibling it is not (s3_head_object), with scope clarified by prefix/delimiter for folder-style browsing. An agent can distinguish this from s3_list_buckets and neighboring object tools without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes metadata lookups to s3_head_object and implies folder-style browsing via prefix/delimiter. It does not, however, cover when-not-to-use beyond the metadata case, e.g. no guidance on choosing this over s3_list_buckets or on pagination workflows.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s3_put_objectPut S3 objectA
Destructive

Upload object content. Requires S3_ALLOW_WRITE=true. Pass encoding=base64 to upload binary data from a base64 string.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYesObject key
bucketYesBucket name
contentYesObject body (text or base64)
encodingNoHow to decode content (default: utf8)
metadataNoUser metadata key/value map
contentTypeNoContent-Type header

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and openWorldHint=true, so the mutation/global side effects are covered. The description adds value by disclosing the S3_ALLOW_WRITE=true authorization gate, which an agent cannot infer from annotations or schema. It omits whether existing keys are overwritten, which would be the remaining useful detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with the core action first, then the prerequisite, then the binary-data hint. No filler and everything is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and full schema coverage, the definition covers the action, the authorization prerequisite, and binary encoding. The main gap is overwrite/conflict behavior on an existing key, which is relevant for a put operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so bucket, key, content, encoding, metadata, and contentType are all documented in the schema. The description's encoding=base64 note merely restates the enum's intent, adding no syntax or edge-case detail beyond the structured fields, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Upload object content'), which is unambiguous against siblings like s3_read_object, s3_delete_object, and s3_list_objects. It does not explicitly name a sibling to disambiguate, but the write action is inherently distinct from the read/list/delete tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete precondition ('Requires S3_ALLOW_WRITE=true') and a format hint ('Pass encoding=base64 to upload binary data'), which tells the agent when the tool will work and how to handle binary payloads. It stops short of comparing against alternatives or stating when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s3_read_objectRead S3 objectA
Read-only

Read object content. Uses a Range request capped by maxBytes so large objects never stream in full. encoding=auto returns UTF-8 text when decodable, otherwise base64.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYesObject key
bucketYesBucket name
encodingNoHow to encode the body (default: auto)
maxBytesNoMax bytes to read (default: 262144)

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/destructive/openWorld, so the bar is lower, yet the description adds real operational context: a Range request capped by maxBytes means large objects are never fully streamed, and encoding=auto has defined fallback behavior. It does not state error behavior for missing keys, but the added traits go meaningfully beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the core purpose front-loaded and no filler. Each sentence carries distinct information: purpose, size-bound behavior, and encoding behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must convey what comes back, and it does explain that the returned body is UTF-8 or base64 depending on encoding. It leaves out failure/not-found behavior and pagination-style continuation for truncated reads, which is a minor gap for a read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3, but the description adds semantics the schema lacks: that maxBytes is enforced via a Range request (bounding transfer cost) and that encoding=auto returns UTF-8 when decodable and falls back to base64. These explain the behavior of the two optional parameters rather than restating their names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read object content') that is clearly distinct in intent from sibling operations like s3_list_objects, s3_head_object, and s3_put_object. It stops short of explicitly contrasting itself with s3_head_object (metadata-only), so it misses the top tier.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance and no alternatives named. The obvious selection question (content read vs s3_head_object for metadata-only) is left entirely to inference. This matches the calibration case of a description with no explicit usage conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv1.0.0
    • First observeds3_delete_object
    • First observeds3_head_object
    • First observeds3_list_buckets
    • First observeds3_list_objects
    • First observeds3_put_object
    • First observeds3_read_object

TDQS

A4.2/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct S3 operation: listing buckets, listing objects, fetching metadata, reading content, uploading, and deleting. The descriptions explicitly clarify the tricky boundary between s3_head_object (metadata only) and s3_read_object (content), and between s3_list_objects and s3_head_object regarding user metadata.

Naming Consistency5/5

Every tool follows the same predictable `s3_verb_noun` snake_case pattern (s3_list_buckets, s3_read_object, s3_put_object, etc.). No mixed conventions or vague verbs.

Tool Count5/5

Six tools is well-scoped for a focused S3 object-access server, covering the core read/write lifecycle without bloat. Each tool earns its place with a non-overlapping job.

Completeness4/5

Core object lifecycle is covered: list buckets, list objects, head, read, put, delete. Minor gaps exist — no bucket create/delete, no copy_object, and no multi-object delete — but agents can work around these for typical object read/write tasks.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables AI assistants to manage MinIO object storage through comprehensive bucket operations, file uploads/downloads, batch processing, permissions management, and URL generation. Supports both automatic and manual connection modes with flexible authentication options.
    19
    15 npm
    2
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables interaction with S3-compatible storage services like AWS S3 and Cloudflare R2, supporting bucket management, object listing, reading, uploading, and deletion operations.
    5
    199 npm
    ISC
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables interaction with AWS S3 storage through bucket operations (create, delete, list), object management (upload, download, delete, list), and bucket policy configuration using AWS credentials.
    21 npm
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    It Integration for MinIO / S3-compatible object storage, providing AI assistants with direct access to bucket management, object CRUD, presigned URLs, policies, lifecycle rules, and storage analytics.
    1
    MIT