Skip to content
6 changes: 5 additions & 1 deletion cmd/github-mcp-server/generate_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,12 @@ func generateToolDoc(tool mcp.Tool) string {
lines = append(lines, fmt.Sprintf("- **%s** - %s", tool.Name, tool.Annotations.Title))

// Parameters
if tool.InputSchema == nil {
lines = append(lines, " - No parameters required")
return strings.Join(lines, "\n")
}
schema, ok := tool.InputSchema.(*jsonschema.Schema)
if !ok {
if !ok || schema == nil {
lines = append(lines, " - No parameters required")
return strings.Join(lines, "\n")
}
Expand Down
30 changes: 30 additions & 0 deletions pkg/github/__toolsnaps__/get_secret_scanning_alert.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"annotations": {
"readOnlyHint": true,
"title": "Get secret scanning alert"
},
"description": "Get details of a specific secret scanning alert in a GitHub repository.",
"inputSchema": {
"type": "object",
"required": [
"owner",
"repo",
"alertNumber"
],
"properties": {
"alertNumber": {
"type": "number",
"description": "The number of the alert."
},
"owner": {
"type": "string",
"description": "The owner of the repository."
},
"repo": {
"type": "string",
"description": "The name of the repository."
}
}
},
"name": "get_secret_scanning_alert"
}
49 changes: 49 additions & 0 deletions pkg/github/__toolsnaps__/list_secret_scanning_alerts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"annotations": {
"readOnlyHint": true,
"title": "List secret scanning alerts"
},
"description": "List secret scanning alerts in a GitHub repository.",
"inputSchema": {
"type": "object",
"required": [
"owner",
"repo"
],
"properties": {
"owner": {
"type": "string",
"description": "The owner of the repository."
},
"repo": {
"type": "string",
"description": "The name of the repository."
},
"resolution": {
"type": "string",
"description": "Filter by resolution",
"enum": [
"false_positive",
"wont_fix",
"revoked",
"pattern_edited",
"pattern_deleted",
"used_in_tests"
]
},
"secret_type": {
"type": "string",
"description": "A comma-separated list of secret types to return. All default secret patterns are returned. To return generic patterns, pass the token name(s) in the parameter."
},
"state": {
"type": "string",
"description": "Filter by state",
"enum": [
"open",
"resolved"
]
}
}
},
"name": "list_secret_scanning_alerts"
}
99 changes: 48 additions & 51 deletions pkg/github/context_tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,61 +36,58 @@ type UserDetails struct {

// GetMe creates a tool to get details of the authenticated user.
func GetMe(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any, any]) {
tool := mcp.Tool{
Name: "get_me",
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."),
Annotations: &mcp.ToolAnnotations{
Title: t("TOOL_GET_ME_USER_TITLE", "Get my user profile"),
ReadOnlyHint: true,
return mcp.Tool{
Name: "get_me",
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."),
Annotations: &mcp.ToolAnnotations{
Title: t("TOOL_GET_ME_USER_TITLE", "Get my user profile"),
ReadOnlyHint: true,
},
},
}

handler := mcp.ToolHandlerFor[map[string]any, any](func(ctx context.Context, _ *mcp.CallToolRequest, _ map[string]any) (*mcp.CallToolResult, any, error) {
client, err := getClient(ctx)
if err != nil {
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err
}

user, res, err := client.Users.Get(ctx, "")
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx,
"failed to get user",
res,
err,
), nil, err
}
mcp.ToolHandlerFor[map[string]any, any](func(ctx context.Context, _ *mcp.CallToolRequest, _ map[string]any) (*mcp.CallToolResult, any, error) {
client, err := getClient(ctx)
if err != nil {
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, err
}

// Create minimal user representation instead of returning full user object
minimalUser := MinimalUser{
Login: user.GetLogin(),
ID: user.GetID(),
ProfileURL: user.GetHTMLURL(),
AvatarURL: user.GetAvatarURL(),
Details: &UserDetails{
Name: user.GetName(),
Company: user.GetCompany(),
Blog: user.GetBlog(),
Location: user.GetLocation(),
Email: user.GetEmail(),
Hireable: user.GetHireable(),
Bio: user.GetBio(),
TwitterUsername: user.GetTwitterUsername(),
PublicRepos: user.GetPublicRepos(),
PublicGists: user.GetPublicGists(),
Followers: user.GetFollowers(),
Following: user.GetFollowing(),
CreatedAt: user.GetCreatedAt().Time,
UpdatedAt: user.GetUpdatedAt().Time,
PrivateGists: user.GetPrivateGists(),
TotalPrivateRepos: user.GetTotalPrivateRepos(),
OwnedPrivateRepos: user.GetOwnedPrivateRepos(),
},
}
user, res, err := client.Users.Get(ctx, "")
if err != nil {
return ghErrors.NewGitHubAPIErrorResponse(ctx,
"failed to get user",
res,
err,
), nil, err
}

return MarshalledTextResult(minimalUser), nil, nil
})
// Create minimal user representation instead of returning full user object
minimalUser := MinimalUser{
Login: user.GetLogin(),
ID: user.GetID(),
ProfileURL: user.GetHTMLURL(),
AvatarURL: user.GetAvatarURL(),
Details: &UserDetails{
Name: user.GetName(),
Company: user.GetCompany(),
Blog: user.GetBlog(),
Location: user.GetLocation(),
Email: user.GetEmail(),
Hireable: user.GetHireable(),
Bio: user.GetBio(),
TwitterUsername: user.GetTwitterUsername(),
PublicRepos: user.GetPublicRepos(),
PublicGists: user.GetPublicGists(),
Followers: user.GetFollowers(),
Following: user.GetFollowing(),
CreatedAt: user.GetCreatedAt().Time,
UpdatedAt: user.GetUpdatedAt().Time,
PrivateGists: user.GetPrivateGists(),
TotalPrivateRepos: user.GetTotalPrivateRepos(),
OwnedPrivateRepos: user.GetOwnedPrivateRepos(),
},
}

return tool, handler
return MarshalledTextResult(minimalUser), nil, nil
})
}

type TeamInfo struct {
Expand Down
4 changes: 3 additions & 1 deletion pkg/github/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ func createMCPRequest(args any) mcp.CallToolRequest {
}

argsJSON, err := json.Marshal(argsMap)
require.NoError(nil, err)
if err != nil {
return mcp.CallToolRequest{}
}

jsonRawMessage := json.RawMessage(argsJSON)

Expand Down
Loading