-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Add ProjectV2 status update tools (list, get, create) #1987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Closes github#1963 Add three new individual tools and wire them into the consolidated project tools for managing GitHub ProjectV2 status updates: - list_project_status_updates / projects_list: List status updates for a project with pagination, ordered by creation date descending - get_project_status_update / projects_get: Fetch a single status update by node ID - create_project_status_update / projects_write: Create a status update with optional body, status, start_date, and target_date New GraphQL types and queries (statusUpdateNode, statusUpdatesUserQuery, statusUpdatesOrgQuery, statusUpdateNodeQuery) support both user-owned and org-owned projects. The CreateProjectV2StatusUpdateInput type is defined locally since the shurcooL/githubv4 library does not include it. Also includes quality improvements discovered during implementation: - Extract resolveProjectNodeID helper to deduplicate ~70 lines of project ID resolution logic shared between addProjectItem and createProjectStatusUpdate - Add client-side YYYY-MM-DD date format validation for start_date and target_date fields before sending to the API - Fix brittle node type check in getProjectStatusUpdate that relied on stringifying a githubv4.ID and comparing to "<nil>" - Refactor createProjectStatusUpdate to accept typed parameters instead of raw args map - Add deprecated tool aliases for all three new individual tools - Add ProjectResolveIDFailedError constant for consistent error reporting Test coverage includes 21 subtests covering both user and org paths, pagination, error handling, input validation, field verification, and consolidated tool dispatch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds ProjectV2 status update support to the GitHub MCP Server by introducing dedicated tools and integrating them into the consolidated projects_* tools, enabling listing, fetching, and creating ProjectV2 status updates via GraphQL.
Changes:
- Added three new tools:
list_project_status_updates,get_project_status_update, andcreate_project_status_update, plus consolidated-tool dispatch support. - Introduced new minimal response type(s) and GraphQL query/mutation structs (including a locally-defined
CreateProjectV2StatusUpdateInput). - Added extensive unit test coverage and updated docs/toolsnaps/tool aliases accordingly.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/github/projects.go | Implements GraphQL types/queries/mutation + new tools and consolidated dispatch wiring. |
| pkg/github/minimal_types.go | Adds MinimalProjectStatusUpdate response type. |
| pkg/github/tools.go | Registers the new tools in the tool inventory. |
| pkg/github/toolset_instructions.go | Updates projects toolset instructions to mention status update workflows. |
| pkg/github/deprecated_tool_aliases.go | Adds deprecated aliases mapping new individual tools to consolidated tools. |
| pkg/github/projects_test.go | Adds comprehensive tests for new tools + consolidated dispatch paths. |
| pkg/github/toolsnaps/*.snap | Updates/creates tool schema snapshots for new/updated tools. |
| docs/tool-renaming.md | Documents the new deprecated aliases. |
| README.md | Updates generated docs sections for consolidated tool schema changes. |
Comments suppressed due to low confidence (1)
pkg/github/projects.go:2450
getProjectStatusUpdatechecksq.Node.StatusUpdate.ID == nil, butgithubv4.IDcannot be compared tonil(it’s a string alias), which will not compile. Use an empty-string/zero-value check (or make the field a pointer type if you truly need nil semantics) to detect a missing inline-fragment match.
if q.Node.StatusUpdate.ID == nil || q.Node.StatusUpdate.ID == "" {
return utils.NewToolResultError(fmt.Sprintf("%s: node is not a ProjectV2StatusUpdate or was not found", ProjectStatusUpdateGetFailedError)), nil, nil
}
| return nil, fmt.Errorf("%s: %w", ProjectResolveIDFailedError, err) | ||
| } | ||
| return projectIDQueryOrg.Organization.ProjectV2.ID, nil | ||
| } | ||
|
|
||
| err := gqlClient.Query(ctx, &projectIDQueryUser, queryVars) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("%s: %w", ProjectResolveIDFailedError, err) | ||
| } | ||
| return projectIDQueryUser.User.ProjectV2.ID, nil |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolveProjectNodeID returns nil for the githubv4.ID return value on error, but githubv4.ID is a string alias and cannot be nil (this won’t compile). Return the zero value (e.g., githubv4.ID("")) and keep the wrapped error, and consider also checking for an empty ID in the success path to catch unexpected null project IDs.
This issue also appears on line 2448 of the same file.
| return nil, fmt.Errorf("%s: %w", ProjectResolveIDFailedError, err) | |
| } | |
| return projectIDQueryOrg.Organization.ProjectV2.ID, nil | |
| } | |
| err := gqlClient.Query(ctx, &projectIDQueryUser, queryVars) | |
| if err != nil { | |
| return nil, fmt.Errorf("%s: %w", ProjectResolveIDFailedError, err) | |
| } | |
| return projectIDQueryUser.User.ProjectV2.ID, nil | |
| return githubv4.ID(""), fmt.Errorf("%s: %w", ProjectResolveIDFailedError, err) | |
| } | |
| id := projectIDQueryOrg.Organization.ProjectV2.ID | |
| if id == "" { | |
| return githubv4.ID(""), fmt.Errorf("%s: empty project node ID for owner %s project %d", ProjectResolveIDFailedError, owner, projectNumber) | |
| } | |
| return id, nil | |
| } | |
| err := gqlClient.Query(ctx, &projectIDQueryUser, queryVars) | |
| if err != nil { | |
| return githubv4.ID(""), fmt.Errorf("%s: %w", ProjectResolveIDFailedError, err) | |
| } | |
| id := projectIDQueryUser.User.ProjectV2.ID | |
| if id == "" { | |
| return githubv4.ID(""), fmt.Errorf("%s: empty project node ID for owner %s project %d", ProjectResolveIDFailedError, owner, projectNumber) | |
| } | |
| return id, nil |
| type statusUpdateNode struct { | ||
| ID githubv4.ID | ||
| Body githubv4.String | ||
| Status githubv4.String | ||
| CreatedAt githubv4.DateTime | ||
| StartDate githubv4.String | ||
| TargetDate githubv4.String | ||
| Creator struct { | ||
| Login githubv4.String | ||
| } | ||
| } |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
statusUpdateNode uses non-pointer githubv4.String fields for values that are optional in the API (e.g., body/status/startDate/targetDate are optional in the mutation, so they can come back as null). If the GraphQL response contains null, JSON unmarshalling into a non-pointer string type will fail at runtime. Use pointer fields for nullable values (e.g., *githubv4.String) and update convertToMinimalStatusUpdate to handle nils safely.
| Description: "The node ID of the project status update. Required for 'get_project_status_update' method.", | ||
| }, | ||
| }, | ||
| Required: []string{"method", "owner", "project_number"}, |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
projects_get now supports get_project_status_update and the handler path says it “only needs status_update_id”, but the schema still requires owner and project_number (and documents them as required). This makes the API awkward/inconsistent for a node-ID lookup and may confuse clients. Consider loosening Required to only what’s universally required (e.g., method) and enforcing per-method required params in code (including making status_update_id required for this method).
| Required: []string{"method", "owner", "project_number"}, | |
| Required: []string{"method"}, |
8196111 to
ad3fcf5
Compare
Summary
Add three new tools for managing GitHub ProjectV2 status updates (list, get, create), wired into both individual and consolidated project tools.
Why
Fixes #1963
What changed
list_project_status_updatestool (+projects_listmethod): list status updates with pagination, ordered by creation date descendingget_project_status_updatetool (+projects_getmethod): fetch a single status update by node IDcreate_project_status_updatetool (+projects_writemethod): create a status update with optional body, status, start_date, and target_datestatusUpdateNode,statusUpdatesUserQuery,statusUpdatesOrgQuery,statusUpdateNodeQuery) supporting both user-owned and org-owned projectsCreateProjectV2StatusUpdateInputlocally (not in shurcooL/githubv4 library)MinimalProjectStatusUpdateresponse type inminimal_types.goresolveProjectNodeIDhelper to deduplicate ~70 lines of project ID resolution logic shared betweenaddProjectItemandcreateProjectStatusUpdatestart_dateandtarget_dategetProjectStatusUpdate(was stringifyinggithubv4.IDand comparing to "<nil>")createProjectStatusUpdateto accept typed parameters instead of rawargs map[string]anyProjectResolveIDFailedErrorconstant for consistent error reportingMCP impact
list_project_status_updates,get_project_status_update,create_project_status_update) and three new methods on the consolidated tools (projects_list,projects_get,projects_write)Prompts tested (tool changes only)
Security / limits
per_pageis capped toMaxProjectsPerPage(50). Date inputs are validated client-side before hitting the API. Status values are validated against an allowlist.Tool renaming
deprecated_tool_aliases.goLint & tests
./script/lint./script/testDocs
script/generate-docsrun, README.md and docs/tool-renaming.md updated