Services → GitHub

Connect GitHub

One connection that reads GitHub: repositories, code, commits, pull requests, issues, releases and Actions — including the job logs that say why the deploy failed. The narrowing that matters is the token's repository scope.

Tier 2 A fine-grained personal access token ~5 min profile github/read-only

Setting this up with your own agent? Give it these instructions.

Why there is one profile and not three

There used to be github/actions-read, github/code-read and

github/triage-read. Choosing between them meant deciding, at connection time,

which third of GitHub an agent would ever need — and during an incident the

honest answer is "I do not know yet".

Someone debugging a failed deploy needs the workflow run, the job log that says

what broke, the commit that triggered it, the file that commit changed and the

pull request it arrived in. That is all three profiles. Expressing it as three

connections meant three tokens, three audit trails and three chances to bind the

wrong one.

So there is one connection that reads GitHub. **The narrowing that matters is the

token**, and it is a better fence than the split ever was: a fine-grained token

names its repositories, and the gateway cannot widen that.

Step 1 — mint the token

  1. **Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**.
  2. Resource owner: the organisation, not your personal account, if the repositories belong to one.
  3. Repository access → Only select repositories, and pick exactly the ones this connection should reach.
  4. Permissions, all on Read-only:

| Permission | Why |

|---|---|

| Contents | files, commits, branches, releases |

| Metadata | required; repository basics |

| Pull requests | PRs, files, reviews, status |

| Issues | issues and comments |

| Actions | workflow runs, jobs and logs |

  1. Leave Secret scanning alerts and Code scanning alerts at No access.
  2. Set an expiry. Generate. Copy it.

Step 2 — connect it

Services → Add a service, pick github/read-only. The upstream is GitHub's

hosted MCP server and is filled in for you:

| Field | Value |

|---|---|

| Upstream | https://api.githubcopilot.com/mcp/ |

| Credential | the fine-grained token |

Name it for what it reaches — ejd-github — because the name is the namespace an

agent sees.

The two judgement calls worth knowing about

Job logs are allowed. get_job_logs is classified read_leaks, honestly: a

build log contains whatever the build printed, and builds print more than they

should. It is allowed anyway, because "why did the deploy fail" is unanswerable

without it — and a denied log just means somebody opens the GitHub UI and reads

the same thing unaudited. The leak is stated rather than hidden, and

[principle 13](../reference/egress.md) keeps that output away from an AI.

Secret scanning alerts are denied, and always will be. That endpoint returns

the leaked credential itself. There is no scoping that makes handing an agent

your committed secrets acceptable, so it is not a setting.

Artifact downloads are denied too: an artifact is an arbitrary blob — a built

image, a tarball of the workspace — and that is a download, not a diagnostic.

list_workflow_run_artifacts says what exists and get_job_logs says what

happened.

Checking the token really cannot write


# Should succeed: reading
curl -sS -H "Authorization: Bearer $GH_TOKEN" \
https://api.github.com/repos/OWNER/REPO/actions/runs?per_page=1 | head -c 200

# Should FAIL with 403: creating an issue
curl -sS -o /dev/null -w '%{http_code}\n' -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-d '{"title":"prodpeek-permission-test"}' \
https://api.github.com/repos/OWNER/REPO/issues

# Should FAIL with 403: secret scanning
curl -sS -o /dev/null -w '%{http_code}\n' \
-H "Authorization: Bearer $GH_TOKEN" \
https://api.github.com/repos/OWNER/REPO/secret-scanning/alerts

Two 403s and a 200 is what a correctly minted token looks like.

Screenshots

A fine-grained token, scoped to two repositories rather than all of them. Screenshot pending — the steps above stand on their own.
A fine-grained token, scoped to two repositories rather than all of them.
Every permission on Read-only, with the scanning alerts left at No access. Screenshot pending — the steps above stand on their own.
Every permission on Read-only, with the scanning alerts left at No access.