Skip to content

Commit fc68db5

Browse files
committed
.
1 parent d1ba41f commit fc68db5

File tree

4 files changed

+50
-68
lines changed

4 files changed

+50
-68
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,12 +807,11 @@ The following sets of tools are available (all are on by default):
807807
- `query`: Filter projects by a search query (matches title and description) (string, optional)
808808

809809
- **update_project_item** - Update project item
810-
- `field_id`: The unique identifier of the project field to be updated. (number, required)
811-
- `field_value`: The new value for the field: For text, number, and date fields, provide the new value directly. For single select and iteration fields, provide the ID of the option or iteration. To clear the field, set this to null. Example: {"field_value": "Done"} (object, required)
812810
- `item_id`: The unique identifier of the project item. This is not the issue or pull request ID. (number, required)
813811
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
814812
- `owner_type`: Owner type (string, required)
815813
- `project_number`: The project's number. (number, required)
814+
- `updated_field`: Object consisting of the ID of the project field to update and the new value for the field. To clear the field, set "value" to null. Example: {"id": 123456, "value": "New Value"} (object, required)
816815

817816
</details>
818817

pkg/github/__toolsnaps__/update_project_item.snap

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@
66
"description": "Update a specific Project item for a user or org",
77
"inputSchema": {
88
"properties": {
9-
"field_id": {
10-
"description": "The unique identifier of the project field to be updated.",
11-
"type": "number"
12-
},
13-
"field_value": {
14-
"description": "The new value for the field: For text, number, and date fields, provide the new value directly. For single select and iteration fields, provide the ID of the option or iteration. To clear the field, set this to null. Example: {\"field_value\": \"Done\"}",
15-
"properties": {},
16-
"type": "object"
17-
},
189
"item_id": {
1910
"description": "The unique identifier of the project item. This is not the issue or pull request ID.",
2011
"type": "number"
@@ -34,15 +25,19 @@
3425
"project_number": {
3526
"description": "The project's number.",
3627
"type": "number"
28+
},
29+
"updated_field": {
30+
"description": "Object consisting of the ID of the project field to update and the new value for the field. To clear the field, set \"value\" to null. Example: {\"id\": 123456, \"value\": \"New Value\"}",
31+
"properties": {},
32+
"type": "object"
3733
}
3834
},
3935
"required": [
4036
"owner_type",
4137
"owner",
4238
"project_number",
4339
"item_id",
44-
"field_id",
45-
"field_value"
40+
"updated_field"
4641
],
4742
"type": "object"
4843
},

pkg/github/projects.go

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -691,13 +691,9 @@ func UpdateProjectItem(getClient GetClientFn, t translations.TranslationHelperFu
691691
mcp.Required(),
692692
mcp.Description("The unique identifier of the project item. This is not the issue or pull request ID."),
693693
),
694-
mcp.WithNumber("field_id",
695-
mcp.Required(),
696-
mcp.Description("The unique identifier of the project field to be updated."),
697-
),
698-
mcp.WithObject("field_value",
694+
mcp.WithObject("updated_field",
699695
mcp.Required(),
700-
mcp.Description("The new value for the field: For text, number, and date fields, provide the new value directly. For single select and iteration fields, provide the ID of the option or iteration. To clear the field, set this to null. Example: {\"field_value\": \"Done\"}"),
696+
mcp.Description("Object consisting of the ID of the project field to update and the new value for the field. To clear the field, set \"value\" to null. Example: {\"id\": 123456, \"value\": \"New Value\"}"),
701697
),
702698
), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
703699
owner, err := RequiredParam[string](req, "owner")
@@ -717,28 +713,21 @@ func UpdateProjectItem(getClient GetClientFn, t translations.TranslationHelperFu
717713
return mcp.NewToolResultError(err.Error()), nil
718714
}
719715

720-
fieldID, err := RequiredInt(req, "field_id")
721-
if err != nil {
722-
return mcp.NewToolResultError(err.Error()), nil
723-
}
724-
725-
rawFieldValue, exists := req.GetArguments()["field_value"]
716+
rawUpdatedField, exists := req.GetArguments()["updated_field"]
726717
if !exists {
727-
return mcp.NewToolResultError("missing required parameter: field_value"), nil
718+
return mcp.NewToolResultError("missing required parameter: updated_field"), nil
728719
}
729720

730-
fieldValue, ok := rawFieldValue.(map[string]any)
721+
fieldValue, ok := rawUpdatedField.(map[string]any)
731722
if !ok || fieldValue == nil {
732723
return mcp.NewToolResultError("field_value must be an object"), nil
733724
}
734725

735-
valueField, ok := fieldValue["value"]
736-
if !ok {
737-
return nil, fmt.Errorf("field_value is required")
726+
updatePayload, err := buildUpdateProjectItem(fieldValue)
727+
if err != nil {
728+
return mcp.NewToolResultError(err.Error()), nil
738729
}
739730

740-
updatePayload := &updateProjectItem{ID: fieldID, Value: valueField}
741-
742731
client, err := getClient(ctx)
743732
if err != nil {
744733
return mcp.NewToolResultError(err.Error()), nil
@@ -924,29 +913,29 @@ type listProjectsOptions struct {
924913
Query string `url:"q,omitempty"`
925914
}
926915

927-
// func buildUpdateProjectItem(input map[string]any) (*updateProjectItem, error) {
928-
// if input == nil {
929-
// return nil, fmt.Errorf("new_field must be an object")
930-
// }
931-
932-
// idField, ok := input["id"]
933-
// if !ok {
934-
// return nil, fmt.Errorf("new_field.id is required")
935-
// }
936-
937-
// idFieldAsFloat64, ok := idField.(float64) // JSON numbers are float64
938-
// if !ok {
939-
// return nil, fmt.Errorf("new_field.id must be a number")
940-
// }
941-
942-
// valueField, ok := input["value"]
943-
// if !ok {
944-
// return nil, fmt.Errorf("new_field.value is required")
945-
// }
946-
// payload := &updateProjectItem{ID: int(idFieldAsFloat64), Value: valueField}
947-
948-
// return payload, nil
949-
// }
916+
func buildUpdateProjectItem(input map[string]any) (*updateProjectItem, error) {
917+
if input == nil {
918+
return nil, fmt.Errorf("updated_field must be an object")
919+
}
920+
921+
idField, ok := input["id"]
922+
if !ok {
923+
return nil, fmt.Errorf("updated_field.id is required")
924+
}
925+
926+
idFieldAsFloat64, ok := idField.(float64) // JSON numbers are float64
927+
if !ok {
928+
return nil, fmt.Errorf("updated_field.id must be a number")
929+
}
930+
931+
valueField, ok := input["value"]
932+
if !ok {
933+
return nil, fmt.Errorf("updated_field.value is required")
934+
}
935+
payload := &updateProjectItem{ID: int(idFieldAsFloat64), Value: valueField}
936+
937+
return payload, nil
938+
}
950939

951940
// addOptions adds the parameters in opts as URL query parameters to s. opts
952941
// must be a struct whose fields may contain "url" tags.

pkg/github/projects_test.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,9 +1175,8 @@ func Test_UpdateProjectItem(t *testing.T) {
11751175
assert.Contains(t, tool.InputSchema.Properties, "owner")
11761176
assert.Contains(t, tool.InputSchema.Properties, "project_number")
11771177
assert.Contains(t, tool.InputSchema.Properties, "item_id")
1178-
assert.Contains(t, tool.InputSchema.Properties, "field_id")
1179-
assert.Contains(t, tool.InputSchema.Properties, "field_value")
1180-
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner_type", "owner", "project_number", "item_id", "field_id", "field_value"})
1178+
assert.Contains(t, tool.InputSchema.Properties, "updated_field")
1179+
assert.ElementsMatch(t, tool.InputSchema.Required, []string{"owner_type", "owner", "project_number", "item_id", "updated_field"})
11811180

11821181
orgUpdatedItem := map[string]any{
11831182
"id": 801,
@@ -1224,8 +1223,8 @@ func Test_UpdateProjectItem(t *testing.T) {
12241223
"owner_type": "org",
12251224
"project_number": float64(1001),
12261225
"item_id": float64(5555),
1227-
"field_id": float64(101),
1228-
"field_value": map[string]any{
1226+
"updated_field": map[string]any{
1227+
"id": float64(101),
12291228
"value": "Done",
12301229
},
12311230
},
@@ -1259,8 +1258,8 @@ func Test_UpdateProjectItem(t *testing.T) {
12591258
"owner_type": "user",
12601259
"project_number": float64(2002),
12611260
"item_id": float64(6666),
1262-
"field_id": float64(202),
1263-
"field_value": map[string]any{
1261+
"updated_field": map[string]any{
1262+
"id": float64(202),
12641263
"value": float64(42),
12651264
},
12661265
},
@@ -1279,8 +1278,8 @@ func Test_UpdateProjectItem(t *testing.T) {
12791278
"owner_type": "org",
12801279
"project_number": float64(3003),
12811280
"item_id": float64(7777),
1282-
"field_id": float64(303),
1283-
"field_value": map[string]any{
1281+
"updated_field": map[string]any{
1282+
"id": float64(303),
12841283
"value": "In Progress",
12851284
},
12861285
},
@@ -1363,7 +1362,7 @@ func Test_UpdateProjectItem(t *testing.T) {
13631362
"owner_type": "org",
13641363
"project_number": float64(1),
13651364
"item_id": float64(2),
1366-
"new_field": "not-an-object",
1365+
"updated_field": "not-an-object",
13671366
},
13681367
expectError: true,
13691368
},
@@ -1375,7 +1374,7 @@ func Test_UpdateProjectItem(t *testing.T) {
13751374
"owner_type": "org",
13761375
"project_number": float64(1),
13771376
"item_id": float64(2),
1378-
"new_field": map[string]any{},
1377+
"updated_field": map[string]any{},
13791378
},
13801379
expectError: true,
13811380
},
@@ -1387,7 +1386,7 @@ func Test_UpdateProjectItem(t *testing.T) {
13871386
"owner_type": "org",
13881387
"project_number": float64(1),
13891388
"item_id": float64(2),
1390-
"new_field": map[string]any{
1389+
"updated_field": map[string]any{
13911390
"id": float64(9),
13921391
},
13931392
},
@@ -1419,7 +1418,7 @@ func Test_UpdateProjectItem(t *testing.T) {
14191418
case "missing item_id":
14201419
assert.Contains(t, text, "missing required parameter: item_id")
14211420
case "missing field_value":
1422-
assert.Contains(t, text, "missing required parameter: field_value")
1421+
assert.Contains(t, text, "missing required parameter: updated_field")
14231422
case "field_value not object":
14241423
assert.Contains(t, text, "field_value must be an object")
14251424
case "field_value missing id":

0 commit comments

Comments
 (0)