Skip to content

Latest commit

 

History

History
983 lines (766 loc) · 41.1 KB

File metadata and controls

983 lines (766 loc) · 41.1 KB

MCP tools (canonical reference)

Single source of truth for registered tool ids, parameters, JSON output shapes, error codes, and idempotency. Install and MCP clients: install.md. Operator guide: HUMANS.md. Implementation map: AGENTS.md.

Naming

MCP clients expose tools as {serverName}_{toolName}. With the server registered as rethunk-github, examples use the prefix rethunk-github_.

Tools

Short id Client id (server rethunk-github) Mode Purpose
repo_status rethunk-github_repo_status read Multi-repo dashboard: default branch HEAD, CI, open PRs/issues, latest commit. Up to 64 repos per call; omit repos to use the active MCP workspace root.
my_work rethunk-github_my_work read Cross-repo personal queue: authored PRs, review requests, assigned issues. blockedOnMe lens for action items.
pr_preflight rethunk-github_pr_preflight read Pre-merge safety check: mergeability, reviews, CI, behind-base count, commit granularity, and computed safe verdict.
pr_comment_batch rethunk-github_pr_comment_batch write Submit a single PR review with inline comments in one API call.
pr_create rethunk-github_pr_create write Create a pull request from an existing head branch.
issue_from_template rethunk-github_issue_from_template write Create an issue by rendering a repository issue template.
release_readiness rethunk-github_release_readiness read What would ship if we release now? Unreleased commits, PR metadata, CI on head, diff stats, and release-asset checksum coverage when applicable.
release_create rethunk-github_release_create write Create a GitHub release with optional GitHub-generated notes.
ci_diagnosis rethunk-github_ci_diagnosis read Why is CI red? Resolves the failed run, extracts failed job logs, shows trigger commit.
org_pulse rethunk-github_org_pulse read Org-wide dashboard: failing CI, stale PRs, unreviewed PRs across recently active repos.
pin_drift rethunk-github_pin_drift read Audit upstream dependency pins in a local repo. Defaults to the active MCP workspace root; accepts glob patterns for pinFiles.
ecosystem_activity rethunk-github_ecosystem_activity read Chronological commit feed across multiple repos since a given timestamp or relative duration.
module_pin_hint rethunk-github_module_pin_hint read Return the Go pseudo-version string (v0.0.0-YYYYMMDDHHMMSS-sha12) for any repo ref.
changelog_draft rethunk-github_changelog_draft read Draft a CHANGELOG.md section for unreleased commits, grouped by PR metadata.
workflow_dispatch rethunk-github_workflow_dispatch write Trigger a GitHub Actions workflow_dispatch event.
gh_auth_status rethunk-github_gh_auth_status read Check whether the server currently has usable GitHub credentials.
actions_runs_filter rethunk-github_actions_runs_filter read List and filter GitHub Actions workflow runs.
labels_sync rethunk-github_labels_sync write Converge a repository's labels to a declared set.
check_run_create rethunk-github_check_run_create write Publish a synthetic GitHub check run against a commit SHA.
security_alerts rethunk-github_security_alerts read Roll up Dependabot and Code Scanning alerts by severity. Requires security_events scope (or repo).
pr_review_thread_ops rethunk-github_pr_review_thread_ops write List, resolve, or unresolve PR review threads. Requires PR write (repo / pull_requests:write).
branch_protection_status rethunk-github_branch_protection_status read Check branch protection rules for a repository branch. Requires branch-protection read (admin or repo).
deployment_status rethunk-github_deployment_status read Check deployment status and latest state per environment. Requires deployments read (repo).
issue_dedup rethunk-github_issue_dedup read Find likely-duplicate issues by title similarity before opening a new one. Requires issues read (repo).

Output and mutation model

  • Read-only rollup tools with format support default to JSON and accept format: "markdown" for human-readable output.
  • gh_auth_status is read-only and always returns compact JSON.
  • Write-capable tools always return compact JSON. labels_sync, release_create, workflow_dispatch, pr_create, pr_comment_batch, check_run_create, issue_from_template, and pr_review_thread_ops accept dryRun to compute and return the planned action without mutating GitHub state. pr_create, pr_comment_batch, check_run_create, and issue_from_template return { dryRun: true, plan: { ... } } where plan contains the resolved parameters. pr_review_thread_ops returns { dryRun: true, action, targetThreadIds }.
  • repo_status and org_pulse accept compact: true for a condensed summary (counts and top highlights) instead of full per-item detail.
  • actions_runs_filter, ecosystem_activity, and changelog_draft emit truncatedCount when results are capped by the limit parameter (matches release_readiness behaviour).

Workspace root resolution

The server advertises MCP roots support and reads file:// roots from the client at runtime. Local-repository read tools normalize the selected root to its git toplevel, so a single globally installed server follows the project opened in VS Code, Claude Code, Cursor, or any roots-capable MCP client.

This default applies to repo_status, pr_preflight, pin_drift, and ecosystem_activity. Explicit arguments still win: pass localPath or repos when you want a target other than the active workspace.

JSON responses

Payloads are minified (JSON.stringify, no pretty-print). MCP_JSON_FORMAT_VERSION is "2". Optional fields are omitted when empty/null.

Error envelope

Tool-level failures return a top-level error object:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "PR Rethunk-AI/github-mcp#42 not found.",
    "retryable": false,
    "suggestedFix": "Verify the PR number."  // optional
  }
}

Per-item failures (inside arrays like repos[] or pins[]) follow the same envelope shape in the item's error field. The batch does not fail as a whole when a per-item failure occurs.

Agents can decide programmatically whether to retry (e.g. exponential backoff on retryable: true) vs. surface the problem to the user (retryable: false).

Error codes

Code Meaning Retryable
AUTH_MISSING No GITHUB_TOKEN/GH_TOKEN and gh auth token failed. no
AUTH_FAILED GitHub rejected the token (HTTP 401). no
NOT_FOUND Repository, PR, org, ref, or workflow run does not exist (HTTP 404). no
PERMISSION_DENIED Token lacks scopes or repo access (HTTP 403, not rate limit). no
RATE_LIMITED GitHub rate limit exhausted (HTTP 403 + x-ratelimit-remaining: 0). suggestedFix includes the reset time. yes
VALIDATION Request failed GitHub's input validation (HTTP 422). no
UPSTREAM_FAILURE GitHub 5xx or GraphQL-level error. yes
NO_CI_RUNS No workflow runs found for the given ref/PR (ci_diagnosis). no
COMPARE_FAILED Reserved: base...head comparison failure distinct from a 404. no
LOCAL_REPO_NO_REMOTE Local path has no resolvable GitHub origin remote. no
UNSUPPORTED_LANGUAGE module_pin_hint was called with a language other than "go". no
AMBIGUOUS_REPO Reserved: pin source does not encode which GitHub repo a value belongs to. no
INTERNAL Unrecognized/unexpected failure. no

Idempotency

  • Read-only tools are idempotent.
  • labels_sync is convergent: repeating the same desired label set should produce the same repository label state.
  • workflow_dispatch, check_run_create, issue_from_template, pr_create, pr_comment_batch, and release_create are not idempotent. Retrying may create additional GitHub state or fail validation because state already exists.

Tool details

repo_status

Parameters:

Name Type Required Default Description
repos (RepoRef | LocalPath)[] no active workspace root 1–64 repos. Each is { owner, repo } or { localPath }.
format "markdown" | "json" no "json" Output format.
compact boolean no false Return a condensed summary (counts + top highlights) instead of full per-repo detail.

JSON output:

{
  "repos": [{
    "owner": "org",
    "repo": "name",
    "defaultBranch": "main",
    "latestCommit": { "sha7": "abc1234", "message": "Fix bug", "author": "alice", "date": "2h ago" },
    "ci": { "status": "success", "failedChecks": [/* only if failing */] },
    "openPRs": 3,
    "draftPRs": 1,
    "openIssues": 12,
    "local": { "branch": "feature", "dirty": 2, "ahead": 1, "behind": 0 }
    // "error": { "code": "NOT_FOUND", "message": "...", "retryable": false }
    //   — on per-repo failure (does not fail the batch)
  }]
}

When localPath is given, the tool resolves the GitHub remote from git remote get-url origin and includes the local object with branch/dirty/ahead/behind.


my_work

Parameters:

Name Type Required Default Description
username string no authenticated user GitHub username to query. Must match ^[A-Za-z0-9-]+$; other values return a VALIDATION error.
maxResults int no 30 1–100 results per section.
blockedOnMe boolean no false When true, filters to items needing your immediate action: authored PRs with CI failure or changes requested, plus all pending review requests.
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "username": "alice",
  "authoredPrs": [{ "repo": "org/name", "number": 42, "title": "...", "draft": false, "ci": "SUCCESS", "reviewDecision": "APPROVED", "updatedAt": "..." }],
  "reviewRequests": [{ "repo": "org/name", "number": 45, "title": "...", "author": "bob", "updatedAt": "..." }],
  "assignedIssues": [{ "repo": "org/name", "number": 99, "title": "...", "labels": ["bug"], "updatedAt": "..." }]
}

pr_preflight

Parameters:

Name Type Required Default Description
owner string no active workspace root GitHub owner/org. Not required when localPath or workspace roots are available.
repo string no active workspace root Repository name. Not required when localPath or workspace roots are available.
localPath string no active workspace root Local clone path; auto-detects owner/repo from git remote get-url origin.
number int no Single PR number.
numbers int[] no Batch of PR numbers to check in one call (alternative to number).
ref string no PR number, GitHub PR URL, or owner/repo#N slug (alternative to number).
includeLogs boolean no false When true, also fetches truncated CI logs for failing jobs — combining preflight + diagnosis in one call.
maxLogLines int no 50 10–500 log lines per failing job when includeLogs is true.
format "markdown" | "json" no "json" Output format.

Exactly one of number, numbers, or ref must be given; numbers accepts 1–20 entries and is processed with concurrency 4.

JSON output:

{
  "number": 42,
  "title": "Fix auth bug",
  "safe": false,
  "reasons": ["CI failing: test-unit", "3 commits behind main"],
  "mergeable": "MERGEABLE",
  "reviewDecision": "APPROVED",
  "reviews": [{ "author": "alice", "state": "APPROVED" }],
  "pendingReviewers": ["charlie"],
  "ci": {
    "status": "FAILURE",
    "checks": [{ "name": "test-unit", "conclusion": "FAILURE", "status": "COMPLETED" }]
  },
  "behindBase": 3,
  "labels": ["bug"],
  "conflicts": false,
  "commitGranularity": {
    "verdict": "warn",
    "details": "1 of 4 commits are over-bundled (>15 files).",
    "oversizedCommits": [{ "sha": "abc1234", "message": "feat: refactor everything", "filesChanged": 29 }]
  },
  "failingLogs": [{ "job": "test-unit", "log": "..." }]
}

The safe boolean is computed from: PR must be open, not a draft, no conflicts, approved or no required reviews, CI passing, no pending checks.

reasons lists all blockers and warnings. Warnings (e.g. behind base) do not set safe: false by themselves.


release_readiness

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
base string no latest semver tag Base ref to compare from (e.g. v1.2.0). Omit to auto-pick the latest semver tag.
head string no default branch Head ref to compare to.
maxCommits int no 50 1–200 commits.
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "base": "v1.2.0",
  "head": "main",
  "aheadBy": 15,
  "truncatedCount": 0,        // commits not shown when the list is capped (omitted when 0)
  "headCi": { "status": "success", "failedChecks": [] },
  "commits": [{
    "sha7": "abc1234",
    "message": "Fix auth bug",
    "author": "alice",
    "date": "2025-04-10T12:00:00Z",
    "pr": { "number": 42, "title": "Fix auth bug", "labels": ["bug"] }
  }],
  "stats": { "additions": 1234, "deletions": 567, "changedFiles": 23 },
  "artifactIntegrity": {
    "verdict": "ok",
    "details": "All assets covered by checksum file",
    "missingFromChecksum": [],
    "checksumAsset": "SHA256SUMS"
  }
}

PR associations are extracted from commit message (#123) patterns, then resolved via GraphQL in batches of 20. When base resolves to a GitHub release tag, the tool also checks whether that release's checksum asset covers the other uploaded artifacts. truncatedCount is set (and commits is shorter than aheadBy) when the compared range exceeds the GitHub compare-endpoint cap or maxCommits.


ci_diagnosis

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
ref string no Branch or SHA. Finds latest run for this ref.
prNumber int no PR number. Alternative to ref.
runId int no Specific run ID. Highest priority.
maxLogLines int no 50 10–500 lines of log output per job.
grepLog string no Regex applied to each log; only matching lines are returned.
format "markdown" | "json" no "json" Output format.

Run resolution priority: runId > prNumber > ref > latest failed run on default branch.

JSON output:

{
  "runId": 12345,
  "workflow": "CI",
  "conclusion": "failure",
  "branch": "main",
  "url": "https://github.com/org/repo/actions/runs/12345",
  "triggerCommit": { "sha7": "abc1234", "message": "Bump deps", "author": "alice" },
  "failedJobs": [{
    "name": "build",
    "conclusion": "failure",
    "failedSteps": [{ "name": "logs", "log": "... [last 150 lines] ..." }]
  }]
}

Logs are tail-truncated (last N lines kept) since failure output is at the bottom.


org_pulse

Parameters:

Name Type Required Default Description
org string yes GitHub organization login.
maxRepos int no 30 1–100 repos (ordered by most recently pushed).
staleDays int no 7 Days without activity before a PR is stale.
includeArchived boolean no false Include archived repositories.
format "markdown" | "json" no "json" Output format.
compact boolean no false Return a condensed summary (counts + top highlights) instead of full per-repo detail.

JSON output:

{
  "org": "my-org",
  "scannedRepos": 30,
  "summary": {
    "failingCI": 2,
    "stalePRs": 5,
    "unreviewedPRs": 3,
    "totalOpenPRs": 18,
    "totalOpenIssues": 42
  },
  "attention": [{
    "repo": "my-org/api",
    "ci": "failure",
    "openPRs": 4,
    "openIssues": 8,
    "stalePRs": [{ "number": 12, "title": "...", "author": "bob", "daysSinceUpdate": 14 }],
    "unreviewedPRs": [{ "number": 15, "title": "...", "author": "alice" }],
    "lastPush": "2025-04-09T08:00:00Z"
  }]
}

The attention array is sorted by urgency: failing CI repos first, then by stale PR count. Healthy repos (no failing CI, no stale/unreviewed PRs) are listed only in markdown mode.


pin_drift

Parameters:

Name Type Required Default Description
localPath string no active workspace root Local repo whose dependency pins to audit.
pinFiles string[] no auto-detect Files to parse. Accepts glob patterns (e.g. **/go.mod). Auto-detection tries: go.mod, .gitmodules, scripts/versions.env, package.json.
ownerAllowlist string[] no Only audit pins whose GitHub owner matches one of these values (case-insensitive). Useful to skip third-party upstreams.
grep string no Regex filter: only commits whose message matches are counted in grepMatches. All commits still count toward behindBy.
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "localPath": "/home/me/myapp",
  "pins": [{
    "source": "go.mod",
    "owner": "Rethunk-Tech",
    "repo": "bastion-satcom",
    "pinnedRef": "877f8d94448e",
    "pinnedDate": "2026-04-11T12:22:16Z",
    "defaultBranch": "main",
    "headSha": "6589cad7c93e5fd59ece17284b4636c525bf8cf0",
    "behindBy": 17,
    "grepMatches": 3,           // only when grep supplied
    "commits": [{ "sha7": "abc1234", "message": "Fix bug", "author": "alice", "date": "2026-04-12T..." }],
    "stale": true
  }],
  "skipped": [{
    "source": "scripts/versions.env",
    "key": "BASTION_SATCOM_REF",
    "value": "877f8d94448e8cc843e83409dd0a59bb73562e45",
    "reason": "ambiguous_repo"
  }],
  "summary": { "totalPins": 4, "stale": 2, "upToDate": 2 }
}

Pin source notes:

  • go.mod: handles replace directives and require lines with pseudo-versions (v0.0.0-YYYYMMDDHHMMSS-sha12). The 12-char SHA prefix is resolved to a full SHA via the GitHub API.
  • .gitmodules: reads submodule paths + URLs, uses git ls-tree HEAD <path> to obtain the pinned commit SHA.
  • scripts/versions.env: shell KEY=VALUE lines whose key ends in _REF, _SHA, or _VERSION and whose value is a 40-char hex SHA. These are always reported under skipped with reason: "ambiguous_repo" because the file does not encode which GitHub repo each key belongs to.
  • package.json: dependencies/devDependencies whose version is a GitHub shorthand (owner/repo#ref) or HTTPS GitHub URL.

behindBy: -1 signals an error resolving that pin. When this happens the pin entry also carries an error: { code, message, retryable, suggestedFix? } field explaining why (e.g. NOT_FOUND, RATE_LIMITED, UPSTREAM_FAILURE).

skipped[].reason remains a free-text parser-level code (ambiguous_repo, ambiguous_ref, not_github, ls_tree_no_sha, ls_tree_failed) — it describes a pin that couldn't be parsed at all, not a GitHub-side error.


ecosystem_activity

Parameters:

Name Type Required Default Description
repos (RepoRef | LocalPath)[] no active workspace root 1–64 repos. Each is { owner, repo } or { localPath }.
since string yes ISO8601 timestamp or relative duration: "48h", "7d".
paths string[] no Filter to commits touching these paths (applied per repo via GraphQL history(path:...)). Multiple paths are OR'd together.
grep string no Regex filter applied client-side to commit message subjects.
maxCommitsPerRepo int no 50 1–200 commits fetched per repo before merge.
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "since": "2026-04-10T17:19:40Z",
  "repos": [
    { "owner": "Rethunk-Tech", "repo": "bastion-satcom", "commitCount": 12 },
    {
      "owner": "Rethunk-AI",
      "repo": "some-lib",
      "commitCount": 0,
      "error": { "code": "NOT_FOUND", "message": "...", "retryable": false }
    }
  ],
  "commits": [{
    "owner": "Rethunk-Tech",
    "repo": "bastion-satcom",
    "sha7": "abc1234",
    "message": "Fix SATCOM reconnect",
    "author": "alice",
    "date": "2026-04-12T08:00:00Z",
    "pr": { "number": 42, "title": "Fix SATCOM reconnect" }  // null when no (#N) in message
  }],  // merged + sorted date desc
  "summary": {
    "totalCommits": 47,
    "repoBreakdown": { "bastion-satcom": 12, "some-lib": 35 }
  },
  "truncatedCount": 5   // omitted when 0; commits beyond maxCommitsPerRepo that were not returned
}

Commits are merged across repos and sorted newest-first. Per-repo errors do not fail the batch.


module_pin_hint

Parameters:

Name Type Required Default Description
owner string yes GitHub owner or organization.
repo string yes GitHub repository name.
ref string no default branch HEAD Branch, tag, or SHA to resolve.
language string no "go" Module system. Only "go" is supported in MVP.
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "owner": "Rethunk-Tech",
  "repo": "bastion-satcom",
  "ref": "main",
  "resolvedSha": "6589cad7c93e5fd59ece17284b4636c525bf8cf0",
  "committerDate": "2026-04-13T00:17:01Z",
  "goPseudoVersion": "v0.0.0-20260413001701-6589cad7c93e"
}

The pseudo-version is formatted as v0.0.0-YYYYMMDDHHMMSS-<first12SHAchars> using the committer date in UTC. Use this when pinning a module in go.mod via a SHA rather than a release tag.


changelog_draft

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
base string no latest semver tag Base ref (tag/branch). Omit to auto-pick the latest semver tag.
head string no default branch Head ref to compare to.
version string no "Unreleased" Version string for the section header (e.g. "v1.3.0").
maxCommits int no 50 1–200 commits.
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "version": "v1.3.0",
  "date": "2026-04-21",
  "base": "v1.2.0",
  "head": "main",
  "entries": [{
    "sha7": "abc1234",
    "message": "feat: add blockedOnMe lens to my_work",
    "author": "alice",
    "date": "2026-04-20T10:00:00Z",
    "pr": { "number": 42, "title": "feat: add blockedOnMe lens", "labels": ["enhancement"] }
  }],
  "truncatedCount": 3   // omitted when 0; commits beyond maxCommits that were not returned
}

Commits are compared as base...head. PR metadata (title, labels) is resolved via GraphQL for up to 20 PRs. Markdown output is Keep-a-Changelog style, ready to paste into CHANGELOG.md.


pr_comment_batch

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
pullNumber int yes Pull request number.
body string no Overall review body text.
event "COMMENT" | "APPROVE" | "REQUEST_CHANGES" no "COMMENT" Review event type.
comments { path, line, body }[] no Inline comments relative to repository root.
dryRun boolean no false Return the planned review without mutating.

commentsRequested reports the number of inline comments submitted in the request; GitHub's review-creation response does not echo the created comments, so this is the requested count, not a server-confirmed one.

JSON output:

{ "reviewId": 123456, "url": "https://github.com/org/repo/pull/42#pullrequestreview-123456", "state": "COMMENTED", "commentsRequested": 2 }

When dryRun: true:

{ "dryRun": true, "plan": { "owner": "org", "repo": "name", "prNumber": 42, "event": "COMMENT", "commentCount": 2, "comments": [{ "path": "src/foo.ts", "line": 10, "bodySnippet": "..." }] } }

pr_create

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
title string yes Pull request title.
body string no Pull request body.
head string yes Source branch name. The branch must already exist on GitHub.
base string yes Target branch name.
draft boolean no false Create the PR as a draft.
maintainerCanModify boolean no true Allow maintainers to modify the PR branch.
dryRun boolean no false Return the planned creation without mutating.

JSON output:

{ "number": 42, "url": "https://github.com/org/repo/pull/42", "state": "open", "draft": false }

When dryRun: true:

{ "dryRun": true, "plan": { "owner": "org", "repo": "name", "head": "feature/x", "base": "main", "title": "My PR", "draft": false, "bodyPreview": "..." } }

issue_from_template

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
template string yes Template filename or partial match under .github/ISSUE_TEMPLATE.
variables Record<string, unknown> yes Values used to replace {{ key }} (mustache) patterns. The legacy $key form is no longer substituted.
title string yes Issue title.
assignees string[] no Assignee usernames.
labels string[] no Labels to apply.
dryRun boolean no false Fetch and render the template (with variable substitution), then return the planned issue without mutating.

JSON output:

{ "number": 101, "url": "https://github.com/org/repo/issues/101", "title": "Investigate release drift" }

When dryRun: true:

{ "dryRun": true, "plan": { "owner": "org", "repo": "name", "title": "...", "bodyPreview": "...", "labels": ["bug"] } }

Template matching tries exact filename first, then case-insensitive partial matching.


release_create

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
tag string yes Release tag (for example v1.2.3).
name string no tag Release title.
body string no "" Release notes body.
draft boolean no false Create as draft.
prerelease boolean no false Mark as prerelease.
generateNotes boolean no false Ask GitHub to generate release notes.
dryRun boolean no false When true, return the resolved release parameters without creating the release.

JSON output:

{ "url": "https://github.com/org/repo/releases/tag/v1.2.3", "id": 999, "tag": "v1.2.3", "draft": false, "prerelease": false }

When both body and generateNotes are supplied, GitHub-generated notes win and the response carries a warnings array noting that the supplied body was overridden. If a release already exists for tag, the tool returns a VALIDATION error rather than mutating. A dryRun response carries dryRun: true and the parameters that would have been used.


workflow_dispatch

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
workflow string yes Workflow filename (for example ci.yml) or numeric workflow id.
ref string yes Branch or tag to run against.
inputs Record<string, string> no {} Optional workflow input values.
dryRun boolean no false When true, return the resolved dispatch parameters without triggering the workflow.

JSON output:

{ "message": "Workflow 'ci.yml' dispatched successfully on org/repo:main. GitHub returns 204 (no run ID); poll workflow runs to find the dispatched run." }

gh_auth_status

Parameters: none.

JSON output:

{ "authenticated": true, "login": "alice", "scopes": ["repo", "read:org"] }

On missing or invalid auth, the tool returns { "authenticated": false } instead of a top-level error envelope.


actions_runs_filter

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
workflow string no Workflow name substring or id filter.
status "queued" | "in_progress" | "completed" no Filter by run status.
conclusion "success" | "failure" | "cancelled" no Filter by run conclusion.
branch string no Filter by branch name.
limit int no 20 Maximum number of runs to return (1–500, default 20).
format "markdown" | "json" no "json" Output format.

JSON output:

{
  "runs": [{
    "id": 12345,
    "name": "CI",
    "status": "completed",
    "conclusion": "failure",
    "branch": "main",
    "createdAt": "2026-05-01T10:00:00Z",
    "url": "https://github.com/org/repo/actions/runs/12345"
  }],
  "truncatedCount": 12   // omitted when 0; total available minus returned
}

labels_sync

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
labels { name, color, description? }[] yes Desired label set. color may be passed with or without #.
deleteExtra boolean no false Delete labels not present in the declared set.
dryRun boolean no false When true, compute and return the planned create/update/delete set without mutating any label.

JSON output:

{
  "created": ["bug"],
  "updated": ["enhancement"],
  "deleted": ["needs-triage"],
  "skipped": ["docs"],
  "failures": [{ "name": "wontfix", "action": "update", "error": "..." }],  // per-label failures; empty when all succeeded
  "dryRun": true   // present and true only when dryRun was requested
}

The existing label set is fully paginated, so the deleteExtra "extra" computation is correct for repositories with more than 100 labels. Each label operation is applied independently: a partial failure populates failures while completed work still appears in created/updated/deleted — the call never discards successful mutations.


check_run_create

Parameters:

Name Type Required Default Description
owner string yes GitHub owner/org.
repo string yes Repository name.
name string yes Check run name.
headSha string yes Commit SHA to attach the check run to.
status "queued" | "in_progress" | "completed" no "queued" Check run status.
conclusion "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" no Required when status is "completed".
title string no Output title.
summary string no Output summary.
dryRun boolean no false Return the planned check run without mutating.

JSON output:

{ "id": 5555, "url": "https://github.com/org/repo/runs/5555" }

When dryRun: true:

{ "dryRun": true, "plan": { "owner": "org", "repo": "name", "name": "my-check", "headSha": "abc1234", "status": "completed", "conclusion": "success" } }

If status is "completed" without a conclusion, the tool returns a VALIDATION error envelope. The dryRun path applies the same validation before returning.


security_alerts

Parameters:

Name Type Required Default Description
owner string yes GitHub owner or organization.
repo string yes GitHub repository name.
state "open" | "dismissed" | "fixed" | "auto_dismissed" no "open" Alert state to filter by.
severity "critical" | "high" | "medium" | "low" no Filter to a specific severity. Omit to return all severities.
includeDependabot boolean no true Include Dependabot alerts.
includeCodeScanning boolean no true Include Code Scanning alerts.
limit int no 30 Maximum alerts per source (1–100).
format "markdown" | "json" no "json" Output format.

Requires: security_events scope (or repo).

JSON output:

{
  "rollup": { "critical": 1, "high": 3, "medium": 5, "low": 2 },
  "dependabot": {
    "enabled": true,
    "total": 4,
    "truncatedCount": 0,
    "alerts": [{
      "number": 12,
      "ghsaId": "GHSA-xxxx-xxxx-xxxx",
      "severity": "high",
      "state": "open",
      "package": "lodash",
      "summary": "Prototype pollution in lodash",
      "htmlUrl": "https://github.com/org/repo/security/dependabot/12"
    }]
  },
  "codeScanning": {
    "enabled": true,
    "total": 7,
    "truncatedCount": 0,
    "alerts": [{
      "number": 3,
      "ruleId": "js/code-injection",
      "severity": "critical",
      "state": "open",
      "htmlUrl": "https://github.com/org/repo/security/code-scanning/3"
    }]
  }
}

When a source is disabled or not accessible (HTTP 403/404), it reports { "enabled": false, "reason": "..." } instead of an error, and the other source is still returned. truncatedCount on each source shows how many alerts matched but were not returned due to limit.

Idempotency: read-only.


pr_review_thread_ops

Parameters:

Name Type Required Default Description
owner string yes GitHub repository owner or organization.
repo string yes GitHub repository name.
prNumber int yes Pull request number.
action "list" | "resolve" | "unresolve" yes Operation to perform.
threadIds string[] no Review thread node IDs to resolve/unresolve. Required for resolve/unresolve unless resolveOutdated is true.
resolveOutdated boolean no false When action=resolve: resolve all currently unresolved and outdated threads instead of specifying threadIds.
dryRun boolean no false Compute the target thread set and return it without mutating.

Requires: PR write (repo or pull_requests:write). action=list is read-only in effect but still uses a write-capable token for the GraphQL endpoint.

JSON output — action=list:

{
  "threads": [{
    "id": "PRRT_...",
    "path": "src/foo.ts",
    "line": 42,
    "isResolved": false,
    "isOutdated": true,
    "author": "alice",
    "bodySnippet": "Please use const here…"
  }],
  "truncatedCount": 5   // present when PR has more than 100 threads
}

JSON output — action=resolve or action=unresolve:

{ "action": "resolve", "resolved": ["PRRT_aaa", "PRRT_bbb"], "failures": [] }

JSON output — dryRun=true:

{ "dryRun": true, "action": "resolve", "targetThreadIds": ["PRRT_aaa", "PRRT_bbb"] }

Idempotency: convergent — resolving an already-resolved thread is a no-op. action=list is read-only.


branch_protection_status

Parameters:

Name Type Required Default Description
owner string yes GitHub owner or organization.
repo string yes GitHub repository name.
branch string no default branch Branch name. Omit to query the repository default branch.
format "markdown" | "json" no "json" Output format.

Requires: branch-protection read (repository admin or repo scope).

JSON output:

{
  "branch": "main",
  "protected": true,
  "requiredStatusChecks": { "strict": true, "contexts": ["ci/test"] },
  "requiredReviews": { "count": 1, "dismissStaleReviews": true, "requireCodeOwnerReviews": false },
  "enforceAdmins": false,
  "requiredLinearHistory": true,
  "allowForcePushes": false,
  "requiredSignatures": false,
  "restrictions": null
}

When the branch has no protection rules, returns { "branch": "main", "protected": false }. The restrictions field is null (no restrictions) or { "users": [...], "teams": [...] }.

Idempotency: read-only.


deployment_status

Parameters:

Name Type Required Default Description
owner string yes GitHub owner or organization.
repo string yes GitHub repository name.
environment string no Filter by environment name (e.g. "production").
limit int no 10 Maximum deployments to fetch (1–50).
format "markdown" | "json" no "json" Output format.

Requires: deployments read (repo scope).

JSON output:

{
  "environmentFilter": "production",
  "deployments": [{
    "id": 123456,
    "environment": "production",
    "ref": "main",
    "sha": "abc1234",
    "state": "success",
    "creator": "alice",
    "createdAt": "2026-05-20T10:00:00Z",
    "updatedAt": "2026-05-20T10:05:00Z",
    "url": "https://myapp.example.com"
  }],
  "byEnvironment": { "production": "success", "staging": "failure" },
  "truncatedCount": 0
}

byEnvironment maps each environment name to its latest deployment state (first-seen wins since the API returns newest-first). truncatedCount is always 0 in this version (reserved for future use).

Idempotency: read-only.


issue_dedup

Parameters:

Name Type Required Default Description
owner string yes GitHub owner or organization.
repo string yes GitHub repository name.
title string yes The candidate issue title to check for duplicates.
labels string[] no Filter candidate issues by these labels (OR semantics).
state "open" | "closed" | "all" no "open" Which issue states to scan.
limit int no 50 Maximum existing issues to scan (1–100).
threshold number no 0.5 Minimum similarity score (0–1) to include in results.
format "markdown" | "json" no "json" Output format.

Requires: issues read (repo scope).

JSON output:

{
  "candidateTitle": "Button click handler broken in Safari",
  "scanned": 50,
  "matches": [{
    "number": 88,
    "title": "Safari click handler regression",
    "state": "open",
    "url": "https://github.com/org/repo/issues/88",
    "score": 0.67,
    "exactMatch": false
  }],
  "truncatedCount": 3   // omitted when absent; matches above threshold capped at 20
}

Similarity uses token-set Jaccard on normalized titles (lowercase, punctuation stripped). exactMatch: true is set when normalized titles match exactly. Results are sorted by score descending and capped at 20 matches (excess reported in truncatedCount).

Idempotency: read-only.


Authentication

All tools except gh_auth_status require a GitHub token. Resolution order:

  1. GITHUB_TOKEN environment variable
  2. GH_TOKEN environment variable (matches gh CLI convention)
  3. gh auth token subprocess fallback (if gh CLI is installed and authenticated)

Set the token in the MCP client's env block. For GitHub Enterprise, set GITHUB_API_URL (and optionally GITHUB_GRAPHQL_URL).