Skip to content
Merged
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
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ The following sets of tools are available:
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/code-square-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/code-square-light.png"><img src="pkg/octicons/icons/code-square-light.png" width="20" height="20" alt="code-square"></picture> | `code_quality` | GitHub Code Quality related tools |
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/codescan-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/codescan-light.png"><img src="pkg/octicons/icons/codescan-light.png" width="20" height="20" alt="codescan"></picture> | `code_security` | Code security related tools, such as GitHub Code Scanning |
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/copilot-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/copilot-light.png"><img src="pkg/octicons/icons/copilot-light.png" width="20" height="20" alt="copilot"></picture> | `copilot` | Copilot related tools |
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/copilot-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/copilot-light.png"><img src="pkg/octicons/icons/copilot-light.png" width="20" height="20" alt="copilot"></picture> | `copilot_issue_intents` | Opt-in Copilot issue assignment tools that carry intent metadata (rationale, confidence, suggestion) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/dependabot-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/dependabot-light.png"><img src="pkg/octicons/icons/dependabot-light.png" width="20" height="20" alt="dependabot"></picture> | `dependabot` | Dependabot tools |
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/comment-discussion-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/comment-discussion-light.png"><img src="pkg/octicons/icons/comment-discussion-light.png" width="20" height="20" alt="comment-discussion"></picture> | `discussions` | GitHub Discussions related tools |
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/logo-gist-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/logo-gist-light.png"><img src="pkg/octicons/icons/logo-gist-light.png" width="20" height="20" alt="logo-gist"></picture> | `gists` | GitHub Gist related tools |
Expand Down Expand Up @@ -750,6 +751,23 @@ The following sets of tools are available:

<details>

<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/copilot-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/copilot-light.png"><img src="pkg/octicons/icons/copilot-light.png" width="20" height="20" alt="copilot"></picture> Copilot Issue Intents</summary>

- **assign_copilot_to_issue_with_intent** - Assign Copilot to issue with intent
- **Required OAuth Scopes**: `repo`
- `base_ref`: Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch. Ignored when is_suggestion is true (string, optional)
- `confidence`: How confident you are in this choice. 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal. (string, required)
- `custom_instructions`: Optional custom instructions to guide the agent beyond the issue body. Ignored when is_suggestion is true (string, optional)
- `is_suggestion`: If true, records a pending Copilot assignment intent rather than launching the agent. Approval later supplies the launch context; base_ref and custom_instructions are ignored in this case. (boolean, required)
- `issue_number`: Issue number (number, required)
- `owner`: Repository owner (string, required)
- `rationale`: One concise sentence explaining what specifically about the issue led to choosing Copilot. State the concrete signal (e.g. 'Well-scoped task with clear acceptance criteria'). (string, required)
- `repo`: Repository name (string, required)

</details>

<details>

<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/dependabot-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/dependabot-light.png"><img src="pkg/octicons/icons/dependabot-light.png" width="20" height="20" alt="dependabot"></picture> Dependabot</summary>

- **get_dependabot_alert** - Get dependabot alert
Expand Down
1 change: 1 addition & 0 deletions docs/remote-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Below is a table of available toolsets for the remote GitHub MCP Server. Each to
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/code-square-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/code-square-light.png"><img src="../pkg/octicons/icons/code-square-light.png" width="20" height="20" alt="code-square"></picture><br>`code_quality` | GitHub Code Quality related tools | https://api.githubcopilot.com/mcp/x/code_quality | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-code_quality&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcode_quality%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/code_quality/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-code_quality&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcode_quality%2Freadonly%22%7D) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/codescan-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/codescan-light.png"><img src="../pkg/octicons/icons/codescan-light.png" width="20" height="20" alt="codescan"></picture><br>`code_security` | Code security related tools, such as GitHub Code Scanning | https://api.githubcopilot.com/mcp/x/code_security | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-code_security&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcode_security%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/code_security/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-code_security&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcode_security%2Freadonly%22%7D) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/copilot-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/copilot-light.png"><img src="../pkg/octicons/icons/copilot-light.png" width="20" height="20" alt="copilot"></picture><br>`copilot` | Copilot related tools | https://api.githubcopilot.com/mcp/x/copilot | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-copilot&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcopilot%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/copilot/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-copilot&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcopilot%2Freadonly%22%7D) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/copilot-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/copilot-light.png"><img src="../pkg/octicons/icons/copilot-light.png" width="20" height="20" alt="copilot"></picture><br>`copilot_issue_intents` | Opt-in Copilot issue assignment tools that carry intent metadata (rationale, confidence, suggestion) | https://api.githubcopilot.com/mcp/x/copilot_issue_intents | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-copilot_issue_intents&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcopilot_issue_intents%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/copilot_issue_intents/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-copilot_issue_intents&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fcopilot_issue_intents%2Freadonly%22%7D) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/dependabot-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/dependabot-light.png"><img src="../pkg/octicons/icons/dependabot-light.png" width="20" height="20" alt="dependabot"></picture><br>`dependabot` | Dependabot tools | https://api.githubcopilot.com/mcp/x/dependabot | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-dependabot&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fdependabot%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/dependabot/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-dependabot&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fdependabot%2Freadonly%22%7D) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/comment-discussion-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/comment-discussion-light.png"><img src="../pkg/octicons/icons/comment-discussion-light.png" width="20" height="20" alt="comment-discussion"></picture><br>`discussions` | GitHub Discussions related tools | https://api.githubcopilot.com/mcp/x/discussions | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-discussions&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fdiscussions%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/discussions/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-discussions&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fdiscussions%2Freadonly%22%7D) |
| <picture><source media="(prefers-color-scheme: dark)" srcset="../pkg/octicons/icons/logo-gist-dark.png"><source media="(prefers-color-scheme: light)" srcset="../pkg/octicons/icons/logo-gist-light.png"><img src="../pkg/octicons/icons/logo-gist-light.png" width="20" height="20" alt="logo-gist"></picture><br>`gists` | GitHub Gist related tools | https://api.githubcopilot.com/mcp/x/gists | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-gists&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fgists%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/gists/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-gists&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fgists%2Freadonly%22%7D) |
Expand Down
111 changes: 110 additions & 1 deletion e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,7 @@ func TestAssignCopilotToIssue(t *testing.T) {
textContent, ok = resp.Content[0].(*mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")

possibleExpectedFailure := "copilot isn't available as an assignee for this issue. Please inform the user to visit https://docs.github.com/en/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks/about-assigning-tasks-to-copilot for more information."
possibleExpectedFailure := "copilot isn't available as an assignee for this issue. Please inform the user to visit https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent for more information."
if resp.IsError && textContent.Text == possibleExpectedFailure {
t.Skip("skipping because copilot wasn't available as an assignee on this issue, it's likely that the owner doesn't have copilot enabled in their settings")
}
Expand All @@ -1104,6 +1104,115 @@ func TestAssignCopilotToIssue(t *testing.T) {
require.Equal(t, "Copilot", *assignees.Assignees[0].Login, "expected copilot to be assigned to the issue")
}

// TestAssignCopilotToIssueWithIntent exercises the opt-in intent-aware assignment
// tool along the is_suggestion=true path. That path records a pending Copilot
// assignment intent rather than launching the agent, so the tool returns a
// suggestion-shaped result without a linked pull request and no Copilot user is
// added to the issue's assignees.
func TestAssignCopilotToIssueWithIntent(t *testing.T) {
t.Parallel()

if getE2EHost() != "" && getE2EHost() != "https://github.com" {
t.Skip("Skipping test because the host does not support copilot being assigned to issues")
}

mcpClient := setupMCPClient(t)
ctx := context.Background()

t.Log("Getting current user...")
resp, err := mcpClient.CallTool(ctx, &mcp.CallToolParams{Name: "get_me"})
require.NoError(t, err, "expected to call 'get_me' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))
require.Len(t, resp.Content, 1, "expected content to have one item")

textContent, ok := resp.Content[0].(*mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")

var trimmedGetMeText struct {
Login string `json:"login"`
}
err = json.Unmarshal([]byte(textContent.Text), &trimmedGetMeText)
require.NoError(t, err, "expected to unmarshal text content successfully")
currentOwner := trimmedGetMeText.Login

repoName := fmt.Sprintf("github-mcp-server-e2e-%s-%d", t.Name(), time.Now().UnixMilli())

t.Logf("Creating repository %s/%s...", currentOwner, repoName)
_, err = mcpClient.CallTool(ctx, &mcp.CallToolParams{
Name: "create_repository",
Arguments: map[string]any{
"name": repoName,
"private": true,
"autoInit": true,
},
})
require.NoError(t, err, "expected to call 'create_repository' tool successfully")

t.Cleanup(func() {
ghClient := getRESTClient(t)
t.Logf("Deleting repository %s/%s...", currentOwner, repoName)
_, err := ghClient.Repositories.Delete(context.Background(), currentOwner, repoName)
require.NoError(t, err, "expected to delete repository successfully")
})

t.Logf("Creating issue in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, &mcp.CallToolParams{
Name: "issue_write",
Arguments: map[string]any{
"method": "create",
"owner": currentOwner,
"repo": repoName,
"title": "Test issue for intent-aware copilot suggestion",
},
})
require.NoError(t, err, "expected to call 'issue_write' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

t.Logf("Recording pending copilot assignment suggestion in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, &mcp.CallToolParams{
Name: "assign_copilot_to_issue_with_intent",
Arguments: map[string]any{
"owner": currentOwner,
"repo": repoName,
"issue_number": 1,
"rationale": "E2E: well-scoped test task.",
"confidence": "HIGH",
"is_suggestion": true,
},
})
require.NoError(t, err, "expected to call 'assign_copilot_to_issue_with_intent' tool successfully")

require.Len(t, resp.Content, 1, "expected content to have one item")
textContent, ok = resp.Content[0].(*mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")

possibleExpectedFailure := "copilot isn't available as an assignee for this issue. Please inform the user to visit https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent for more information."
if resp.IsError && textContent.Text == possibleExpectedFailure {
t.Skip("skipping because copilot wasn't available as an assignee on this issue, it's likely that the owner doesn't have copilot enabled in their settings")
}

require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

var response map[string]any
require.NoError(t, json.Unmarshal([]byte(textContent.Text), &response), "expected suggestion result to be JSON")
require.Equal(t, true, response["is_suggestion"], "expected is_suggestion=true in result")
require.Contains(t, response["message"], "pending copilot assignment suggestion",
"expected suggestion-shaped message, got %v", response["message"])
require.NotContains(t, response, "pull_request",
"suggestion path must not claim PR creation")

// A pure suggestion does not launch Copilot, so no Copilot user should appear
// on the issue's assignees list.
ghClient := getRESTClient(t)
issue, response2, err := ghClient.Issues.Get(context.Background(), currentOwner, repoName, 1)
require.NoError(t, err, "expected to get issue successfully")
require.Equal(t, http.StatusOK, response2.StatusCode, "expected to get issue successfully")
for _, a := range issue.Assignees {
require.NotEqual(t, "Copilot", *a.Login,
"suggestion path must not add Copilot to applied assignees")
}
}

func TestPullRequestAtomicCreateAndSubmit(t *testing.T) {
t.Parallel()

Expand Down
2 changes: 1 addition & 1 deletion pkg/github/__toolsnaps__/assign_copilot_to_issue.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"readOnlyHint": false,
"title": "Assign Copilot to issue"
},
"description": "Assign Copilot to a specific issue in a GitHub repository.\n\nThis tool can help with the following outcomes:\n- a Pull Request created with source code changes to resolve the issue\n\n\nMore information can be found at:\n- https://docs.github.com/en/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks/about-assigning-tasks-to-copilot\n",
"description": "Assign Copilot to a specific issue in a GitHub repository.\n\nThis tool can help with the following outcomes:\n- a Pull Request created with source code changes to resolve the issue\n\n\nMore information can be found at:\n- https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent\n",
"icons": [
{
"mimeType": "image/png",
Expand Down
Loading
Loading