An MCP server that provides access to the GitHub GraphQL API, allowing execution of arbitrary GraphQL queries and mutations against GitHub.
The server exposes a single tool 'github_execute_graphql' with a lengthy, well-structured description containing examples and error handling guidance. However, the tool definition relies on a very generic pattern (execute arbitrary GraphQL) that violates the single-responsibility principle. The input schema is visible and typed (query: string, variables: object), but lacks critical validation constraints. The description, while comprehensive (~1800 chars), exceeds the recommended 10-1024 char range and includes example values that could be literal-copied by LLMs. Parameter descriptions are present but variables parameter is underdescribed ('optional dictionary' lacks format/constraint detail). Output is documented as returning the raw GitHub API response (JSON), but the schema structure is not formally declared, just 'returns a dict'. No tool annotations (readOnlyHint, destructiveHint) despite handling both queries and mutations. Error handling section exists in description but lacks actionable recovery steps for specific error codes. Overall, the tool is functional but design pattern gaps and lack of formal output schema documentation hold it back from a higher score.
Executes an arbitrary GraphQL query or mutation against the GitHub API. This powerful tool provides unlimited flexibility for any GitHub GraphQL operation by directly passing queries with full control over selection sets and variables. ## GraphQL Introspection You can discover the GitHub API schema using GraphQL introspection queries such as: ```graphql # Get all available query types query IntrospectionQuery { __schema { queryType { name } types { name kind description fields { name description args { name description type { name kind } } type { name kind } } } } } # Get details for a specific type query TypeQuery { __type(name: "Repository") { name description fields { name description type { name kind ofType { name kind } } } } } ``` ## Common Operation Patterns ### Fetching a repository ```graphql query GetRepository($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { name description url stargazerCount forkCount issues(first: 10, states: OPEN) { nodes { title url createdAt } } } } ``` Variables: `{"owner": "octocat", "name": "Hello-World"}` ### Fetching user information ```graphql query GetUser($login: String!) { user(login: $login) { name bio avatarUrl url repositories(first: 10, orderBy: {field: STARGAZERS, direction: DESC}) { nodes { name description stargazerCount } } } } ``` Variables: `{"login": "octocat"}` ### Creating an issue ```graphql mutation CreateIssue($repositoryId: ID!, $title: String!, $body: String) { createIssue(input: { repositoryId: $repositoryId, title: $title, body: $body }) { issue { id url number } } } ``` ### Searching repositories ```graphql query SearchRepositories($query: String!, $first: Int!) { search(query: $query, type: REPOSITORY, first: $first) { repositoryCount edges { node { ... on Repository { name owner { login } description url stargazerCount } } } } } ``` Variables: `{"query": "language:javascript stars:>1000", "first": 10}` ## Pagination For paginated results, use the `after` parameter with the `endCursor` from previous queries: ```graphql query GetNextPage($login: String!, $after: String) { user(login: $login) { repositories(first: 10, after: $after) { pageInfo { hasNextPage endCursor } nodes { name } } } } ``` ## Error Handling Tips - Check for the "errors" array in the response - Common error reasons: - Invalid GraphQL syntax: verify query structure - Unknown fields: check field names through introspection - Missing required fields: ensure all required fields are in queries - Permission issues: verify API token has appropriate permissions - Rate limits: GitHub has API rate limits which may be exceeded ## Variables Usage Variables should be provided as a Python dictionary where: - Keys match the variable names defined in the query/mutation - Values follow the appropriate data types expected by GitHub - Nested objects must be structured according to GraphQL input types
Tool performs two distinct responsibilities: query execution AND mutation execution. Should split into separate tools (e.g., github_query_graphql and github_mutate_graphql) to allow LLM to disambiguate intent and apply appropriate safety checks.
Tool description is 1800+ characters and includes example GraphQL queries and response fields. LLMs tend to literal-copy example queries. Replace with constraint-based description (10-200 chars) and move examples to separate discovery tools or docs.
No input validation or enum constraints. 'variables' parameter is documented as 'optional dictionary' but lacks format specification (required keys, type hints per key, nesting depth limits). This invites malformed GraphQL variable payloads.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 58 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 37 | - | v1 |
Output schema is not formally documented. Tool returns raw GitHub API response (dict with 'data' and 'errors' fields), but LLMs cannot infer the structure of 'data' field or pagination semantics. Declare output schema with field types.
No tool annotations for destructiveness. Mutations (createIssue, updateRepository) are executable via the same tool as read queries, but no destructiveHint or confirmation-request pattern to warn LLMs. Agents may accidentally execute write operations.
Error handling guidance in description ('Check for the errors array', 'Common error reasons') is narrative, not machine-readable. Function returns dict with errors field but does not categorize as retryable vs. user-fixable vs. fatal, nor does it provide recovery hints (e.g., 'Rate limit exceeded. Retry after X seconds').
GitHub token is required but exposed to environment without server-side injection pattern. While not a parameter, the reliance on GITHUB_TOKEN env var and the lack of token rotation/expiry docs suggest weak secrets management.
No pagination support. Tool can execute arbitrary queries, but no guidance or enforcement of pagination limits. An LLM could request all issues in a large repo (thousands of items), exhausting context and timeout.