Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The remote GitHub MCP Server is hosted by GitHub and provides the easiest method

1. A compatible MCP host with remote server support (VS Code 1.101+, Claude Desktop, Cursor, Windsurf, etc.)
2. Any applicable [policies enabled](https://github.com/github/github-mcp-server/blob/main/docs/policies-and-governance.md)
3. (Optional) [Tool-level policies](#tool-level-policy-enforcement) configured for rate limiting and access control

### Install in VS Code

Expand Down Expand Up @@ -1575,3 +1576,50 @@ The exported Go API of this module should currently be considered unstable, and
## License

This project is licensed under the terms of the MIT open source license. Please refer to [MIT](./LICENSE) for the full terms.

## Tool-level policy enforcement

The [policies and governance](docs/policies-and-governance.md) doc covers access control via PATs, OAuth, and SSO. For tool-level enforcement — rate limiting, daily caps, and blocking specific operations — you can wrap the server with [PolicyLayer Intercept](https://github.com/policylayer/intercept), an open-source MCP proxy.

Three policy presets are included in [`/policies`](/policies):

| Policy | Description |
|--------|-------------|
| `recommended.yaml` | Rate limits on writes, blocks `delete_file`, daily caps on merges and pushes |
| `strict.yaml` | Default deny — only read tools allowed unless explicitly opted in |
| `permissive.yaml` | Everything allowed, rate limits on destructive and high-risk operations |

### Usage

Local server:

```sh
npx -y @policylayer/intercept \
--policy policies/recommended.yaml \
-- docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN ghcr.io/github/github-mcp-server
```

Or in your MCP client config:

```json
{
"mcpServers": {
"github": {
"command": "npx",
"args": [
"-y", "@policylayer/intercept",
"--policy", "policies/recommended.yaml",
"--", "docker", "run", "-i", "--rm",
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "<your-token>"
}
}
}
}
```

Policies are YAML files you can customise. See the [Intercept docs](https://github.com/policylayer/intercept) for the full reference.

42 changes: 42 additions & 0 deletions policies/permissive.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
version: "1"
description: "GitHub MCP — permissive policy. All tools allowed. Rate limits on destructive and high-risk operations."
default: allow

tools:
# Destructive — blocked even in permissive mode
delete_file:
rules:
- action: deny
on_deny: "File deletion blocked by policy"

# High-risk writes — rate limited
merge_pull_request:
rules:
- name: "rate-limit"
rate_limit: "20/hour"
on_deny: "Max 20 merges per hour"

push_files:
rules:
- name: "rate-limit"
rate_limit: "30/hour"
on_deny: "Max 30 pushes per hour"

actions_run_trigger:
rules:
- name: "rate-limit"
rate_limit: "10/hour"
on_deny: "Max 10 workflow triggers per hour"

create_repository:
rules:
- name: "rate-limit"
rate_limit: "10/hour"
on_deny: "Max 10 repository creations per hour"

# Global safety net
"*":
rules:
- name: "global-rate-limit"
rate_limit: "180/minute"
on_deny: "Global rate limit — max 180 tool calls per minute"
127 changes: 127 additions & 0 deletions policies/recommended.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
version: "1"
description: "GitHub MCP — recommended policy. Rate limits on writes, blocks destructive ops, reads allowed freely."
default: allow

tools:
# Destructive — blocked entirely
delete_file:
hide: true
rules:
- action: deny
on_deny: "File deletion blocked by policy"

# High-risk writes — tight limits
merge_pull_request:
rules:
- name: "burst-limit"
rate_limit: "2/minute"
on_deny: "Slow down — max 2 merges per minute"
- name: "hourly-cap"
rate_limit: "10/hour"
on_deny: "Hourly merge limit (10) reached"

push_files:
rules:
- name: "burst-limit"
rate_limit: "3/minute"
on_deny: "Slow down — max 3 pushes per minute"
- name: "hourly-cap"
rate_limit: "20/hour"
on_deny: "Hourly push limit (20) reached"

create_or_update_file:
rules:
- name: "rate-limit"
rate_limit: "30/hour"
on_deny: "Max 30 file writes per hour"

# Execution — rate limited
actions_run_trigger:
rules:
- name: "rate-limit"
rate_limit: "5/hour"
on_deny: "Max 5 workflow triggers per hour"

# Repository management — moderate limits
create_repository:
rules:
- name: "rate-limit"
rate_limit: "5/hour"
on_deny: "Max 5 repository creations per hour"

fork_repository:
rules:
- name: "rate-limit"
rate_limit: "5/hour"
on_deny: "Max 5 forks per hour"

# PR and issue writes — reasonable throughput
create_pull_request:
rules:
- name: "rate-limit"
rate_limit: "20/hour"
on_deny: "Max 20 PR creations per hour"

update_pull_request:
rules:
- name: "rate-limit"
rate_limit: "30/hour"
on_deny: "Max 30 PR updates per hour"

update_pull_request_branch:
rules:
- name: "rate-limit"
rate_limit: "20/hour"
on_deny: "Max 20 branch updates per hour"

issue_write:
rules:
- name: "rate-limit"
rate_limit: "30/hour"
on_deny: "Max 30 issue writes per hour"

add_issue_comment:
rules:
- name: "rate-limit"
rate_limit: "30/hour"
on_deny: "Max 30 issue comments per hour"

# Branch creation
create_branch:
rules:
- name: "rate-limit"
rate_limit: "20/hour"
on_deny: "Max 20 branch creations per hour"

# Copilot tools — limited
assign_copilot_to_issue:
rules:
- name: "rate-limit"
rate_limit: "10/hour"
on_deny: "Max 10 Copilot assignments per hour"

request_copilot_review:
rules:
- name: "rate-limit"
rate_limit: "10/hour"
on_deny: "Max 10 Copilot review requests per hour"

create_pull_request_with_copilot:
rules:
- name: "rate-limit"
rate_limit: "10/hour"
on_deny: "Max 10 Copilot PR creations per hour"

# Gist writes
create_gist:
rules:
- name: "rate-limit"
rate_limit: "20/hour"
on_deny: "Max 20 gist creations per hour"

# Global safety net
"*":
rules:
- name: "global-rate-limit"
rate_limit: "120/minute"
on_deny: "Global rate limit — max 120 tool calls per minute"
Loading