ghGetFileContentGithub | Read a file or a specific region from a GitHub repository. | Use after ghSearchCode/ghViewRepoStructure when you know the repo path — not for discovery. If a ghSearchCode snippet already answers the question, STOP — don't re-read the file.
Least-cost path: unknown/large file → minify:"symbols" outline, then a region (matchString or startLine+endLine). fullContent only for genuinely small whole-file reads, never to scan. A small structured/config file (package.json, tsconfig, lockfile) → read it whole with minify:"none"/fullContent, don't minify it — compaction can elide object boundaries and break exact key/value membership. For a literal value or quote, read the defining region with minify:"none" and copy the exact bytes.
Every response reports the file's full size (totalLines + sourceChars) and isPartial. A matchString/region read is a SLICE, not the whole file — it can cut a nested object mid-way; never conclude a key/field/value is absent or empty from a partial slice: continue via charOffset/next, or re-read the whole small structured file (package.json/tsconfig/lockfile) with minify:"none". Report only bytes you fetched — never invent a field, value, or quote.
Param relations: choose one extraction mode: fullContent OR matchString OR startLine+endLine. matchString pairs with contextLines and returns matchRanges (padded windows, not the exact hit) plus matchedLines (exact hit lines — see matchString field); charOffset continues isPartial pages. type:"directory" materializes localPath for local tools when clone is enabled.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"owner": {
"type": "string",
"description": "Repository owner (user or org)."
},
"repo": {
"type": "string",
"description": "Repository name, without the owner."
},
"branch": {
"description": "Branch, tag, or commit SHA; omit for the default branch.",
"type": "string"
},
"path": {
"type": "string",
"description": "Target path. GitHub tools: repo-relative, exact case, no leading slash. Local tools: absolute path."
},
"startLine": {
"description": "Requires endLine; exclusive with fullContent/matchString.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"endLine": {
"description": "Requires startLine; must be >= startLine.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"fullContent": {
"description": "Whole file; SMALL files only; exclusive with range/match. For large/unknown files use minify:symbols then a region instead.",
"type": "boolean"
},
"matchString": {
"description": "Anchor returning slices plus matchRanges ({start,end} padded windows) and matchedLines (exact hit line numbers).",
"type": "string"
},
"matchStringIsRegex": {
"description": "Makes matchString a regex.",
"type": "boolean"
},
"matchStringCaseSensitive": {
"description": "Case-sensitive matchString (default insensitive).",
"type": "boolean"
},
"forceRefresh": {
"description": "Bypass the 24h fetch cache and re-read from GitHub.",
"type": "boolean"
},
"type": {
"default": "file",
"description": "\"file\" reads; \"directory\" materializes localPath.",
"type": "string",
"enum": [
"file",
"directory"
]
},
"contextLines": {
"description": "Extra source lines around each match/anchor.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"charOffset": {
"description": "Use pagination.nextCharOffset.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charLength": {
"description": "Characters per content window; continue via the returned next offset when partial.",
"type": "integer",
"minimum": 1,
"maximum": 50000
},
"minify": {
"description": "\"symbols\" outline, \"standard\" compact, \"none\" exact.",
"type": "string",
"enum": [
"none",
"standard",
"symbols"
]
}
},
"required": [
"owner",
"repo",
"path"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub File Content Fetch",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
ghSearchCodeGithub | Search code contents or file paths across GitHub repositories. | Use for remote code/file discovery. Start match:"path" + concise for filenames; match:"file" only when snippets matter. Skip if you already have the path (ghGetFileContent) or need repo discovery (ghSearchRepos).
One-shot: if a match:"file" snippet already contains the answer (a field value, a symbol name, a state), STOP — that snippet is the evidence; don't chain a structure view or a content read to "confirm" it.
Param relations: owner+repo scopes tightly; path scopes a directory prefix; extension/language/filename narrow candidates; keywords are ANDed. Follow into ghGetFileContent, ghViewRepoStructure, or clone for AST/LSP proof. Empty/unindexed is not absence.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"keywords": {
"description": "ANDed; keep a phrase as one item; alternatives need separate queries.",
"type": "array",
"items": {
"type": "string"
}
},
"owner": {
"description": "Repository owner (user or org).",
"type": "string"
},
"repo": {
"description": "Repository name, without the owner.",
"type": "string"
},
"extension": {
"description": "File extension filter, e.g. \"ts\" (no dot).",
"type": "string"
},
"filename": {
"description": "Exact filename filter.",
"type": "string"
},
"path": {
"description": "Repo path prefix, not a full file path.",
"type": "string"
},
"language": {
"description": "GitHub language filter, e.g. \"typescript\".",
"type": "string"
},
"match": {
"default": "file",
"description": "\"file\" searches file contents and returns snippets with matchIndices. \"path\" searches only file paths/names — no snippets, far cheaper; use it to confirm a file exists before reading it. (Unlike ghSearchRepos/ghSearchPullRequests, where `match` instead selects which text FIELDS to search — a different concept sharing this name.)",
"type": "string",
"enum": [
"file",
"path"
]
},
"limit": {
"description": "Results per page (paginate with page).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"concise": {
"description": "Flat \"owner/repo:path\" rows.",
"type": "boolean"
}
}
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub Code Search",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
ghSearchCommitsGithub | Walk a GitHub repository's commit history for a path or range. | Commit archaeology — when/why a file/area changed — not current code (ghSearchCode/ghGetFileContent) or PRs (ghSearchPullRequests).
No message-keyword filter — only path/since/until/author/committer narrow the walk. Looking for a specific change (e.g. a rename) with no known SHA/path/date? Try ghSearchPullRequests/ghSearchCode for a lead first; otherwise page raw history by eye.
One commit's exact changes: set base:"SHA^", head:"SHA", includeDiff:true — its files+patches in one call; don't page history or fetch files.
owner+repo identify the repo; path scopes a file/dir (trailing / = subtree); since/until bound the window; branch selects a ref; includeDiff is heavy — scope to one SHA or a tight window; itemsPerPage/page walk history. For code identity, clone + local/LSP.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"owner": {
"type": "string",
"description": "Repository owner."
},
"repo": {
"type": "string",
"description": "Repository name."
},
"path": {
"description": "File/dir prefix; trailing / scopes the subtree.",
"type": "string"
},
"since": {
"description": "Only commits after this point. ISO date (\"2026-01-01\") or a relative window (\"30d\", \"2w\", \"6m\", \"1y\").",
"type": "string"
},
"until": {
"description": "Only commits before this point. ISO date or a relative window (same formats as since).",
"type": "string"
},
"branch": {
"description": "Ref to walk; defaults to the default branch.",
"type": "string"
},
"author": {
"description": "Filter to commits by this author (GitHub login or email).",
"type": "string"
},
"committer": {
"description": "Filter to commits by this committer (GitHub login or email).",
"type": "string"
},
"base": {
"description": "Compare mode: set base+head (branch/tag/sha) to diff two refs (base...head) instead of walking history — returns status, ahead/behind counts, and the commits between them.",
"type": "string"
},
"head": {
"description": "Compare mode: the head ref for the base...head comparison.",
"type": "string"
},
"itemsPerPage": {
"default": 30,
"description": "Commits returned per page (walk with page).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"includeDiff": {
"default": false,
"description": "Attach per-commit diffs. Scope it: with base:SHA^/head:SHA it returns one commit's full diff in a single call; heavier on a broad history walk.",
"type": "boolean"
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"filePage": {
"description": "With includeDiff: page through the changed-file list (walk with pagination.nextFilePage).",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"charOffset": {
"description": "With includeDiff: start offset into a file's patch window — copy from patchPagination.nextCharOffset, do not compute.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charLength": {
"description": "With includeDiff: characters of patch per window; continue via the returned next offset when hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"limit": {
"description": "Commits per page — alias of itemsPerPage (preferred when both are set).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"owner",
"repo"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub Commit History",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
ghSearchIssuesGithub | Search GitHub issues, or read one issue's body and comments. | Issue triage/archaeology — bug reports, feature threads — not PRs (ghSearchPullRequests) or code (ghSearchCode).
List mode: keywordsToSearch+filters+sort/page. Detail mode: owner+repo+issueNumber + content selectors; body/comment windows continue via charOffset/commentBodyOffset, comments page via commentPage.
totalCount appears only when one page is the full set (the endpoint also returns PRs, filtered out — so per-page counts aren't totals); an empty page with hasMore:true was PR-only — follow nextPage.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"owner": {
"description": "Repository owner (user or org).",
"type": "string"
},
"repo": {
"description": "Repository name, without the owner.",
"type": "string"
},
"keywordsToSearch": {
"description": "Issue search terms.",
"type": "array",
"items": {
"type": "string"
}
},
"issueNumber": {
"description": "Switches to issue detail mode; needs owner+repo.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"concise": {
"description": "Issue list triage; ignored with issueNumber.",
"type": "boolean"
},
"state": {
"description": "open or closed.",
"type": "string",
"enum": [
"open",
"closed"
]
},
"assignee": {
"description": "Filter by assigned GitHub login.",
"type": "string"
},
"author": {
"description": "Filter by issue author login.",
"type": "string"
},
"commenter": {
"description": "Filter by a login that commented.",
"type": "string"
},
"mentions": {
"description": "Filter by a mentioned login.",
"type": "string"
},
"label": {
"description": "Label name(s); multiple are ANDed.",
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"created": {
"description": "Created-date filter, e.g. \">2024-01-01\" or \"2024-01-01..2024-06-30\".",
"type": "string"
},
"updated": {
"description": "Updated-date filter (same format as created).",
"type": "string"
},
"closed": {
"description": "Closed-date filter (same format as created).",
"type": "string"
},
"comments": {
"description": "Comment-count range filter (\">5\"); not comment content.",
"type": "string"
},
"reactions": {
"description": "Reaction-count range filter (\">10\").",
"type": "string"
},
"match": {
"description": "Keyword fields: title, body, comments.",
"type": "array",
"items": {
"type": "string",
"enum": [
"title",
"body",
"comments"
]
}
},
"sort": {
"description": "created, updated, comments, reactions, best-match.",
"type": "string",
"enum": [
"created",
"updated",
"best-match",
"comments",
"reactions"
]
},
"order": {
"description": "asc/desc; asc+created helps archaeology.",
"type": "string",
"enum": [
"asc",
"desc"
]
},
"limit": {
"description": "Max issues in the search list (list-result cap).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"archived": {
"description": "Include issues from archived repos.",
"type": "boolean"
},
"commentPage": {
"description": "Comments page from contentPagination.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Comments per page when reading one issue (with commentPage).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"content": {
"description": "Detail selector for issueNumber.",
"type": "object",
"properties": {
"metadata": {
"description": "Include issue metadata (state, labels, counts).",
"type": "boolean"
},
"body": {
"description": "Include the issue description body.",
"type": "boolean"
},
"comments": {
"type": "object",
"properties": {
"discussion": {
"description": "Include the comment thread.",
"type": "boolean"
},
"includeBots": {
"default": false,
"description": "Include bot/CI comments.",
"type": "boolean"
}
}
}
}
},
"matchString": {
"description": "Substring filter for body/comment windows.",
"type": "string"
},
"commentBodyOffset": {
"description": "Comment-body continuation offset from nextQuery.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charOffset": {
"description": "Body continuation offset from nextQuery.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charLength": {
"description": "Characters per content window; continue via the returned next offset when partial.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"minify": {
"default": "standard",
"description": "\"standard\" (default) compacts body/comment text; \"none\" keeps it exact.",
"type": "string",
"enum": [
"none",
"standard"
]
}
}
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub Issue Search",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
ghSearchPullRequestsGithub | Search GitHub pull requests, or read one PR's files, diffs, and reviews. | Use for PR archaeology — how/why a change landed, review discussion, diffs — not current code (ghSearchCode/ghGetFileContent), commits (ghSearchCommits), or issues (ghSearchIssues).
Comments, review replies, and requested changes are claims — confirm what actually landed against content.patches (mode:"selected") or the file at the merge SHA, not the conversation.
Param relations: list mode uses keywordsToSearch+filters+sort/page; detail mode needs owner+repo+prNumber and content selectors. content.patches.mode:"selected" requires files or ranges. Body/patch/comment windows continue via returned charOffset/commentBodyOffset; file/comment/commit lists use their page fields. For code identity, clone and use local/LSP.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"keywordsToSearch": {
"description": "PR search terms.",
"type": "array",
"items": {
"type": "string"
}
},
"prNumber": {
"description": "Switches to PR detail mode; needs owner+repo.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"owner": {
"description": "Repository owner (user or org).",
"type": "string"
},
"repo": {
"description": "Repository name, without the owner.",
"type": "string"
},
"concise": {
"description": "PR list triage; ignored with prNumber.",
"type": "boolean"
},
"state": {
"description": "open, closed, or merged.",
"type": "string",
"enum": [
"open",
"closed",
"merged"
]
},
"assignee": {
"description": "Filter by assigned GitHub login.",
"type": "string"
},
"author": {
"description": "Filter by PR author login.",
"type": "string"
},
"commenter": {
"description": "Filter by a login that commented.",
"type": "string"
},
"mentions": {
"description": "Filter by a mentioned login.",
"type": "string"
},
"review-requested": {
"description": "PRs where this login is a requested reviewer.",
"type": "string"
},
"reviewed-by": {
"description": "PRs this login has reviewed.",
"type": "string"
},
"label": {
"description": "Label name(s); multiple are ANDed.",
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"checks": {
"description": "success, failure, or pending.",
"type": "string",
"enum": [
"success",
"failure",
"pending"
]
},
"review": {
"description": "approved, changes_requested, required, or none.",
"type": "string",
"enum": [
"approved",
"changes_requested",
"required",
"none"
]
},
"head": {
"description": "Head branch name filter.",
"type": "string"
},
"base": {
"description": "Base branch name filter.",
"type": "string"
},
"created": {
"description": "Created-date filter, e.g. \">2024-01-01\" or \"2024-01-01..2024-06-30\".",
"type": "string"
},
"updated": {
"description": "Updated-date filter (same format as created).",
"type": "string"
},
"closed": {
"description": "Closed-date filter (same format as created).",
"type": "string"
},
"merged-at": {
"description": "Merged-date filter (same format as created).",
"type": "string"
},
"comments": {
"description": "Comment-count range filter (\">5\"); not comment content.",
"type": "string"
},
"reactions": {
"description": "Reaction-count range filter (\">10\").",
"type": "string"
},
"draft": {
"description": "true = only drafts; false = exclude drafts.",
"type": "boolean"
},
"match": {
"description": "Keyword fields: title, body, comments.",
"type": "array",
"items": {
"type": "string",
"enum": [
"title",
"body",
"comments"
]
}
},
"sort": {
"description": "created, updated, comments, reactions, best-match.",
"type": "string",
"enum": [
"created",
"updated",
"best-match",
"comments",
"reactions"
]
},
"order": {
"description": "asc/desc; asc+created helps archaeology.",
"type": "string",
"enum": [
"asc",
"desc"
]
},
"limit": {
"description": "Max PRs in the search list (list-result cap).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"archived": {
"description": "Include PRs from archived repos.",
"type": "boolean"
},
"filePage": {
"description": "Changed-files page from contentPagination.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"commentPage": {
"description": "Comments page from contentPagination.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"commitPage": {
"description": "PR commits page from contentPagination.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Items per page when reading one PR's comments/files/commits (with page).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"reviewMode": {
"description": "\"full\" fetches all PR detail surfaces.",
"type": "string",
"const": "full"
},
"content": {
"description": "Detail selector for prNumber.",
"type": "object",
"properties": {
"metadata": {
"description": "Include PR metadata (state, refs, counts).",
"type": "boolean"
},
"body": {
"description": "Include the PR description body.",
"type": "boolean"
},
"changedFiles": {
"description": "Include the changed-file list with +/- counts.",
"type": "boolean"
},
"patches": {
"type": "object",
"properties": {
"mode": {
"default": "none",
"description": "\"none\", \"selected\", or \"all\"; selected is cheapest.",
"type": "string",
"enum": [
"none",
"selected",
"all"
]
},
"files": {
"description": "Restrict selected patches to these files (mode:\"selected\").",
"type": "array",
"items": {
"type": "string"
}
},
"ranges": {
"description": "Line ranges for selected patch hunks.",
"type": "array",
"items": {
"type": "object",
"properties": {
"file": {
"type": "string",
"description": "File the line range applies to."
},
"additions": {
"description": "Added-side line numbers to include.",
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 1000000000
}
},
"deletions": {
"description": "Deleted-side line numbers to include.",
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 1000000000
}
}
},
"required": [
"file"
]
}
}
}
},
"comments": {
"type": "object",
"properties": {
"discussion": {
"description": "Include the PR conversation timeline.",
"type": "boolean"
},
"reviewInline": {
"description": "Include inline review comments (threads via in_reply_to_id).",
"type": "boolean"
},
"includeBots": {
"default": false,
"description": "Include bot/CI comments.",
"type": "boolean"
},
"file": {
"description": "Filter comments to one file path.",
"type": "string"
}
}
},
"reviews": {
"description": "Include review verdicts per reviewer.",
"type": "boolean"
},
"commits": {
"description": "PR-bound commits selector.",
"type": "object",
"properties": {
"list": {
"description": "Include the PR's commit list.",
"type": "boolean"
},
"includeFiles": {
"description": "Attach per-commit file changes.",
"type": "boolean"
}
}
}
}
},
"matchString": {
"description": "Substring filter for body/patch/comment windows.",
"type": "string"
},
"commentBodyOffset": {
"description": "Comment-body continuation offset from nextQuery.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charOffset": {
"description": "Body/patch continuation offset from nextQuery.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charLength": {
"description": "Characters per content window; continue via the returned next offset when partial.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"minify": {
"default": "standard",
"description": "\"standard\" compact patches; \"none\" exact diff; \"symbols\" not available.",
"type": "string",
"enum": [
"none",
"standard"
]
}
}
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub Pull Request Search",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
ghSearchReposGithub | Discover GitHub repositories by name, topic, language, or popularity. | Find candidate repos before code search; skip when owner/repo is known (go straight to ghSearchCode/ghViewRepoStructure). Start concise:true, then inspect with ghViewRepoStructure/ghSearchCode.
keywords ANDed; topics also required but sparse; owner scopes/enumerates; match picks searched text fields; sort/range rank candidates. Empty → drop filters/topics or broaden language/owner.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"keywords": {
"description": "ANDed; keep a phrase as one item; alternatives need separate queries.",
"type": "array",
"items": {
"type": "string"
}
},
"topicsToSearch": {
"description": "Sparse required topics; pair with keywords/language.",
"type": "array",
"items": {
"type": "string"
}
},
"language": {
"description": "Primary language filter, e.g. \"rust\".",
"type": "string"
},
"owner": {
"description": "Repository owner (user or org).",
"type": "string"
},
"stars": {
"description": "Star range: \">100\", \"10..50\".",
"type": "string"
},
"forks": {
"description": "Fork range: \">50\", \"10..100\".",
"type": "string"
},
"goodFirstIssues": {
"description": "Good-first-issue count range, e.g. \">5\".",
"type": "string"
},
"updated": {
"description": "Last push date: \">2024-01-01\" or \"a..b\".",
"type": "string"
},
"created": {
"description": "Creation date: \">2023-01-01\" or \"a..b\".",
"type": "string"
},
"size": {
"description": "Repo size in KB: \">1000\", \"50..500\".",
"type": "string"
},
"match": {
"description": "Which text fields to search: name, description, and/or readme. Defaults to name+description; add 'readme' for broader, slower full-text search. (Unlike ghSearchCode, where `match` instead selects file-contents vs file-paths — a different concept sharing this name.)",
"type": "array",
"items": {
"type": "string",
"enum": [
"name",
"description",
"readme"
]
}
},
"sort": {
"default": "best-match",
"description": "stars, forks, updated, help-wanted-issues, best-match.",
"type": "string",
"enum": [
"stars",
"forks",
"help-wanted-issues",
"updated",
"best-match"
]
},
"limit": {
"description": "Results per page (paginate with page).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"archived": {
"description": "true = archived only; default excludes archived.",
"type": "boolean"
},
"visibility": {
"description": "\"public\" or \"private\" (private needs token scope).",
"type": "string",
"enum": [
"public",
"private"
]
},
"license": {
"description": "SPDX id, e.g. \"mit\".",
"type": "string"
},
"concise": {
"description": "Flat \"owner/repo\" rows for triage.",
"type": "boolean"
}
}
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub Repository Search",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
ghViewRepoStructureGithub | Browse a GitHub repository's directory tree. | Orient a repo/tree before fetching files, or verify paths/branches after 404s. Know a filename fragment? ghSearchCode(match:"path") is cheaper. Follow structure[] paths into ghGetFileContent or a clone sparsePath.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"owner": {
"type": "string",
"description": "Repository owner (user or org)."
},
"repo": {
"type": "string",
"description": "Repository name, without the owner."
},
"branch": {
"description": "Ref; fallback warning means default branch was used.",
"type": "string"
},
"path": {
"description": "Repo-relative directory; \"\"/\".\" for root.",
"type": "string"
},
"maxDepth": {
"description": "Tree recursion depth.",
"type": "integer",
"minimum": 0,
"maximum": 20
},
"page": {
"description": "Advance only on hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Items per result page.",
"type": "integer",
"minimum": 1,
"maximum": 200
},
"include": {
"description": "Optional repo enrichments (each adds ~1 API call, fetched concurrently): \"sizes\" per-file bytes; \"languages\" byte breakdown + dominant language; \"contributors\" top contributors; \"branches\"; \"tags\". Repo-level (ignore path) except \"sizes\".",
"type": "array",
"items": {
"type": "string",
"enum": [
"sizes",
"languages",
"contributors",
"branches",
"tags"
]
}
}
},
"required": [
"owner",
"repo"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "GitHub Repository Structure Explorer",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |
localFindDeadCodeLocal | Find likely-unreferenced exports and dead-code clusters via whole-repo reachability analysis. | Repo-wide dead-export candidates — not single-symbol checks (use lspGetSemantics references/callers). One pass builds a file/symbol graph (native AST, no per-symbol round-trips) and walks reachability from entrypoints, so it scales with repo size, not candidate count. Catches mutually-referencing dead clusters (files that only call each other, unreachable from any entrypoint) that a one-symbol check misses. Retention is symbol-level: a same-file call retains its callee only if the caller is live; named re-exports are followed through export* barrels to the entrypoint. Each candidate carries viaHeuristic: "reexport-chain" (chain ended with no consumer — most fragile, verify first) or "lexical-count" (no import, no unexplained same-file use). Candidates, not proof — run next.verifyReferences (a prefilled lspGetSemantics references query) per candidate; zero references = confirmed dead. Follow file/line anchors into localGetFileContent or lspGetSemantics.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"path": {
"type": "string",
"description": "Target path. GitHub tools: repo-relative, exact case, no leading slash. Local tools: absolute path."
},
"entrypoints": {
"description": "File paths considered reachability roots; omit to auto-detect from package.json main/exports/bin.",
"type": "array",
"items": {
"type": "string"
}
},
"includeTests": {
"default": true,
"description": "Treat test files (*.test.*, *.spec.*, __tests__/) as entrypoints (default true).",
"type": "boolean"
},
"excludeDir": {
"description": "Dir names to prune from the scan; defaults to node_modules/dist/build/out/coverage/.git/target/.next/.cache.",
"type": "array",
"items": {
"type": "string"
}
},
"maxFiles": {
"description": "Cap total files scanned; scan stops and warns past this bound.",
"type": "integer",
"minimum": 1,
"maximum": 50000
},
"limit": {
"description": "Dead-export result cap before pagination.",
"type": "integer",
"minimum": 1,
"maximum": 5000
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Items per result page.",
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"required": [
"path"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Local Find Dead Code",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
} | — | Read onlyNon-destructiveIdempotentClosed world | — |
localFindFilesLocal | Find local files and directories by name, size, time, or permissions. | Local path discovery by name/type/metadata — not contents (localSearchCode) or tree shape (localViewStructure). All filters AND. Prunes common generated/vendor dirs by default (node_modules, .git, dist, build, out, coverage, target, .next, .cache) — excludeDir:[] prunes nothing, or set excludeDir explicitly. Follow paths into read/search/LSP.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"path": {
"type": "string",
"description": "Target path. GitHub tools: repo-relative, exact case, no leading slash. Local tools: absolute path."
},
"maxDepth": {
"description": "Recurse at most this many levels below path (0 = path's own entries).",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"minDepth": {
"description": "Requires <= maxDepth when both set.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"names": {
"description": "Basename globs; ORed.",
"type": "array",
"items": {
"type": "string"
}
},
"pathPattern": {
"description": "Full-path glob.",
"type": "string"
},
"regex": {
"description": "Basename Rust regex.",
"type": "string"
},
"empty": {
"description": "Match only empty files/dirs.",
"type": "boolean"
},
"time": {
"description": "{ modifiedWithin?, modifiedBefore?, accessedWithin? } d/h/w/m windows.",
"type": "object",
"properties": {
"modifiedWithin": {
"type": "string"
},
"modifiedBefore": {
"type": "string"
},
"accessedWithin": {
"type": "string"
}
}
},
"size": {
"description": "{ greater?, less? } e.g. 100k, 1m, 500b.",
"type": "object",
"properties": {
"greater": {
"type": "string"
},
"less": {
"type": "string"
}
}
},
"permissions": {
"description": "Exact permission filter.",
"type": "string"
},
"access": {
"description": "\"executable\", \"readable\", or \"writable\" filter.",
"type": "string",
"enum": [
"executable",
"readable",
"writable"
]
},
"extensions": {
"description": "Extensions to include, e.g. [\"ts\",\"tsx\"] (no dot); cheaper and clearer than a names glob for this.",
"type": "array",
"items": {
"type": "string"
}
},
"excludeDir": {
"description": "Directory names to prune from the walk. Common generated/vendor dirs are pruned by default (node_modules, .git, dist, build, out, coverage, target, .next, .cache); pass [] to prune nothing, or pass an explicit list to choose pruned dirs.",
"type": "array",
"items": {
"type": "string"
}
},
"limit": {
"description": "Discovery cap applied after sort, before pagination — total results are capped here; itemsPerPage/page page within that cap.",
"type": "integer",
"minimum": 1,
"maximum": 10000
},
"detail": {
"default": "basic",
"description": "\"basic\" (default), \"modified\" (+mtime), or \"full\" (all metadata).",
"type": "string",
"enum": [
"basic",
"modified",
"full"
]
},
"sortBy": {
"default": "modified",
"description": "\"modified\" (default), \"name\", \"path\", or \"size\".",
"type": "string",
"enum": [
"modified",
"name",
"path",
"size"
]
},
"entryType": {
"description": "\"f\" files, \"d\" dirs.",
"type": "string",
"enum": [
"f",
"d"
]
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Items per result page.",
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"required": [
"path"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Local Find Files",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
} | — | Read onlyNon-destructiveIdempotentClosed world | — |
localGetFileContentLocal | Read a local file or a specific region. | Use after localSearchCode/localViewStructure/localFindFiles when you have a path — not for discovery. Unknown/large file: minify:"symbols" first, then exact range or matchString. A small structured/config file (package.json, tsconfig, lockfile) → read it whole with minify:"none"/fullContent, don't minify it — compaction can elide object boundaries and break exact key/value membership. For a literal value or quote, read the defining region with minify:"none" and copy the exact bytes.
Every response reports the file's full size (totalLines + sourceChars) and isPartial. A matchString/region read is a SLICE, not the whole file — it can cut a nested object mid-way; never conclude a key/field/value is absent or empty from a partial slice: continue via charOffset/next, or re-read the whole small structured file with minify:"none". Report only bytes you fetched — never invent a field, value, or quote.
Param relations: choose one extraction mode: fullContent OR matchString OR startLine+endLine. matchString pairs with contextLines and returns matchRanges ({start,end} line windows padded by contextLines, NOT the exact hit) plus matchedLines (the exact matched line numbers); charOffset continues isPartial pages. Follow matchedLines/matchRanges into LSP.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"path": {
"type": "string",
"description": "Target path. GitHub tools: repo-relative, exact case, no leading slash. Local tools: absolute path."
},
"fullContent": {
"description": "Whole file; small files only; exclusive with range/match.",
"type": "boolean"
},
"matchString": {
"description": "Anchor returning slices plus matchRanges ({start,end} padded windows) and matchedLines (exact hit line numbers).",
"type": "string"
},
"matchStringIsRegex": {
"description": "Makes matchString a regex.",
"type": "boolean"
},
"matchStringCaseSensitive": {
"description": "Case-sensitive matchString (default insensitive).",
"type": "boolean"
},
"startLine": {
"description": "Requires endLine; exclusive with fullContent/matchString.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"endLine": {
"description": "Requires startLine; must be >= startLine.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"contextLines": {
"description": "Extra source lines around each match/anchor.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"charOffset": {
"description": "Use pagination.nextCharOffset.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"charLength": {
"description": "Characters per content window; continue via the returned next offset when partial.",
"type": "integer",
"minimum": 1,
"maximum": 50000
},
"minify": {
"description": "\"symbols\" outline, \"standard\" compact, \"none\" exact.",
"type": "string",
"enum": [
"none",
"standard",
"symbols"
]
}
},
"required": [
"path"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Local Fetch Content",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
} | — | Read onlyNon-destructiveIdempotentClosed world | — |
localSearchCodeLocal | Search local files for text, regex, or AST patterns to find file and line. | Find local file+line anchors — not path/name lookup (localFindFiles) or tree shape (localViewStructure). Modes: discovery=paths, paginated=snippets, detailed=context, structural=AST.
text/regex need searchText (one string, not array); structural needs pattern XOR rule and rejects search knobs (langType is valid — scopes to that language's extensions). $$$ list captures are budgeted: metavarRanges gives pruned/truncated line anchors, captureText:true for verbatim. matchWindow/unique need output:"matchOnly"; maxMatchesPerFile pairs matchPage. Follow with localGetFileContent, lspGetSemantics.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"searchText": {
"description": "The search pattern. regex:\"fixed\" for a literal match, \"perl\" for advanced features (lookaheads, backreferences), else \"smart\". (Unlike ghSearchCode/ghSearchRepos, where `keywords` is an array of ANDed terms — this is a single string.)",
"type": "string"
},
"path": {
"type": "string",
"description": "Target path. GitHub tools: repo-relative, exact case, no leading slash. Local tools: absolute path."
},
"mode": {
"default": "paginated",
"description": "\"paginated\" snippets; \"discovery\" paths only; \"detailed\" snippets plus context; \"structural\" AST/code-shape search with pattern or rule. Structural matches return line/capture anchors that can feed lspGetSemantics when symbol identity matters. (Unrelated to ghSearchPullRequests's `content.patches.mode` — different concepts sharing this name.)",
"type": "string",
"enum": [
"paginated",
"discovery",
"detailed",
"structural"
]
},
"pattern": {
"description": "Structural only: code-shaped AST pattern with $X (one node) or $$$ARGS (node list). Modifiers are part of the node — `function $NAME` does not match `async function` or `export function`; include the modifiers or use a YAML `kind` rule for modifier-agnostic matches. Use this to find syntax shape, then use lspGetSemantics for semantic proof.",
"type": "string"
},
"rule": {
"description": "Structural only: YAML ast-grep rule for not/inside/has/all/any. Use for partial or relational AST queries before escalating matched anchors to lspGetSemantics.",
"type": "string"
},
"regex": {
"default": "smart",
"description": "\"smart\" (default), \"fixed\" (literal), or \"perl\" (advanced).",
"type": "string",
"enum": [
"smart",
"fixed",
"perl"
]
},
"caseMode": {
"default": "smart",
"description": "\"smart\" (default), \"sensitive\", or \"insensitive\".",
"type": "string",
"enum": [
"smart",
"sensitive",
"insensitive"
]
},
"wholeWord": {
"description": "Match whole words only (text/regex modes).",
"type": "boolean"
},
"invertMatch": {
"description": "Return non-matching lines (text/regex modes).",
"type": "boolean"
},
"include": {
"description": "Glob(s) of files to include.",
"type": "array",
"items": {
"type": "string"
}
},
"exclude": {
"description": "Glob(s) of files to exclude.",
"type": "array",
"items": {
"type": "string"
}
},
"excludeDir": {
"description": "Directory names to prune from the walk.",
"type": "array",
"items": {
"type": "string"
}
},
"noIgnore": {
"description": "Also search .gitignored files.",
"type": "boolean"
},
"hidden": {
"description": "Include dot-files.",
"type": "boolean"
},
"contextLines": {
"description": "Extra source lines around each match/anchor.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"matchContentLength": {
"description": "Characters of matched-line content kept per hit; longer lines are truncated (numeric default/bounds live in the schema).",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"maxMatchesPerFile": {
"description": "Pairs with matchPage.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"maxFiles": {
"description": "Cap total matched files.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"multiline": {
"default": "off",
"description": "\"off\" (default), \"on\", or \"dotall\" (. spans newlines).",
"type": "string",
"enum": [
"off",
"on",
"dotall"
]
},
"sort": {
"default": "relevance",
"description": "\"relevance\" (default), \"matchCount\", \"path\", \"modified\", \"accessed\", or \"created\".",
"type": "string",
"enum": [
"relevance",
"matchCount",
"path",
"modified",
"accessed",
"created"
]
},
"sortReverse": {
"description": "Reverse the sort order.",
"type": "boolean"
},
"rankingProfile": {
"default": "auto",
"description": "Language-aware relevance tuning for sort:\"relevance\"; \"auto\" (default) detects, else a language id or \"generic\".",
"type": "string",
"enum": [
"auto",
"typescript",
"javascript",
"rust",
"python",
"go",
"java",
"scala",
"markdown",
"json",
"yaml",
"generic"
]
},
"langType": {
"description": "Restrict to a language/file type, e.g. \"ts\" (ripgrep --type; in structural mode it maps to that language's include globs).",
"type": "string"
},
"captureText": {
"description": "Structural only: return full verbatim capture text for `$$$` list metavars (bodies, arg lists). Default false — list-capture text is omitted from `metavars`, and `metavarRanges` entries are comment-pruned and truncated to keep results lean; ranges always remain as line anchors.",
"type": "boolean"
},
"output": {
"default": "content",
"description": "\"content\" (default) matches with line text; \"files\"/\"filesWithout\" return matching/non-matching paths; \"countLines\"/\"countMatches\" return per-file counts; \"matchOnly\" returns just the matched substring (required for unique/matchWindow). (\"files\" is unlike localViewStructure's `filesOnly`, which filters a directory listing to file entries.)",
"type": "string",
"enum": [
"content",
"files",
"filesWithout",
"countLines",
"countMatches",
"matchOnly"
]
},
"unique": {
"default": "off",
"description": "Needs output:\"matchOnly\". \"list\" returns each matched value once per file; \"count\" adds its frequency.",
"type": "string",
"enum": [
"off",
"list",
"count"
]
},
"matchWindow": {
"description": "Requires output:\"matchOnly\".",
"type": "integer",
"minimum": 0,
"maximum": 200
},
"matchPage": {
"description": "Per-file match page.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Items per result page.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"maxDepth": {
"description": "Keep files at most this many directory levels below the search root (0 = files directly in the root). Structural mode pushes this into the native walker; text/regex mode applies it after the native search and emits a warning when it filters deeper matches.",
"type": "integer",
"minimum": 0,
"maximum": 20
},
"semanticRanking": {
"description": "DISABLED in this build — do not pass. sort:\"relevance\" already includes declaration/export/AST signals."
}
},
"required": [
"path"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Local Ripgrep Search",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
} | — | Read onlyNon-destructiveIdempotentClosed world | — |
localViewStructureLocal | Browse a local directory tree — cheapest first orientation step; no content loaded. | Cheapest local orientation before reading. Metadata/name filters → localFindFiles; files containing text → localSearchCode(mode:"discovery").
path is the root; pattern/extensions/entryType filter names; recursive enables maxDepth; detail switches output shape; page advances only on hasMore. Follow paths into localGetFileContent/search/LSP.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"path": {
"type": "string",
"description": "Target path. GitHub tools: repo-relative, exact case, no leading slash. Local tools: absolute path."
},
"detail": {
"default": "basic",
"description": "\"basic\" (default), \"modified\" (+mtime), or \"full\" (size/perms).",
"type": "string",
"enum": [
"basic",
"modified",
"full"
]
},
"hidden": {
"description": "Include dot-files/dirs.",
"type": "boolean"
},
"sortBy": {
"default": "name",
"description": "\"name\" (default), \"size\", \"time\", or \"extension\".",
"type": "string",
"enum": [
"name",
"size",
"time",
"extension"
]
},
"reverse": {
"description": "Reverse the sort order.",
"type": "boolean"
},
"pattern": {
"description": "Name glob/substr; use localFindFiles for regex.",
"type": "string"
},
"entryType": {
"description": "\"f\" files only, \"d\" dirs only; omit for both.",
"type": "string",
"enum": [
"f",
"d"
]
},
"recursive": {
"description": "Enables maxDepth.",
"type": "boolean"
},
"extensions": {
"description": "Allowlist without dots.",
"type": "array",
"items": {
"type": "string"
}
},
"maxDepth": {
"description": "Maximum recursion depth: 1 = the target directory's immediate children, 2 = children + grandchildren, and so on (upper bound lives in the schema). Setting maxDepth on its own enables recursion to that depth — recursive:true is not required. Effective depth when OMITTED: 1 (immediate children only) if recursive is unset, or 5 if recursive:true. maxDepth:0 is treated as unset and falls back to those defaults.",
"type": "integer",
"minimum": 0,
"maximum": 20
},
"limit": {
"description": "Discovery cap before pagination.",
"type": "integer",
"minimum": 1,
"maximum": 10000
},
"page": {
"description": "Result page, 1-based. Advance only while pagination.hasMore.",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "Items per result page.",
"type": "integer",
"minimum": 1,
"maximum": 50
},
"excludeDir": {
"description": "Directory names to prune from recursive walks (default: common generated/vendor dirs such as node_modules, dist, build, out, coverage, target). Pass [] to inspect everything.",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"path"
]
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Local View Structure",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
} | — | Read onlyNon-destructiveIdempotentClosed world | — |
lspGetSemanticsLocal | Run LSP semantic queries — definitions, references, call hierarchy, symbols, type hierarchy, diagnostics. | Use after search/read gives a real file+line anchor. documentSymbols/diagnostic need uri only; workspaceSymbol needs symbolName; others need uri+symbolName+lineHint.
lineHint must come from a prior anchor, never guessed; orderHint disambiguates same-line symbols; references take groupByFile/includeDeclaration; callers/callees/callHierarchy take depth/contextLines; format:"compact" saves tokens. Empty/serverUnavailable → re-anchor or fall back to search.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"uri": {
"description": "Target file path/URI; required for every type except workspaceSymbol.",
"type": "string"
},
"type": {
"default": "definition",
"description": "Semantic operation for local code intelligence. Use after text or structural AST search when you need identity, references, call flow, type relations, hover, symbols, or diagnostics.",
"type": "string",
"enum": [
"definition",
"references",
"callers",
"callees",
"callHierarchy",
"hover",
"documentSymbols",
"typeDefinition",
"implementation",
"workspaceSymbol",
"supertypes",
"subtypes",
"diagnostic"
]
},
"symbolName": {
"description": "Exact bare identifier at the lineHint anchor for symbol operations; workspaceSymbol uses this as the fuzzy project-wide symbol query.",
"type": "string",
"minLength": 1,
"maxLength": 1024
},
"lineHint": {
"description": "Real line containing symbolName; never guess.",
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"orderHint": {
"description": "Disambiguate repeated symbols on one line.",
"type": "integer",
"minimum": 0,
"maximum": 100000
},
"depth": {
"description": "Traversal depth for call-hierarchy / type-hierarchy queries (0 = direct only).",
"type": "integer",
"minimum": 0,
"maximum": 20
},
"includeDeclaration": {
"default": true,
"description": "references only; defaults true, which counts the declaration itself as one hit — set false (or expect a floor of 1) before treating a low count as unused.",
"type": "boolean"
},
"groupByFile": {
"description": "references summary mode.",
"type": "boolean"
},
"page": {
"description": "Result page for paginated reference/symbol lists (advance while pagination.hasMore).",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"itemsPerPage": {
"description": "References/symbols returned per page (with page).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"contextLines": {
"description": "Lines of surrounding source shown around each result location.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"format": {
"default": "structured",
"description": "\"compact\" saves tokens; \"structured\" has typed locations.",
"type": "string",
"enum": [
"structured",
"compact"
]
},
"workspaceRoot": {
"description": "Use when auto-root is wrong.",
"type": "string"
}
}
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Get Semantic Content",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
} | — | Read onlyNon-destructiveIdempotentClosed world | — |
npmSearchNPM | Look up npm packages and find their source repositories. | Resolve a package to its source repository; skip if owner/repo is known. Exact name → one rich result; keywords → paged candidates. Follow repository into GitHub tools.Input schema{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"queries": {
"minItems": 1,
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"description": "Stable ID to correlate this query with its result in a batch.",
"type": "string"
},
"mainResearchGoal": {
"description": "Goal shared by every query in this batch; set once per call.",
"type": "string"
},
"researchGoal": {
"description": "The specific sub-question this query answers.",
"type": "string"
},
"reasoning": {
"description": "Why this query advances the goal.",
"type": "string"
},
"packageName": {
"type": "string",
"description": "Exact package or keyword query; include scope."
},
"keywords": {
"description": "Registry keyword query (string; an array of terms is accepted and joined with spaces).",
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"page": {
"description": "Keyword-result page only.",
"type": "integer",
"minimum": 1,
"maximum": 1000
}
},
"required": [
"packageName"
],
"additionalProperties": false
},
"description": "Parallel queries."
},
"responseCharOffset": {
"description": "Full-response char offset; re-call with returned value when hasMore.",
"type": "integer",
"minimum": 0,
"maximum": 100000000
},
"responseCharLength": {
"description": "Full-response char window.",
"type": "integer",
"minimum": 1,
"maximum": 50000
}
},
"required": [
"queries"
]
}Annotations{
"title": "Package Search",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | Read onlyNon-destructiveIdempotentOpen world | — |