mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-02 03:00:15 -04:00
Merge pull request #224 from himanshuladia31/himanshu/github/list-commits
feat: github: add capability to list commits of a branch
This commit is contained in:
@@ -170,6 +170,16 @@ MCP Server for the GitHub API, enabling file operations, repository management,
|
||||
- `page` (optional number): Page number
|
||||
- Returns: User search results
|
||||
|
||||
16. `list_commits`
|
||||
- Gets commits of a branch in a repository
|
||||
- Inputs:
|
||||
- `owner` (string): Repository owner
|
||||
- `repo` (string): Repository name
|
||||
- `page` (optional string): page number
|
||||
- `per_page` (optional string): number of record per page
|
||||
- `sha` (optional string): branch name
|
||||
- Returns: List of commits
|
||||
|
||||
## Search Query Syntax
|
||||
|
||||
### Code Search
|
||||
|
||||
@@ -25,12 +25,15 @@ import {
|
||||
GitHubCreateUpdateFileResponseSchema,
|
||||
GitHubForkSchema,
|
||||
GitHubIssueSchema,
|
||||
GitHubListCommits,
|
||||
GitHubListCommitsSchema,
|
||||
GitHubPullRequestSchema,
|
||||
GitHubReferenceSchema,
|
||||
GitHubRepositorySchema,
|
||||
GitHubSearchResponseSchema,
|
||||
GitHubTreeSchema,
|
||||
IssueCommentSchema,
|
||||
ListCommitsSchema,
|
||||
ListIssuesOptionsSchema,
|
||||
PushFilesSchema,
|
||||
SearchCodeResponseSchema,
|
||||
@@ -54,7 +57,7 @@ import {
|
||||
type GitHubTree,
|
||||
type SearchCodeResponse,
|
||||
type SearchIssuesResponse,
|
||||
type SearchUsersResponse,
|
||||
type SearchUsersResponse
|
||||
} from './schemas.js';
|
||||
|
||||
const server = new Server(
|
||||
@@ -487,6 +490,40 @@ async function createRepository(
|
||||
return GitHubRepositorySchema.parse(await response.json());
|
||||
}
|
||||
|
||||
async function listCommits(
|
||||
owner: string,
|
||||
repo: string,
|
||||
page: number = 1,
|
||||
perPage: number = 30,
|
||||
sha?: string,
|
||||
): Promise<GitHubListCommits> {
|
||||
const url = new URL(`https://api.github.com/repos/${owner}/${repo}/commits`);
|
||||
url.searchParams.append("page", page.toString());
|
||||
url.searchParams.append("per_page", perPage.toString());
|
||||
if (sha) {
|
||||
url.searchParams.append("sha", sha);
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
url.toString(),
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
"User-Agent": "github-mcp-server",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`GitHub API error: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return GitHubListCommitsSchema.parse(await response.json());
|
||||
}
|
||||
|
||||
async function listIssues(
|
||||
owner: string,
|
||||
repo: string,
|
||||
@@ -705,6 +742,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
description: "Create a new branch in a GitHub repository",
|
||||
inputSchema: zodToJsonSchema(CreateBranchSchema),
|
||||
},
|
||||
{
|
||||
name: "list_commits",
|
||||
description: "Get list of commits of a branch in a GitHub repository",
|
||||
inputSchema: zodToJsonSchema(ListCommitsSchema)
|
||||
},
|
||||
{
|
||||
name: "list_issues",
|
||||
description: "List issues in a GitHub repository with filtering options",
|
||||
@@ -924,6 +966,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
return { toolResult: comment };
|
||||
}
|
||||
|
||||
case "list_commits": {
|
||||
const args = ListCommitsSchema.parse(request.params.arguments);
|
||||
const results = await listCommits(args.owner, args.repo, args.page, args.perPage, args.sha);
|
||||
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${request.params.name}`);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,25 @@ export const GitHubTreeSchema = z.object({
|
||||
truncated: z.boolean(),
|
||||
});
|
||||
|
||||
export const GitHubListCommitsSchema = z.array(z.object({
|
||||
sha: z.string(),
|
||||
node_id: z.string(),
|
||||
commit: z.object({
|
||||
author: GitHubAuthorSchema,
|
||||
committer: GitHubAuthorSchema,
|
||||
message: z.string(),
|
||||
tree: z.object({
|
||||
sha: z.string(),
|
||||
url: z.string()
|
||||
}),
|
||||
url: z.string(),
|
||||
comment_count: z.number(),
|
||||
}),
|
||||
url: z.string(),
|
||||
html_url: z.string(),
|
||||
comments_url: z.string()
|
||||
}));
|
||||
|
||||
export const GitHubCommitSchema = z.object({
|
||||
sha: z.string(),
|
||||
node_id: z.string(),
|
||||
@@ -322,6 +341,15 @@ export const SearchRepositoriesSchema = z.object({
|
||||
.describe("Number of results per page (default: 30, max: 100)"),
|
||||
});
|
||||
|
||||
export const ListCommitsSchema = z.object({
|
||||
owner: z.string().describe("Repository owner (username or organization)"),
|
||||
repo: z.string().describe("Repository name"),
|
||||
page: z.number().optional().describe("Page number for pagination (default: 1)"),
|
||||
perPage: z.number().optional().describe("Number of results per page (default: 30, max: 100)"),
|
||||
sha: z.string().optional()
|
||||
.describe("SHA of the file being replaced (required when updating existing files)")
|
||||
});
|
||||
|
||||
export const CreateRepositorySchema = z.object({
|
||||
name: z.string().describe("Repository name"),
|
||||
description: z.string().optional().describe("Repository description"),
|
||||
@@ -663,6 +691,7 @@ export type GitHubContent = z.infer<typeof GitHubContentSchema>;
|
||||
export type FileOperation = z.infer<typeof FileOperationSchema>;
|
||||
export type GitHubTree = z.infer<typeof GitHubTreeSchema>;
|
||||
export type GitHubCommit = z.infer<typeof GitHubCommitSchema>;
|
||||
export type GitHubListCommits = z.infer<typeof GitHubListCommitsSchema>;
|
||||
export type GitHubReference = z.infer<typeof GitHubReferenceSchema>;
|
||||
export type CreateRepositoryOptions = z.infer<
|
||||
typeof CreateRepositoryOptionsSchema
|
||||
|
||||
Reference in New Issue
Block a user