Skip to content

Commit e5ace36

Browse files
Merge pull request #224 from himanshuladia31/himanshu/github/list-commits
feat: github: add capability to list commits of a branch
2 parents fc71839 + 54d6b58 commit e5ace36

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

src/github/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,16 @@ MCP Server for the GitHub API, enabling file operations, repository management,
170170
- `page` (optional number): Page number
171171
- Returns: User search results
172172

173+
16. `list_commits`
174+
- Gets commits of a branch in a repository
175+
- Inputs:
176+
- `owner` (string): Repository owner
177+
- `repo` (string): Repository name
178+
- `page` (optional string): page number
179+
- `per_page` (optional string): number of record per page
180+
- `sha` (optional string): branch name
181+
- Returns: List of commits
182+
173183
## Search Query Syntax
174184

175185
### Code Search

src/github/index.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ import {
2525
GitHubCreateUpdateFileResponseSchema,
2626
GitHubForkSchema,
2727
GitHubIssueSchema,
28+
GitHubListCommits,
29+
GitHubListCommitsSchema,
2830
GitHubPullRequestSchema,
2931
GitHubReferenceSchema,
3032
GitHubRepositorySchema,
3133
GitHubSearchResponseSchema,
3234
GitHubTreeSchema,
3335
IssueCommentSchema,
36+
ListCommitsSchema,
3437
ListIssuesOptionsSchema,
3538
PushFilesSchema,
3639
SearchCodeResponseSchema,
@@ -54,7 +57,7 @@ import {
5457
type GitHubTree,
5558
type SearchCodeResponse,
5659
type SearchIssuesResponse,
57-
type SearchUsersResponse,
60+
type SearchUsersResponse
5861
} from './schemas.js';
5962

6063
const server = new Server(
@@ -487,6 +490,40 @@ async function createRepository(
487490
return GitHubRepositorySchema.parse(await response.json());
488491
}
489492

493+
async function listCommits(
494+
owner: string,
495+
repo: string,
496+
page: number = 1,
497+
perPage: number = 30,
498+
sha?: string,
499+
): Promise<GitHubListCommits> {
500+
const url = new URL(`https://api.github.com/repos/${owner}/${repo}/commits`);
501+
url.searchParams.append("page", page.toString());
502+
url.searchParams.append("per_page", perPage.toString());
503+
if (sha) {
504+
url.searchParams.append("sha", sha);
505+
}
506+
507+
const response = await fetch(
508+
url.toString(),
509+
{
510+
method: "GET",
511+
headers: {
512+
"Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
513+
"Accept": "application/vnd.github.v3+json",
514+
"User-Agent": "github-mcp-server",
515+
"Content-Type": "application/json"
516+
},
517+
}
518+
);
519+
520+
if (!response.ok) {
521+
throw new Error(`GitHub API error: ${response.statusText}`);
522+
}
523+
524+
return GitHubListCommitsSchema.parse(await response.json());
525+
}
526+
490527
async function listIssues(
491528
owner: string,
492529
repo: string,
@@ -705,6 +742,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
705742
description: "Create a new branch in a GitHub repository",
706743
inputSchema: zodToJsonSchema(CreateBranchSchema),
707744
},
745+
{
746+
name: "list_commits",
747+
description: "Get list of commits of a branch in a GitHub repository",
748+
inputSchema: zodToJsonSchema(ListCommitsSchema)
749+
},
708750
{
709751
name: "list_issues",
710752
description: "List issues in a GitHub repository with filtering options",
@@ -924,6 +966,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
924966
return { toolResult: comment };
925967
}
926968

969+
case "list_commits": {
970+
const args = ListCommitsSchema.parse(request.params.arguments);
971+
const results = await listCommits(args.owner, args.repo, args.page, args.perPage, args.sha);
972+
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
973+
}
974+
927975
default:
928976
throw new Error(`Unknown tool: ${request.params.name}`);
929977
}

src/github/schemas.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,25 @@ export const GitHubTreeSchema = z.object({
9393
truncated: z.boolean(),
9494
});
9595

96+
export const GitHubListCommitsSchema = z.array(z.object({
97+
sha: z.string(),
98+
node_id: z.string(),
99+
commit: z.object({
100+
author: GitHubAuthorSchema,
101+
committer: GitHubAuthorSchema,
102+
message: z.string(),
103+
tree: z.object({
104+
sha: z.string(),
105+
url: z.string()
106+
}),
107+
url: z.string(),
108+
comment_count: z.number(),
109+
}),
110+
url: z.string(),
111+
html_url: z.string(),
112+
comments_url: z.string()
113+
}));
114+
96115
export const GitHubCommitSchema = z.object({
97116
sha: z.string(),
98117
node_id: z.string(),
@@ -322,6 +341,15 @@ export const SearchRepositoriesSchema = z.object({
322341
.describe("Number of results per page (default: 30, max: 100)"),
323342
});
324343

344+
export const ListCommitsSchema = z.object({
345+
owner: z.string().describe("Repository owner (username or organization)"),
346+
repo: z.string().describe("Repository name"),
347+
page: z.number().optional().describe("Page number for pagination (default: 1)"),
348+
perPage: z.number().optional().describe("Number of results per page (default: 30, max: 100)"),
349+
sha: z.string().optional()
350+
.describe("SHA of the file being replaced (required when updating existing files)")
351+
});
352+
325353
export const CreateRepositorySchema = z.object({
326354
name: z.string().describe("Repository name"),
327355
description: z.string().optional().describe("Repository description"),
@@ -663,6 +691,7 @@ export type GitHubContent = z.infer<typeof GitHubContentSchema>;
663691
export type FileOperation = z.infer<typeof FileOperationSchema>;
664692
export type GitHubTree = z.infer<typeof GitHubTreeSchema>;
665693
export type GitHubCommit = z.infer<typeof GitHubCommitSchema>;
694+
export type GitHubListCommits = z.infer<typeof GitHubListCommitsSchema>;
666695
export type GitHubReference = z.infer<typeof GitHubReferenceSchema>;
667696
export type CreateRepositoryOptions = z.infer<
668697
typeof CreateRepositoryOptionsSchema

0 commit comments

Comments
 (0)