Skip to content

fix: support binary file content via base64 encoding in create_or_update_file and push_files - #3313

Open
kyletser wants to merge 1 commit into
github:mainfrom
kyletser:fix/binary-file-write-encoding
Open

kyletser wants to merge 1 commit into
github:mainfrom
kyletser:fix/binary-file-write-encoding

Conversation

@kyletser

Copy link
Copy Markdown

Summary

Adds an optional encoding parameter ("utf-8" default, "base64") to create_or_update_file and push_files so binary file content (e.g. images) can be written. Base64 content is decoded once and the raw bytes are written to the repository.

Why

JSON tool arguments must be valid UTF-8, so a binary file cannot be passed as a plain string: non-UTF-8 bytes are corrupted on the way to the API. Both tools previously passed content through verbatim, which made it impossible to commit binary assets through the GitHub MCP server.

Fixes #3312

What changed

  • create_or_update_file: new optional encoding parameter. base64 content is decoded once before being handed to the Contents API (which receives raw bytes and base64-encodes them itself). Invalid base64 and unsupported encoding values return clear tool errors.
  • push_files: each file object accepts an optional encoding parameter. Base64 content is decoded, uploaded via the Blobs API, and referenced by its blob SHA in the tree, because the Trees API rejects TreeEntry content that is not valid UTF-8.
  • Tool schema snapshots updated for both tools.
  • Tests cover: binary file creation via base64, mixed text + binary push, invalid base64 content, and unsupported encoding values, for both tools.

MCP impact

  • Tool schema or behavior changed

encoding is optional with default "utf-8", so existing callers behave exactly as before.

Prompts tested (tool changes only)

Tested through unit tests with mocked HTTP (see Test_CreateOrUpdateFile / Test_PushFiles), covering the request bodies sent to the Contents, Blobs, and Trees APIs:

  • "Create assets/logo.png with this base64-encoded image on branch main" → create_or_update_file with encoding: "base64".
  • "Push README.md and a binary logo in one commit" → push_files with one utf-8 file and one base64 file; the tree references the binary by blob SHA.

Security / limits

  • No security or limits impact

The change only adds a decode step of caller-supplied content; no new data sources, permissions, or unbounded operations are introduced.

Tool renaming

  • I am renaming tools as part of this PR (e.g. a part of a consolidation effort)
    • I have added the new tool aliases in deprecated_tool_aliases.go
  • I am not renaming tools as part of this PR

Lint & tests

  • Linted locally with ./script/lint
  • Tested locally with ./script/test

gofmt -s clean on changed files, golangci-lint run ./pkg/github/... reports 0 issues, and go test ./... passes (verified: temporarily disabling the base64 branches turns the new tests red, then green again after restoring).

Docs

  • Not needed
  • Updated (README / docs / examples)

Tool descriptions in the schemas document the new parameter; tool documentation is generated from these schemas.

…ate_file and push_files

JSON tool arguments must be valid UTF-8, so binary file content (e.g.
images) could not be written through create_or_update_file or
push_files: the content string was passed through verbatim, corrupting
non-UTF-8 bytes.

Add an optional encoding parameter (utf-8, the default, or base64)
to both tools. For base64 content, create_or_update_file decodes it
once before handing the raw bytes to the Contents API. push_files
uploads decoded content as a git blob and references it by SHA in the
tree, because the Trees API rejects TreeEntry content that is not
valid UTF-8. Invalid base64 and unsupported encoding values return
clear tool errors.

Closes github#3312
@kyletser
kyletser requested a review from a team as a code owner September 20, 2026 11:36
Copilot AI balanced review requested due to automatic review settings September 20, 2026 11:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

create_or_update_file cannot represent true binary content — no encoding parameter, JSON string requires valid UTF-8

2 participants