DeepSeek Harness Plugin

JohnXu22786/github-mcp

Stars ★ 0 Category Tools & Capabilities Added 2026-08-16

GitHub workbench MCP server (dsh bundle): 23 MCP tools for repos, issues, PRs, code review, and search, with zero runtime dependencies and PAT/OAuth auth.

Install

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:JohnXu22786/github-mcp

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).

README

简体中文

repogate — GitHub Developer Workbench (agent tool set)

repogate is a GitHub workbench for coding agents: it wraps the GitHub REST API into a set of MCP (Model Context Protocol) tools, letting agents perform repo queries, issue management, PR creation and merging, code review, search, and other common operations directly in a conversation.

  • Zero runtime dependencies: uses only built-in Node.js capabilities (fetch, node:test); no packages need to be installed to run;
  • Standard MCP stdio server: works with any MCP-capable client (dsh, Claude Code, Codex, opencode, etc.);
  • Built for dsh: ships a dsh bundle (cordis.patch.yml + a self-developed bridge plugin), connected with dsh plugin add in one step — tools appear automatically in the model's tool list (mcp__repogate__*);
  • Dual auth channels: personal access token (PAT) and OAuth device authorization flow, with local token caching;
  • Read-only mode: blocks all write operations with one switch, ideal for research-only sessions;
  • Actionable errors: rate limits, invalid tokens, insufficient permissions, rejected parameters — every error includes a Chinese fix guide;
  • Slim output for models: lists/search return concise summaries instead of full JSON, saving context tokens.

Quick Start

Option A: connect directly from any MCP client

# requires Node.js ≥ 18.17
REPOGATE_TOKEN=ghp_yourtoken node src/entry.js

Example config line using the official dsh bridge (also works in Claude Code / Codex MCP configs):

# dsh: insert into $DSH_HOME/profiles/<profile>/cordis.patch.yml
- insert:
    - id: mcp-repogate
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: repogate
        transport: stdio
        command: node
        args: ['/absolute/path/to/src/entry.js']
        env:
          REPOGATE_TOKEN: !!js process.env.REPOGATE_TOKEN ?? ''

After connecting, the model sees 23 tools such as gh_issue_fetch and gh_pr_merge (generic MCP clients see bare names; under dsh they carry the mcp__repogate__ prefix, see below).

Option B: install as a dsh plugin bundle (recommended)

This plugin is declared as a dsh bundle (the dsh.bundle field in package.json). In the plugin checkout directory run:

dsh plugin --profile web add .
  • On first use it initializes the web profile automatically and adds this package to dsh.profile.bundles;
  • The repogate/bridge plugin defined in the package's cordis.patch.yml launches this MCP server directly inside the dsh process, and after the handshake registers all tools into ctx.toolsno manual config changes needed;
  • The token is inherited from the dsh process environment by default (REPOGATE_TOKEN or GITHUB_TOKEN);
  • Uninstall: dsh plugin --profile web remove repogate.

After installing, restart dsh and simply say in a session:

"Look at the open issues of the octo/hello repo, close #12, then comment 'fixed, waiting for verification' on #12."

The corresponding tool call chain: mcp__repogate__gh_issue_browsemcp__repogate__gh_issue_fetchmcp__repogate__gh_issue_editmcp__repogate__gh_issue_respond.

Note: dsh does not enable any MCP server by default (each server command is trusted code executed outside the sandbox); this plugin's bundle line is the "enable" action itself; only install trusted plugins.


Installing in DSH

dsh plugin --profile demo add github:JohnXu22786/github-mcp

A single command installs this plugin into the dsh demo profile from the GitHub repository. Integration, auth, and lifecycle details follow in the "dsh integration" section below.


dsh Integration (how a plugin-style harness loads it)

dsh uses the Cordis plugin framework; the unit of composition is a bundle: an npm package + a patch layer. The loading chain is as follows:

package.json (dsh.bundle.patch → ./cordis.patch.yml)
  └─ a line in cordis.patch.yml: name: 'repogate/bridge'
       └─ src/bridge/plugin.js (Cordis plugin, inject: ['tools'])
            ├─ spawns src/entry.js (the MCP server child process, stdio) using Node itself
            ├─ completes the initialize / tools/list handshake
            └─ registers each tool as mcp__repogate__<tool name> into ctx.tools
  • Tool interface: the tool name visible to the model = mcp__<serverName>__<original tool name>, serverName defaults to repogate;
  • Events/skills: this plugin registers no events or skills; it only exposes capabilities through the ctx.tools tool interface;
  • Lifecycle: handshake and registration happen during the plugin's apply; on unload it kills the child process and unregisters all tools automatically (cleanup registered via ctx.effect, so hot reloads/unloads leave no residue);
  • Two bridges to choose from: the bundle's built-in bridge repogate/bridge (zero dependencies, works out of the box) and the official dsh @deepseek-ai/dsh-mcp-client config line (see examples/overlay-for-dsh.yml.example); the tools are named and behave identically — pick either one, do not enable both;
  • Environment variables: dsh filters credential-type variables from the MCP child process environment, so the official bridge line needs the token written into the env config; the built-in bridge's child process inherits the host environment, so REPOGATE_TOKEN is passed through automatically.

Common dsh issues

Symptom Treatment
Tools don't appear in the list Check whether the cordis.patch.yml line took effect (dsh --profile <name> --dump-config to inspect layers), confirm no errors in the startup log
401 invalid token Check the env.REPOGATE_TOKEN config; or ask the model to call mcp__repogate__gh_auth_login in the session to use OAuth
Want read-only Configure args: ['--read-only'] on the bridge line, or append --read-only to the official line's args
pnpm ≥10 rejects prepare scripts on git installs This plugin is pure JS with no build script, so it's not affected; install from checkout or tarball

Tool List (23 tools)

Domain Tool Purpose Write op
Repo gh_repo_fetch Repo details: default branch, stars, language, visibility
Repo gh_repo_browse List user/org/own repos (paginated)
Issue gh_issue_open Create an issue (title required, optional labels/assignee)
Issue gh_issue_fetch View full issue info
Issue gh_issue_browse Filter by state/labels/assignee/author (pages may exclude PRs)
Issue gh_issue_edit Edit title/body/state/assignee/labels
Issue gh_issue_respond Post a comment (works in PR threads too)
PR gh_pr_open Create a pull request (head/base/draft)
PR gh_pr_fetch PR details: mergeability, changed stats, review count
PR gh_pr_browse Filter by state/branch, sort, paginate
PR gh_pr_edit Edit title/body/state/draft/base branch
PR gh_pr_merge Merge (method/commit message/delete source branch)
Review gh_review_submit Submit a full review: approve / request_changes / comment
Review gh_review_comment Line-level diff comments (including range comments)
Review gh_review_fetch List all line-level comments
Review gh_review_browse List submitted full reviews
Search gh_search_repos Search repos with GitHub search syntax
Search gh_search_issues Search issues/PRs (type:pr distinguishes)
Search gh_search_code Search code (requires token, returns file hits)
Account gh_whoami Current identity, token source, read-only mode, API quota
Auth gh_auth_login Start OAuth device authorization (requires configured clientId)
Auth gh_auth_check Poll authorization result once
Auth gh_auth_logout Clear the local token cache

All tools take JSON Schema inputs (name/description/inputSchema) that models can discover on their own; write tools are intercepted with a clear message in read-only mode.


Configuration

Priority: CLI flags > environment variables > config file > defaults. The config file is JSON, its path given by --config or REPOGATE_CONFIG; see examples/repogate.config.json.example.

Config item Environment variable Default
Access token REPOGATE_TOKEN (also accepts GITHUB_TOKEN / GH_TOKEN) none
API base URL (enterprise instances) REPOGATE_BASE_URL https://api.github.com
Read-only mode REPOGATE_READ_ONLY (1/true/yes/on) false
Per-request timeout (ms) REPOGATE_TIMEOUT_MS 30000
OAuth Client ID REPOGATE_OAUTH_CLIENT_ID none
OAuth token cache file REPOGATE_TOKEN_FILE ~/.repogate/token.json when oauth.clientId is configured
Config file path REPOGATE_CONFIG none
Debug logging (stderr) REPOGATE_DEBUG false

CLI flags: --config --token --read-only --base-url --timeout-ms --oauth-client-id --token-file --debug --version --help.


Authentication

Personal access token (PAT)

Generate one in GitHub's Developer settings (check the repo permissions needed on a fine-grained token), then choose any of:

REPOGATE_TOKEN=ghp_xxx node src/entry.js          # environment variable
node src/entry.js --token ghp_xxx                 # CLI flag
node src/entry.js --config repogate.config.json   # config file (token field)

Token resolution order: --token > REPOGATE_TOKEN > GITHUB_TOKEN > GH_TOKEN > config file > cache file.

OAuth device authorization (token-free interactive login)

For those who'd rather not assemble a token by hand. You first need a GitHub App's Client ID (the device flow only requires a public client_id):

  1. Configure oauth.clientId (config file or REPOGATE_OAUTH_CLIENT_ID);
  2. Ask the model to call gh_auth_login → returns an authorization URL and a one-time code;
  3. The user opens the URL in a browser, enters the code, and confirms;
  4. The model calls gh_auth_check (may be called multiple times; each call checks once) → once granted, the token is written to the cache file, and all tools become available; the cached token survives process restarts;
  5. gh_auth_logout clears the cache.

Note: the device authorization endpoint always uses github.com; for enterprise instances (custom baseUrl) use a PAT. The token cache file is written with 0600 permissions; do not commit the cache file to version control.


Read-only Mode

node src/entry.js --read-only          # or REPOGATE_READ_ONLY=1

When enabled, the 8 write tools (gh_issue_open / gh_issue_edit / gh_issue_respond / gh_pr_open / gh_pr_edit / gh_pr_merge / gh_review_submit / gh_review_comment) are intercepted after argument validation and return a [readonly] error explaining how to turn it off; query, search, and auth tools are unaffected.


Error Handling

All failures are returned as structured errors (MCP isError: true + structuredContent.error) in the form [error code] reason. Common error codes and typical scenarios:

Error code Scenario Guide
auth Token missing/invalid (401) Configure a token or use OAuth device authorization
ratelimit Quota exhausted (403/429) Report reset time or Retry-After seconds
http 404/403/422/409 etc. Explain the specific cause (not found/no permission/params rejected/conflict)
validation Argument validation failed Point out which argument is invalid
readonly Read-only mode blocks a write Explain how to disable
timeout Request timeout Suggest increasing timeoutMs
network Network-layer failure Check the network and baseUrl

The gateway automatically retries once on 502/503/504 and network jitter (idempotent read requests only; writes are not retried to avoid duplicate side effects); if a 5xx still fails after retry, it returns an http error instead of failing silently.


Architecture and Layout

src/
├── entry.js              entry: config parsing → assembly → start the stdio session
├── protocol/             protocol layer (MCP over stdio, line-delimited JSON-RPC 2.0)
│   ├── jsonrpc.js        message encoding/decoding and classification
│   ├── transport.js      stdin/stdout read/write loop (logs go to stderr only)
│   └── engine.js         session engine: initialize / ping / tools/list / tools/call
├── core/                 core layer
│   ├── config.js         layered config merge (flag > env > config file > defaults)
│   ├── auth.js           credential hub: token resolution + OAuth device auth state machine + cache
│   ├── gateway.js        REST gateway: request assembly/retry/timeout/status-code mapping
│   └── errors.js         unified error model with actionable hints
├── tools/                tool layer
│   ├── registry.js       registry: argument validation (JSON Schema subset) + read-only gate + dispatch
│   ├── repo.js / issue.js / pull.js / review.js / search.js / account.js
│   └── index.js          assembles the 23 tools
├── bridge/               dsh integration
│   ├── client.js         MCP stdio client (initialize/list/call, cancellation and timeout)
│   └── plugin.js         Cordis plugin: spawns the server and registers tools into ctx.tools
└── util/format.js        output shaping: entity summaries, pagination detection, URL building

test/                     tests (node:test, zero dependencies)
├── helpers/              fake fetch and a local mock API service
└── *.test.js             protocol/gateway/config/auth/registry/tool/end-to-end (121 test cases)

Design highlights:

  • Layered one-way dependencies: protocol layer → core layer → tool layer; tools don't know protocol details, and the protocol doesn't know API details;
  • On-demand token resolution: OAuth authorization takes effect after completion without restart (the gateway holds a tokenResolver rather than a static token);
  • One codebase, both ends: bridge/client.js and the server share the same JSON-RPC vocabulary, so handshake and call logic are consistent.

Development and Testing

node --test          # run all 121 tests (including real child-process end-to-end)
node src/entry.js --help

Test coverage: protocol handshake and error paths (including interception of uninitialized sessions), gateway retry (idempotent methods only) and status-code mapping, the full OAuth state machine (including expiry), config priority, argument validation, the read-only gate, request construction and output shaping for all 23 tools, and an end-to-end chain of "real child process + local mock API".

Security Notes

  • A token has the same power as the account; do not write it into logs, commit it to version control, or leak it to untrusted conversations;
  • Under dsh, MCP server commands are trusted code outside the sandbox; install this plugin only from trusted sources;
  • Read-only mode significantly reduces the risk of misuse; research-only sessions are recommended to enable it.

License

MIT

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →