Skip to main content
Glama
Hemanth-hexo

GitHub Discovery MCP Server

by Hemanth-hexo
README.md
# Gitty

*An MCP server that helps Claude find, inspect, and compare open-source GitHub repos.*

[![Test](https://github.com/Hemanth-hexo/Git_mcp/actions/workflows/test.yml/badge.svg)](https://github.com/Hemanth-hexo/Git_mcp/actions/workflows/test.yml)

An MCP server that helps Claude find relevant open-source GitHub repositories for research, learning, or a project you're building — and then dig into a specific repo's structure, code, history, and branches once you've found it worth a closer look.

> **Try it now — genuinely public, no setup:** `https://git-mcp-rvrp.onrender.com/mcp` is live and open to anyone. In Claude, go to Settings → Connectors → Add custom connector, paste that URL, set Authentication to **None**, and connect — no token, no signup. It's free tier, so the first request after a few idle minutes can take 30-60 seconds to wake up — that's expected, just retry. See [Rate limits](#rate-limits) if you want higher limits than the shared free tier gives you.

## What it does

**Discovery** — find repos from a description or topic:

- `search_github_repos(query, filters)` — free-text search, ranked by a blend of stars and recent activity so an actively maintained project can beat a similarly popular but abandoned one
- `search_by_topic(topic, filters)` — search by GitHub's curated topic tags (e.g. `rag`, `llm-agent`) instead of free text
- `get_trending_repos(since, filters)` — repos created recently that are already gaining stars fast, as an approximation of "trending" (GitHub's API has no official trending endpoint)

**Inspection** — once you've picked a repo, look inside it:

- `get_repo_overview(repo)` — description, stars/forks/issues, license, topics, language breakdown, latest release, approx. contributor count, and a README preview
- `get_repo_structure(repo, path)` — browse the file tree one directory at a time
- `get_file_content(repo, path)` — read a specific file's contents
- `get_recent_commits(repo, branch, limit)` — recent commit history
- `list_branches(repo, limit)` — branches and what each currently points to

**Comparison** — deciding between a few candidates:

- `compare_repos(repos)` — 2-4 repos side by side as a table (stars, forks, issues, license, language, contributors, age, activity)

All the `repo` parameters above accept either `"owner/name"` or a full GitHub URL — you can paste the `full_name`/URL straight out of a search result.

**Shortcuts** — MCP clients that support "prompts" (Claude Desktop, Claude Code, claude.ai) surface these as slash commands, e.g. `/gitty:getinfo`:

- `/getinfo repo:<owner/name>` — full repo overview
- `/getcodeinfo repo:<owner/name> path:<file path>` — read and explain one file
- `/findrepos query:<what you're looking for>` — search
- `/comparerepos repos:<comma-separated list>` — side-by-side comparison

These don't add any capability beyond the tools above — they're just a shortcut for the handful of things people ask for most, so you don't have to phrase the same request in full sentences every time. See [tools/prompts.js](tools/prompts.js).

## Requirements

- Node.js 20 or later
- No GitHub account or API key required for light use — see [Rate limits](#rate-limits) for when you'll want one

## Run it locally (optional)

Most people should just use the shared link above. Run it on your own machine instead only if you want to skip Render entirely — e.g. for development, or to avoid any shared rate limits.

```bash
git clone https://github.com/Hemanth-hexo/Git_mcp.git
cd Git_mcp
npm install
```

**Or run it in Docker** (mainly useful for deploying somewhere other than Render, which builds natively and doesn't need this):

```bash
docker build -t gitty-mcp .
docker run -p 3000:3000 --env GITHUB_TOKEN=your_token_here gitty-mcp
```

Add to Claude Desktop's config (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`, Windows: `%APPDATA%\Claude\claude_desktop_config.json`), using the absolute path to `server.js`:

```json
{
  "mcpServers": {
    "gitty": {
      "command": "node",
      "args": ["/absolute/path/to/Git_mcp/server.js"]
    }
  }
}
```

Restart Claude Desktop. No token needed here — this runs as a local process, not over the network, so the HTTP auth in [Security](#security) doesn't apply. Optionally add `GITHUB_TOKEN` in an `env` block to raise GitHub's rate limits (see [Rate limits](#rate-limits)). For quick manual testing without Claude Desktop at all, `npm run inspect` opens a local web UI to call tools by hand.

## Deploy as a shared connector (a URL instead of a local install)

Everything above runs the server as a local process only you can use. To make it available to anyone — friends, strangers, whoever — without them installing anything, deploy [server-http.js](server-http.js) instead: it's the same tools over Streamable HTTP, so anyone can add it in Claude as a **custom connector** by pasting a URL (works on claude.ai, Claude Desktop, Cowork, and mobile — see [Anthropic's docs](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp)).

**Deploy to Render (free tier is fine to start):**

1. Push this repo to GitHub (already done if you're reading this from the repo).
2. On [render.com](https://render.com), create a new **Web Service** and connect this GitHub repo.
3. Set the **Build Command** to `npm install` and the **Start Command** to `npm run start:http`. Leave the instance type on **Free** to start.
4. Deploy. Render assigns a URL like `https://your-app-name.onrender.com` — MCP clients connect to `https://your-app-name.onrender.com/mcp` (note the `/mcp`, the bare domain only serves a health-check page).

That's it — **no token setup required.** The server is public by design: anyone with the URL can use it immediately.

*(Optional)* In Render's Environment tab, you can still add:
- `PUBLIC_HOST` — just the hostname (e.g. `your-app-name.onrender.com`, no `https://`). Locks the server to that hostname instead of accepting any `Host` header — protects against DNS-rebinding-style tricks, not a login of any kind.
- `GITHUB_TOKEN` — a personal access token this server falls back to for anonymous callers who don't bring their own (see [Rate limits](#rate-limits)). Optional; the server works fine without it.
- `GEMINI_API_KEY` — funds a small free daily trial of the AI-explanation feature for every visitor (see [AI explanations](#ai-explanations)). Optional; without it, that feature just asks people to bring their own AI API key instead.

**Connect in Claude:** Settings → Connectors → Add custom connector → paste `https://your-app-name.onrender.com/mcp` → set **Authentication** to **None** (this server doesn't use OAuth or any login) → connect. Share the URL with anyone — that's the whole distribution step, nothing else to hand out.

**Worth knowing:**

- Render's free tier spins the service down after 15 minutes of inactivity; the next request after that takes 30-60 seconds to wake it back up.
- Because it's genuinely open, GitHub's own rate limits are the only thing standing between this and abuse — see [Rate limits](#rate-limits) for how that's handled and what its limits are.

## REST API (for a web frontend, or anything that isn't an MCP client)

Everything above is for MCP clients (Claude, etc.). The same server also exposes a plain JSON REST API under `/api` — same deployment, same rate limiting, same bring-your-own-GitHub-token support, no MCP protocol involved. This is what a website or app would call directly. CORS is open (`Access-Control-Allow-Origin: *`) so it can be called straight from browser JavaScript on any origin — this is a fully public, read-only, unauthenticated-by-default API, so that doesn't widen access to anything.

| Method & path | Query params | What it does |
|---|---|---|
| `GET /api/search` | `q` (required), `language`, `minStars`, `limit` | Free-text repo search |
| `GET /api/search/topic` | `topic` (required), `language`, `minStars`, `limit` | Search by GitHub topic tag |
| `GET /api/trending` | `since` (`daily`\|`weekly`\|`monthly`), `language`, `minStars`, `limit` | New repos gaining stars fast |
| `GET /api/repos/:owner/:name` | — | Full repo overview |
| `GET /api/repos/:owner/:name/structure` | `path` | List files/folders at a path |
| `GET /api/repos/:owner/:name/file` | `path` (required) | Read one file's contents |
| `GET /api/repos/:owner/:name/commits` | `branch`, `limit` | Recent commits |
| `GET /api/repos/:owner/:name/branches` | `limit` | List branches |
| `POST /api/repos/:owner/:name/explain` | headers: `X-AI-Key`, `X-AI-Provider` (both optional) | AI-generated explanation of the repo — see [AI explanations](#ai-explanations) |
| `POST /api/compare` | body: `{"repos": ["owner/name", ...]}` (2-4) | Side-by-side comparison |

All responses are JSON. Send `Authorization: Bearer <your GitHub token>` on any request to use your own rate limit instead of the shared pool — identical to how the MCP connector's bring-your-own-token works. Errors come back as `{"error": "<code>", "message": "..."}` with a matching HTTP status (`400` bad input, `404` not found, `429` rate limited with a `Retry-After` header, `502`/`500` for upstream/unexpected failures) — internal details are never included, same policy as the MCP error path (see [Security](#security)).

Example:

```bash
curl "https://git-mcp-rvrp.onrender.com/api/search?q=rag&limit=3"
curl "https://git-mcp-rvrp.onrender.com/api/repos/facebook/react"
```

See [routes/api.js](routes/api.js) for the exact route definitions, and [core/](core) for the underlying logic — both the MCP tools and this API call the same functions there, so a bug fix or improvement in one benefits both automatically.

## Web frontend

A plain HTML/CSS/JS website in [web/](web) — search, repo detail (overview/files/commits/branches), and compare, all calling the REST API above. No build step, no framework: it's static files, so it deploys to Vercel (or any static host) by pointing it at the `web/` folder directly.

**Deploy to Vercel:**
1. Import this GitHub repo into Vercel.
2. Set **Root Directory** to `web`, framework preset to **Other** (no build command needed — it's static).
3. Deploy. That's it.

**Run it locally:**
```bash
cd web
npx serve .
```
It defaults to calling the live Render API. To point it at a local backend instead (e.g. while developing the API), open it with `?api=` before the `#`, e.g. `http://localhost:3000/?api=http://localhost:3000/api#/`.

**Security note on rendering repo content:** README files and AI explanations come from arbitrary public repos (or an AI model summarizing them) and are rendered as Markdown via [marked](https://github.com/markedjs/marked) — which does *not* sanitize embedded raw HTML on its own. Everything rendered this way is passed through [DOMPurify](https://github.com/cure53/DOMPurify) first (see `renderMarkdown()` in [web/app.js](web/app.js)); a malicious repo's README can't inject a working `<script>` tag through this page.

## AI explanations

The Overview tab has an "✨ Explain this repo with AI" button — a genuinely thorough, decision-ready briefing generated from the README, repo stats (license, activity, contributor count, archived status, etc.), *and* a small sample of the repo's actual source code, not just a summary of the README. `core/explain.js` picks a manifest file (`package.json`, `pyproject.toml`, `go.mod`, etc.) plus one or two representative source files — searching conventionally-named directories (`src`, `lib`, `packages`, ...) breadth-first when the real code isn't at the repo root, which is the common case — so the write-up can comment on actual code, not just what the README claims. It covers up to eight sections depending on what's available: **What it is**, **How it works**, **Code quality notes** (only when source was sampled), **Who it's for**, **Getting started**, **Strengths**, **Watch out for**, and a direct **Verdict** ("use this if ___, skip it if ___") — aiming for ~700-1000 words, enough that someone shouldn't need to go ask a different AI follow-up questions about the same repo. This is the one place in the whole project that calls an LLM; everything else is deterministic GitHub API aggregation.

Two ways it gets paid for:

1. **The operator's free trial** — if you (the operator) set a `GEMINI_API_KEY` environment variable (Google's Gemini API has an actual free tier, unlike most providers), every visitor gets a few free explanations per day, tracked per caller IP (see [lib/aiTrialQuota.js](lib/aiTrialQuota.js)) so it can't run up an unbounded bill. No key configured = no free trial; the button then just asks people to bring their own.
2. **Bring your own key** — anyone can add their own Gemini or Anthropic API key in the website's Settings panel (stored only in their browser, sent as `X-AI-Key`/`X-AI-Provider` headers directly to the API). Unlimited use, at their own cost, and it never touches the trial quota.

If neither is available for a given request, the endpoint fails clearly (`503`, "bring your own key") rather than a confusing provider error.

This is the exact same shift-the-cost-to-whoever-wants-it pattern as the GitHub bring-your-own-token design (see [Rate limits](#rate-limits)) — applied to AI instead of GitHub's API. The same trust note applies too: a bring-your-own AI key is sent to *this server*, which then calls Gemini/Anthropic on your behalf (the same shape as the GitHub token flow) — it is never sent directly from your browser to the AI provider. Verified by test that the key never appears in a log line, error message, or request body (see `test/aiProvider.test.js`), but that's a claim about this specific deployment, not a platform guarantee — the same "treat it like handing a password to a site you didn't build" caution applies here too.

## Example prompts

Once connected, just talk to Claude naturally:

- "Find me RAG implementation repos"
- "Show me containerization examples in Go"
- "What's trending in agent frameworks this week?"
- "Find repos tagged with vector-database"
- "Give me an overview of huggingface/transformers"
- "What's the file structure of that repo look like?"
- "Show me the recent commits on it"
- "Compare langchain, llamaindex, and haystack for me"

## Rate limits

GitHub's REST API has **two separate rate-limit buckets**, and this server's tools split across both:

| Bucket | Used by | Anonymous | With a token |
|---|---|---|---|
| **search** | `search_github_repos`, `search_by_topic`, `get_trending_repos` | 10 requests/min | 30 requests/min |
| **core** | `get_repo_overview`, `get_repo_structure`, `get_file_content`, `get_recent_commits`, `list_branches`, `compare_repos` | 60 requests/**hour** | 5,000 requests/hour |

The search bucket is generous enough for casual interactive use. The core bucket is not — it resets hourly, not per-minute, and some tools spend more than one request per call (`get_repo_overview` makes up to 4, `compare_repos` makes 2 per repo compared).

**How tokens work on the deployed connector (this is the key design point):** the server is public and takes no login, but it *does* read an optional `Authorization: Bearer <token>` header — and if you put your own [GitHub personal access token](https://github.com/settings/tokens) there (no scopes needed), your requests use *your own* rate limit, not a pool shared with every other stranger using the same link. Order of priority per request:

1. **Your own GitHub token**, if you sent one — you get your own 5,000/hour, unaffected by anyone else's usage.
2. The **operator's `GITHUB_TOKEN`** (if set on the server) — a shared fallback pool for anonymous callers.
3. Otherwise, **GitHub's fully anonymous limit** — the 60/hour (or 10/min search) figures above, shared across everyone not bringing their own token.

To use your own token when connecting in Claude: Add custom connector → Authentication: **None** → **Additional request headers** → Add header → name `Authorization`, value `Bearer <your GitHub token>`. Entirely optional — the server works with zero setup, this just gets you a bigger, un-shared quota.

**If you do bring your own token, two things worth knowing:**
- You're trusting *this server's operator* not to log or misuse it — verified in code and by test that it never is (see [Security](#security)), but that's a claim about this specific deployment, not a platform guarantee. Treat any third-party MCP connector's request for your token the same way you'd treat handing a password to a website you didn't build.
- Use a token scoped to **read-only, public-repo access only** (no `repo` write scope, no admin/org scopes) — this server only ever makes read requests, but a token with broader permissions than that is unnecessary risk if it were ever exposed, regardless of how this server itself behaves. If your token happens to have access to private repos, this server will read those too when asked — same as any GitHub API client using that token would.

**This server also has its own, separate rate limit** — 30 requests/minute per caller (by IP), regardless of GitHub tokens. This isn't about GitHub's API quota; it protects this server's own bandwidth/compute from being hammered directly (see [lib/rateLimit.js](lib/rateLimit.js)). Hitting it returns `429` with a `Retry-After` header and resets a minute later — normal interactive use won't come close to it.

Running locally (`server.js`/stdio), the same priority applies except there's no per-request header to bring — set `GITHUB_TOKEN` in the Claude Desktop config's `env` block (or your shell) to raise your own limit.

**Response caching further reduces load on the shared/anonymous pool.** Repo lookups, file contents, and search results are cached in memory for 5 minutes — so if two different people (or the same person twice) ask about the same repo or search within that window, only the first request actually calls GitHub; the rest are served from cache, instantly and without spending any quota. This only ever applies to anonymous/server-token requests, never to a caller's own token (two different tokens can have different access to the same URL, so caching across them could leak one caller's data to another — see [Security](#security) and [lib/cache.js](lib/cache.js)). Verified live: a repeated `get_repo_overview` call dropped from ~1.4s to ~1ms.

If a rate limit is hit, the server returns a clear message (instead of failing silently) telling you when it resets and reminding you that bringing your own token is an option.

## Security

This server underwent a security review, then a deliberate follow-up change: it moved from a single shared access token to fully public access with optional per-caller GitHub tokens (see [Rate limits](#rate-limits)). Current posture:

- **Input validation** — every tool argument is validated against a Zod schema before the handler runs; malformed input is rejected before it reaches any network call.
- **Public by design (HTTP transport)** — `/mcp` takes no login and rejects nothing based on identity. It optionally reads an `Authorization: Bearer <token>` header and, when present, uses that value as *that caller's own* GitHub token for GitHub API calls made on their behalf — see [lib/auth.js](lib/auth.js) and `createGitHubClient` in [lib/github.js](lib/github.js). A caller's token is used only for their own request and never stored, logged, or reused for anyone else (verified by test — see `test/githubClient.test.js`'s "no cross-caller leakage" case). `server.js` (stdio, for local/Claude Desktop use) is a separate, locally-spawned process, inherently scoped to whoever can run commands on that machine.
- **Untrusted content boundary** — README previews and file contents fetched from GitHub repos are wrapped in explicit `[UNTRUSTED CONTENT]` delimiters with an instruction not to treat them as commands, and the two tool descriptions that return this content say the same. This is a mitigation for indirect prompt injection (a malicious repo's README or source could otherwise contain text phrased as instructions to the model reading it) — framing, not content filtering; the underlying text is never altered or stripped.
- **SSRF-safe file downloads** — `get_file_content` follows GitHub's `download_url` for large files only if it resolves to `https://raw.githubusercontent.com`; any other host or scheme is refused rather than fetched (see `isAllowedDownloadUrl` in [lib/github.js](lib/github.js)).
- **No write access** — every GitHub API call this server makes is a read (`GET`). There is no code path that can create, modify, or delete anything on GitHub — including with a caller-supplied token, which is only ever attached to the same read-only calls every other request makes.
- **Error handling** — GitHub API errors return their normal (already-safe) user-facing text. Any *unexpected* exception is logged in full server-side and reduced to a generic message for the client — internal details (stack traces, file paths, dependency internals) are never returned in a tool result. No token (a caller's own or the operator's `GITHUB_TOKEN`) is ever logged, echoed in output, or embedded in a URL.
- **Caller-token forwarding was verified, not assumed** — since accepting an arbitrary caller-supplied credential and attaching it to outbound requests is the one genuinely new attack surface this change introduces, it was tested directly: an attempted header-injection payload (embedded CR/LF in the token) is rejected by Node's own `fetch` with a clean `TypeError` before any request leaves the server, caught by the existing error handling with no crash. A caller's token is confirmed (by code inspection and by `test/githubClient.test.js`) to reach only `createGitHubClient` — it's never interpolated into a log line, error message, or response text.
- **Per-caller rate limiting on this server itself** — 30 requests/minute per IP, independent of GitHub's own limits; see [Rate limits](#rate-limits) and [lib/rateLimit.js](lib/rateLimit.js). Protects the server's own bandwidth/compute from being hammered directly, which GitHub's API limits alone don't cover (they only throttle GitHub calls, not requests that never get that far).
- **Basic request logging** — every `/mcp` request logs its timestamp, caller IP, JSON-RPC method, and tool name (for `tools/call`) to stderr (visible in Render's Logs tab). Deliberately excludes tool arguments, query text, and tokens — see [lib/requestLog.js](lib/requestLog.js) and its tests for what is and isn't logged.
- **CI** — every push to `main` and every pull request runs the full test suite via GitHub Actions ([.github/workflows/test.yml](.github/workflows/test.yml)); the badge at the top of this README reflects the current status.
- **Response cache never crosses the token boundary** — caching (see [Rate limits](#rate-limits)) only applies when a request carries no caller-supplied token; a request bringing one always fetches fresh. This is deliberate: two different tokens can have different access to the same URL (e.g. a private repo), and a shared cache entry keyed only by URL would otherwise be able to serve one caller's authorized data to a different, unauthorized caller. Tested directly (see `test/githubClient.test.js`'s "does not pollute the anonymous cache" and "never cached" cases).
- **AI-generated text is sanitized identically to README content** — the [web frontend](#web-frontend) renders both through the same `renderMarkdown()` (marked + DOMPurify) pipeline, so even if a repo's README contained a prompt-injection attempt that influenced the AI's output, the rendered result still can't execute a script in the viewer's browser.
- **The AI-explain trial has its own separate, much stricter budget** — [lib/aiTrialQuota.js](lib/aiTrialQuota.js) caps the operator-funded free tier at a few calls per caller per day, independent of the general 30/minute rate limiter, since this one bounds real API spend rather than just server load. A caller bringing their own AI key skips this budget entirely (see [AI explanations](#ai-explanations)).

**Remaining risks / not covered here:**

- Rate limiting is per-IP, not per-identity — there's no login, so a caller behind a shared/rotating IP (or simply willing to rotate IPs) isn't meaningfully throttled by this alone. It stops accidental or unsophisticated hammering, not a determined attacker.
- Logging is basic (stderr text, 7-day retention on Render's free tier) — there's no persistent store, dashboard, or alerting on top of it; someone has to go look at the logs.
- `PUBLIC_HOST` (Host-header validation) is still available and recommended, but it only restricts *which hostname* the server answers on the network layer — it has nothing to do with who's allowed to use the tools, since there's no identity concept here at all.
- The trial quota (like the general rate limiter) is keyed by IP, not identity — the same caveat about shared/rotating IPs applies to AI-spend protection too, just with a much smaller daily budget at stake.

## Project files

- [server.js](server.js) — local entry point; serves the tools over stdio (for Claude Desktop / the Inspector)
- [server-http.js](server-http.js) — deployable entry point; serves the same tools over Streamable HTTP, plus mounts the REST API, for a shared connector URL
- [lib/createServer.js](lib/createServer.js) — the shared `McpServer` factory both entry points use
- [core/discovery.js](core/discovery.js), [core/inspect.js](core/inspect.js), [core/compare.js](core/compare.js) — the actual GitHub logic (search ranking, repo inspection, comparison), as plain functions returning plain data. Both the MCP tools and the REST API call these directly — one implementation, two interfaces.
- [core/explain.js](core/explain.js) — builds the "explain this repo" prompt from repo data and calls whichever AI provider applies
- [routes/api.js](routes/api.js) — the REST API (see [above](#rest-api-for-a-web-frontend-or-anything-that-isnt-an-mcp-client)); thin JSON/HTTP-status wrapping over `core/`
- [web/](web) — the static frontend (search, repo detail, compare); see [Web frontend](#web-frontend)
- [tools/discovery.js](tools/discovery.js), [tools/inspect.js](tools/inspect.js), [tools/compare.js](tools/compare.js) — the MCP tool registrations; thin text-formatting wrapping over the same `core/` functions
- [tools/prompts.js](tools/prompts.js) — slash-command shortcuts: `getinfo`, `getcodeinfo`, `findrepos`, `comparerepos`
- [lib/github.js](lib/github.js) — shared GitHub API client (`githubFetch`, `createGitHubClient`), per-caller token priority, response caching, rate-limit/error handling, SSRF allowlist
- [lib/format.js](lib/format.js) — shared formatting helpers (relative dates, repo-ref parsing, truncation, untrusted-content wrapping)
- [lib/auth.js](lib/auth.js) — extracts an optional caller-supplied GitHub token from the Authorization header; never blocks a request
- [lib/rateLimit.js](lib/rateLimit.js) — per-IP request rate limiting for the HTTP transport (protects this server, independent of GitHub's own limits)
- [lib/requestLog.js](lib/requestLog.js) — minimal per-request logging (method, tool name, caller IP) with no arguments/tokens ever logged
- [lib/cache.js](lib/cache.js) — in-memory TTL cache for anonymous/server-token GitHub responses (never for caller-supplied tokens — see [Security](#security))
- [lib/aiProvider.js](lib/aiProvider.js) — thin wrappers over the Gemini and Anthropic REST APIs for the "explain this repo" feature
- [lib/aiTrialQuota.js](lib/aiTrialQuota.js) — the operator-funded free trial's per-caller daily budget, separate from the general rate limiter
- [Dockerfile](Dockerfile) — optional containerized build of the HTTP entry point, for deploying somewhere other than Render (Render itself doesn't need this — it builds natively from `package.json`)
- [test/](test) — unit and integration tests, run with `npm test` (Node's built-in test runner + `@modelcontextprotocol/client`/`proxy-addr` as devDependencies for tests specifically)
- [.github/workflows/test.yml](.github/workflows/test.yml) — CI: runs the test suite on every push to `main` and every pull request
- [package.json](package.json) — dependencies (`@modelcontextprotocol/server`, `@modelcontextprotocol/express`, `@modelcontextprotocol/node`, `express`, `zod`)

TDQS

A4.4/5.0

Scored across 9 tools

Disambiguation5/5

Each tool targets a distinct stage: searching, topic filtering, trending, overview, structure, comparison, file content, commits, and branches. The two search tools are differentiated by free-text vs. curated topic tags, so an agent can choose without confusion.

Naming Consistency5/5

Tool names consistently follow a snake_case verb_noun pattern: search_, get_, compare_, and list_. The small variation in search_github_repos vs. search_by_topic does not break the overall predictability.

Tool Count5/5

Nine tools is well-scoped for a GitHub discovery server. Each tool earns its place in the workflow from finding repositories to inspecting their internals, without redundant or excessive surface area.

Completeness5/5

The tool set covers the full discovery lifecycle: find candidates via search/topic/trending, evaluate them via overview/compare, and explore details via structure/file/commits/branches. There are no obvious dead ends or missing operations for the server's stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues