Skip to content

Commit 15905bf

Browse files
committed
Merge remote-tracking branch 'origin/omgitsads/go-sdk' into copilot/migrate-security-advisories-toolset
2 parents 695d806 + 5ab610c commit 15905bf

File tree

5 files changed

+77
-60
lines changed

5 files changed

+77
-60
lines changed

cmd/github-mcp-server/generate_docs.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,12 @@ func generateToolDoc(tool mcp.Tool) string {
225225
lines = append(lines, fmt.Sprintf("- **%s** - %s", tool.Name, tool.Annotations.Title))
226226

227227
// Parameters
228+
if tool.InputSchema == nil {
229+
lines = append(lines, " - No parameters required")
230+
return strings.Join(lines, "\n")
231+
}
228232
schema, ok := tool.InputSchema.(*jsonschema.Schema)
229-
if !ok {
233+
if !ok || schema == nil {
230234
lines = append(lines, " - No parameters required")
231235
return strings.Join(lines, "\n")
232236
}

pkg/github/context_tools.go

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -36,61 +36,58 @@ type UserDetails struct {
3636

3737
// GetMe creates a tool to get details of the authenticated user.
3838
func GetMe(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any, any]) {
39-
tool := mcp.Tool{
40-
Name: "get_me",
41-
Description: t("TOOL_GET_ME_DESCRIPTION", "Get details of the authenticated GitHub user. Use this when a request is about the user's own profile for GitHub. Or when information is missing to build other tool calls."),
42-
Annotations: &mcp.ToolAnnotations{
43-
Title: t("TOOL_GET_ME_USER_TITLE", "Get my user profile"),
44-
ReadOnlyHint: true,
39+
return mcp.Tool{
40+
Name: "get_me",
41+
Description: t("TOOL_GET_ME_DESCRIPTION", "Get details of the authenticated GitHub user. Use this when a request is about the user's own profile for GitHub. Or when information is missing to build other tool calls."),
42+
Annotations: &mcp.ToolAnnotations{
43+
Title: t("TOOL_GET_ME_USER_TITLE", "Get my user profile"),
44+
ReadOnlyHint: true,
45+
},
4546
},
46-
}
47-
48-
handler := mcp.ToolHandlerFor[map[string]any, any](func(ctx context.Context, _ *mcp.CallToolRequest, _ map[string]any) (*mcp.CallToolResult, any, error) {
49-
client, err := getClient(ctx)
50-
if err != nil {
51-
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err
52-
}
53-
54-
user, res, err := client.Users.Get(ctx, "")
55-
if err != nil {
56-
return ghErrors.NewGitHubAPIErrorResponse(ctx,
57-
"failed to get user",
58-
res,
59-
err,
60-
), nil, err
61-
}
47+
mcp.ToolHandlerFor[map[string]any, any](func(ctx context.Context, _ *mcp.CallToolRequest, _ map[string]any) (*mcp.CallToolResult, any, error) {
48+
client, err := getClient(ctx)
49+
if err != nil {
50+
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err
51+
}
6252

63-
// Create minimal user representation instead of returning full user object
64-
minimalUser := MinimalUser{
65-
Login: user.GetLogin(),
66-
ID: user.GetID(),
67-
ProfileURL: user.GetHTMLURL(),
68-
AvatarURL: user.GetAvatarURL(),
69-
Details: &UserDetails{
70-
Name: user.GetName(),
71-
Company: user.GetCompany(),
72-
Blog: user.GetBlog(),
73-
Location: user.GetLocation(),
74-
Email: user.GetEmail(),
75-
Hireable: user.GetHireable(),
76-
Bio: user.GetBio(),
77-
TwitterUsername: user.GetTwitterUsername(),
78-
PublicRepos: user.GetPublicRepos(),
79-
PublicGists: user.GetPublicGists(),
80-
Followers: user.GetFollowers(),
81-
Following: user.GetFollowing(),
82-
CreatedAt: user.GetCreatedAt().Time,
83-
UpdatedAt: user.GetUpdatedAt().Time,
84-
PrivateGists: user.GetPrivateGists(),
85-
TotalPrivateRepos: user.GetTotalPrivateRepos(),
86-
OwnedPrivateRepos: user.GetOwnedPrivateRepos(),
87-
},
88-
}
53+
user, res, err := client.Users.Get(ctx, "")
54+
if err != nil {
55+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
56+
"failed to get user",
57+
res,
58+
err,
59+
), nil, err
60+
}
8961

90-
return MarshalledTextResult(minimalUser), nil, nil
91-
})
62+
// Create minimal user representation instead of returning full user object
63+
minimalUser := MinimalUser{
64+
Login: user.GetLogin(),
65+
ID: user.GetID(),
66+
ProfileURL: user.GetHTMLURL(),
67+
AvatarURL: user.GetAvatarURL(),
68+
Details: &UserDetails{
69+
Name: user.GetName(),
70+
Company: user.GetCompany(),
71+
Blog: user.GetBlog(),
72+
Location: user.GetLocation(),
73+
Email: user.GetEmail(),
74+
Hireable: user.GetHireable(),
75+
Bio: user.GetBio(),
76+
TwitterUsername: user.GetTwitterUsername(),
77+
PublicRepos: user.GetPublicRepos(),
78+
PublicGists: user.GetPublicGists(),
79+
Followers: user.GetFollowers(),
80+
Following: user.GetFollowing(),
81+
CreatedAt: user.GetCreatedAt().Time,
82+
UpdatedAt: user.GetUpdatedAt().Time,
83+
PrivateGists: user.GetPrivateGists(),
84+
TotalPrivateRepos: user.GetTotalPrivateRepos(),
85+
OwnedPrivateRepos: user.GetOwnedPrivateRepos(),
86+
},
87+
}
9288

93-
return tool, handler
89+
return MarshalledTextResult(minimalUser), nil, nil
90+
})
9491
}
9592

9693
type TeamInfo struct {

pkg/github/helper_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ func createMCPRequest(args any) mcp.CallToolRequest {
117117
}
118118

119119
argsJSON, err := json.Marshal(argsMap)
120-
require.NoError(nil, err)
120+
if err != nil {
121+
return mcp.CallToolRequest{}
122+
}
121123

122124
jsonRawMessage := json.RawMessage(argsJSON)
123125

pkg/github/server.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,13 @@ func OptionalBigIntArrayParam(args map[string]any, p string) ([]int64, error) {
268268
// https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api
269269
func WithPagination(schema *jsonschema.Schema) *jsonschema.Schema {
270270
schema.Properties["page"] = &jsonschema.Schema{
271-
Type: "Number",
271+
Type: "number",
272272
Description: "Page number for pagination (min 1)",
273273
Minimum: jsonschema.Ptr(1.0),
274274
}
275275

276276
schema.Properties["perPage"] = &jsonschema.Schema{
277-
Type: "Number",
277+
Type: "number",
278278
Description: "Results per page for pagination (min 1, max 100)",
279279
Minimum: jsonschema.Ptr(1.0),
280280
Maximum: jsonschema.Ptr(100.0),
@@ -287,20 +287,20 @@ func WithPagination(schema *jsonschema.Schema) *jsonschema.Schema {
287287
// GraphQL tools will use this and convert page/perPage to GraphQL cursor parameters internally.
288288
func WithUnifiedPagination(schema *jsonschema.Schema) *jsonschema.Schema {
289289
schema.Properties["page"] = &jsonschema.Schema{
290-
Type: "Number",
290+
Type: "number",
291291
Description: "Page number for pagination (min 1)",
292292
Minimum: jsonschema.Ptr(1.0),
293293
}
294294

295295
schema.Properties["perPage"] = &jsonschema.Schema{
296-
Type: "Number",
296+
Type: "number",
297297
Description: "Results per page for pagination (min 1, max 100)",
298298
Minimum: jsonschema.Ptr(1.0),
299299
Maximum: jsonschema.Ptr(100.0),
300300
}
301301

302302
schema.Properties["after"] = &jsonschema.Schema{
303-
Type: "String",
303+
Type: "string",
304304
Description: "Cursor for pagination. Use the endCursor from the previous page's PageInfo for GraphQL APIs.",
305305
}
306306

@@ -310,14 +310,14 @@ func WithUnifiedPagination(schema *jsonschema.Schema) *jsonschema.Schema {
310310
// WithCursorPagination adds only cursor-based pagination parameters to a tool (no page parameter).
311311
func WithCursorPagination(schema *jsonschema.Schema) *jsonschema.Schema {
312312
schema.Properties["perPage"] = &jsonschema.Schema{
313-
Type: "Number",
313+
Type: "number",
314314
Description: "Results per page for pagination (min 1, max 100)",
315315
Minimum: jsonschema.Ptr(1.0),
316316
Maximum: jsonschema.Ptr(100.0),
317317
}
318318

319319
schema.Properties["after"] = &jsonschema.Schema{
320-
Type: "String",
320+
Type: "string",
321321
Description: "Cursor for pagination. Use the endCursor from the previous page's PageInfo for GraphQL APIs.",
322322
}
323323

pkg/log/io.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,17 @@ func (l *IOLogger) Write(p []byte) (n int, err error) {
4545
l.logger.Info("[stdout]: sending bytes", "count", len(p), "data", string(p))
4646
return l.writer.Write(p)
4747
}
48+
49+
func (l *IOLogger) Close() error {
50+
var errReader, errWriter error
51+
if closer, ok := l.reader.(io.Closer); ok {
52+
errReader = closer.Close()
53+
}
54+
if closer, ok := l.writer.(io.Closer); ok {
55+
errWriter = closer.Close()
56+
}
57+
if errReader != nil {
58+
return errReader
59+
}
60+
return errWriter
61+
}

0 commit comments

Comments
 (0)