{"_id":"@brycepelletier/github-app-mcp","_rev":"5-370a25fc42da057d88ed4bad76b67808","name":"@brycepelletier/github-app-mcp","dist-tags":{"latest":"0.5.1"},"versions":{"0.3.0":{"name":"@brycepelletier/github-app-mcp","version":"0.3.0","license":"MIT","_id":"@brycepelletier/github-app-mcp@0.3.0","maintainers":[{"name":"brycepelletier","email":"brycepelletier@gmail.com"}],"homepage":"https://github.com/brycepelletier/github-app-mcp#readme","bugs":{"url":"https://github.com/brycepelletier/github-app-mcp/issues"},"bin":{"github-app-mcp":"index.mjs"},"dist":{"shasum":"7580531adc9a9bf0417b39b9e4704db5ca701c54","tarball":"https://registry.npmjs.org/@brycepelletier/github-app-mcp/-/github-app-mcp-0.3.0.tgz","fileCount":12,"integrity":"sha512-uzDY7MtCM9AqXUO//4OANnd3VM64ut50mA0jglVDnK/2lELQiJ7dyNxkt/fcByY4CyisPS12LTUNuufwP6rdcQ==","signatures":[{"sig":"MEQCICybf4jChoa2ny94zCNJXK0SepJMquHTexJ6Yj4EFBs+AiAGsacQ9l+9N0E4Cyx3ovUVdPwBFN4SzNC/CoLtTDw8nQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":90602},"type":"module","engines":{"node":">=24"},"gitHead":"7cb796d0b8853d54fbfdb08aa07aed739de7d089","scripts":{"link":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm install && npm link","test":"node --test","unlink":"npm uninstall --global @brycepelletier/github-app-mcp","validate":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm test && npm pack --dry-run"},"_npmUser":{"name":"brycepelletier","email":"brycepelletier@gmail.com"},"repository":{"url":"git+https://github.com/brycepelletier/github-app-mcp.git","type":"git"},"_npmVersion":"11.17.0","description":"Capability-focused MCP facade for bounded Git and official GitHub App operations.","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.22.0","@octokit/auth-app":"8.3.0","@modelcontextprotocol/sdk":"^1.15.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":true,"_npmOperationalInternal":{"tmp":"tmp/github-app-mcp_0.3.0_1787516023466_0.30191574045818115","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@brycepelletier/github-app-mcp","version":"0.3.1","license":"MIT","_id":"@brycepelletier/github-app-mcp@0.3.1","maintainers":[{"name":"brycepelletier","email":"brycepelletier@gmail.com"}],"homepage":"https://github.com/brycepelletier/github-app-mcp#readme","bugs":{"url":"https://github.com/brycepelletier/github-app-mcp/issues"},"bin":{"github-app-mcp":"index.mjs"},"dist":{"shasum":"1130282b7fa3b29461deae5edb40e2a437be3769","tarball":"https://registry.npmjs.org/@brycepelletier/github-app-mcp/-/github-app-mcp-0.3.1.tgz","fileCount":12,"integrity":"sha512-SVCu3/JEGh7QwfYvqwocowQF5R7uVkGZUZpAYanLNSTp/tRN6kXFXXQEn8MAVcCUzPixWsAyI7SR0GsZYO7//Q==","signatures":[{"sig":"MEYCIQDbcrJANJjZ/DEy3C0DWMhdI+2oF+VfWkkWRhg+nUI8qAIhAJd2fzq8Y0jbAmGiN8bunTCVcuYVCw6mZMIAIqyE2PG6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":91090},"type":"module","engines":{"node":">=24"},"gitHead":"109cfc73b49963c65e18e12ba1ebbb769b354013","scripts":{"link":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm install && npm link","test":"node --test","unlink":"npm uninstall --global @brycepelletier/github-app-mcp","validate":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm test && npm pack --dry-run"},"_npmUser":{"name":"brycepelletier","email":"brycepelletier@gmail.com"},"repository":{"url":"git+https://github.com/brycepelletier/github-app-mcp.git","type":"git"},"_npmVersion":"11.17.0","description":"Capability-focused MCP facade for bounded Git and official GitHub App operations.","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.22.0","@octokit/auth-app":"8.3.0","@modelcontextprotocol/sdk":"^1.15.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":true,"_npmOperationalInternal":{"tmp":"tmp/github-app-mcp_0.3.1_1787699239960_0.8901469748227591","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@brycepelletier/github-app-mcp","version":"0.4.0","license":"MIT","_id":"@brycepelletier/github-app-mcp@0.4.0","maintainers":[{"name":"brycepelletier","email":"brycepelletier@gmail.com"}],"homepage":"https://github.com/brycepelletier/github-app-mcp#readme","bugs":{"url":"https://github.com/brycepelletier/github-app-mcp/issues"},"bin":{"github-app-mcp":"index.mjs"},"dist":{"shasum":"8b357fd6c00b5b2497f361a7be5cba21bf306fd5","tarball":"https://registry.npmjs.org/@brycepelletier/github-app-mcp/-/github-app-mcp-0.4.0.tgz","fileCount":13,"integrity":"sha512-K0A0pQ3tfNQ3FzUbP7dH1DtJ/9z9xHqgpEiSdosmywG6Wuki9L7cxoLB2yhXBfRLFtK36KbQw50WJaLNEktLYQ==","signatures":[{"sig":"MEQCIGcF/Jp9Nl2L1fytHHKr0KzAl8bZLEtR7Yzkfmyg1sSBAiBObzVd2yafu5FjpcGfLr8p84XGp/wob0Q8AkGoE3/KUQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96564},"type":"module","engines":{"node":">=24"},"gitHead":"8e42f05ff550ab100086365612771d5f48245906","scripts":{"link":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm install && npm link","test":"node --test","unlink":"npm uninstall --global @brycepelletier/github-app-mcp","validate":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/runner-capability.mjs && node --check ./runtime/schemas.mjs && npm test && npm pack --dry-run"},"_npmUser":{"name":"brycepelletier","email":"brycepelletier@gmail.com"},"repository":{"url":"git+https://github.com/brycepelletier/github-app-mcp.git","type":"git"},"_npmVersion":"11.17.0","description":"Capability-focused MCP facade for bounded Git and official GitHub App operations.","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.22.0","@octokit/auth-app":"8.3.0","@modelcontextprotocol/sdk":"^1.15.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":true,"_npmOperationalInternal":{"tmp":"tmp/github-app-mcp_0.4.0_1787799588069_0.39871463562111775","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@brycepelletier/github-app-mcp","version":"0.5.0","license":"MIT","_id":"@brycepelletier/github-app-mcp@0.5.0","maintainers":[{"name":"brycepelletier","email":"brycepelletier@gmail.com"}],"homepage":"https://github.com/brycepelletier/github-app-mcp#readme","bugs":{"url":"https://github.com/brycepelletier/github-app-mcp/issues"},"bin":{"github-app-mcp":"index.mjs"},"dist":{"shasum":"502c29782e13a7efba3f02982c2026a773719bcb","tarball":"https://registry.npmjs.org/@brycepelletier/github-app-mcp/-/github-app-mcp-0.5.0.tgz","fileCount":14,"integrity":"sha512-96AFjcbDzcGsUqllvR2IEkXR4X1BLCFRgVMDh8XHzvSbnmZAhcdrpIwyLIG+GYprgnPdFm18D2nhp/QndQtl4A==","signatures":[{"sig":"MEQCIC2BUT38YMSjjDioF3AJtHxXr6A0atWozEz4DBiNWFMIAiBNZHCQ5LK9E4ZXVZLya1Cs3MM4zK8cBDEbPaBapAtUXw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDBg5kFpg01DfT7OgeRUo/gtn+IArQR5an9rwAInanUJQIhAMqLxVg9uVNsdvnGLwS1vwIxyIn1fCYfqo/cDHYffILX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107225},"type":"module","engines":{"node":">=24"},"gitHead":"9f1e5eb7696da77ac68880cb67f8e152695796bb","scripts":{"link":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm install && npm link","test":"node --test","unlink":"npm uninstall --global @brycepelletier/github-app-mcp","validate":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-guidance.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/runner-capability.mjs && node --check ./runtime/schemas.mjs && npm test && npm pack --dry-run"},"_npmUser":{"name":"brycepelletier","email":"brycepelletier@gmail.com"},"repository":{"url":"git+https://github.com/brycepelletier/github-app-mcp.git","type":"git"},"_npmVersion":"11.17.0","description":"Capability-focused MCP facade for bounded Git and official GitHub App operations.","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.22.0","@octokit/auth-app":"8.3.0","@modelcontextprotocol/sdk":"^1.15.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":true,"_npmOperationalInternal":{"tmp":"tmp/github-app-mcp_0.5.0_1787880892160_0.4701304153385655","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"_id":"@brycepelletier/github-app-mcp@0.5.1","bin":{"github-app-mcp":"index.mjs"},"bugs":{"url":"https://github.com/brycepelletier/github-app-mcp/issues"},"dist":{"shasum":"b6025cc60f1842aaa57f62ce25ede7f8ea5b2531","tarball":"https://registry.npmjs.org/@brycepelletier/github-app-mcp/-/github-app-mcp-0.5.1.tgz","fileCount":14,"integrity":"sha512-06BAtyWH1p11uUKe4wchfMGHRGcWoaYlyZJ05k+D/aolSGG6z2xQst9Wfu4EYbS3ek2Hg+kI6ADSH6C4jdIGrg==","signatures":[{"sig":"MEUCIQC4V8UM6kKvyKmS5+A2+ZenvAMIuSYUehtziPP2JwBBvAIgUFfnUoIy9jHrxMbudTvv9WAfIrzSDOY2aQDHf1XgY9o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC7pBE+B4pVgAgSuTL+HvhjEwkYFKL1amaKmlsaC5D3AQIhAMNHC2sVC6G1De0X+EDViQJo23pgvXpH7pW3F9ALytjA"}],"unpackedSize":109653},"name":"@brycepelletier/github-app-mcp","type":"module","engines":{"node":">=24"},"gitHead":"d0ac0af87833bda59875eb3752e3cb5a33da2456","license":"MIT","scripts":{"link":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/schemas.mjs && npm install && npm link","test":"node --test","unlink":"npm uninstall --global @brycepelletier/github-app-mcp","validate":"node --check ./index.mjs && node --check ./runtime/config.mjs && node --check ./runtime/git-guidance.mjs && node --check ./runtime/git-helper.mjs && node --check ./runtime/lifecycle.mjs && node --check ./runtime/runner-capability.mjs && node --check ./runtime/schemas.mjs && npm test && npm pack --dry-run"},"version":"0.5.1","_npmUser":{"name":"brycepelletier","email":"brycepelletier@gmail.com"},"homepage":"https://github.com/brycepelletier/github-app-mcp#readme","repository":{"url":"git+https://github.com/brycepelletier/github-app-mcp.git","type":"git"},"_npmVersion":"11.17.0","description":"Capability-focused MCP facade for bounded Git and official GitHub App operations.","directories":{},"maintainers":[{"name":"brycepelletier","email":"brycepelletier@gmail.com"}],"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.22.0","@octokit/auth-app":"8.3.0","@modelcontextprotocol/sdk":"^1.15.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":true,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/github-app-mcp_0.5.1_1789752614303_0.970109902599571"}}},"time":{"created":"2026-08-23T20:13:43.332Z","modified":"2026-09-18T17:30:14.853Z","0.3.0":"2026-08-23T20:13:43.613Z","0.3.1":"2026-08-25T23:07:20.105Z","0.4.0":"2026-08-27T02:59:48.235Z","0.5.0":"2026-08-28T01:34:52.297Z","0.5.1":"2026-09-18T17:30:14.391Z"},"bugs":{"url":"https://github.com/brycepelletier/github-app-mcp/issues"},"license":"MIT","homepage":"https://github.com/brycepelletier/github-app-mcp#readme","repository":{"url":"git+https://github.com/brycepelletier/github-app-mcp.git","type":"git"},"description":"Capability-focused MCP facade for bounded Git and official GitHub App operations.","maintainers":[{"name":"brycepelletier","email":"brycepelletier@gmail.com"}],"readme":"# `@brycepelletier/github-app-mcp`\r\n\r\nA single MCP stdio facade for the GitHub Operator role. It combines bounded Git\r\noperations over the active workspace with GitHub API tools delegated to GitHub's\r\nofficial MCP server. It never returns a GitHub App private key or installation\r\ntoken.\r\n\r\n## Architecture and responsibility split\r\n\r\n```text\r\nSoftware Engineer                    GitHub Operator\r\n       |                                    |\r\nagent-env-mcp                         github-app-mcp\r\n       |                         /-----------+-----------\\\r\nsource/build/edit            ephemeral Git runtime   official GitHub MCP\r\n.git masked                  real .git               GitHub API\r\nno GitHub credentials        local: no network       fixed toolsets\r\n                             remote: App auth\r\n```\r\n\r\n`agent-env-mcp` remains the engineering capability surface. Its engineering\r\ncontainer physically masks `.git` and receives no GitHub credential. This package\r\nis the sole intended model-facing Git/GitHub surface for `github-operator.agent.md`.\r\n\r\nThe facade discovers the workspace with MCP `roots/list`, requires exactly one\r\nlocal `file:` root, rejects filesystem roots, and requires real `.git` metadata.\r\nNo model tool parameter can select a host path, PEM, image, toolset, or Docker\r\nargument.\r\n\r\n## Trust boundaries and Docker behavior\r\n\r\n```text\r\nMCP client\r\n   | stdio\r\nhost-side trusted launcher (may control Docker; no Docker socket is mounted)\r\n   |-- git_local  -> ephemeral container, workspace mount, network=none, no PEM\r\n   |-- git_remote -> ephemeral container, workspace + read-only PEM, GitHub HTTPS\r\n   `-- API tools  -> ghcr.io/github/github-mcp-server, read-only PEM\r\n```\r\n\r\nLocal Git and remote Git have different execution modes. `git_local` exposes an\r\noperation enum and typed fields rather than a shell or arbitrary Git argument\r\narray. Its container has real `.git`, but no network and no credential material.\r\n\r\n`git_local` diff output preserves file headers and verbatim context/change lines\r\nbut removes numeric hunk coordinates. No source line is prefixed with generated\r\nline-position metadata that could be mistaken for editable file content.\r\n\r\nGit validation and nonzero exits do not escape as raw MCP exceptions. The\r\nfacade returns `isError` with a stable code, category, no-blind-retry policy,\r\nand ordered `next_actions` that name only authorized tools. Recognized cases\r\ninclude leading-colon/unsafe refs, missing revisions, non-fast-forward pushes,\r\ndirty worktrees, conflicts, authorization failures, and PR creation attempts\r\nwhose head has no commits beyond the base. The last case directs the operator\r\nto update the existing PR head branch rather than inventing a replacement PR.\r\n\r\n`git_remote` accepts only `fetch`, fast-forward-only `pull`, `push`, `ls_remote`,\r\n`auth_check`, and `push_dry_run`, with bounded remote/ref fields. It requires a credential-free\r\nGitHub HTTPS or SSH remote, derives repository identity from that configured\r\nremote, canonicalizes SSH forms to credential-free HTTPS internally without\r\nchanging `.git/config`, and requests an installation token restricted to that\r\nrepository with `contents:write` and `workflows:write`. The token is minted inside\r\nthe ephemeral runtime, supplied to Git through a private askpass helper, redacted\r\nfrom output, and discarded with the container. `pull` performs authenticated\r\nfetch first, followed by a credential-free `--ff-only` merge.\r\n\r\nGit hooks, global/system configuration, file transport, submodule recursion,\r\ninteractive editors, GPG signing, and terminal credential prompts are disabled.\r\nOutput is bounded and scrubbed for GitHub token patterns and credential-bearing\r\nURLs.\r\n\r\n## Authentication verification\r\n\r\n`git ls-remote` is not proof of authentication: it can succeed anonymously for\r\na public repository. `auth_check` instead mints a repository-restricted\r\ninstallation token and calls GitHub's authenticated repository endpoint. Its\r\nfixed response confirms App authentication and repository authorization without\r\nreturning the API response or any credential:\r\n\r\n```json\r\n{ \"operation\": \"auth_check\", \"remote\": \"origin\" }\r\n```\r\n\r\n```json\r\n{\r\n  \"authenticated\": true,\r\n  \"repository_authorized\": true,\r\n  \"repository\": \"owner/repository\",\r\n  \"remote_scheme\": \"https\",\r\n  \"permissions\": { \"contents\": \"write\", \"workflows\": \"write\" },\r\n  \"credential_exposed\": false\r\n}\r\n```\r\n\r\n`push_dry_run` additionally proves that authenticated Git HTTPS transport can\r\nnegotiate a push. The runtime always inserts `--dry-run`; callers cannot supply\r\nGit arguments, force flags, or deletion refspecs. GitHub evaluates the proposed\r\nupdate, but neither local nor remote refs are changed.\r\n\r\n```json\r\n{ \"operation\": \"push_dry_run\", \"remote\": \"origin\", \"branch\": \"main\" }\r\n```\r\n\r\n```json\r\n{\r\n  \"authenticated\": true,\r\n  \"transport\": \"https\",\r\n  \"dry_run\": true,\r\n  \"exit_code\": 0,\r\n  \"signal\": null,\r\n  \"stdout\": \"\",\r\n  \"stderr\": \"Everything up-to-date\\n\",\r\n  \"truncated\": false,\r\n  \"credential_exposed\": false,\r\n  \"summary\": \"Authenticated push dry run succeeded; no refs were changed.\"\r\n}\r\n```\r\n\r\nThese checks require an installed App with the requested `contents:write` and\r\n`workflows:write` permissions, repository access, network access, and an exact\r\nconfigured PEM path. They do not prove that unrelated repositories are\r\nauthorized and do not inspect branch-protection outcomes beyond GitHub's dry-run\r\nresponse.\r\n\r\nRun automated checks with `npm test` or the full local package validation with\r\n`npm run validate`. Optional live verification should record the remote branch\r\nobject ID with `git ls-remote` before and after `auth_check` and `push_dry_run`,\r\nthen confirm the IDs match and all returned `credential_exposed` fields are\r\nfalse. Never substitute a normal push.\r\n\r\nGitHub Issues, pull requests, reviews, Actions, Projects, and searches are not\r\nreimplemented. They are proxied over MCP to:\r\n\r\n```text\r\nghcr.io/github/github-mcp-server\r\n```\r\n\r\nThe official server receives exactly:\r\n\r\n```text\r\nGITHUB_TOOLSETS=context,issues,pull_requests,actions,projects\r\n```\r\n\r\nNo unrelated toolsets are silently enabled.\r\n\r\nThe facade additionally exposes\r\n`actions_issue_runner_registration_capability`. It requests a repository runner\r\nregistration token internally, stores it behind a random five-minute loopback\r\ncapability, and returns only that single-use opaque reference. The Docker MCP\r\nconsumes the reference with one POST; a second or expired exchange returns\r\n`410 Gone`. The App installation must grant repository administration write\r\npermission for GitHub's runner-registration endpoint in addition to the\r\nexisting content/workflow permissions.\r\n\r\n## Configuration and provenance\r\n\r\nThe launcher requires all three external configuration values and fails closed\r\nbefore starting an authenticated container if any is absent or invalid:\r\n\r\n- `GITHUB_APP_ID` — positive numeric GitHub App identifier.\r\n- `GITHUB_APP_INSTALLATION_ID` — positive numeric installation identifier.\r\n- `GITHUB_APP_PRIVATE_KEY_PATH` — required absolute or resolvable host path.\r\n\r\nThe known working values `GITHUB_APP_ID=4618233` and\r\n`GITHUB_APP_INSTALLATION_ID=154276908` come from the user's existing VS Code\r\nGitHub MCP configuration and earlier compose setup for GitHub App\r\n`bp-agent-github-app`. They are documented provenance for this deployment, not\r\npackage defaults. Every installation must provide its own values. The GitHub\r\ninstallation/settings page remains the source of truth for repository access.\r\nThe App was originally installed for `brycepelletier/environment-controller`.\r\n\r\nThe package deliberately has no default host PEM filename. Earlier material only\r\nestablishes that it was somewhere below `C:/Users/bryce/.ssh/`; that is not enough\r\nto guess safely. The configured host file is mounted read-only at the fixed\r\ncontainer path `/secrets/github-app.pem`. The key is never copied into the npm\r\npackage, printed, accepted as tool input, or returned through MCP.\r\n\r\n## Host prerequisites and MCP lifecycle\r\n\r\n- Node.js 24 LTS or compatible Node 24 release\r\n- Docker with Linux-container support\r\n- GitHub App PEM readable by the trusted host-side launcher\r\n- One local Git workspace supplied through MCP roots\r\n- Network access from the remote Git and official GitHub containers\r\n\r\nThe official GitHub child server starts lazily when tools are listed or an API\r\ntool is called. Git runtime images build lazily on the first Git operation and are\r\nreused by a package-version/content-derived local tag; Git operation containers\r\nare ephemeral (`--rm`). SIGINT/SIGTERM closes the official child transport.\r\n\r\nThe official GitHub container has a unique infrastructure-generated name for\r\neach facade process. MCP stdin EOF/close, SIGINT, SIGTERM, SIGHUP, and fatal\r\nprocess errors trigger idempotent cleanup: the facade closes the child transport\r\nand then explicitly removes its own named container as a fallback. Container\r\nnames and cleanup targets are never accepted from MCP tool input, and concurrent\r\nVS Code sessions do not share a cleanup target.\r\n\r\n## Local linking\r\n\r\nFrom Git Bash in this package directory:\r\n\r\n```bash\r\nnpm run link\r\n```\r\n\r\nUnlink with:\r\n\r\n```bash\r\nnpm run unlink\r\n```\r\n\r\n## VS Code configuration\r\n\r\nProvide the host PEM path as environment configuration and expose one MCP entry:\r\n\r\n```json\r\n{\r\n  \"servers\": {\r\n    \"github\": {\r\n      \"type\": \"stdio\",\r\n      \"command\": \"npx\",\r\n      \"args\": [\"--yes\", \"@brycepelletier/github-app-mcp@0.3.0\"],\r\n      \"env\": {\r\n        \"GITHUB_APP_ID\": \"4618233\",\r\n        \"GITHUB_APP_INSTALLATION_ID\": \"154276908\",\r\n        \"GITHUB_APP_PRIVATE_KEY_PATH\": \"<exact-host-path-to-existing-pem>\"\r\n      }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nAll three values are mandatory. The numeric identifiers select the caller's App\r\nand installation; the package never supplies a tenant-specific identity.\r\n\r\n## Migration from `github-token-broker`\r\n\r\nThe old private broker listened on `0.0.0.0:8080` and returned installation\r\ntokens from `GET /credential` in Git credential-helper format. That architecture\r\nis retired: this package has no HTTP listener, credential endpoint, or token\r\nresponse. Existing broker source is retained for audit/migration history but is\r\nnot shipped by this package.\r\n\r\nAs of `agent-env-mcp` 0.4.0, its Git service and public `git_command` have been\r\nremoved. The engineering service continues masking real `.git` and never\r\nreceives the PEM, installation tokens, or GitHub MCP tools.\r\n\r\n## License\r\n\r\nMIT. See `LICENSE`.\r\n\r\n## Preflight evidence and safe diagnostics\r\n\r\npush_dry_run responses explicitly identify operation_completed=push_dry_run and requested_push_completed=false. A successful preflight does not mutate refs or automatically authorize a push. When a real push is already delegated, GitHub Operator must call push next and verify ls_remote against the intended commit.\r\n\r\nAuthentication failures retain only allowlisted HTTP status or network codes, never upstream response bodies/headers, credentials, or request objects. A failure for one installation-scoped repository is not proof that another authorized repository is unavailable.\r\n","readmeFilename":"README.md"}