Skip to main content
Glama

list_pull_requests

Retrieve pull requests from a GitHub repository with filters for state, head branch, base branch, sorting, and pagination.

Instructions

List pull requests in a GitHub repository.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ownerYesRepository owner
repoYesRepository name
stateNoFilter by state
headNoFilter by head user/org and branch
baseNoFilter by base branch
sortNoSort by
directionNoSort direction
per_pageNoResults per page (default 10, max 100)
pageNoPage number (default 1)

Implementation Reference

  • The full handler definition for the 'list_pull_requests' tool, including the schema definition (lines 101-128) and async handler function (lines 129-201) that calls octokit.rest.pulls.list() and formats results as markdown.
    // Tool: List Pull Requests
    server.tool(
    	"list_pull_requests",
    	"List pull requests in a GitHub repository.",
    	{
    		owner: z.string().describe("Repository owner"),
    		repo: z.string().describe("Repository name"),
    		state: z
    			.enum(["open", "closed", "all"])
    			.optional()
    			.describe("Filter by state"),
    		head: z
    			.string()
    			.optional()
    			.describe("Filter by head user/org and branch"),
    		base: z.string().optional().describe("Filter by base branch"),
    		sort: z
    			.enum(["created", "updated", "popularity", "long-running"])
    			.optional()
    			.describe("Sort by"),
    		direction: z.enum(["asc", "desc"]).optional().describe("Sort direction"),
    		per_page: z
    			.number()
    			.optional()
    			.default(10)
    			.describe("Results per page (default 10, max 100)"),
    		page: z
    			.number()
    			.optional()
    			.default(1)
    			.describe("Page number (default 1)"),
    	},
    	async ({
    		owner,
    		repo,
    		state,
    		head,
    		base,
    		sort,
    		direction,
    		per_page,
    		page,
    	}) => {
    		try {
    			const response = await octokit.rest.pulls.list({
    				owner,
    				repo,
    				state,
    				head,
    				base,
    				sort,
    				direction,
    				per_page,
    				page,
    			})
    
    			// Format the response as clean markdown
    			const prs = response.data
    			if (prs.length === 0) {
    				return {
    					content: [{ type: "text", text: "No pull requests found." }],
    				}
    			}
    
    			let markdown = `# Pull Requests for ${owner}/${repo}\n\n`
    			markdown += `Showing ${prs.length} pull request(s) - Page ${page}\n`
    			if (prs.length === per_page) {
    				markdown += `*Note: More results may be available. Use 'page' parameter to see next page.*\n`
    			}
    			markdown += `\n`
    
    			prs.forEach(pr => {
    				markdown += `## #${pr.number}: ${pr.title}\n\n`
    				markdown += `- **State**: ${pr.state}\n`
    				markdown += `- **Author**: ${pr.user?.login || "Unknown"}\n`
    				markdown += `- **Created**: ${new Date(pr.created_at).toLocaleDateString()}\n`
    				markdown += `- **Updated**: ${new Date(pr.updated_at).toLocaleDateString()}\n`
    				markdown += `- **Branch**: ${pr.head.ref} → ${pr.base.ref}\n`
    
    				if (pr.draft) {
    					markdown += `- **Status**: Draft\n`
    				}
    
    				if (pr.labels && pr.labels.length > 0) {
    					markdown += `- **Labels**: ${pr.labels.map(l => l.name).join(", ")}\n`
    				}
    
    				if (pr.assignees && pr.assignees.length > 0) {
    					markdown += `- **Assignees**: ${pr.assignees.map(a => a.login).join(", ")}\n`
    				}
    
    				markdown += `- **URL**: ${pr.html_url}\n`
    				markdown += `\n`
    			})
    
    			return {
    				content: [{ type: "text", text: markdown }],
    			}
    		} catch (e: any) {
    			return {
    				content: [{ type: "text", text: `Error: ${e.message}` }],
    			}
    		}
    	},
    )
  • src/index.ts:14-18 (registration)
    The 'registerAllToolsAndResources' function calls 'registerPullRequestTools(server, octokit)' at line 18, which registers all pull request tools including 'list_pull_requests'.
    export function registerAllToolsAndResources(server: McpServer, octokit: Octokit): void {
    	registerSearchTools(server, octokit)
    	registerIssueTools(server, octokit)
    	registerRepositoryTools(server, octokit)
    	registerPullRequestTools(server, octokit)
  • src/index.ts:5-5 (registration)
    Import of the registerPullRequestTools function from the pullrequests module.
    import { registerPullRequestTools } from "./tools/pullrequests.js"
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It only states 'List pull requests' without disclosing pagination behavior, data volume, or any side effects. The read-only nature is implied but not explicitly stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence with no redundancy. It is appropriately sized but lacks any additional context that could be included without verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description does not explain return format, pagination, or filtering options. While the schema covers parameters, an overview of the response or page behavior is missing for a tool with 9 parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with all parameters thoroughly described in the input schema. The description adds no additional parameter meaning, which is acceptable as the schema does the heavy lifting, earning the baseline score of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists pull requests in a GitHub repository, using a specific verb and resource. However, with many sibling tools like get_pull_request and list_issues, it does not differentiate itself, which would help an agent select the correct tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. The description does not mention that it returns a list, supports filtering, or that for a single PR one should use get_pull_request. This is a significant gap given the many related sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hithereiamaliff/mcp-github'

If you have feedback or need assistance with the MCP directory API, please join our Discord server