MCP server for Amazon S3 and S3-compatible endpoints (LocalStack, MinIO). Single Go binary.
Talk to Amazon S3 β or LocalStack, MinIO, any S3-compatible store β from an MCP-speaking agent.
A single static Go binary that speaks the Model Context Protocol and exposes 8 tools for working with S3: list buckets, list/read/write/delete objects, create/delete buckets. Point it at real AWS or at a local LocalStack/MinIO instance with one environment variable β same binary, same tools, zero code changes.
No Python, no uv, no runtime dependency to install β just a binary and
an .mcp.json.
An agent that can only talk about your S3 buckets isn't that useful. This gives it hands: it can look inside a bucket, read a config file out of it, drop a report back in, or clean up a stale prefix β safely, with guardrails on size and destructive actions built in.
| Tool | What it does | Write? |
|---|---|---|
s3_list_buckets | List buckets visible to the credentials | |
s3_list_objects | List objects in a bucket, optional prefix, paginated | |
s3_head_object | Object metadata (size, type, ETag) without downloading | |
s3_get_object | Read an object's content β text or base64, size-capped | |
s3_put_object | Write a small text/base64 object (β€ 5 MB) | βοΈ |
s3_delete_object | Delete one object | ποΈ destructive |
s3_create_bucket | Create a bucket | βοΈ |
s3_delete_bucket | Delete an empty bucket | ποΈ destructive |
Every tool accepts an optional response_format: markdown (default,
pretty tables for a chat UI) or json (for programmatic use).
s3_get_object auto-detects text vs. binary content and caps output at
200,000 bytes by default (raise via max_bytes, hard cap
5,000,000) β it's built for reading configs, logs, and small data
files, not bulk transfer. Reach for the AWS CLI or SDK directly for large
objects.
Fastest path: grab a prebuilt bundle from the latest release β
download s3-mcp-connector-plugin-<version>-<os>-<arch>.zip, unzip it,
and point Cowork/Claude at the plugin/ folder inside (see step 4 of
SETUP.md). No Go toolchain required.
From source:
# 1. Build
cd go-server
go mod tidy
go build -o s3-connector-server .
cp s3-connector-server ../plugin/servers/go/
# 2. Spin up LocalStack to test against (no AWS account needed)
cd ..
docker compose up -d
# 3. Point the connector at it
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_REGION=us-east-1
export S3_ENDPOINT_URL=http://localhost:4566
export S3_FORCE_PATH_STYLE=true
./go-server/s3-connector-server # serves MCP over stdio
Or make build && make localstack-up β see the Makefile for
every shortcut (test, vet, fmt, lint, tidy, localstack-down).
Full walkthrough β including wiring this up as a Claude/Cowork plugin and switching from LocalStack to real AWS β is in SETUP.md.
Everything is environment variables, passed through by the plugin's
.mcp.json:
| Variable | Purpose | Default |
|---|---|---|
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY | AWS credentials. Any non-empty values work against LocalStack. | β |
AWS_REGION | Region to use. | us-east-1 |
S3_ENDPOINT_URL | Custom endpoint. Leave unset for real AWS. | (unset) |
S3_FORCE_PATH_STYLE | true for LocalStack/MinIO (path-style addressing). | false |
This isn't a toy script β it's got the same checks you'd expect from a production Go service:
go test ./...)go vet + gofmt cleanAll of it runs in CI on every push and PR.
Versions follow semver and are cut automatically by
release-please from
Conventional Commits on main:
fix: ... β patch (v0.1.0 β v0.1.1)feat: ... β minor (v0.1.1 β v0.2.0)feat!: ... / BREAKING CHANGE: footer β major (v0.2.0 β v1.0.0)Every merged PR updates a standing "chore(main): release vX.Y.Z" PR with an auto-generated CHANGELOG.md. Merging that PR:
server.json from those exact assets (fresh version +
SHA-256 hashes) and publishes it to the
official MCP Registry via
mcp-publisher, authenticated with GitHub OIDC β no stored secretsSee .github/workflows/release-please.yml
and .github/workflows/publish-mcp-registry.yml
(also runnable by hand for an existing tag via workflow_dispatch).
s3-mcp-connector/
βββ README.md β you are here
βββ SETUP.md β step-by-step setup guide (LocalStack + real AWS)
βββ CONTRIBUTING.md β how to contribute
βββ CODE_OF_CONDUCT.md
βββ SECURITY.md β vulnerability reporting
βββ CODEOWNERS
βββ LICENSE β MIT
βββ Makefile β build / test / lint / localstack shortcuts
βββ docker-compose.yml β LocalStack, for local testing
βββ .golangci.yml β lint rules
βββ release-please-config.json β semver/changelog automation config
βββ .release-please-manifest.json
βββ server.json β MCP Registry manifest (regenerated fresh per release by CI)
βββ scripts/
β βββ render-server-json.sh β rebuilds server.json from a release's zip assets
βββ .github/
β βββ workflows/
β β βββ ci.yml β build, vet, test, lint, govulncheck
β β βββ codeql.yml β security scanning
β β βββ pr-title.yml β Conventional Commits PR title check
β β βββ release-please.yml β version PRs, tagging, GitHub releases
β β βββ publish-mcp-registry.yml β publishes server.json to the MCP Registry
β β βββ rebuild-release-assets.yml β manual re-attach fallback
β βββ ISSUE_TEMPLATE/
β βββ PULL_REQUEST_TEMPLATE.md
β βββ dependabot.yml
βββ go-server/ β the MCP server source
β βββ main.go
β βββ main_test.go
β βββ go.mod / go.sum
β βββ README.md
βββ plugin/ β installable Cowork/Claude plugin
βββ .claude-plugin/plugin.json
βββ .mcp.json β holds credentials locally β never commit real ones
βββ servers/go/ β compiled binary goes here
PRs and issues are very welcome β see CONTRIBUTING.md for the full guide (setup, coding conventions, how to add a new tool) and the Code of Conduct.
main is protected: every change, including the maintainer's, lands via
pull request with CI green. PR titles must follow
Conventional Commits β that's what
drives the automatic versioning above.
Found a security issue? Please follow SECURITY.md instead of opening a public issue.
MIT Β© Ferhat Dundar
This listing does not have a supported local package template. Use the maintainerβs documentation for its hosted endpoint, authentication, and client-specific setup. No install command has been inferred.
https://github.com/FerhatDundar/s3-mcp-connector/releases/download/v0.2.0/s3-mcp-connector-plugin-v0.2.0-darwin-arm64.zipotherio.github.FerhatDundar/s3-mcp-connector works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.