Skip to main content
Glama
Productdeveloper5192

github-directory-mcp

github-directory-mcp

An MCP (Model Context Protocol) server, written in TypeScript, that gives an AI assistant two tools for querying GitHub: listing a user/org's repositories, and listing the directories inside a repo.

This README covers MCP from first principles through to this project's internals, running it, and extending it.


Table of contents

  1. What is MCP

  2. How the protocol actually works

  3. Transports: stdio vs HTTP

  4. What this project does

  5. Project layout

  6. Setup from scratch

  7. Tool reference

  8. Accessing the server

  9. Troubleshooting

  10. Advanced: extending this server

  11. Security notes


Related MCP server: HTTP MCP Server

Quick command reference

Every command actually needed to build, run, register, and debug this server, in one place. Run these from a normal terminal (VS Code integrated terminal or system PowerShell) in the project folder, C:\Users\banda\OneDrive\Desktop\Mcp — not a sandboxed/CI shell.

These are wired up as real npm run scripts in package.json — not just copy-paste text:

# One-time setup
npm install
cp .env.example .env          # then paste your GITHUB_TOKEN into .env

# Build (re-run after any src/index.ts edit)
npm run build

# Register with Claude Code (one-time; restart the session afterwards)
npm run register

# Manual visual testing via MCP Inspector
npm run inspector

# Same, but skip the session-token requirement (fixes stale-tab proxy errors)
npm run inspector:noauth

# Raw run (server just listens on stdio; used for scripted JSON-RPC testing)
npm start

# Verify GITHUB_TOKEN is valid
npm run check-token

# Find + stop whatever is holding the Inspector's ports (6274 UI / 6277 proxy)
netstat -ano | findstr "6274 6277"
Stop-Process -Id <PID> -Force

Script

What it runs

npm run build

tsc — compiles src/index.tsdist/index.js

npm start

node dist/index.js — raw stdio server

npm run dev

build then start, in one step

npm run inspector

Launches MCP Inspector against the built server

npm run inspector:noauth

Same, with DANGEROUSLY_OMIT_AUTH=true (via cross-env, so it works on Windows too)

npm run register

claude mcp add github-directory -- node dist/index.js

npm run check-token

Hits GET /user with your GITHUB_TOKEN and prints the resolved account or the raw error


1. What is MCP

Model Context Protocol is an open standard (created by Anthropic, now used across the industry) that defines a common way for an AI application — a chat client, an IDE assistant, an agent — to discover and call external capabilities, without every AI vendor and every tool vendor needing a custom integration for each other.

Before MCP: if you wanted Claude to talk to GitHub, Slack, a database, and a filesystem, someone had to write four bespoke integrations inside the AI application, each with its own auth handling, its own API shape, its own way of describing what it can do.

With MCP: each of those four things (GitHub, Slack, DB, filesystem) is wrapped in a small standalone program called an MCP server. Any MCP-compatible client (Claude Code, Claude Desktop, other agent frameworks) can talk to any MCP server using the same protocol. The server describes its own capabilities at connection time — the client doesn't need prior knowledge of what a "GitHub server" looks like.

The analogy people reach for is USB-C for AI: one physical/logical connector, many devices behind it, no per-device custom cable.

The three primitives MCP servers expose

Primitive

What it is

Example in this project

Tools

Functions the model can call, with typed inputs/outputs. The model decides when to call them.

list_github_repositories, list_github_directories

Resources

Read-only data the client can attach to context (files, query results). Not used in this project.

Prompts

Reusable prompt templates the server offers. Not used in this project.

This project only implements tools, which is the most common case — "let the model call a function and get a result back."


2. How the protocol actually works

Under the hood, MCP is JSON-RPC 2.0 — a simple, transport-agnostic RPC format where every message is a JSON object with a method, optional params, and an id to match requests to responses.

A session looks like this:

Client                                   Server (this project)
  |--- initialize ------------------------->|   client says "here's my protocol version/capabilities"
  |<-- initialize result -------------------|   server replies with its name/version/capabilities
  |--- notifications/initialized ---------->|   client confirms handshake is done
  |
  |--- tools/list -------------------------->|   client asks "what tools do you have?"
  |<-- tools/list result -------------------|   server returns tool names + JSON Schema for each input
  |
  |--- tools/call (list_github_repositories)->|  client invokes a tool with arguments
  |<-- tools/call result --------------------|   server runs it, returns text/structured content

Every tool advertises an input schema (we use Zod to define it, which the SDK converts to JSON Schema automatically). This is what lets the calling model know it must supply owner and repo as strings for list_github_directories, for instance — the schema is enforced before your tool code even runs (see src/index.ts's .min(1) validators, which reject empty strings with a clear error instead of letting a malformed request reach the GitHub API).


3. Transports: stdio vs HTTP

MCP defines the message format (JSON-RPC) separately from the transport (how bytes physically move between client and server). Two transports matter in practice:

  • stdio (what this project uses): the client spawns your server as a child process and talks to it over its stdin/stdout. Zero networking, zero ports, zero auth needed — the client owns the process. This is the right choice for a local tool a single user runs on their own machine, which is what claude mcp add ... -- node dist/index.js does.

  • Streamable HTTP: the server runs independently (its own process, possibly remote), and clients connect to it over HTTP. Needed when the server is shared, long-running, or not co-located with the client. Requires you to think about auth, since now it's a network-reachable service.

This project only implements stdio (see StdioServerTransport in src/index.ts). If you ever need to expose it to multiple remote clients, that's the piece you'd swap out — the tool logic itself wouldn't change.


4. What this project does

Two tools, both backed directly by the GitHub REST API (no GitHub SDK dependency — just fetch):

  • list_github_repositories — calls GET /users/{owner}/repos (falling back to GET /orgs/{owner}/repos if that 404s), or GET /user/repos when owner is omitted and a token is set. Returns full_name, description, privacy/fork flags, and URL for each repo.

  • list_github_directories — calls GET /repos/{owner}/{repo}/contents/{path} for a shallow listing, or GET /repos/{owner}/{repo}/git/trees/{ref}?recursive=1 (filtered to type: "tree") for a full recursive directory walk.

Both accept an optional GITHUB_TOKEN (read from .env via dotenv) which is sent as a Bearer token — required for your own private repos / own-account listing, and generally useful to avoid GitHub's 60 req/hour unauthenticated rate limit (jumps to 5000 req/hour authenticated).


5. Project layout

Mcp/
├── src/index.ts        Server source: tool definitions, GitHub API calls, stdio bootstrap
├── dist/index.js        Compiled output — this is what actually gets executed
├── .env                  Your real GITHUB_TOKEN (git-ignored, never commit)
├── .env.example          Template for .env (safe to commit)
├── .gitignore            Excludes node_modules/, dist/, .env, Repository_token.txt
├── repositories.txt      A saved snapshot of a list_github_repositories run
├── package.json          Scripts: build (tsc), start, dev
└── tsconfig.json         TypeScript compiler config (NodeNext modules, ES2022 target)

6. Setup from scratch

Requirements: Node.js 18+ (this was built and tested on Node 25).

cd "C:\Users\banda\OneDrive\Desktop\Mcp"
npm install
cp .env.example .env

Edit .env and paste in a GitHub token:

GITHUB_TOKEN=github_pat_xxxxxxxxxxxxxxxxxxxx

(Generate one at github.com → Settings → Developer settings → Personal access tokens. Fine-grained, read-only "Contents" + "Metadata" repo permissions are enough for these two tools.)

Build:

npm run build

This compiles src/index.tsdist/index.js via tsc. Re-run this any time you edit src/index.ts.


7. Tool reference

list_github_repositories

Param

Type

Required

Notes

owner

string

no

Username or org. Omit to list the authenticated user's own repos (needs GITHUB_TOKEN).

perPage

number 1-100

no

Default 30.

page

number

no

Default 1.

list_github_directories

Param

Type

Required

Notes

owner

string

yes

e.g. "anthropics". Must be non-empty (validated).

repo

string

yes

e.g. "claude-code". Must be non-empty (validated).

path

string

no

Default: repo root.

ref

string

no

Branch/tag/SHA. Default: repo's default branch.

recursive

boolean

no

Default false. true walks the entire tree via the Git Trees API.

Note: both owner and repo must actually be provided — if you ask something vague like "list my repo's directories" without naming a repo, the calling model may send empty strings, which now fails fast with a validation error instead of silently hitting a malformed GitHub URL.


8. Accessing the server

There are two ways to actually use this server, depending on your goal.

A. Through Claude Code (the real use case)

Register it once, from a normal terminal (not a sandboxed/CI one):

claude mcp add github-directory -- node "C:\Users\banda\OneDrive\Desktop\Mcp\dist\index.js"

Restart your Claude Code session (MCP servers load at session start), then just ask, naming the repo explicitly:

"List directories in Productdeveloper5192/MCP" "List my github repositories"

Claude reads the tool schemas via tools/list, decides when a request warrants calling one, and calls it via tools/call — all of that JSON-RPC exchange happens invisibly.

B. MCP Inspector (manual/visual testing, no client needed)

npx @modelcontextprotocol/inspector node dist/index.js

This starts two things: a proxy on port 6277 (bridges the browser to your stdio process) and a UI on port 6274. It prints a URL with a session token baked in — open that exact URL.

  1. Click Connect.

  2. Tools tab → List Tools.

  3. Pick a tool, fill the form, Run Tool.

If you keep hitting "Error Connecting to MCP Inspector Proxy" from stale browser tabs/tokens, skip the token entirely for local testing:

$env:DANGEROUSLY_OMIT_AUTH="true"
npx @modelcontextprotocol/inspector node dist/index.js

C. Raw JSON-RPC over stdio (for scripting/debugging)

node dist/index.js

Feed it JSON-RPC lines on stdin, one per line — this is what's used internally to smoke-test the server. Example sequence: initializenotifications/initializedtools/call.


9. Troubleshooting

GitHub API 404 for /repos// owner/repo were empty when the tool was called — usually because the prompt to Claude didn't name a specific repo. Now blocked at the schema level with a clear validation error instead (see .min(1) in src/index.ts). Name the repo explicitly in your prompt.

"Error Connecting to MCP Inspector Proxy" The Inspector mints a new session token every time it starts. This almost always means an old browser tab is using a stale token from a previous run. Close all old Inspector tabs and open the exact URL (with token) printed by the current run.

MCP Inspector PORT IS IN USE at http://localhost:6274 A leftover node process from a prior Inspector run is still holding the port. Find and stop it:

netstat -ano | findstr 6274
Stop-Process -Id <PID> -Force

claude: command not found You're not in a terminal where Claude Code's CLI is on PATH — use VS Code's integrated terminal or your normal system terminal, not a restricted/sandboxed shell.

Rate limited / can't see private repos / owner omitted fails Check GITHUB_TOKEN is actually set in .env and non-empty. Verify it directly:

curl -H "Authorization: Bearer $env:GITHUB_TOKEN" https://api.github.com/user

A 200 with your account info confirms the token is valid.


10. Advanced: extending this server

To add a new tool, follow the pattern already in src/index.ts:

server.registerTool(
  "your_tool_name",
  {
    title: "Human-readable title",
    description: "What it does — this is what the model reads to decide when to call it.",
    inputSchema: {
      someParam: z.string().min(1).describe("Shown to the model as field docs"),
    },
  },
  async ({ someParam }) => {
    // ... do work, call APIs, etc.
    return { content: [{ type: "text", text: "result" }] };
  }
);

Ideas in scope for this GitHub-focused server: list branches, list commits on a path, search code, read a single file's content, list pull requests. Each is one more githubFetch call plus one more registerTool block — no architectural changes needed.

If you ever need this reachable by more than one local client (e.g. a shared team server), swap StdioServerTransport for the SDK's Streamable HTTP transport — at that point also add real auth in front of it, since it stops being "only reachable by whoever can spawn the process" and becomes a network service.


11. Security notes

  • .env holds a live GitHub token — it is git-ignored. Never commit it, never paste its contents into chat, issues, or logs.

  • Repository_token.txt is also git-ignored as a safety net, but the token has already been moved into .env — that plaintext file is redundant and can be deleted.

  • Fine-grained PATs scoped to only the repos/permissions you need are safer than classic PATs with broad scopes — regenerate and re-scope if the current token was created broadly.

  • This server only ever reads from GitHub (no write/delete endpoints are implemented), so the blast radius of a leaked token is limited to whatever that token itself can do on your account — treat it with the same care as a password.

Available Tools

2 tools
list_github_directoriesList GitHub directoriesA

Lists directories (folders) inside a GitHub repository at a given path. Set recursive=true to list every subdirectory in the repo instead of just the immediate children.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoBranch, tag, or commit SHA (default: repo's default branch)
pathNoPath within the repo to list (default: repo root)
repoYesRepository name, e.g. 'claude-code'
ownerYesRepository owner, e.g. 'anthropics'
recursiveNoIf true, list all directories in the repo tree recursively (default: false)

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full responsibility for behavioral disclosure. It only states the core functionality and does not mention authentication, rate limits, pagination, error handling, or any side effects. This is insufficient for a tool with no annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, front-loaded with the main purpose. Every word contributes useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of output schema and annotations, the description is incomplete. It does not describe what the returned results contain (e.g., names, paths), which is important for an agent to interpret the output. Additional context about output structure is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline is 3. The description adds value by explaining how the path and recursive parameters interact, clarifying the scope of the listing. This slightly exceeds the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists directories inside a GitHub repository at a given path, using a specific verb and resource. It distinguishes itself from the sibling tool list_github_repositories which lists repositories, not directories.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides guidance on when to use the recursive parameter, but does not explicitly state when not to use this tool or mention alternatives beyond the sibling. The context is clear enough for basic usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_github_repositoriesList GitHub repositoriesA

Lists repositories for a GitHub user or organization. If 'owner' is omitted, lists repositories for the authenticated user (requires GITHUB_TOKEN env var).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage number (default 1)
ownerNoGitHub username or organization name. Omit to list the authenticated user's repos.
perPageNoResults per page, 1-100 (default 30)

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It discloses auth dependency for the authenticated user case but lacks details on error handling, pagination behavior, or response format. Adequate but not comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with no unnecessary words. Front-loaded with main purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers two usage modes and auth condition. No output schema but return type inferable. Lacks explicit pagination guidance, though schema describes page/perPage. Sufficient for a simple list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. Description adds minimal param info beyond schema (only references 'owner' implicitly). Meets minimum but does not enhance understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses specific verb 'Lists' and resource 'repositories for a GitHub user or organization'. It distinguishes between listing for a specified owner vs authenticated user, and differs from sibling tool 'list_github_directories'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly states when to omit 'owner' (authenticated user) and mentions prerequisite GITHUB_TOKEN env var. Does not explicitly exclude alternatives, but sibling context makes it implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv1.0.0
    • First observedlist_github_directories
    • First observedlist_github_repositories

TDQS

A3.9/5.0
Disambiguation5/5

Each tool targets a distinct resource: one lists directories within a repository, the other lists repositories for a user/org. No overlap in purpose.

Naming Consistency5/5

Both tools follow a consistent 'list_github_<plural>' pattern, using snake_case and similar structure.

Tool Count3/5

With only 2 tools, the server feels thin for a GitHub utility. It may be intentionally scoped, but the count is borderline low.

Completeness2/5

The server only covers listing of directories and repositories, missing essential operations like file content access, creation, update, or deletion for either resource.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that enables AI assistants to fetch public GitHub repository lists for any username via HTTP or stdio transports. It provides a specialized tool for repository retrieval and supports both remote web server and local integration modes.
    2
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that provides tools for interacting with the GitHub API, enabling AI assistants to query repositories, pull requests, issues, commits, users, and more.
    467
    ISC

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Productdeveloper5192/MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server