Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add GitHub Docs search MCP endpoint#1338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
Copilot wants to merge10 commits intomain
base:main
Choose a base branch
Loading
fromcopilot/add-mcp-github-docs-endpoint
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
10 commits
Select commitHold shift + click to select a range
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
13 changes: 13 additions & 0 deletionsREADME.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -400,6 +400,7 @@ The following sets of tools are available:
| `discussions` | GitHub Discussions related tools |
| `experiments` | Experimental features that are not considered stable yet |
| `gists` | GitHub Gist related tools |
| `github_docs` | GitHub Docs search related tools |
| `issues` | GitHub Issues related tools |
| `labels` | GitHub Labels related tools |
| `notifications` | GitHub Notifications related tools |
Expand DownExpand Up@@ -630,6 +631,18 @@ The following sets of tools are available:

<details>

<summary>GitHub Docs</summary>

- **search_github_docs** - Search GitHub Docs
- `language`: Language code for documentation. Options: 'en' (default), 'es', 'ja', 'pt', 'zh', 'ru', 'fr', 'ko', 'de' (string, optional)
- `max_results`: Maximum number of results to return (default: 10, max: 100) (number, optional)
- `query`: Search query for GitHub documentation. Examples: 'actions workflow syntax', 'pull request review', 'GitHub Pages' (string, required)
- `version`: GitHub version to search. Options: 'dotcom' (default, free/pro/team), 'ghec' (GitHub Enterprise Cloud), or a specific GHES version like '3.12' (string, optional)

</details>

<details>

<summary>Issues</summary>

- **add_issue_comment** - Add comment to issue
Expand Down
2 changes: 2 additions & 0 deletionscmd/github-mcp-server/generate_docs.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,8 @@ func formatToolsetName(name string) string {
return "Secret Protection"
case "orgs":
return "Organizations"
case "github_docs":
return "GitHub Docs"
default:
// Fallback: capitalize first letter and replace underscores with spaces
parts := strings.Split(name, "_")
Expand Down
1 change: 1 addition & 0 deletionsdocs/remote-server.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,7 @@ Below is a table of available toolsets for the remote GitHub MCP Server. Each to
| 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) |
| Experiments | Experimental features that are not considered stable yet | https://api.githubcopilot.com/mcp/x/experiments | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-experiments&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fexperiments%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/experiments/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-experiments&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fexperiments%2Freadonly%22%7D) |
| 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) |
| GitHub Docs | GitHub Docs search related tools | https://api.githubcopilot.com/mcp/x/github_docs | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-github_docs&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fgithub_docs%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/github_docs/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-github_docs&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fgithub_docs%2Freadonly%22%7D) |
| Issues | GitHub Issues related tools | https://api.githubcopilot.com/mcp/x/issues | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-issues&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fissues%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/issues/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-issues&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fissues%2Freadonly%22%7D) |
| Labels | GitHub Labels related tools | https://api.githubcopilot.com/mcp/x/labels | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-labels&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Flabels%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/labels/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-labels&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Flabels%2Freadonly%22%7D) |
| Notifications | GitHub Notifications related tools | https://api.githubcopilot.com/mcp/x/notifications | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-notifications&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fnotifications%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/notifications/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-notifications&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fnotifications%2Freadonly%22%7D) |
Expand Down
2 changes: 0 additions & 2 deletionsgo.sum
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,8 +24,6 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30=
github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M=
github.com/google/go-github/v74 v74.0.0 h1:yZcddTUn8DPbj11GxnMrNiAnXH14gNs559AsUpNpPgM=
github.com/google/go-github/v74 v74.0.0/go.mod h1:ubn/YdyftV80VPSI26nSJvaEsTOnsjrxG3o9kJhcyak=
github.com/google/go-github/v76 v76.0.0 h1:MCa9VQn+VG5GG7Y7BAkBvSRUN3o+QpaEOuZwFPJmdFA=
github.com/google/go-github/v76 v76.0.0/go.mod h1:38+d/8pYDO4fBLYfBhXF5EKO0wA3UkXBjfmQapFsNCQ=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
Expand Down
32 changes: 32 additions & 0 deletionspkg/github/__toolsnaps__/search_github_docs.snap
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
{
"annotations": {
"title": "Search GitHub Docs",
"readOnlyHint": true
},
"description": "Search GitHub's official documentation at docs.github.com. Use this to find help articles, guides, and API documentation for GitHub features and products.",
"inputSchema": {
"properties": {
"language": {
"description": "Language code for documentation. Options: 'en' (default), 'es', 'ja', 'pt', 'zh', 'ru', 'fr', 'ko', 'de'",
"type": "string"
},
"max_results": {
"description": "Maximum number of results to return (default: 10, max: 100)",
"type": "number"
},
"query": {
"description": "Search query for GitHub documentation. Examples: 'actions workflow syntax', 'pull request review', 'GitHub Pages'",
"type": "string"
},
"version": {
"description": "GitHub version to search. Options: 'dotcom' (default, free/pro/team), 'ghec' (GitHub Enterprise Cloud), or a specific GHES version like '3.12'",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "search_github_docs"
}
144 changes: 144 additions & 0 deletionspkg/github/docs.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
package github

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"

"github.com/github/github-mcp-server/pkg/translations"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)

// DocsSearchResult represents a single search result from GitHub Docs
type DocsSearchResult struct {
Title string `json:"title"`
URL string `json:"url"`
Breadcrumbs string `json:"breadcrumbs"`
Content string `json:"content,omitempty"`
}

// DocsSearchResponse represents the response from GitHub Docs search API
type DocsSearchResponse struct {
Meta struct {
Found struct {
Value int `json:"value"`
} `json:"found"`
Took struct {
PrettyMs string `json:"pretty_ms"`
} `json:"took"`
} `json:"meta"`
Hits []DocsSearchResult `json:"hits"`
}

// SearchGitHubDocs creates a tool to search GitHub documentation.
func SearchGitHubDocs(t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
return mcp.NewTool("search_github_docs",
mcp.WithDescription(t("TOOL_SEARCH_GITHUB_DOCS_DESCRIPTION", "Search GitHub's official documentation at docs.github.com. Use this to find help articles, guides, and API documentation for GitHub features and products.")),
mcp.WithToolAnnotation(mcp.ToolAnnotation{
Title: t("TOOL_SEARCH_GITHUB_DOCS_USER_TITLE", "Search GitHub Docs"),
ReadOnlyHint: ToBoolPtr(true),
}),
mcp.WithString("query",
mcp.Required(),
mcp.Description("Search query for GitHub documentation. Examples: 'actions workflow syntax', 'pull request review', 'GitHub Pages'"),
),
mcp.WithString("version",
mcp.Description("GitHub version to search. Options: 'dotcom' (default, free/pro/team), 'ghec' (GitHub Enterprise Cloud), or a specific GHES version like '3.12'"),
),
mcp.WithString("language",
mcp.Description("Language code for documentation. Options: 'en' (default), 'es', 'ja', 'pt', 'zh', 'ru', 'fr', 'ko', 'de'"),
),
mcp.WithNumber("max_results",
mcp.Description("Maximum number of results to return (default: 10, max: 100)"),
),
),
func(_ context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
query, err := RequiredParam[string](request, "query")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}

version, err := OptionalParam[string](request, "version")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
if version == "" {
version = "dotcom"
}

language, err := OptionalParam[string](request, "language")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
if language == "" {
language = "en"
}

maxResults, err := OptionalIntParam(request, "max_results")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}

// Check if max_results was explicitly provided
_, maxResultsProvided := request.GetArguments()["max_results"]
if maxResultsProvided {
// Validate max_results only if it was provided
if maxResults < 1 || maxResults > 100 {
return mcp.NewToolResultError("max_results must be between 1 and 100"), nil
}
} else {
// Use default if not provided
maxResults = 10
}

// Build the search URL with client_name parameter
searchURL := fmt.Sprintf("https://docs.github.com/api/search/v1?version=%s&language=%s&query=%s&limit=%d&client_name=github-mcp-server",
url.QueryEscape(version),
url.QueryEscape(language),
url.QueryEscape(query),
maxResults,
)

// Make the HTTP request
// #nosec G107 - URL is constructed from validated parameters with proper escaping
resp, err := http.Get(searchURL)
Comment on lines +107 to +108

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

The nosec comment justifies URL construction with proper escaping, but the URL concatenation in line 99-104 usesurl.QueryEscape which is intended for query parameter values. For the entire URL construction, consider usingurl.Values withEncode() or ensure each component is escaped with the appropriate function (e.g.,url.PathEscape for path segments if needed).

Copilot uses AI. Check for mistakes.
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to search GitHub Docs: %v", err)), nil
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return mcp.NewToolResultError(fmt.Sprintf("GitHub Docs API returned status %d: %s", resp.StatusCode, string(body))), nil
}

// Parse the response
body, err := io.ReadAll(resp.Body)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to read response body: %v", err)), nil
}

var searchResp DocsSearchResponse
if err := json.Unmarshal(body, &searchResp); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to parse response: %v", err)), nil
}

// Format the results
result := map[string]interface{}{
"total_results": searchResp.Meta.Found.Value,
"search_time": searchResp.Meta.Took.PrettyMs,
"results": searchResp.Hits,
}

resultJSON, err := json.Marshal(result)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to format results: %v", err)), nil
}

return mcp.NewToolResultText(string(resultJSON)), nil
}
}
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp