eye-mcp
v0.1.1
Published
A TypeScript MCP server for source-code browsing in large repositories.
Maintainers
Readme
eye-mcp
eye-mcp is a source-browsing MCP server for coding agents working in large local repositories.
Public docs: mym0404.github.io/eye
What It Does
| Tool | What it does |
| --- | --- |
| get_project_structure | Returns a bounded tree and skips generated paths such as build, dist, out, and .eye. |
| read_source_range | Reads source around a requested line with numbered output. |
| query_symbol | Resolves definition, references, and context from anchor, symbolId, or symbol. |
| refresh_index | Refreshes the local .eye cache for the whole project or a narrowed scope. |
| get_index_status | Reports cache generation, counts, and readiness. |
Quick Start
Requirements:
- Node.js 20+
Universal CtagsonPATHasctagsripgreponPATHasrg
Install prerequisites:
- macOS:
brew install universal-ctags ripgrep - Ubuntu 24.04:
sudo apt-get update && sudo apt-get install --yes universal-ctags ripgrep
Run the published package:
npx -y eye-mcpAdd It To Your Agent
Codex
codex mcp add eye -- npx -y eye-mcpClaude Code
claude mcp add --scope project eye -- npx -y eye-mcpGeneric .mcp.json
{
"mcpServers": {
"eye": {
"command": "npx",
"args": ["-y", "eye-mcp"]
}
}
}How query_symbol Works
query_symbol always returns matches. When action is context, it also returns one bounded context block for the first match.
Current behavior:
- anchor definitions, anchor references, and
symbolIdreferences try semantic navigation first - if semantic resolution throws or returns nothing useful, the query falls back to indexed rows and then lower-confidence text search when needed
- semantic reference results do not infer
symbolIdfrom usage-site proximity - when a
symbolIdtarget resolved successfully, semantic reference matches reuse that requestedsymbolIdand indexed symbol name - merged reference candidates are deduped by
filePath:line:columnbefore truncation
Typical flow:
get_project_structureread_source_rangequery_symbolwithaction: "definition"- reuse the returned
symbolIdforreferencesorcontext refresh_indexwhen the repository changed or you want a deterministic refresh
Example:
{
"name": "query_symbol",
"arguments": {
"target": {
"by": "anchor",
"filePath": "src/main.ts",
"line": 42,
"column": 17
},
"action": "definition"
}
}Then follow up with the returned symbolId:
{
"name": "query_symbol",
"arguments": {
"target": {
"by": "symbolId",
"symbolId": "sym:typescript:src/utils/helper.ts:helper:1"
},
"action": "references",
"includeDeclaration": false
}
}Project Root And Cache
eye works on one project root at a time.
Root detection order:
- explicit
projectRoot - nearest ancestor with
.eye/config.json - nearest workspace root such as
.git,pnpm-workspace.yaml, orturbo.json - nearest project root such as
package.json,tsconfig.json,jsconfig.json,pyproject.toml, orsetup.py - server process cwd
On the first index-backed operation, eye creates .eye/config.json and fills sourceRoots with inferred relative paths such as src, app, or packages/web/src.
sourceRoots controls indexing and helps get_project_structure show source roots before sibling directories. Structure and source reads still work across the whole resolved project root.
Runtime init also creates .eye/.gitignore, which keeps local cache files out of Git while leaving .eye/config.json visible.
Limitations
- indexing is lazy and query-triggered; there is no watch mode
- name-based lookups can still be ambiguous
contextis bounded for navigation, not whole-file dumping- the persisted index is ctags-backed, so some queries can still fall back to lower-confidence text search
