GitHub Client

The GitHub REST api, as the Smarter Project MCP server’s tools call it.

github_request() sends one request to api.github.com, with the caller’s own GitHub token, or anonymously. Its callers are smarter.apps.mcpserver.github.issues, which searches and reads issues, and opens issues and comments as the caller, and smarter.apps.mcpserver.github.pulls, which opens pull requests as the caller. refuse_secrets() stops every one of them from writing a credential to GitHub.

The caller’s token. An MCP client sends the user’s GitHub classic personal access token in the request’s Authorization: Bearer header (see smarter.apps.mcpserver.protocol.views). validate_token() accepts only a classic token, ghp_..., which can write to any public repository with the public_repo scope. A fine-grained token, github_pat_..., can write only to the repositories of the account or organization that it was created for, so it is refused with an explanation. The platform holds no GitHub credential that can write.

The token is sent only to api.github.com, without redirects, and is never logged, cached, stored, or passed as a tool argument, which the LLM would see. explain_failure() turns GitHub’s errors into messages for the LLM, e.g. a token without the public_repo scope.

Note

Experimental. The MCPServer was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented.

smarter.apps.mcpserver.github.client.explain_failure(response, repository, action, not_found=None)[source]

Explain why GitHub refused a request, for the LLM.

Parameters:
  • response (Response) – GitHub’s response.

  • repository (ProjectRepository) – The repository.

  • action (str) – What the request would have done, e.g. open the issue.

  • not_found (str | None) – What a 404 means, if not that the repository was not found.

Return type:

str

Returns:

The explanation.

smarter.apps.mcpserver.github.client.github_request(method, path, token=None, json=None, params=None)[source]

Send one request to the GitHub REST api.

Parameters:
  • method (str) – The HTTP method, e.g. GET or POST.

  • path (str) – The path, e.g. /repos/smarter-sh/smarter/issues.

  • token (str | None) – The caller’s token, from validate_token(), or None to send the request anonymously.

  • json (TypeAliasType | None) – The request’s JSON body, if any.

  • params (dict[str, str] | None) – The request’s query parameters, if any.

Return type:

Response

Returns:

GitHub’s response, whatever its status.

Raises:

SmarterMCPServerToolError – If GitHub could not be reached.

smarter.apps.mcpserver.github.client.optional_token(token)[source]

Return a caller’s GitHub token for a request that also works anonymously, e.g. a search.

Only a classic personal access token is sent, so that a secret that is not GitHub’s, e.g. a Smarter api key in the Authorization header, never reaches GitHub.

Parameters:

token (SecretStr | None) – The token, from the request’s Authorization: Bearer header, or None.

Return type:

str | None

Returns:

The token’s value, or None to send the request anonymously.

smarter.apps.mcpserver.github.client.refuse_secrets(token, *texts)[source]

Refuse to write a credential to GitHub, where everything that the tools write is public.

The text of an issue, a comment or a pull request is often written from material that the LLM read, e.g. a log, which may hold a credential. The caller’s own GitHub token, and every credential that the Guardrail’s secret detectors recognize (api keys, AWS access keys, JWTs, private keys), are refused. The error never quotes the credential.

Parameters:
  • token (str) – The caller’s GitHub token, from validate_token().

  • texts (str) – The text that would be written.

Raises:

SmarterMCPServerToolError – If a text holds a credential.

Return type:

None

smarter.apps.mcpserver.github.client.validate_token(token)[source]

Return a caller’s GitHub token, if it is a classic personal access token.

Parameters:

token (SecretStr | None) – The token, from the request’s Authorization: Bearer header.

Return type:

str

Returns:

The token’s value.

Raises:

SmarterMCPServerToolError – If there is no token, or it is not a classic personal access token.