Skip to main content
Glama

Git Workflow Automation MCP Server

by Arcia125

create_pull_request

Automate GitHub pull request creation with proper authentication. Specify title, description, base and head branches, and working directory. Supports dry runs for previewing changes.

Instructions

Create a GitHub pull request with proper authentication handling

Input Schema

NameRequiredDescriptionDefault
baseBranchNoBase branch (target)main
bodyYesPull request description
dryRunNoPreview without executing
headBranchNoHead branch (source, defaults to current branch)
titleYesPull request title
workingDirNoWorking directory path

Input Schema (JSON Schema)

{ "properties": { "baseBranch": { "default": "main", "description": "Base branch (target)", "type": "string" }, "body": { "description": "Pull request description", "type": "string" }, "dryRun": { "default": false, "description": "Preview without executing", "type": "boolean" }, "headBranch": { "description": "Head branch (source, defaults to current branch)", "type": "string" }, "title": { "description": "Pull request title", "type": "string" }, "workingDir": { "description": "Working directory path", "type": "string" } }, "required": [ "title", "body" ], "type": "object" }

Implementation Reference

  • The main handler function that implements the create_pull_request tool. It uses GitHub CLI (gh pr create) to create a pull request, with proper token clearing and input escaping to handle authentication securely.
    async function createPullRequest( title: string, body: string, baseBranch: string = 'main', headBranch?: string, workingDir?: string, dryRun: boolean = false ): Promise<WorkflowResult> { try { if (dryRun) { return { success: true, message: "Dry run: Would create pull request", details: { title, body, baseBranch, headBranch } }; } // Get current branch if not specified if (!headBranch) { const git = getGit(workingDir); headBranch = await git.revparse(['--abbrev-ref', 'HEAD']); } // Create PR using GitHub CLI with cleared tokens and proper escaping const command = `gh pr create --title "${title}" --body "${body}" --base ${baseBranch} --head ${headBranch}`; const result = await executeGitHubCommand(command, { title, body, cwd: workingDir }); // Extract PR URL from output const prUrl = result.stdout.trim(); return { success: true, message: "Successfully created pull request", details: { url: prUrl, title, baseBranch, headBranch } }; } catch (error: any) { return { success: false, message: "Failed to create pull request", error: `Failed to create pull request: ${error.message}` }; } }
  • The input schema definition for the create_pull_request tool, specifying parameters like title, body, branches, and options.
    inputSchema: { type: "object", properties: { title: { type: "string", description: "Pull request title" }, body: { type: "string", description: "Pull request description" }, baseBranch: { type: "string", description: "Base branch (target)", default: "main" }, headBranch: { type: "string", description: "Head branch (source, defaults to current branch)" }, workingDir: { type: "string", description: "Working directory path" }, dryRun: { type: "boolean", description: "Preview without executing", default: false } }, required: ["title", "body"] }
  • src/index.ts:595-604 (registration)
    The dispatch/registration in the CallToolRequestSchema handler that routes calls to the createPullRequest function.
    case "create_pull_request": result = await createPullRequest( args?.title as string, args?.body as string, (args?.baseBranch as string) || 'main', args?.headBranch as string, args?.workingDir as string, (args?.dryRun as boolean) || false ); break;
  • src/index.ts:452-486 (registration)
    The tool registration in the ListToolsRequestSchema response, including name, description, and schema.
    name: "create_pull_request", description: "Create a GitHub pull request with proper authentication handling", inputSchema: { type: "object", properties: { title: { type: "string", description: "Pull request title" }, body: { type: "string", description: "Pull request description" }, baseBranch: { type: "string", description: "Base branch (target)", default: "main" }, headBranch: { type: "string", description: "Head branch (source, defaults to current branch)" }, workingDir: { type: "string", description: "Working directory path" }, dryRun: { type: "boolean", description: "Preview without executing", default: false } }, required: ["title", "body"] } },
  • Helper function used by createPullRequest to execute GitHub CLI commands securely, clearing tokens and handling PowerShell escaping.
    async function executeGitHubCommand( baseCommand: string, options?: { title?: string; body?: string; cwd?: string; } ): Promise<{ stdout: string; stderr: string }> { let tempBodyFile: string | null = null; try { let finalCommand = baseCommand; // If we have a body, write it to a temporary file to avoid PowerShell parsing issues if (options?.body) { tempBodyFile = join(tmpdir(), `gh-pr-body-${Date.now()}.txt`); writeFileSync(tempBodyFile, options.body, 'utf8'); // Replace --body with --body-file, handling both quoted and unquoted body content finalCommand = finalCommand.replace(/--body\s+"[^"]*"/, `--body-file "${tempBodyFile}"`); finalCommand = finalCommand.replace(/--body\s+[^\s]+/, `--body-file "${tempBodyFile}"`); } // If we have a title, properly escape it for PowerShell if (options?.title) { const escapedTitle = escapePowerShellString(options.title); finalCommand = finalCommand.replace(/--title\s+"([^"]*)"/, `--title '${escapedTitle}'`); } // Build the PowerShell command with proper token clearing const powerShellCommand = `powershell -Command "Remove-Item Env:GH_TOKEN -ErrorAction SilentlyContinue; Remove-Item Env:GITHUB_TOKEN -ErrorAction SilentlyContinue; ${finalCommand}"`; const result = await execAsync(powerShellCommand, { cwd: options?.cwd || process.cwd(), maxBuffer: 1024 * 1024 // 1MB buffer }); return result; } catch (error: any) { throw new Error(`Command failed: ${error.message}\nStdout: ${error.stdout}\nStderr: ${error.stderr}`); } finally { // Clean up temporary file if (tempBodyFile) { try { unlinkSync(tempBodyFile); } catch (e) { // Ignore cleanup errors } } } }

Other Tools

Related 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/Arcia125/git-workflow-mcp-server'

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