Skip to content

craft-agent/github-tools

v0.3.1MIT

GitHub tools for coding agents: issues, project boards, pull requests, repositories, releases and Actions.

github-tools

GitHub tools for coding agents: issues, project boards, pull requests, repositories, releases and Actions. One implementation, delivered to each agent harness in the form that suits it best.

HarnessDeliveryPinned by
OpenCode V2native plugin (npm package, with skills)the version in the package
OpenCode V1native plugin (npm package, no skills)the version in the package
Claude Codeplugin: MCP server and skillsthe release tag, as the ref
Codexplugin: MCP server and skillsthe release tag, as the ref
Grok Buildplugin: MCP server and skillsthe release tag, as @ref
Antigravityplugin: MCP server and skillsthe release tag's tree URL
Hermes Agentnative plugin (Python, calls the command line)the release commit, as the SHA
other MCP hostMCP server from npmthe version in the package

0.3.0 moved the package from craftsamo/agent-github to craft-agent/github-tools and renamed it: npm @craftsamo/github-tools (was @craftsamo/agent-github, now removed from npm), plugin and MCP server github-tools, programs github-tools and github-tools-cli, settings GITHUB_TOOLS_*. Allow rules, plugin installs and MCP configurations written for 0.2.0 change; the tool IDs do not.

The tools need Node.js 24 or later and the GitHub CLI, authenticated as you. docs/conventions.md describes how the tools are named and how they behave.

Install

Install from a release, never from the default branch: a release is a tag whose commit carries the built dist/, and the default branch does not. In the commands below, <version> is a release's version (1.2.3) and <sha> is the commit its tag names:

gh api repos/craft-agent/github-tools/commits/v<version> --jq .sha

OpenCode

OpenCode V2 takes the package and its options in opencode.json:

{
  "plugins": [
    {
      "package": "@craftsamo/github-tools@<version>",
      "options": { "toolsets": ["issues", "pull_requests", "projects"] }
    }
  ],
  "permissions": [{ "action": "github_*", "resource": "*", "effect": "ask" }]
}

OpenCode V1 takes the package as a string, or as a pair with its options:

{
  "plugin": [["@craftsamo/github-tools@<version>", { "toolsets": ["issues", "pull_requests", "projects"] }]],
  "permission": { "github_*": "ask" }
}

OpenCode allows any action no rule names, so the plugin's request is granted silently unless a rule says ask. Read tools never ask, so the github_* glob is safe.

V1 registers no skills. Unpack the package and copy its skills/* folders into ~/.config/opencode/skills/:

npm pack @craftsamo/github-tools@<version>
tar -xzf craftsamo-github-tools-<version>.tgz
mkdir -p ~/.config/opencode/skills
cp -r package/skills/* ~/.config/opencode/skills/
rm -rf package craftsamo-github-tools-<version>.tgz

Claude Code

claude plugin marketplace add craft-agent/github-tools#v<version>
claude plugin install github-tools@craft-agent

Codex

codex plugin marketplace add craft-agent/github-tools --ref v<version>
codex plugin add github-tools@craft-agent

Codex turns - into _ in server names, so it shows the tools as mcp__github_tools__github_issue_*. It starts the MCP server in the plugin's install directory, so name issues as owner/repo#N or pass repo (a bare number fails there with a message saying so).

Grok Build

grok plugin install craft-agent/github-tools@v<version> --trust

Grok starts the MCP server in the session's working directory, so inside a clone a bare issue number names an issue of that repository.

Antigravity

Install from the tree of the release tag, never from the default branch, which has no built dist/; Antigravity clones the tag into ~/.gemini/config/plugins/github-tools.

agy plugin install https://github.com/craft-agent/github-tools/tree/v<version>

Hermes Agent

Hermes installs a commit, not a tag, and the plugin installs disabled:

hermes plugins install craft-agent/github-tools --ref <sha>
hermes plugins enable github-tools

If a Hermes gateway is already running, restart it (hermes gateway restart) to load the plugin.

Any other MCP host

Add the server to the host's MCP configuration. Flags go in args:

{
  "mcpServers": {
    "github-tools": {
      "command": "npx",
      "args": ["-y", "@craftsamo/github-tools@<version>", "--toolsets", "issues,pull_requests,projects"]
    }
  }
}

Tools and skills

Each toolset comes with a skill that tells an agent how to use its tools. A toolset with no tools yet registers none (so far only issues has tools).

Issues (issues)

ToolWhat it doesClass
github_issue_readview one issue in full, or list a repository's issues or a parent's sub-issuesread
github_issue_createcreate an issue with its kind, labels, assignees, milestone, parent and blocked-by issuesadd
github_issue_editchange the title, body (or append to it), kind, labels, assignees or milestoneoverwrite
github_issue_commentcomment on an issueadd
github_issue_closeclose with a reason (completed, not_planned, duplicate)overwrite
github_issue_reopenreopen a closed issueoverwrite
github_issue_relateset the parent, sub-issues, blocked-by and blocking issues, sending only what differsidempotent
github_issue_developcreate a branch on GitHub linked to the issue, or return the one already linkedidempotent

The skill is github-issues, shown as github-tools:github-issues in Claude Code and github-tools:issues in Hermes. An issue's kind is the organization's Issue Type of that name when it defines one, otherwise a type:<kind> label.

Reads and writes

Every read tool is named github_<domain>_read. Reads can run unasked; writes are confirmed by the harness.

HarnessReads without asking
OpenCodealways; the plugin asks only before a write
Claude Codethe rule mcp__plugin_github-tools_github-tools__*_read in permissions.allow of ~/.claude/settings.json or a project
Codexalways; Codex runs tools that declare readOnlyHint unasked, as the read tools do
Grok Buildgrok --allow 'MCPTool(github-tools__*_read)'
Antigravitythe rule mcp(github-tools_github-tools/github_issue_read) in permissions.allow of ~/.gemini/antigravity-cli/settings.json, one for each read tool
Hermesalways; the plugin asks only before a write

Where a write is asked about, and where it is not:

  • OpenCode grants any action no rule names, so a write runs unasked unless a rule asks for it: add the github_* rule shown under OpenCode.
  • Codex under codex exec, and Grok Build under grok -p, refuse a write they cannot ask about, unless it is allowed beforehand.
  • Antigravity asks before any MCP tool no rule allows, reads included, and names the plugin's server github-tools_github-tools (plugin, then server). agy -p refuses a tool it cannot ask about; --dangerously-skip-permissions runs every tool unasked.
  • Hermes hermes chat -q refuses a write it cannot ask about; hermes -z and --yolo skip approval, so writes then run unasked.

Settings

Every entry point takes the same settings. A flag wins over its environment variable, and an option or setting wins over the variable too.

SettingFlagVariableMeaning
toolsets--toolsetsGITHUB_TOOLS_TOOLSETSissues, pull_requests, projects, repos, releases, actions or all; default issues and pull_requests
read_only--read-onlyGITHUB_TOOLS_READ_ONLYregisters no tool that writes; wins over every other setting
tools--toolsGITHUB_TOOLS_TOOLSsingle tools to add by ID, whatever their toolset
exclude_tools--exclude-toolsGITHUB_TOOLS_EXCLUDE_TOOLSsingle tools to remove by ID; wins over tools and toolsets
confirm--confirmGITHUB_TOOLS_CONFIRMMCP server only: harness (default) or elicitation, as docs/conventions.md describes

Lists are comma-separated in a flag or a variable. GitHub Actions does not let a secret or configuration variable be named GITHUB_*, so in a workflow pass a value through env: from a secret of another name, e.g. GITHUB_TOOLS_READ_ONLY: ${{ secrets.TOOLS_READ_ONLY }} (setting such an environment variable in env: is allowed). Where each harness reads them:

  • OpenCode takes the plugin options shown above, with lists as arrays and read_only as a boolean.

  • Hermes takes plugins.entries.github-tools.settings in config.yaml:

    plugins:
      entries:
        github-tools:
          settings:
            toolsets: [issues, pull_requests, projects]
            read_only: false
            exclude_tools: [github_pr_merge]
    
  • Claude Code and Antigravity start the plugin's server without flags and pass it the client's environment, so set the variables in the environment the harness runs in.

  • Codex and Grok Build pass no environment to a plugin's MCP server, so the GITHUB_TOOLS_* variables have no effect there. To change settings in Codex, add the server under [mcp_servers] in Codex's config with flags in args (as in Any other MCP host) instead of using the plugin.

Layout

  • src/core/ — the tools, free of any harness.
  • src/mcp/ — the MCP server, built to dist/mcp.js and run by github-tools.
  • src/opencode/ — the OpenCode plugin, built to dist/opencode.js.
  • src/cli/ — the command line the Hermes plugin calls, built to dist/cli.js and run by github-tools-cli.
  • src/hermes/, plugin.yaml and __init__.py — the Hermes plugin.
  • skills/ — one skill per toolset, skills/<name>/SKILL.md, which every harness that takes skills loads from the package or plugin root.
  • plugin.json, mcp.json, .mcp.json, .claude-plugin/, .agents/plugins/, .antigravity-plugin/ and mcp_config.json — the plugin manifests of the other harnesses. The root .mcp.json is the configuration Grok Build reads (with ${CLAUDE_PLUGIN_ROOT}, the variable both Grok Build and Claude Code expand); when working on this repository in Claude Code, decline the project MCP server it offers from that file.

How a release is made is in RELEASING.md.

License

MIT