Skip to content

mcp-s3-v1.4.0

Choose a tag to compare

@github-actions github-actions released this 19 Aug 19:42
· 2 commits to main since this release
Immutable release. Only release title and notes can be modified.
a99d4ca

Fixes a bug that made failed and empty S3 listings unusable for MCP clients, and brings the dependency set current.

Anyone running v1.3.0 against an endpoint that can refuse a listing should upgrade.


The fix — failed listings no longer reach clients as transport errors

Before this release, a failed s3_list_buckets, s3_list_objects, or s3_list_connections call reached the MCP client as a JSON-RPC error instead of the tool's own error result. The client saw a transport failure and never saw why the call failed — the permission error, the bad bucket, the refused connection were all discarded:

calling "tools/call": validating tool output: validating root:
validating /properties/buckets: type: <invalid reflect.Value> has type "null", want "array"

Who was affected

  • Any deployment where a listing can fail — expired credentials, a 403 from a bucket policy, an unreachable endpoint. The more locked-down the deployment, the more often this fired.
  • Any deployment running the read-only extension or a custom authorization interceptor. s3_list_connections makes no S3 call of its own and looks immune, but it broke identically whenever middleware denied a request.
  • Reported against go-sdk v1.7.0; the same defect is present under v1.6.1, which v1.3.0 shipped with.

Cause

The MCP Go SDK's typed-handler wrapper does not skip output handling for an error result. When a handler returns an error result with no typed output, the SDK substitutes the zero value of the result struct, marshals it, and validates that JSON against the tool's declared OutputSchema before the result leaves the handler. A Go nil slice marshals as null, the schemas declared a bare "type": "array", and null is not an array. The validation failure surfaced as a Go error, which the SDK encoded as a JSON-RPC error — discarding the tool's real error message on the way out.

What changed

Every output-schema property backed by a Go slice or map now admits null alongside its real type — buckets, objects, common_prefixes, connections, and both metadata maps. This fixes every error path at once, including middleware and interceptor denials, rather than patching individual handlers.

Empty listings were already safe (the handlers initialize their slices), and that behavior is now pinned by a test rather than left implicit.


⚠️ Breaking change for one Go consumer shape

tools.DefaultOutputSchema() now returns []string where it returned string for "type" values.

This affects you only if you import github.com/txn2/mcp-s3/pkg/tools and type-assert on a schema property's "type":

// Breaks in v1.4.0
typ := prop["type"].(string)

// Works in both
switch t := prop["type"].(type) {
case string:
    // v1.3.0 and earlier
case []string:
    // v1.4.0+
}

MCP clients consuming the schema over the wire are not affected — JSON Schema has always permitted a type array, and widening a schema is backward compatible for validation. Clients that generate types from the schema will now see array | null, which accurately describes what the server has always been able to send on an error result.

This is a v1.4.0 rather than v2.0.0 because a Go major bump would require a /v2 module path and force every consumer to rewrite their imports — disproportionate to one type assertion on a schema internal. If you maintain a downstream override of these schemas, drop it and use the upstream defaults.


Upgrading

go get github.com/txn2/mcp-s3@v1.4.0

No configuration changes. No behavior change for successful calls. If you carried a local workaround that supplied null-tolerant output schemas via WithOutputSchemas, you can remove it.


Dependencies

Module v1.3.0 v1.4.0
modelcontextprotocol/go-sdk 1.6.1 1.7.0
aws-sdk-go-v2 1.41.12 1.43.2
aws-sdk-go-v2/config 1.32.23 1.32.33
aws-sdk-go-v2/credentials 1.19.22 1.19.32
aws-sdk-go-v2/service/s3 1.103.2 1.106.2
aws-sdk-go-v2/feature/s3/transfermanager 0.2.8 0.3.7

Plus the transitive sso, ssooidc, sts, and smithy-go updates.

Security

  • Go toolchain 1.26.4 → 1.26.6, clearing five standard-library advisories that reach this code: GO-2026-6218, GO-2026-6090, GO-2026-6088, GO-2026-5972, GO-2026-5026. govulncheck reports no vulnerabilities against this release.
  • Base image alpine 3.23 → 3.24.
  • All artifacts are Cosign-signed with SBOMs attached.

Engineering

Repository-internal, no runtime effect: a tool-version parity gate that holds local scanners to the CI-pinned versions, a govulncheck allow-list gate so an advisory with no upstream fix cannot silently disable the whole scan, patch-coverage enforcement on changed lines, and tightened complexity limits (cyclomatic 10, cognitive 15). The regression tests added for this fix exercise tools through a real mcp.Server and an in-memory client rather than calling handlers directly — the class of test whose absence let this bug ship, since every handler test passed while three tools were broken for real clients.


Installation

Homebrew (macOS)

brew install txn2/tap/mcp-s3

Claude Code CLI

claude mcp add s3 \
  -e AWS_REGION=us-east-1 \
  -e AWS_ACCESS_KEY_ID=your-key \
  -e AWS_SECRET_ACCESS_KEY=your-secret \
  -- mcp-s3

Docker

docker pull ghcr.io/txn2/mcp-s3:v1.4.0

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-s3_1.4.0_linux_amd64.tar.gz.sigstore.json \
  mcp-s3_1.4.0_linux_amd64.tar.gz

Changelog

Bug Fixes

  • a99d4ca fix(tools): admit null in output schemas so failed listings keep their result (#142) — closes #141

Dependencies

  • 2be37cf deps: roll up open Dependabot updates (aws-sdk + GitHub Actions) (#130)
  • deps: bump the aws-sdk group (#111, #114, #122)
  • docker: bump alpine 3.23 → 3.24 (#110, #112)

CI

  • ci: bump actions/checkout (#113, #131), actions/setup-go (#116), actions/setup-python (#115), docker/login-action (#118), docker/setup-qemu-action (#117), github/codeql-action (#119), golangci/golangci-lint-action (#121)

Docs

  • dcb8c0e docs: graphite re-skin (type, color, chrome) (#129)

Full diff: v1.3.0...v1.4.0