Add file mode (executable bit) support to `push_files`
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
Research direction
Start in pkg/github/repositories.go at the push_files tool definition and the loop that builds Git Data API tree entries. Trace the files[] input schema and existing defaults, then verify that the accepted modes and omitted-mode behavior are represented consistently. Done means push_files can preserve the requested mode, defaults remain compatible, and create_or_update_file stays out of scope.
Written by the indexing model from the issue text.
Description
Feature request: expose file mode (executable bit) on push_files
Use case
Agentic coding harnesses use this MCP server to publish files into a repo
on behalf of an LLM (issue execution, autonomous PR workflows, etc.).
When the work the agent is asked to produce is a shell script, build
helper, or other executable, the resulting file needs the executable
bit set (100755) — otherwise reviewers either have to chmod +x after
merge or merge a broken artifact.
Today there is no way for an MCP client to land an executable file
through this server. Both file-write tools use APIs that surface a fixed
mode:
create_or_update_file→ Contents API (PUT /repos/.../contents/{path}),
which always writes mode100644. This is a GitHub API limitation, not
something this server can route around.push_files→ Git Data API (CreateTree+CreateCommit+
UpdateRef). The underlying API does support per-entry mode, but
the tool's input schema doesn't expose it. Each entry is currently
{content, path}only.
We've observed agents react to this in two unhelpful ways:
- Quiet hallucination. The agent reports in the PR body that it
pushed with mode100755when in fact the blob landed as100644. - Workaround scope drift. The agent invents a second file (e.g.
scripts/permissions.shcontainingfind scripts/ -exec chmod +x)
that wasn't part of the task, hoping a CI step or human will run it.
A first-class mode parameter on push_files would close both failure
modes cleanly.
Proposed change
Extend the push_files.files[] input schema with an optional mode
field, validated against the set the Git Data API accepts:
| Mode | Meaning |
|---|---|
100644 |
regular file (default if omitted) |
100755 |
executable file |
120000 |
symlink |
040000 |
subdirectory (subtree) |
160000 |
submodule |
For most agentic use cases only 100644 (default) and 100755 matter,
but echoing the full Git Data API set keeps parity with the underlying
endpoint.
Backwards compatible: existing callers that omit mode get 100644,
which is what they get today.
Implementation pointer
The relevant code is already calling Git.CreateTree with a
[]*github.TreeEntry (in pkg/github/repositories.go, around the
PushFiles tool definition). The go-github TreeEntry struct
already has a Mode *string field — it just isn't being set from the
tool input. Threading it through should be a small change:
// in the loop that builds entries:
mode := "100644"
if f.Mode != nil {
mode = *f.Mode
}
entries = append(entries, &github.TreeEntry{
Path: github.String(f.Path),
Mode: github.String(mode),
Type: github.String("blob"),
Content: github.String(f.Content),
})
Plus input-schema additions for the optional field with the validated
set above.
Single-file case
create_or_update_file can't be fixed the same way because the Contents
API doesn't support mode at all — it's a GitHub API constraint, not a
server constraint. For the single-file executable case, callers can use
push_files with a one-entry files array. Worth noting that in the
tool's description so clients pick the right call.
Out of scope
- Changes to
create_or_update_file(blocked by Contents API). - Symlink/submodule write flows beyond just accepting their modes on the
schema. - Validating the executable-bit semantics on the receiving end.
Context
Filed against this server because we've been hitting the limitation
from a Claude-Code-plans / Goose-executes harness
(why-pengo/claude_and_goose),
where local-model executors are asked to ship small bash helpers as
part of issue-driven PRs. Happy to send a PR if the proposed shape
looks right.
- Dominant language
- Go
- Stars
- 33.1k
- Forks
- 5k
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 27
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from github/github-mcp-server
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/github-mcp-server#3235 ·
-
enhancement
Difficulty 1/5 Under an hour Newbie friendliness 88/100
github/github-mcp-server#3042 · 2 comments ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
github/github-mcp-server#3032 · 1 reaction ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
github/github-mcp-server#2803 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
github/github-mcp-server#2740 ·
All issues in github/github-mcp-server
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100
-
enhancement needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
kind/cleanup
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
kubernetes-sigs/kueue#15947 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
sympozium-ai/sympozium#627 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100