Skip to content

Commit bdc7180

Browse files
zwickCopilot
andcommitted
Add issue dependency read/write MCP tools
Add two feature-flagged tools for issue blocked-by / blocking relationships, gated behind the issue_dependencies flag so they stay off the default tool surface (auto-enabled for insiders only): - issue_dependency_read: get_blocked_by / get_blocking via the Issue.blockedBy / Issue.blocking GraphQL connections, cursor-paginated. - issue_dependency_write: add / remove x blocked_by / blocking via the addBlockedBy / removeBlockedBy mutations. Accepts issue numbers and resolves them to node IDs in a single aliased query; "blocking" is the inverse of "blocked_by" with the subject/related roles swapped. Closes the MCP gap behind the gh CLI dependency verbs (cli/cli#13057). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4f73cfd commit bdc7180

8 files changed

Lines changed: 1034 additions & 2 deletions

docs/feature-flags.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ runtime behavior (such as output formatting) won't appear here.
7575
- `type`: Type of this issue. Only use if issue types are enabled for this repository. Use list_issue_types tool to get valid type values for this repository or its owner organization. If the repository doesn't support issue types, omit this parameter. (string, optional)
7676

7777
- **ui_get** - Get UI data
78-
- **Required OAuth Scopes**: `repo`, `read:org`
78+
- **Required OAuth Scopes (any of)**: `repo`, `read:org`
7979
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `repo`, `write:org`
8080
- `method`: The type of data to fetch (string, required)
8181
- `owner`: Repository owner (required for all methods) (string, required)
@@ -324,4 +324,36 @@ runtime behavior (such as output formatting) won't appear here.
324324
- `repo`: Repository name (string, required)
325325
- `start_line`: Optional 1-based starting line of the window of interest. Only ranges overlapping [start_line, end_line] are returned, clamped to the window. (number, optional)
326326

327+
### `issue_dependencies`
328+
329+
- **issue_dependency_read** - Read issue dependencies
330+
- **Required OAuth Scopes**: `repo`
331+
- `after`: Cursor for pagination. Use the cursor from the previous response. (string, optional)
332+
- `issue_number`: The number of the issue (number, required)
333+
- `method`: The read operation to perform on a single issue's dependencies.
334+
Options are:
335+
1. get_blocked_by - List the issues that block this issue (this issue is blocked by them).
336+
2. get_blocking - List the issues that this issue blocks.
337+
(string, required)
338+
- `owner`: The owner of the repository (string, required)
339+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
340+
- `repo`: The name of the repository (string, required)
341+
342+
- **issue_dependency_write** - Change issue dependency
343+
- **Required OAuth Scopes**: `repo`
344+
- `issue_number`: The number of the subject issue (number, required)
345+
- `method`: The action to perform.
346+
Options are:
347+
- 'add' - create the dependency relationship.
348+
- 'remove' - delete the dependency relationship. (string, required)
349+
- `owner`: The owner of the subject issue's repository (string, required)
350+
- `related_issue_number`: The number of the related issue to link or unlink (number, required)
351+
- `related_owner`: The owner of the related issue's repository. Defaults to 'owner' when omitted. (string, optional)
352+
- `related_repo`: The name of the related issue's repository. Defaults to 'repo' when omitted. (string, optional)
353+
- `repo`: The name of the subject issue's repository (string, required)
354+
- `type`: The relationship direction relative to the subject issue.
355+
Options are:
356+
- 'blocked_by' - the subject issue is blocked by the related issue.
357+
- 'blocking' - the subject issue blocks the related issue. (string, required)
358+
327359
<!-- END AUTOMATED FEATURE FLAG TOOLS -->

docs/insiders-features.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ The list below is generated from the Go source. It covers tool **inventory and s
6969
- `type`: Type of this issue. Only use if issue types are enabled for this repository. Use list_issue_types tool to get valid type values for this repository or its owner organization. If the repository doesn't support issue types, omit this parameter. (string, optional)
7070

7171
- **ui_get** - Get UI data
72-
- **Required OAuth Scopes**: `repo`, `read:org`
72+
- **Required OAuth Scopes (any of)**: `repo`, `read:org`
7373
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `repo`, `write:org`
7474
- `method`: The type of data to fetch (string, required)
7575
- `owner`: Repository owner (required for all methods) (string, required)
@@ -144,6 +144,38 @@ The list below is generated from the Go source. It covers tool **inventory and s
144144
- `repo`: Repository name (string, required)
145145
- `start_line`: Optional 1-based starting line of the window of interest. Only ranges overlapping [start_line, end_line] are returned, clamped to the window. (number, optional)
146146

147+
### `issue_dependencies`
148+
149+
- **issue_dependency_read** - Read issue dependencies
150+
- **Required OAuth Scopes**: `repo`
151+
- `after`: Cursor for pagination. Use the cursor from the previous response. (string, optional)
152+
- `issue_number`: The number of the issue (number, required)
153+
- `method`: The read operation to perform on a single issue's dependencies.
154+
Options are:
155+
1. get_blocked_by - List the issues that block this issue (this issue is blocked by them).
156+
2. get_blocking - List the issues that this issue blocks.
157+
(string, required)
158+
- `owner`: The owner of the repository (string, required)
159+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
160+
- `repo`: The name of the repository (string, required)
161+
162+
- **issue_dependency_write** - Change issue dependency
163+
- **Required OAuth Scopes**: `repo`
164+
- `issue_number`: The number of the subject issue (number, required)
165+
- `method`: The action to perform.
166+
Options are:
167+
- 'add' - create the dependency relationship.
168+
- 'remove' - delete the dependency relationship. (string, required)
169+
- `owner`: The owner of the subject issue's repository (string, required)
170+
- `related_issue_number`: The number of the related issue to link or unlink (number, required)
171+
- `related_owner`: The owner of the related issue's repository. Defaults to 'owner' when omitted. (string, optional)
172+
- `related_repo`: The name of the related issue's repository. Defaults to 'repo' when omitted. (string, optional)
173+
- `repo`: The name of the subject issue's repository (string, required)
174+
- `type`: The relationship direction relative to the subject issue.
175+
Options are:
176+
- 'blocked_by' - the subject issue is blocked by the related issue.
177+
- 'blocking' - the subject issue blocks the related issue. (string, required)
178+
147179
<!-- END AUTOMATED INSIDERS TOOLS -->
148180

149181
---
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"annotations": {
3+
"readOnlyHint": true,
4+
"title": "Read issue dependencies"
5+
},
6+
"description": "Read an issue's dependency relationships in a GitHub repository: the issues that block it (blocked_by) or the issues it blocks (blocking).",
7+
"inputSchema": {
8+
"properties": {
9+
"after": {
10+
"description": "Cursor for pagination. Use the cursor from the previous response.",
11+
"type": "string"
12+
},
13+
"issue_number": {
14+
"description": "The number of the issue",
15+
"type": "number"
16+
},
17+
"method": {
18+
"description": "The read operation to perform on a single issue's dependencies.\nOptions are:\n1. get_blocked_by - List the issues that block this issue (this issue is blocked by them).\n2. get_blocking - List the issues that this issue blocks.\n",
19+
"enum": [
20+
"get_blocked_by",
21+
"get_blocking"
22+
],
23+
"type": "string"
24+
},
25+
"owner": {
26+
"description": "The owner of the repository",
27+
"type": "string"
28+
},
29+
"perPage": {
30+
"description": "Results per page for pagination (min 1, max 100)",
31+
"maximum": 100,
32+
"minimum": 1,
33+
"type": "number"
34+
},
35+
"repo": {
36+
"description": "The name of the repository",
37+
"type": "string"
38+
}
39+
},
40+
"required": [
41+
"method",
42+
"owner",
43+
"repo",
44+
"issue_number"
45+
],
46+
"type": "object"
47+
},
48+
"name": "issue_dependency_read"
49+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"annotations": {
3+
"title": "Change issue dependency"
4+
},
5+
"description": "Add or remove an issue dependency relationship in a GitHub repository. Use type 'blocked_by' to record that the subject issue is blocked by a related issue, or type 'blocking' to record that the subject issue blocks a related issue. The related issue defaults to the same repository as the subject unless related_owner/related_repo are provided.",
6+
"inputSchema": {
7+
"properties": {
8+
"issue_number": {
9+
"description": "The number of the subject issue",
10+
"type": "number"
11+
},
12+
"method": {
13+
"description": "The action to perform.\nOptions are:\n- 'add' - create the dependency relationship.\n- 'remove' - delete the dependency relationship.",
14+
"enum": [
15+
"add",
16+
"remove"
17+
],
18+
"type": "string"
19+
},
20+
"owner": {
21+
"description": "The owner of the subject issue's repository",
22+
"type": "string"
23+
},
24+
"related_issue_number": {
25+
"description": "The number of the related issue to link or unlink",
26+
"type": "number"
27+
},
28+
"related_owner": {
29+
"description": "The owner of the related issue's repository. Defaults to 'owner' when omitted.",
30+
"type": "string"
31+
},
32+
"related_repo": {
33+
"description": "The name of the related issue's repository. Defaults to 'repo' when omitted.",
34+
"type": "string"
35+
},
36+
"repo": {
37+
"description": "The name of the subject issue's repository",
38+
"type": "string"
39+
},
40+
"type": {
41+
"description": "The relationship direction relative to the subject issue.\nOptions are:\n- 'blocked_by' - the subject issue is blocked by the related issue.\n- 'blocking' - the subject issue blocks the related issue.",
42+
"enum": [
43+
"blocked_by",
44+
"blocking"
45+
],
46+
"type": "string"
47+
}
48+
},
49+
"required": [
50+
"method",
51+
"type",
52+
"owner",
53+
"repo",
54+
"issue_number",
55+
"related_issue_number"
56+
],
57+
"type": "object"
58+
},
59+
"name": "issue_dependency_write"
60+
}

pkg/github/feature_flags.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ const FeatureFlagIssueFields = "remote_mcp_issue_fields"
2121
// is not advertised by default, keeping the tool surface small unless opted in.
2222
const FeatureFlagFileBlame = "file_blame"
2323

24+
// FeatureFlagIssueDependencies is the feature flag name for the issue dependency
25+
// tools (issue_dependency_read / issue_dependency_write), which read and edit an
26+
// issue's blocked-by / blocking relationships. It is gated so these tools are not
27+
// advertised in the default surface, keeping the fixed tool-schema cost small
28+
// unless explicitly opted in.
29+
const FeatureFlagIssueDependencies = "issue_dependencies"
30+
2431
// AllowedFeatureFlags is the allowlist of feature flags that can be enabled
2532
// by users via --features CLI flag or X-MCP-Features HTTP header.
2633
// Only flags in this list are accepted; unknown flags are silently ignored.
@@ -33,6 +40,7 @@ var AllowedFeatureFlags = []string{
3340
FeatureFlagIssuesGranular,
3441
FeatureFlagPullRequestsGranular,
3542
FeatureFlagFileBlame,
43+
FeatureFlagIssueDependencies,
3644
}
3745

3846
// InsidersFeatureFlags is the list of feature flags that insiders mode enables.
@@ -44,6 +52,7 @@ var InsidersFeatureFlags = []string{
4452
FeatureFlagCSVOutput,
4553
FeatureFlagIssueFields,
4654
FeatureFlagFileBlame,
55+
FeatureFlagIssueDependencies,
4756
}
4857

4958
// FeatureFlags defines runtime feature toggles that adjust tool behavior.

0 commit comments

Comments
 (0)