mcp-github-app-auth

legido-ai/mcp-github-app-auth

3.2

If you are the rightful owner of mcp-github-app-auth and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

An MCP server that uses GitHub App authentication for GitHub operations.

MCP GitHub App Server

A lightweight MCP (Model Context Protocol) server that provides GitHub operations using GitHub App authentication instead of personal access tokens.

Table of Contents

Prerequisites

  • A GitHub App installed with repository permissions for Contents (Read & write) and Pull requests (Read & write)
  • Required environment variables:
    • GITHUB_APP_ID - Your GitHub App ID
    • GITHUB_PRIVATE_KEY - Your GitHub App private key (PEM format)
    • GITHUB_INSTALLATION_ID - Your GitHub App installation ID

Tools

The server implements the standard MCP protocol and provides one tool:

  • get_token: Obtain a temporary GitHub token for accessing private repositories using GitHub App authentication
    • Parameters:
      • owner (string, required): GitHub repository owner/organization
      • repo (string, required): GitHub repository name
    • Returns: A temporary GitHub token (valid for ~1 hour) that can be used with Git commands and GitHub REST API calls

What is get_token?

The get_token tool generates a temporary GitHub authentication token that can be used for various Git operations AND GitHub API calls. This is NOT just for cloning - the token can be used for:

Git Operations:

  • git clone: Clone private repositories
  • git push: Push commits to remote repositories
  • git pull: Pull updates from remote repositories
  • git fetch: Fetch remote branches and tags
  • Any other Git operation that requires authentication

GitHub REST API Operations:

  • Create/manage issues: Create, update, comment on issues
  • Pull requests: Create, review, merge pull requests
  • Repository management: List contents, download files, get repository info
  • Releases: Create and manage releases
  • Any GitHub REST API endpoint: The token works with all authenticated API operations

Token Format:

For Git operations, use the token in URLs:

https://x-access-token:<GITHUB_TOKEN>@github.com/<ORGANIZATION>/<REPOSITORY>.git

For GitHub REST API operations, use the token in the Authorization header:

Authorization: Bearer <GITHUB_TOKEN>

Important Notes for Agents:

  • The token is temporary and expires after approximately 1 hour
  • The token can be used for ANY Git operation that requires authentication (clone, push, pull, fetch, etc.)
  • The token can also be used for ANY GitHub REST API operation (create issues, PRs, manage repos, etc.)
  • You do NOT need to call get_token separately for each operation - one token works for all Git and API operations
  • If an operation fails with authentication errors, the token may have expired - simply call get_token again to get a fresh token

This server does not perform Git operations itself, but provides temporary GitHub tokens for use with standard Git commands.

Installation

pip install .

Usage

Docker Usage

Pull the pre-built image from GitHub Container Registry:

docker pull ghcr.io/legido-ai/mcp-github-app-auth:latest

Or build locally from source:

docker build . -t mcp-github-app-auth

Testing the Server

This server implements the Model Context Protocol (MCP), which requires a proper initialization handshake before any operations can be performed. Direct JSON-RPC requests without initialization will be rejected.

Direct JSON-RPC Commands with Initialization

To test the server, you must send the full initialization sequence manually:

  1. Get the tools:
(
  echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "manual-test", "version": "1.0"}}}'; \
  echo '{"jsonrpc": "2.0", "method": "notifications/initialized"}'; \
  echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}'
) | docker run -i --rm \
  -e GITHUB_APP_ID="$GITHUB_APP_ID" \
  -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
  -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
  ghcr.io/legido-ai/mcp-github-app-auth
  1. Get a token. In this example we want to get a token for private Github repository https://github.com/my-org/my-private-repo:
(
  echo '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "manual-test", "version": "1.0"}}}'; \
  echo '{"jsonrpc": "2.0", "method": "notifications/initialized"}'; \
  echo '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "my-org", "repo": "my-private-repo"}}}'
) | docker run -i --rm \
  -e GITHUB_APP_ID="$GITHUB_APP_ID" \
  -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
  -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
  ghcr.io/legido-ai/mcp-github-app-auth

Using with MCP Clients:

The server is designed to be used with MCP-compatible clients such as:

  • Claude Desktop/Code
  • Google Gemini CLI
  • Other MCP-compatible AI assistants

See the integration sections below for setup instructions.

Note on Direct JSON-RPC Testing:

MCP requires a three-step initialization sequence before accepting requests:

  1. Client sends initialize request with protocol version and capabilities
  2. Server responds with its capabilities
  3. Client sends initialized notification
  4. Only then can the client send requests like tools/list or tools/call

Why direct commands without initialization don't work:

Simple echo commands bypass the initialization sequence and will fail with:

WARNING:root:Failed to validate request: Received request before initialization was complete

This is correct MCP protocol behavior. The commands above include the full initialization sequence required by the protocol.

Using the Token for Git Operations

Once you have the token, you can use it for various Git operations:

Clone a repository:
git clone https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git
Clone a specific branch:
git clone -b feature-branch https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git
Push to a repository:
cd private-repo
# Make some changes
git add .
git commit -m "Update files"
git push https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git main
Pull updates:
git pull https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git main
Fetch remote branches:
git fetch https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git
Set as remote URL:
git remote set-url origin https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git
# Now you can use regular git push/pull commands
git push origin main

Using the Token for GitHub API Operations

The token can also be used with GitHub's REST API for various operations beyond Git commands:

Create an Issue:
curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo/issues \
  -d '{"title":"Found a bug","body":"Description of the issue","labels":["bug"]}'
Create a Pull Request:
curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo/pulls \
  -d '{"title":"Amazing new feature","body":"Please pull these changes","head":"feature-branch","base":"main"}'
Add a Comment to an Issue:
curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo/issues/1/comments \
  -d '{"body":"This is a comment on the issue"}'
List Repository Contents:
curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo/contents/path/to/directory
Download a File from Private Repository:
curl -H "Authorization: Bearer ghs_tokenhere" \
  -H "Accept: application/vnd.github.v3.raw" \
  -o downloaded-file.txt \
  -L https://api.github.com/repos/fictional-org/private-repo/contents/path/to/file.txt
Get Repository Information:
curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo
List Pull Requests:
curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo/pulls
Create a Release:
curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer ghs_tokenhere" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/fictional-org/private-repo/releases \
  -d '{"tag_name":"v1.0.0","name":"Release v1.0.0","body":"Description of the release"}'

End-to-End Example

Example 1: Clone a Repository

  1. Pull the pre-built image:
docker pull ghcr.io/legido-ai/mcp-github-app-auth:latest
  1. Get a GitHub token:
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "fictional-org", "repo": "private-repo"}}}' | \
  docker run -i --rm \
  -e GITHUB_APP_ID="$GITHUB_APP_ID" \
  -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
  -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
  ghcr.io/legido-ai/mcp-github-app-auth:latest
  1. Use the returned token to clone the repository:
# Extract the token from the response (example shows ghs_tokenhere)
git clone https://x-access-token:ghs_tokenhere@github.com/fictional-org/private-repo.git

Example 2: Clone, Modify, and Push

  1. Get a GitHub token:
TOKEN=$(echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "fictional-org", "repo": "private-repo"}}}' | \
  docker run -i --rm \
  -e GITHUB_APP_ID="$GITHUB_APP_ID" \
  -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
  -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
  ghcr.io/legido-ai/mcp-github-app-auth:latest | \
  jq -r '.result.content[0].text' | grep -oP 'ghs_\w+')
  1. Clone the repository:
git clone https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git
cd private-repo
  1. Make changes and push:
echo "# New content" >> README.md
git add README.md
git commit -m "Update README"
git push https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git main

Example 3: Using Token with Multiple Operations

# Get token
TOKEN=$(echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "fictional-org", "repo": "private-repo"}}}' | \
  docker run -i --rm \
  -e GITHUB_APP_ID="$GITHUB_APP_ID" \
  -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
  -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
  ghcr.io/legido-ai/mcp-github-app-auth:latest | \
  jq -r '.result.content[0].text' | grep -oP 'ghs_\w+')

# Clone repository
git clone https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git
cd private-repo

# Set remote URL with token for subsequent operations
git remote set-url origin https://x-access-token:$TOKEN@github.com/fictional-org/private-repo.git

# Now you can use regular git commands
git pull origin main
git push origin main
git fetch --all

Integration with Claude Desktop

⚠️ CRITICAL: Variable Expansion Does Not Work

Claude Desktop/Code does NOT support environment variable expansion in configuration files.

This is a fundamental limitation of Claude's configuration system. If you try to use variables like $GITHUB_APP_ID, Claude will treat them as literal strings, not as references to environment variables.

What This Means:

  • GITHUB_APP_ID=$GITHUB_APP_ID → Claude passes the literal string "$GITHUB_APP_ID" to Docker
  • ❌ This causes authentication to fail with errors like "Could not parse the provided public key"
  • ❌ The MCP server receives invalid credentials and cannot authenticate with GitHub

Why This Happens: Claude's JSON configuration parser does not perform shell-style variable substitution. The $VARIABLE syntax is passed unchanged to the underlying command, causing the Docker container to receive the literal string instead of the actual credential values.

❌ This Configuration WILL NOT WORK:

{
  "projects": {
    "/path/to/your/project": {
      "mcpServers": {
        "github": {
          "command": "docker",
          "args": [
            "run",
            "-i",
            "--rm",
            "-e",
            "GITHUB_APP_ID=$GITHUB_APP_ID",    ← Passed as literal "$GITHUB_APP_ID"
            "-e",
            "GITHUB_PRIVATE_KEY=$GITHUB_PRIVATE_KEY",    ← Passed as literal string
            "-e",
            "GITHUB_INSTALLATION_ID=$GITHUB_INSTALLATION_ID",    ← Not expanded
            "ghcr.io/legido-ai/mcp-github-app-auth:latest"
          ]
        }
      }
    }
  }
}

Result: Authentication fails because the MCP receives literal strings instead of your actual credentials.

Option 1: Manual Configuration (Not Recommended)

You can manually edit ~/.claude.json with hardcoded values, but this is not recommended for security reasons:

{
  "projects": {
    "/path/to/your/project": {
      "mcpServers": {
        "github": {
          "command": "docker",
          "args": [
            "run",
            "-i",
            "--rm",
            "-e",
            "GITHUB_APP_ID=123456",
            "-e",
            "GITHUB_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\n...",
            "-e",
            "GITHUB_INSTALLATION_ID=78910",
            "ghcr.io/legido-ai/mcp-github-app-auth:latest"
          ]
        }
      }
    }
  }
}

✅ Option 2: Automated Setup Script (Recommended)

Why You Need This Script:

Since Claude cannot expand variables, you need an external script to:

  1. Read your environment variables ($GITHUB_APP_ID, etc.)
  2. Extract their actual values
  3. Write those literal values into Claude's ~/.claude.json configuration file

This script automates the process and is the recommended solution for setting up the MCP server with Claude.

The Script:

This script is available in the docker-claude-code repository or can be copied from below:

#!/bin/bash
#
# Setup script for configuring GitHub MCP server in Claude Code
# This script properly expands environment variables when adding the MCP server configuration
#

set -e

echo "Configuring GitHub MCP server for Claude Code..."

# Check if required environment variables are set
if [ -z "$GITHUB_APP_ID" ] || [ -z "$GITHUB_INSTALLATION_ID" ] || [ -z "$GITHUB_PRIVATE_KEY" ]; then
    echo "ERROR: Missing required environment variables!"
    echo "Please ensure the following environment variables are set:"
    echo "  - GITHUB_APP_ID"
    echo "  - GITHUB_INSTALLATION_ID"
    echo "  - GITHUB_PRIVATE_KEY"
    exit 1
fi

# Check if Python is available
if ! command -v python3 &> /dev/null; then
    echo "ERROR: python3 is required but not found in PATH"
    exit 1
fi

# Ensure .claude.json exists
if [ ! -f "$HOME/.claude.json" ]; then
    echo "Creating $HOME/.claude.json..."
    echo '{}' > "$HOME/.claude.json"
fi

# Use Python to safely update the JSON configuration with expanded environment variables
python3 << 'EOFPYTHON'
import json
import os
import sys

config_path = os.path.expanduser("~/.claude.json")

# Read the current config
try:
    with open(config_path, "r") as f:
        config = json.load(f)
except Exception as e:
    print(f"ERROR: Failed to read {config_path}: {e}", file=sys.stderr)
    sys.exit(1)

# Get environment variables with actual values
github_app_id = os.environ.get("GITHUB_APP_ID")
github_installation_id = os.environ.get("GITHUB_INSTALLATION_ID")
github_private_key = os.environ.get("GITHUB_PRIVATE_KEY")

if not all([github_app_id, github_installation_id, github_private_key]):
    print("ERROR: Missing required environment variables", file=sys.stderr)
    sys.exit(1)

# Create MCP server configuration with expanded values
mcp_config = {
    "command": "docker",
    "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        f"GITHUB_APP_ID={github_app_id}",
        "-e",
        f"GITHUB_PRIVATE_KEY={github_private_key}",
        "-e",
        f"GITHUB_INSTALLATION_ID={github_installation_id}",
        "ghcr.io/legido-ai/mcp-github-app-auth:latest"
    ]
}

# Get current working directory
cwd = os.getcwd()

# Initialize nested structure if needed
if "projects" not in config:
    config["projects"] = {}
if cwd not in config["projects"]:
    config["projects"][cwd] = {}
if "mcpServers" not in config["projects"][cwd]:
    config["projects"][cwd]["mcpServers"] = {}

# Add/update the github MCP server
config["projects"][cwd]["mcpServers"]["github"] = mcp_config

# Create backup
backup_path = f"{config_path}.backup"
try:
    with open(config_path, "r") as f:
        with open(backup_path, "w") as b:
            b.write(f.read())
except Exception:
    pass  # Ignore backup errors

# Write back the updated config
try:
    with open(config_path, "w") as f:
        json.dump(config, f, indent=2)
    print(f"✓ MCP configuration updated successfully for project: {cwd}")
    print(f"✓ Backup saved to: {backup_path}")
except Exception as e:
    print(f"ERROR: Failed to write {config_path}: {e}", file=sys.stderr)
    sys.exit(1)

EOFPYTHON

echo ""
echo "GitHub MCP server configured successfully!"
echo ""
echo "To verify the configuration, run:"
echo "  claude mcp list"
echo ""
echo "NOTE: This configuration uses expanded environment variable values."
echo "If you change your GitHub App credentials, you must run this script again."

Step-by-Step Setup Instructions:

  1. Save the script as setup-mcp-github.sh

  2. Make it executable:

    chmod +x setup-mcp-github.sh
    
  3. Set your environment variables with your actual GitHub App credentials:

    export GITHUB_APP_ID="123456"
    export GITHUB_INSTALLATION_ID="78910"
    export GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
    MIIEpAIBAAKCAQEA...
    -----END RSA PRIVATE KEY-----"
    
  4. Run the setup script:

    ./setup-mcp-github.sh
    

    The script will:

    • ✓ Validate that all required environment variables are set
    • ✓ Read the actual values from your environment
    • ✓ Create/update ~/.claude.json with the literal values (not variable references)
    • ✓ Create a backup of your existing configuration
  5. Verify the configuration:

    claude mcp list
    

    You should see:

    ✓ github: docker run -i --rm ... ghcr.io/legido-ai/mcp-github-app-auth:latest - Connected
    

Important Notes:

  • The script writes the actual credential values (not $VARIABLE references) into ~/.claude.json
  • If you change your GitHub App credentials, you must run this script again to update the configuration
  • The script creates a backup at ~/.claude.json.backup before making changes

Integration with Google Gemini CLI

IMPORTANT: Google Gemini CLI also does not support environment variable expansion in configuration files. Variables like $GITHUB_APP_ID will be passed as literal strings, not their values.

You must manually edit your Gemini CLI settings.json (located at ~/.gemini/settings.json) with the actual expanded values:

{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITHUB_APP_ID=123456",
        "-e",
        "GITHUB_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\n...",
        "-e",
        "GITHUB_INSTALLATION_ID=78910",
        "ghcr.io/legido-ai/mcp-github-app-auth:latest"
      ],
      "trust": true,
      "timeout": 30000
    }
  }
}

Verify the connection:

gemini mcp list

You should see:

✓ github: docker run -i --rm ... ghcr.io/legido-ai/mcp-github-app-auth:latest (stdio) - Connected

Troubleshooting

Common Authentication Errors

Error: "Could not parse the provided public key"

Symptom:

ERROR: Could not parse the provided public key
Failed to get installation token: 401 ...

Cause: This error occurs when Claude passes literal variable names (like "$GITHUB_PRIVATE_KEY") to the MCP server instead of the actual private key value.

Solution:

  1. ✅ Use the automated setup script to configure Claude
  2. ❌ Do NOT use $VARIABLE syntax in ~/.claude.json
  3. ✅ Ensure your ~/.claude.json contains the actual credential values, not variable references

How to Verify:

# Check what's actually in your configuration
cat ~/.claude.json | grep -A 5 "GITHUB_PRIVATE_KEY"

If you see "$GITHUB_PRIVATE_KEY" or "GITHUB_PRIVATE_KEY=$GITHUB_PRIVATE_KEY", the variable was not expanded. Re-run the setup script.

Error: "Missing required environment variables"

Symptom:

ERROR: Missing GITHUB_APP_ID / GITHUB_INSTALLATION_ID / GITHUB_PRIVATE_KEY

Cause: The MCP server is not receiving the required environment variables.

Solution:

  1. Verify environment variables are set before running the setup script:
    echo $GITHUB_APP_ID
    echo $GITHUB_INSTALLATION_ID
    echo $GITHUB_PRIVATE_KEY | head -1
    
  2. If any are empty, set them and re-run the setup script
  3. Ensure you're setting variables in the same shell session where you run the setup script
Error: MCP Server Shows as "Disconnected"

Symptom:

✗ github: docker run -i --rm ... ghcr.io/legido-ai/mcp-github-app-auth:latest - Disconnected

Possible Causes and Solutions:

  1. Docker is not running:

    docker ps  # Should not error
    
  2. Docker image is not available:

    docker pull ghcr.io/legido-ai/mcp-github-app-auth:latest
    
  3. Invalid credentials in configuration:

    • Re-run the setup script with correct credentials
    • Verify credentials work by testing manually:
      echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "your-org", "repo": "your-repo"}}}' | \
        docker run -i --rm \
        -e GITHUB_APP_ID="$GITHUB_APP_ID" \
        -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
        -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
        ghcr.io/legido-ai/mcp-github-app-auth:latest
      
Error: "401 Unauthorized" from GitHub API

Symptom:

Failed to get installation token: 401 {"message":"Bad credentials",...}

Possible Causes:

  1. Incorrect GitHub App ID:

    • Verify at: https://github.com/settings/apps/your-app
    • The App ID is shown at the top of the settings page
  2. Wrong Private Key:

    • Regenerate if needed at: https://github.com/settings/apps/your-app
    • Scroll to "Private keys" section
    • Ensure you're using the complete key including headers:
      -----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----
      
  3. Incorrect Installation ID:

    • Find it in the installation URL: https://github.com/settings/installations/INSTALLATION_ID
    • Or via API: curl -H "Authorization: Bearer <jwt_token>" https://api.github.com/app/installations
How to Test Configuration Manually

To verify your setup works before configuring Claude:

# 1. Set environment variables
export GITHUB_APP_ID="your-app-id"
export GITHUB_INSTALLATION_ID="your-installation-id"
export GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"

# 2. Test the MCP server directly
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "get_token", "arguments": {"owner": "legido-ai", "repo": "tasks"}}}' | \
  docker run -i --rm \
  -e GITHUB_APP_ID="$GITHUB_APP_ID" \
  -e GITHUB_PRIVATE_KEY="$GITHUB_PRIVATE_KEY" \
  -e GITHUB_INSTALLATION_ID="$GITHUB_INSTALLATION_ID" \
  ghcr.io/legido-ai/mcp-github-app-auth:latest

# 3. You should get a response with a token like:
# {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"GitHub token for legido-ai/tasks: ghs_..."}]}}

If this works, your credentials are correct and you can proceed with Claude configuration.

Testing

Run tests with:

python3 -m pytest tests/ -v

Security Notes

  • Installation tokens expire after approximately 1 hour
  • The server caches and refreshes tokens automatically