Reduce context usage for getting a Pull Request #2017
Reduce context usage for getting a Pull Request #2017tommaso-moro wants to merge 3 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR reduces the response payload (and thus model context usage) of the pull_request_read tool’s get method by returning a trimmed “minimal” pull request representation instead of the full github.PullRequest object.
Changes:
- Introduces
MinimalPullRequest(+ branch subtypes) and conversion helpers inminimal_types.go. - Updates
GetPullRequestto return the minimal representation viaMarshalledTextResult. - Updates
Test_GetPullRequestto unmarshal and validate the minimal PR output.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| pkg/github/pullrequests.go | Returns a minimal PR payload instead of the full GitHub PR object for get. |
| pkg/github/minimal_types.go | Adds minimal PR structs and converters to shrink serialized output. |
| pkg/github/pullrequests_test.go | Adjusts the PR read test to validate the new minimal output shape. |
| if pr.CreatedAt != nil { | ||
| m.CreatedAt = pr.CreatedAt.Format(time.RFC3339) | ||
| } | ||
| if pr.UpdatedAt != nil { | ||
| m.UpdatedAt = pr.UpdatedAt.Format(time.RFC3339) | ||
| } | ||
| if pr.ClosedAt != nil { | ||
| m.ClosedAt = pr.ClosedAt.Format(time.RFC3339) | ||
| } | ||
| if pr.MergedAt != nil { | ||
| m.MergedAt = pr.MergedAt.Format(time.RFC3339) | ||
| } |
There was a problem hiding this comment.
PR timestamp fields in MinimalPullRequest are formatted with time.RFC3339, but other minimal outputs in this repo format timestamps using the fixed layout "2006-01-02T15:04:05Z" (e.g., minimal commit author dates, minimal repository timestamps). To keep output consistent (and avoid offsets like "+00:00"), format CreatedAt/UpdatedAt/ClosedAt/MergedAt using the same layout (ideally via a shared const) instead of time.RFC3339.
Summary
This PR reduces the context window usage by ~87% when getting a single pull request using the
pull_request_readtool.It does so by using the minimal types pattern (which is already used elsewhere in the codebase for the same reason) to reduce the payload that is sent back to the model when the tool is used. Specifically, some irrelevant fields are removed, and nested objects are largely optimized by keeping only the strictly necessary fields.
Tests & Metrics
To give an idea: when tested on a PR like this one #1563, tokens used went from 4'596 to 587, achieving a 87.2% context reduction
Tokens were measured using the OpenAI Tokenizer
Fields preserved
number,title,body,state,draft,merged,mergeable_state,html_url,user(asMinimalUser),labels(name strings),assignees(login strings),requested_reviewers(login strings),merged_by(login string),head/base(ref, sha, repo full_name + description), diff stats, timestamps,milestone(title string)Fields dropped
Nested full
Repository(128 fields × 2), fullUserobjects (62 fields × 4-6), API URL templates (statuses_url,diff_url,patch_url, etc.),_links,node_id,author_association,locked,auto_merge, and other metadata not used for model reasoningBefore
Old payload
{"id":3085553675,"number":1563,"state":"closed","locked":false,"title":"Add support for safe tool renaming","body":"This PR introduces logic to allow non-breaking tool renaming. It does so by introducing Deprecation Aliases, i.e. mappings that map \u0026#34;old\u0026#34;/deprecated tool names (e.g. `get_issue`) to their new equivalent (e.g. `issue_read`) to gracefully handle cases where users have a server configuration that references old tool names.\n\nOverview of changes:\n- Added `DeprecatedToolAliases` in `deprecated_tool_aliases.go` to have a single source of truth for tool names when renaming tools\n- Added logic to resolve aliases before registering tools\n- Added tests\n\n**Demo**\nYou can see that mapping \u0026#34;test_1\u0026#34; to \u0026#34;get_me\u0026#34; enables \u0026#34;get_me\u0026#34;\n\u003cimg width=\"1172\" height=\"384\" alt=\"Screenshot 2025-12-11 at 15 09 16\" src=\"https://github.com/user-attachments/assets/47dce965-ae7c-48f3-8e92-c57e7027df68\"/\u003e\n","created_at":"2025-12-09T13:03:53Z","updated_at":"2025-12-11T16:48:03Z","closed_at":"2025-12-11T16:46:00Z","merged_at":"2025-12-11T16:46:00Z","user":{"login":"tommaso-moro","id":37270480,"node_id":"MDQ6VXNlcjM3MjcwNDgw","avatar_url":"https://avatars.githubusercontent.com/u/37270480?v=4","html_url":"https://github.com/tommaso-moro","gravatar_id":"","type":"User","site_admin":true,"url":"https://api.github.com/users/tommaso-moro","events_url":"https://api.github.com/users/tommaso-moro/events{/privacy}","following_url":"https://api.github.com/users/tommaso-moro/following{/other_user}","followers_url":"https://api.github.com/users/tommaso-moro/followers","gists_url":"https://api.github.com/users/tommaso-moro/gists{/gist_id}","organizations_url":"https://api.github.com/users/tommaso-moro/orgs","received_events_url":"https://api.github.com/users/tommaso-moro/received_events","repos_url":"https://api.github.com/users/tommaso-moro/repos","starred_url":"https://api.github.com/users/tommaso-moro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tommaso-moro/subscriptions"},"draft":false,"url":"https://api.github.com/repos/github/github-mcp-server/pulls/1563","html_url":"https://github.com/github/github-mcp-server/pull/1563","issue_url":"https://api.github.com/repos/github/github-mcp-server/issues/1563","statuses_url":"https://api.github.com/repos/github/github-mcp-server/statuses/7b547ec23e53574f8d9e4fc8ccdf93abcf7dcda1","diff_url":"https://github.com/github/github-mcp-server/pull/1563.diff","patch_url":"https://github.com/github/github-mcp-server/pull/1563.patch","commits_url":"https://api.github.com/repos/github/github-mcp-server/pulls/1563/commits","comments_url":"https://api.github.com/repos/github/github-mcp-server/issues/1563/comments","review_comments_url":"https://api.github.com/repos/github/github-mcp-server/pulls/1563/comments","review_comment_url":"https://api.github.com/repos/github/github-mcp-server/pulls/comments{/number}","author_association":"MEMBER","node_id":"PR_kwDOODGMVM636dAL","merged":true,"mergeable_state":"unknown","merged_by":{"login":"tommaso-moro","id":37270480,"node_id":"MDQ6VXNlcjM3MjcwNDgw","avatar_url":"https://avatars.githubusercontent.com/u/37270480?v=4","html_url":"https://github.com/tommaso-moro","gravatar_id":"","type":"User","site_admin":true,"url":"https://api.github.com/users/tommaso-moro","events_url":"https://api.github.com/users/tommaso-moro/events{/privacy}","following_url":"https://api.github.com/users/tommaso-moro/following{/other_user}","followers_url":"https://api.github.com/users/tommaso-moro/followers","gists_url":"https://api.github.com/users/tommaso-moro/gists{/gist_id}","organizations_url":"https://api.github.com/users/tommaso-moro/orgs","received_events_url":"https://api.github.com/users/tommaso-moro/received_events","repos_url":"https://api.github.com/users/tommaso-moro/repos","starred_url":"https://api.github.com/users/tommaso-moro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tommaso-moro/subscriptions"},"merge_commit_sha":"94ee0745ca46be7e45a4d1a856ec3183cca67aee","comments":2,"commits":16,"additions":182,"deletions":7,"changed_files":5,"maintainer_can_modify":false,"review_comments":3,"_links":{"self":{"href":"https://api.github.com/repos/github/github-mcp-server/pulls/1563"},"html":{"href":"https://github.com/github/github-mcp-server/pull/1563"},"issue":{"href":"https://api.github.com/repos/github/github-mcp-server/issues/1563"},"comments":{"href":"https://api.github.com/repos/github/github-mcp-server/issues/1563/comments"},"review_comments":{"href":"https://api.github.com/repos/github/github-mcp-server/pulls/1563/comments"},"review_comment":{"href":"https://api.github.com/repos/github/github-mcp-server/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/github/github-mcp-server/pulls/1563/commits"},"statuses":{"href":"https://api.github.com/repos/github/github-mcp-server/statuses/7b547ec23e53574f8d9e4fc8ccdf93abcf7dcda1"}},"head":{"label":"github:tommy/safe-tool-rename-logic","ref":"tommy/safe-tool-rename-logic","sha":"7b547ec23e53574f8d9e4fc8ccdf93abcf7dcda1","repo":{"id":942771284,"node_id":"R_kgDOODGMVA","owner":{"login":"github","id":9919,"node_id":"MDEyOk9yZ2FuaXphdGlvbjk5MTk=","avatar_url":"https://avatars.githubusercontent.com/u/9919?v=4","html_url":"https://github.com/github","gravatar_id":"","type":"Organization","site_admin":false,"url":"https://api.github.com/users/github","events_url":"https://api.github.com/users/github/events{/privacy}","following_url":"https://api.github.com/users/github/following{/other_user}","followers_url":"https://api.github.com/users/github/followers","gists_url":"https://api.github.com/users/github/gists{/gist_id}","organizations_url":"https://api.github.com/users/github/orgs","received_events_url":"https://api.github.com/users/github/received_events","repos_url":"https://api.github.com/users/github/repos","starred_url":"https://api.github.com/users/github/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/github/subscriptions"},"name":"github-mcp-server","full_name":"github/github-mcp-server","description":"GitHub's official MCP Server","homepage":"","default_branch":"main","created_at":"2025-03-04T16:42:04Z","pushed_at":"2026-02-16T19:51:39Z","updated_at":"2026-02-16T19:48:45Z","html_url":"https://github.com/github/github-mcp-server","clone_url":"https://github.com/github/github-mcp-server.git","git_url":"git://github.com/github/github-mcp-server.git","ssh_url":"git@github.com:github/github-mcp-server.git","svn_url":"https://github.com/github/github-mcp-server","language":"Go","fork":false,"forks_count":3588,"open_issues_count":262,"open_issues":262,"stargazers_count":26991,"watchers_count":26991,"watchers":26991,"size":51623,"allow_forking":true,"web_commit_signoff_required":false,"topics":["github","mcp","mcp-server"],"archived":false,"disabled":false,"license":{"key":"mit","name":"MIT License","url":"https://api.github.com/licenses/mit","spdx_id":"MIT"},"private":false,"has_issues":true,"has_wiki":false,"has_pages":false,"has_projects":false,"has_downloads":true,"has_discussions":true,"is_template":false,"url":"https://api.github.com/repos/github/github-mcp-server","archive_url":"https://api.github.com/repos/github/github-mcp-server/{archive_format}{/ref}","assignees_url":"https://api.github.com/repos/github/github-mcp-server/assignees{/user}","blobs_url":"https://api.github.com/repos/github/github-mcp-server/git/blobs{/sha}","branches_url":"https://api.github.com/repos/github/github-mcp-server/branches{/branch}","collaborators_url":"https://api.github.com/repos/github/github-mcp-server/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/github/github-mcp-server/comments{/number}","commits_url":"https://api.github.com/repos/github/github-mcp-server/commits{/sha}","compare_url":"https://api.github.com/repos/github/github-mcp-server/compare/{base}...{head}","contents_url":"https://api.github.com/repos/github/github-mcp-server/contents/{+path}","contributors_url":"https://api.github.com/repos/github/github-mcp-server/contributors","deployments_url":"https://api.github.com/repos/github/github-mcp-server/deployments","downloads_url":"https://api.github.com/repos/github/github-mcp-server/downloads","events_url":"https://api.github.com/repos/github/github-mcp-server/events","forks_url":"https://api.github.com/repos/github/github-mcp-server/forks","git_commits_url":"https://api.github.com/repos/github/github-mcp-server/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/github/github-mcp-server/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/github/github-mcp-server/git/tags{/sha}","hooks_url":"https://api.github.com/repos/github/github-mcp-server/hooks","issue_comment_url":"https://api.github.com/repos/github/github-mcp-server/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/github/github-mcp-server/issues/events{/number}","issues_url":"https://api.github.com/repos/github/github-mcp-server/issues{/number}","keys_url":"https://api.github.com/repos/github/github-mcp-server/keys{/key_id}","labels_url":"https://api.github.com/repos/github/github-mcp-server/labels{/name}","languages_url":"https://api.github.com/repos/github/github-mcp-server/languages","merges_url":"https://api.github.com/repos/github/github-mcp-server/merges","milestones_url":"https://api.github.com/repos/github/github-mcp-server/milestones{/number}","notifications_url":"https://api.github.com/repos/github/github-mcp-server/notifications{?since,all,participating}","pulls_url":"https://api.github.com/repos/github/github-mcp-server/pulls{/number}","releases_url":"https://api.github.com/repos/github/github-mcp-server/releases{/id}","stargazers_url":"https://api.github.com/repos/github/github-mcp-server/stargazers","statuses_url":"https://api.github.com/repos/github/github-mcp-server/statuses/{sha}","subscribers_url":"https://api.github.com/repos/github/github-mcp-server/subscribers","subscription_url":"https://api.github.com/repos/github/github-mcp-server/subscription","tags_url":"https://api.github.com/repos/github/github-mcp-server/tags","trees_url":"https://api.github.com/repos/github/github-mcp-server/git/trees{/sha}","teams_url":"https://api.github.com/repos/github/github-mcp-server/teams","visibility":"public"},"user":{"login":"github","id":9919,"node_id":"MDEyOk9yZ2FuaXphdGlvbjk5MTk=","avatar_url":"https://avatars.githubusercontent.com/u/9919?v=4","html_url":"https://github.com/github","gravatar_id":"","type":"Organization","site_admin":false,"url":"https://api.github.com/users/github","events_url":"https://api.github.com/users/github/events{/privacy}","following_url":"https://api.github.com/users/github/following{/other_user}","followers_url":"https://api.github.com/users/github/followers","gists_url":"https://api.github.com/users/github/gists{/gist_id}","organizations_url":"https://api.github.com/users/github/orgs","received_events_url":"https://api.github.com/users/github/received_events","repos_url":"https://api.github.com/users/github/repos","starred_url":"https://api.github.com/users/github/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/github/subscriptions"}},"base":{"label":"github:main","ref":"main","sha":"90a1255e1b0a3ec15da21786a67e9ce542621d6f","repo":{"id":942771284,"node_id":"R_kgDOODGMVA","owner":{"login":"github","id":9919,"node_id":"MDEyOk9yZ2FuaXphdGlvbjk5MTk=","avatar_url":"https://avatars.githubusercontent.com/u/9919?v=4","html_url":"https://github.com/github","gravatar_id":"","type":"Organization","site_admin":false,"url":"https://api.github.com/users/github","events_url":"https://api.github.com/users/github/events{/privacy}","following_url":"https://api.github.com/users/github/following{/other_user}","followers_url":"https://api.github.com/users/github/followers","gists_url":"https://api.github.com/users/github/gists{/gist_id}","organizations_url":"https://api.github.com/users/github/orgs","received_events_url":"https://api.github.com/users/github/received_events","repos_url":"https://api.github.com/users/github/repos","starred_url":"https://api.github.com/users/github/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/github/subscriptions"},"name":"github-mcp-server","full_name":"github/github-mcp-server","description":"GitHub's official MCP Server","homepage":"","default_branch":"main","created_at":"2025-03-04T16:42:04Z","pushed_at":"2026-02-16T19:51:39Z","updated_at":"2026-02-16T19:48:45Z","html_url":"https://github.com/github/github-mcp-server","clone_url":"https://github.com/github/github-mcp-server.git","git_url":"git://github.com/github/github-mcp-server.git","ssh_url":"git@github.com:github/github-mcp-server.git","svn_url":"https://github.com/github/github-mcp-server","language":"Go","fork":false,"forks_count":3588,"open_issues_count":262,"open_issues":262,"stargazers_count":26991,"watchers_count":26991,"watchers":26991,"size":51623,"allow_forking":true,"web_commit_signoff_required":false,"topics":["github","mcp","mcp-server"],"archived":false,"disabled":false,"license":{"key":"mit","name":"MIT License","url":"https://api.github.com/licenses/mit","spdx_id":"MIT"},"private":false,"has_issues":true,"has_wiki":false,"has_pages":false,"has_projects":false,"has_downloads":true,"has_discussions":true,"is_template":false,"url":"https://api.github.com/repos/github/github-mcp-server","archive_url":"https://api.github.com/repos/github/github-mcp-server/{archive_format}{/ref}","assignees_url":"https://api.github.com/repos/github/github-mcp-server/assignees{/user}","blobs_url":"https://api.github.com/repos/github/github-mcp-server/git/blobs{/sha}","branches_url":"https://api.github.com/repos/github/github-mcp-server/branches{/branch}","collaborators_url":"https://api.github.com/repos/github/github-mcp-server/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/github/github-mcp-server/comments{/number}","commits_url":"https://api.github.com/repos/github/github-mcp-server/commits{/sha}","compare_url":"https://api.github.com/repos/github/github-mcp-server/compare/{base}...{head}","contents_url":"https://api.github.com/repos/github/github-mcp-server/contents/{+path}","contributors_url":"https://api.github.com/repos/github/github-mcp-server/contributors","deployments_url":"https://api.github.com/repos/github/github-mcp-server/deployments","downloads_url":"https://api.github.com/repos/github/github-mcp-server/downloads","events_url":"https://api.github.com/repos/github/github-mcp-server/events","forks_url":"https://api.github.com/repos/github/github-mcp-server/forks","git_commits_url":"https://api.github.com/repos/github/github-mcp-server/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/github/github-mcp-server/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/github/github-mcp-server/git/tags{/sha}","hooks_url":"https://api.github.com/repos/github/github-mcp-server/hooks","issue_comment_url":"https://api.github.com/repos/github/github-mcp-server/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/github/github-mcp-server/issues/events{/number}","issues_url":"https://api.github.com/repos/github/github-mcp-server/issues{/number}","keys_url":"https://api.github.com/repos/github/github-mcp-server/keys{/key_id}","labels_url":"https://api.github.com/repos/github/github-mcp-server/labels{/name}","languages_url":"https://api.github.com/repos/github/github-mcp-server/languages","merges_url":"https://api.github.com/repos/github/github-mcp-server/merges","milestones_url":"https://api.github.com/repos/github/github-mcp-server/milestones{/number}","notifications_url":"https://api.github.com/repos/github/github-mcp-server/notifications{?since,all,participating}","pulls_url":"https://api.github.com/repos/github/github-mcp-server/pulls{/number}","releases_url":"https://api.github.com/repos/github/github-mcp-server/releases{/id}","stargazers_url":"https://api.github.com/repos/github/github-mcp-server/stargazers","statuses_url":"https://api.github.com/repos/github/github-mcp-server/statuses/{sha}","subscribers_url":"https://api.github.com/repos/github/github-mcp-server/subscribers","subscription_url":"https://api.github.com/repos/github/github-mcp-server/subscription","tags_url":"https://api.github.com/repos/github/github-mcp-server/tags","trees_url":"https://api.github.com/repos/github/github-mcp-server/git/trees{/sha}","teams_url":"https://api.github.com/repos/github/github-mcp-server/teams","visibility":"public"},"user":{"login":"github","id":9919,"node_id":"MDEyOk9yZ2FuaXphdGlvbjk5MTk=","avatar_url":"https://avatars.githubusercontent.com/u/9919?v=4","html_url":"https://github.com/github","gravatar_id":"","type":"Organization","site_admin":false,"url":"https://api.github.com/users/github","events_url":"https://api.github.com/users/github/events{/privacy}","following_url":"https://api.github.com/users/github/following{/other_user}","followers_url":"https://api.github.com/users/github/followers","gists_url":"https://api.github.com/users/github/gists{/gist_id}","organizations_url":"https://api.github.com/users/github/orgs","received_events_url":"https://api.github.com/users/github/received_events","repos_url":"https://api.github.com/users/github/repos","starred_url":"https://api.github.com/users/github/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/github/subscriptions"}}}After
New payload
{"number":1563,"title":"Add support for safe tool renaming","body":"This PR introduces logic to allow non-breaking tool renaming. It does so by introducing Deprecation Aliases, i.e. mappings that map \u0026#34;old\u0026#34;/deprecated tool names (e.g. `get_issue`) to their new equivalent (e.g. `issue_read`) to gracefully handle cases where users have a server configuration that references old tool names.\n\nOverview of changes:\n- Added `DeprecatedToolAliases` in `deprecated_tool_aliases.go` to have a single source of truth for tool names when renaming tools\n- Added logic to resolve aliases before registering tools\n- Added tests\n\n**Demo**\nYou can see that mapping \u0026#34;test_1\u0026#34; to \u0026#34;get_me\u0026#34; enables \u0026#34;get_me\u0026#34;\n\u003cimg width=\"1172\" height=\"384\" alt=\"Screenshot 2025-12-11 at 15 09 16\" src=\"https://github.com/user-attachments/assets/47dce965-ae7c-48f3-8e92-c57e7027df68\"/\u003e\n","state":"closed","draft":false,"merged":true,"mergeable_state":"unknown","html_url":"https://github.com/github/github-mcp-server/pull/1563","user":{"login":"tommaso-moro","id":37270480,"profile_url":"https://github.com/tommaso-moro","avatar_url":"https://avatars.githubusercontent.com/u/37270480?v=4"},"merged_by":"tommaso-moro","head":{"ref":"tommy/safe-tool-rename-logic","sha":"7b547ec23e53574f8d9e4fc8ccdf93abcf7dcda1","repo":{"full_name":"github/github-mcp-server","description":"GitHub's official MCP Server"}},"base":{"ref":"main","sha":"90a1255e1b0a3ec15da21786a67e9ce542621d6f","repo":{"full_name":"github/github-mcp-server","description":"GitHub's official MCP Server"}},"additions":182,"deletions":7,"changed_files":5,"commits":16,"comments":2,"created_at":"2025-12-09T13:03:53Z","updated_at":"2025-12-11T16:48:03Z","closed_at":"2025-12-11T16:46:00Z","merged_at":"2025-12-11T16:46:00Z"}Why
The full
github.PullRequestpayload is pretty big. Most of its size is due to deeply nestedRepositoryobjects (~128 fields each) inHead/Base, fullUserobjects (~62 fields) on every actor, and ~10 unused API URL template strings. None of this is useful for model reasoning but it burns context window on every call.What changed
MinimalPullRequest,MinimalPRBranch, andMinimalPRBranchRepotypes tominimal_types.go, following the existingMinimalCommit/MinimalRepositorypatternconvertToMinimalPullRequestandconvertToMinimalPRBranchconverter functionsGetPullRequestto returnMinimalPullRequestviaMarshalledTextResultinstead of rawjson.Marshal(pr)fmt.Errorfcalls inGetPullRequestMinimalPullRequestfieldsMCP impact
Prompts tested (tool changes only)
Security / limits
Tool renaming
deprecated_tool_aliases.goNote: if you're renaming tools, you must add the tool aliases. For more information on how to do so, please refer to the official docs.
Lint & tests
./script/lint./script/testDocs