Authenticated remote MCP server that lets Claude read/write one GitHub-backed second-brain vault, for a single user or a team with per-member GitHub attribution.
Strong tool naming (verb_noun pattern), comprehensive descriptions (avg 180 chars), and clear parameter documentation. All 9 tools have explicit schemas with types and descriptions. Good composition: read tools are separate from write. Main gaps: no enum constraints on state parameters (github_list_issues, github_list_pull_requests accept 'open'/'closed'/'all' as free strings), no output schema documentation, limited error recovery guidance, and no tool annotations (readOnlyHint/destructiveHint). Security is well-handled via per-member OAuth token injection. Descriptions are LLM-optimized and include usage guidance ('Prefer this over github_search_notes'). Parameters have clear constraints documented in text ('Must not be absolute and must not contain ".."'). This is a solid B-grade server with room for formalization.
List the files and folders directly under one directory. Returns up to 200 entries. For finding a note anywhere in the vault, github_list_tree is usually better (one call, all paths). path: repository-relative directory path; defaults to the repo root. ref: branch/tag/commit; defaults to the default branch.
List issues in the repository (likely empty for a notes vault). state: "open", "closed", or "all". limit: max issues (max 50).
List pull requests in the repository (likely empty for a notes vault). state: "open", "closed", or "all". limit: max pull requests (max 50).
List every Markdown note path in the repository (recursive). This is the best way to FIND a note when you don't know its exact path: get the full list of paths, then pick the one that matches what the user asked for (e.g. "the Q3 launch plan" -> "projects-and-plans/q3-launch.md"). Reflects the live repository, so notes edited moments ago are included. Prefer this over github_search_notes for finding files. ref: branch/tag/commit to list; defaults to the repository's default branch.
State parameters lack enum constraints. github_list_issues and github_list_pull_requests accept 'state' as free strings ('open', 'closed', 'all') with no formal enum. LLMs may hallucinate invalid values like 'pending' or 'archived'.
No output schema documentation. Tools return dict[str, Any] with no documented field structure. LLMs cannot plan downstream calls or extract specific fields reliably. E.g., github_read_file returns 'sha' and 'content' but this is only documented in the description, not in a formal schema.
No tool annotations. github_write_file is destructive (modifies state) but lacks destructiveHint annotation. github_read_file and read-only tools lack readOnlyHint. Clients cannot infer safety properties without annotations.
Inferred effective spec: 2026-07-28+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 68 | 2026-07-28+ | v2 |
Read a single text file from the repository. Returns the file content plus its 'sha'. Keep that 'sha' if you intend to edit the file later — the write tool uses it to avoid overwriting changes. path: repository-relative path, e.g. "projects-and-plans/q3-launch.md". Must not be absolute and must not contain "..". ref: branch/tag/commit to read from; defaults to the default branch.
Return basic metadata for the one connected repository. Use this to learn the default branch, whether the repo is private, and its URL. Takes no arguments — the repository is fixed by the server.
Search note CONTENT for a phrase (best-effort). Use this only when you can't locate a note by path/title with github_list_tree — for example "the note where I wrote about pricing". Caveat: GitHub's search index lags behind commits, so a note created or edited in the last few minutes may not appear yet. For recent or complete results, use github_list_tree instead. query: words to search for in file contents. limit: max results (max 25).
Create or update one file, committed directly to the main branch. Use this to capture a new note or save edits to an existing one. Any path in the repository can be created or updated — nothing is off-limits — but this tool cannot delete anything. To learn this vault's conventions before writing, github_read_file("CLAUDE.md"). IMPORTANT — this REPLACES the whole file with `content`; there is no partial/patch mode. To edit an existing note, first github_read_file to get its current text and `sha`, modify the full text, then pass the complete new body here together with that `sha`. The `sha` guards against overwriting a change made since you read: if the file moved on, the write fails and you should re-read and retry rather than clobber. path: repository-relative path, e.g. "projects-and-plans/q3-launch.md". Must not be absolute or contain "..". content: the FULL new file body (UTF-8 text). message: commit message; defaults to "Update <path> via Claude". sha: the `sha` from github_read_file when editing an existing file. Omit only when creating a brand-new file.
Health check tool that returns server status and GitHub tools availability.
Error handling lacks recovery guidance. GitHubToolError exceptions are caught and re-raised as ValueError with only the error message. No guidance on retryability, user-fixable vs fatal, or next steps. E.g., 'Not authenticated' should suggest 'Check OAuth token' or 'Re-authenticate'.
Pagination not implemented. github_list_tree, github_list_directory, github_list_issues, and github_list_pull_requests return all results (or up to 200/50) with no limit/offset or cursor. Large vaults could return thousands of paths, exhausting context window.