Skip to main content
Glama

slim-github-mcp

A read-only GitHub MCP server that returns small results.

Most GitHub MCP servers hand the model raw GitHub API objects. That is fine for a frontier model behind a fast API and painful for a local one: a single page of repository search results is around 14 KB of JSON (~3.5k tokens), most of it URLs and permission flags nothing will ever read. Add ~7k tokens of tool schemas on top and a locally-hosted model can spend minutes on "list my repositories" — or never finish.

This server takes the opposite position. Every tool returns a handful of useful fields, every list is capped server-side, and the whole tool surface is nine functions. The model cannot pull a huge payload, no matter what arguments it invents.

typical GitHub MCP

slim-github-mcp

tool schemas

~27 tools, ~7.4k tokens

9 tools, ~830 tokens

"my public repos"

not a tool — needs a search

gh_my_repos(visibility="public")

one repo listing

~14 KB (30 full objects)

~2.4 KB (10 trimmed objects)

writes

usually available

impossible by construction

Tools

Tool

Returns

gh_whoami()

The authenticated account: login, name, public repo count

gh_my_repos(visibility, limit, page)

Your own repos, newest-updated first. visibility: all | public | private

gh_user_repos(username, limit, page)

Public repos of any user or org

gh_search_repos(query, limit, sort)

Repository search. sort: stars | forks | updated

gh_search_code(query, limit)

Code search — repo, path and URL per hit, no snippets

gh_issues(repo, state, limit)

Issues of owner/name

gh_pulls(repo, state, limit)

Pull requests of owner/name

gh_commits(repo, limit, branch)

Recent commits — sha, date, author, subject line

gh_file(repo, path, ref)

One file's contents, or a directory listing

Every limit defaults to 10 and is clamped to 30. gh_file truncates at 20k characters and says so via a truncated flag. Repos come back as full_name, private, a 160-character description, language, stars, updated, url — nothing else.

There is deliberately no write path: the client only ever issues GET to api.github.com.

Related MCP server: GitHub MCP Server

Getting a GitHub token

The server needs one token, used for every call. Only read access is required.

  1. Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token.

  2. Set an expiry and choose which repositories the token may see — Public repositories only if you never want private data to leave GitHub, or All repositories if you want gh_my_repos(visibility="private") to work.

  3. Under Repository permissions, grant read-only access to what you actually need:

    • Metadata: Read-only — required, and enough for repo listings and search

    • Contents: Read-only — for gh_file and gh_commits

    • Issues: Read-only — for gh_issues

    • Pull requests: Read-only — for gh_pulls

  4. Leave every Account permission alone.

  5. Copy the token — GitHub shows it once.

A classic token with the repo scope also works, but it is far broader than this server needs; prefer a fine-grained one.

Unauthenticated GitHub API calls are limited to 60 requests/hour, so a token is not optional in practice. With one you get 5,000/hour.

Installation

git clone https://github.com/0xBakeer/slim-github-mcp.git
cd slim-github-mcp

python3 -m venv venv
./venv/bin/pip install -r requirements.txt

cp .env.example .env
$EDITOR .env            # put your token in GITHUB_MCP_TOKEN

Run it:

set -a; . ./.env; set +a
./venv/bin/uvicorn slim_github_mcp.main:app --host 127.0.0.1 --port "${GITHUB_MCP_PORT:-9130}"

Check it came up, and that the token works:

curl -s http://127.0.0.1:9130/api/health
curl -s -H "Authorization: Bearer $GITHUB_MCP_SECRET" \
     'http://127.0.0.1:9130/api/my-repos?visibility=public&limit=5'

The MCP endpoint itself is:

http://127.0.0.1:9130/tools/mcp/v1

It speaks streamable HTTP, so any MCP client that accepts a URL can use it.

Configuration

Variable

Default

Meaning

GITHUB_MCP_TOKEN

GitHub token used for all API calls. Required.

GITHUB_MCP_SECRET

(empty)

Shared secret clients must send as Authorization: Bearer <secret>. Empty disables auth.

GITHUB_MCP_PORT

9130

Port to listen on.

GITHUB_MCP_PUBLIC_HOST

(empty)

Public hostname when behind a reverse proxy, e.g. github-mcp.example.com.

Set GITHUB_MCP_SECRET if the port is reachable by anything but localhost. The server holds a token that may be able to read your private repositories, and it does not otherwise authenticate callers. Generate one with openssl rand -hex 24.

GITHUB_MCP_PUBLIC_HOST exists because MCP enables DNS-rebinding protection by default: requests arriving through a reverse proxy carry the public Host header and are rejected unless that hostname is declared. Symptom if you forget it is a 400 from the MCP endpoint while /api/health answers fine.

Running as a service

scripts/github-mcp.service is a systemd unit to adapt — set User, the paths, and point EnvironmentFile at a root-owned 0600 file holding the variables above. Keep the token out of the unit file itself.

There is also a Dockerfile:

docker build -t slim-github-mcp .
docker run -d --name github-mcp -p 127.0.0.1:9130:9130 --env-file .env slim-github-mcp

Behind a reverse proxy

Nothing unusual, but MCP streams, so buffering must be off:

location /tools/mcp/ {
    proxy_pass http://127.0.0.1:9130;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 3600s;
}

Set GITHUB_MCP_PUBLIC_HOST to the hostname you proxy from.

Using it with Open WebUI

Open WebUI speaks MCP natively (0.6.x and later). Register the server with the helper script:

export OPEN_WEBUI_URL=https://webui.example.com
export OPEN_WEBUI_KEY=sk-...                      # Settings -> Account -> API keys
export GITHUB_MCP_URL=http://127.0.0.1:9130/tools/mcp/v1
export GITHUB_MCP_SECRET=...                      # if you set one

./scripts/register-open-webui.sh

It merges the entry into Open WebUI's existing tool servers (matched by id, so re-running just updates it) and then prints the tools it discovered:

==> Verifying tool discovery
    9 tools: gh_whoami, gh_my_repos, gh_user_repos, ...

To do it by hand instead: Admin Settings → Tools → Add Tool Server, type MCP, URL as above, Auth Bearer with your secret.

Two things that are easy to miss:

  • Enable the tool in the chat's tool picker. A registered server is not automatically offered to the model.

  • If you pin tools per model (Workspace → Models → Tools), add it there too. Open WebUI stores that as server:mcp:<id>. Rename the server's id later and the pinned reference silently resolves to nothing — the model keeps answering, just without the tools, usually by guessing.

Worth knowing: calling /api/chat/completions directly with tool_ids does not attach tool servers. Tool wiring happens in the frontend, so test through the UI.

License

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides comprehensive access to GitHub repositories, issues, pull requests, commits, user profiles, and statistics through 10 tools with natural language query support and advanced search capabilities.
    -
  • F
    license
    B
    quality
    D
    maintenance
    Enables AI assistants to inspect local Git repositories and interact with the GitHub API for reading commits, diffs, files, issues, comments, pull requests, and project boards.
    10
    100 npm
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to answer natural-language GitHub queries by listing repositories, issues, pull requests, branches, commits, and files, as well as performing writes with dry-run and confirmation safeguards.
    -