gh-attach

gh-attach

Enables AI applications to upload images and videos to GitHub issues, pull requests, and comments through the Model Context Protocol.

Category
访问服务器

README

gh-attach

CI npm version npm downloads

Upload images and videos to GitHub issues, PRs, and comments — from the CLI or via MCP.

<p align="center"> <img src="demo.svg" alt="gh-attach CLI demo" width="700"> </p>

GitHub doesn't provide an official API for comment attachments on issues and pull requests. gh-attach fills this gap with multiple upload strategies, a clean CLI, and an MCP server for AI-powered workflows.

Features

  • Multiple upload strategies — browser session, cookie extraction, release assets (official API), repo-branch fallback
  • Images + videos — PNG, GIF, JPEG, SVG, WebP, MP4, MOV, and WEBM
  • CLI tool — works standalone or as a gh extension (gh attach)
  • MCP server — expose upload capabilities to AI applications via Model Context Protocol
  • Fully tested — unit, integration, and E2E test suites
  • Automated releases — semantic versioning with conventional commits

Install

For most users, install from the public npm registry — no npm authentication is required.

Standalone CLI (npm)

# Install globally from public npm
npm install -g gh-attach

Run it as gh-attach ....

Optional: GitHub Packages mirror

# Install the scoped mirror from GitHub Packages (requires GitHub Packages auth)
npm install -g @addono/gh-attach --registry=https://npm.pkg.github.com

GitHub CLI extension

gh extension install Addono/gh-attach

Run it as gh attach ....

Standalone release binary

Download the matching asset from the latest release and place it on your PATH. Release assets are published as:

  • gh-attach-darwin-arm64
  • gh-attach-darwin-amd64
  • gh-attach-linux-amd64
  • gh-attach-windows-amd64.exe

Run it as gh-attach ....

Run without installing (npx)

# Upload a file
npx -y gh-attach@latest upload ./screenshot.png --target owner/repo#42

# Start the MCP server
npx -y gh-attach@latest mcp --transport stdio

Keeping gh-attach up to date

# npm install
npm install -g gh-attach@latest

# gh extension install
gh extension upgrade Addono/gh-attach

If you run via npx, there is nothing to upgrade locally — each invocation resolves gh-attach@latest. Pin a specific version instead if you do not want the latest release:

npx -y gh-attach@<version> mcp --transport stdio

If you installed a standalone release binary, download the newest matching asset from the latest GitHub release and replace your existing gh-attach executable.

Verify the active version with gh-attach --version or gh attach --version, depending on how you installed it.

Quick Start

If you installed gh-attach as a GitHub CLI extension, replace gh-attach with gh attach in the examples below.

# Upload a file to an issue
gh-attach upload ./screenshot.png --target owner/repo#42

# Upload using the release-asset strategy (official API, works with tokens)
gh-attach upload ./diagram.png --target #42 --strategy release-asset

# Get just the URL
gh-attach upload ./img.png --target #42 --format url

# JSON output
gh-attach upload ./img.png --target #42 --format json

Videos (.mp4, .mov, .webm) are emitted as bare URLs in markdown output so GitHub can render them inline when the target upload URL supports video playback.

Authentication

Strategy 1: Browser Session (default)

gh-attach login  # Opens browser, saves session cookies

Strategy 2: Release Assets (official API)

export GITHUB_TOKEN=ghp_...  # or GH_TOKEN
gh-attach upload ./img.png --target #42 --strategy release-asset

If neither GITHUB_TOKEN nor GH_TOKEN is set, gh-attach automatically falls back to a token from the GitHub CLI (gh auth token) — so an authenticated gh auth login session is enough. The lookup order for the API token is:

  1. GITHUB_TOKEN environment variable
  2. GH_TOKEN environment variable
  3. GitHub CLI stored credentials (gh auth token) — when multiple accounts are signed in, the one most likely to have access to the target repository is preferred

This applies to every code path that needs an API token (the release-asset and repo-branch strategies, in both the CLI and the MCP server).

Strategy 3: Cookie Extraction

Automatically extracts GitHub cookies from Chrome/Firefox.

Strategy 4: Repository Branch

Commits attachments to an orphan branch. Works with any token.

MCP Server

Choose the MCP command that matches how you installed gh-attach:

Install method MCP command
Standalone npm install gh-attach mcp --transport stdio
Standalone release binary gh-attach mcp --transport stdio
gh extension gh attach mcp --transport stdio
npx npx -y gh-attach@latest mcp --transport stdio

When the MCP client supports elicitation, upload_image can prompt for a GitHub token during the same tool call and continue the upload without requiring a separate login step first.

# stdio transport (standalone install or release binary)
gh-attach mcp --transport stdio

# stdio transport (gh extension)
gh attach mcp --transport stdio

# HTTP transport
gh-attach mcp --transport http --port 3000

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

Standalone CLI or release binary

{
  "mcpServers": {
    "gh-attach": {
      "command": "gh-attach",
      "args": ["mcp", "--transport", "stdio"]
    }
  }
}

GitHub CLI extension

{
  "mcpServers": {
    "gh-attach": {
      "command": "bash",
      "args": [
        "-lc",
        "export GITHUB_TOKEN=\"$(gh auth token)\" && exec gh attach mcp --transport stdio"
      ]
    }
  }
}

This wrapper requires bash and an authenticated GitHub CLI session (gh auth login). It resolves the token at startup instead of storing it in the config file, but the token is still present in the MCP server process environment while it is running. If bash is unavailable, use the standalone CLI setup instead.

VS Code / GitHub Copilot

Add to .vscode/settings.json:

Standalone CLI or release binary

{
  "mcp": {
    "servers": {
      "gh-attach": {
        "type": "local",
        "command": "gh-attach",
        "args": ["mcp", "--transport", "stdio"],
        "tools": ["*"]
      }
    }
  }
}

GitHub CLI extension

{
  "mcp": {
    "servers": {
      "gh-attach": {
        "type": "local",
        "command": "bash",
        "args": [
          "-lc",
          "export GITHUB_TOKEN=\"$(gh auth token)\" && exec gh attach mcp --transport stdio"
        ],
        "tools": ["*"]
      }
    }
  }
}

This wrapper requires bash and an authenticated GitHub CLI session (gh auth login). It resolves the token at startup instead of storing it in the config file, but the token is still present in the MCP server process environment while it is running. If bash is unavailable, use the standalone CLI setup instead.

If you prefer npx, use command: "npx" and prepend -y, gh-attach@latest to the args array.

Configuration

gh-attach config set strategy-order "release-asset,browser-session"
gh-attach config set default-target owner/repo
gh-attach config list
gh-attach config get default-target

Config is stored at ~/.config/gh-attach/config.json (overridable via GH_ATTACH_CONFIG or XDG_CONFIG_HOME).

Environment Variables

Variable Description
GITHUB_TOKEN / GH_TOKEN GitHub API token for release-asset and repo-branch strategies. When unset, falls back to gh auth token from the GitHub CLI.
GH_ATTACH_COOKIES Session cookies for browser-session strategy
GH_ATTACH_STRATEGY Override default strategy selection
GH_ATTACH_STATE_PATH Override session state file location
GH_ATTACH_CONFIG Override config file location
NO_COLOR Disable ANSI color codes in output

Exit Codes

Code Meaning
0 Success
1 General error
2 Authentication error
3 Validation error (bad input)
4 Network/upload error

Programmatic Usage

import { upload, selectStrategy } from "gh-attach";

const strategy = await selectStrategy({ token: process.env.GITHUB_TOKEN });
const result = await strategy.upload({
  file: "./screenshot.png",
  target: { owner: "octocat", repo: "hello-world", issue: 42 },
});
console.log(result.url); // https://github.com/user-attachments/assets/...

Development

npm install
npm run build       # Build with tsup
npm test            # Unit + integration tests
npm run test:e2e    # E2E tests (requires secrets)
npm run typecheck   # TypeScript strict mode
npm run lint        # ESLint

Release automation

  • Public npm releases publish the unscoped package as gh-attach.
  • GitHub Packages keeps a scoped mirror at @addono/gh-attach.
  • GitHub Actions publishes to npm via Trusted Publishing (OIDC), so the release workflow does not need an NPM_TOKEN repository secret.
  • Configure npm trusted publishing for package gh-attach with:
    • Organization or user: Addono
    • Repository: gh-attach
    • Workflow filename: release.yml
    • Environment name: leave empty unless you later protect releases with a GitHub Actions environment
  • After the first trusted publish succeeds, npm recommends enabling Require two-factor authentication and disallow tokens in the package publishing access settings.

Branch Protection (Recommended)

For production repositories, configure the following protections on the main branch via Settings → Branches → Branch protection rules:

Setting Value
Require a pull request before merging ✅ enabled
Require approvals 1 review
Require status checks to pass ✅ enabled
Required status checks Lint & Format, Typecheck, Build, and the Test (...) matrix jobs you want to enforce (for example Test (Node 22, ubuntu-latest) and Test (Node 24, ubuntu-latest))
Require branches to be up to date ✅ enabled
Require conversation resolution ✅ enabled
Require linear history ✅ enabled
Do not allow bypassing the above settings ✅ enabled

To configure via the GitHub CLI:

gh api repos/{owner}/{repo}/branches/main/protection \
  --method PUT \
  --field required_status_checks='{"strict":true,"checks":[{"context":"Lint & Format"},{"context":"Typecheck"},{"context":"Build"},{"context":"Test (Node 22, ubuntu-latest)"},{"context":"Test (Node 24, ubuntu-latest)"}]}' \
  --field enforce_admins=true \
  --field required_pull_request_reviews='{"required_approving_review_count":1}' \
  --field restrictions=null

Specifications

See openspec/specs/ for the full OpenSpec specifications:

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选