{"id":41823822,"url":"https://github.com/mariusei/file-scanner-mcp","last_synced_at":"2026-06-16T03:00:36.559Z","repository":{"id":319209759,"uuid":"1077870115","full_name":"mariusei/file-scanner-mcp","owner":"mariusei","description":"MCP server for code structure analysis across 20+ languages. Tree-sitter powered. Works with Claude Code and Claude Desktop.","archived":false,"fork":false,"pushed_at":"2026-06-11T04:03:25.000Z","size":11302,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-11T05:04:37.444Z","etag":null,"topics":["ai-assistant","ast","claude","claude-code","code-analysis","code-search","code-structure","coding-assistant","developer-tools","directory-tree","file-analysis","mcp","mcp-server","model-context-protocol","multi-language","python","source-code","static-analysis","tree-sitter","typescript"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/scantool/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mariusei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-16T21:31:10.000Z","updated_at":"2026-06-11T04:03:30.000Z","dependencies_parsed_at":"2026-06-11T05:02:31.908Z","dependency_job_id":null,"html_url":"https://github.com/mariusei/file-scanner-mcp","commit_stats":null,"previous_names":["mariusei/file-scanner-mcp"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/mariusei/file-scanner-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusei%2Ffile-scanner-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusei%2Ffile-scanner-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusei%2Ffile-scanner-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusei%2Ffile-scanner-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mariusei","download_url":"https://codeload.github.com/mariusei/file-scanner-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariusei%2Ffile-scanner-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34388669,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-assistant","ast","claude","claude-code","code-analysis","code-search","code-structure","coding-assistant","developer-tools","directory-tree","file-analysis","mcp","mcp-server","model-context-protocol","multi-language","python","source-code","static-analysis","tree-sitter","typescript"],"created_at":"2026-01-25T08:01:42.494Z","updated_at":"2026-06-16T03:00:36.552Z","avatar_url":"https://github.com/mariusei.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scantool: Code Analysis MCP Server for Claude\n\n[![PyPI version](https://badge.fury.io/py/scantool.svg)](https://pypi.org/project/scantool/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nMCP server that hands an AI agent a codebase's **structure** — classes, functions, call graphs, imports, hot functions, all with exact line numbers — instead of raw file dumps. Works with **Claude Code**, **Claude Desktop**, **Cursor**, **VS Code** and any **Model Context Protocol** client. 20+ languages via **tree-sitter** — and code *and* documents (Markdown, HTML, CSS, SQL, config) through the same lens, which the code-only tools don't do.\n\n**What that buys, measured — not claimed:**\n\n```\n\"Where is the cache invalidated?\"    scantool   378 tokens / 1 call\n                                     grep      9,370 tokens / 4 calls    -\u003e 25x less\n\npytest skipif-caching bug            scantool   solved in 3 calls\n                                     grep       gave up after 13,450 tokens\n```\n\nOn real agent episodes, scantool agents answered with **88% fact coverage vs 73%** for a grep-only agent — better-anchored answers, fewer wrong files. Honest scope: grep still wins plain literal lookups and top-level overviews. Scantool measures **both** axes and reports the losses too (`experiments/benchmark/`).\n\n**Zero infrastructure**: no index to build, no API keys, no vector database, no model downloads. Point it at a directory and it scans on demand.\n\n## Quick Start\n\n**Requires [uv](https://docs.astral.sh/uv/)** (provides the `uvx` command). Install it first if you don't have it — without it, scantool will silently fail to start:\n\n```bash\n# macOS / Linux / WSL\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n```\n\n### Claude Code\n\n```bash\n# Available in all your projects (recommended)\nclaude mcp add --scope user scantool -- uvx scantool\n\n# Or just for the current project\nclaude mcp add scantool -- uvx scantool\n```\n\nRestart Claude Code and you're ready to go.\n\n### Claude Desktop\n\nAdd to config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):\n\n```json\n{\n  \"mcpServers\": {\n    \"scantool\": {\n      \"command\": \"uvx\",\n      \"args\": [\"scantool\"]\n    }\n  }\n}\n```\n\nRestart Claude Desktop after configuration.\n\n### Cursor\n\nAdd to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project):\n\n```json\n{\n  \"mcpServers\": {\n    \"scantool\": {\n      \"command\": \"uvx\",\n      \"args\": [\"scantool\"]\n    }\n  }\n}\n```\n\n### Windsurf\n\nAdd to `~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"scantool\": {\n      \"command\": \"uvx\",\n      \"args\": [\"scantool\"]\n    }\n  }\n}\n```\n\n### VS Code (Copilot agent mode)\n\nAdd to `.vscode/mcp.json` in your workspace:\n\n```json\n{\n  \"servers\": {\n    \"scantool\": {\n      \"command\": \"uvx\",\n      \"args\": [\"scantool\"]\n    }\n  }\n}\n```\n\n### Cline\n\nIn the Cline panel: MCP Servers icon → *Configure* tab → *Configure MCP Servers*, then add the same `mcpServers` entry as above. (Cline CLI reads `~/.cline/mcp.json`.)\n\n### Troubleshooting: `uvx` not found\n\n`uvx` comes with [uv](https://docs.astral.sh/uv/), the Python package manager. Install it first:\n\n```bash\n# macOS / Linux / WSL\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n\n# Windows (PowerShell)\npowershell -ExecutionPolicy ByPass -c \"irm https://astral.sh/uv/install.ps1 | iex\"\n```\n\n**After installing uv, restart your terminal** (or open a new one) so `uvx` is on your PATH. Then re-run the setup command above.\n\nIf `uvx` still isn't found after restarting the terminal, add it to your PATH manually:\n\n```bash\n# Linux / WSL - add to ~/.bashrc or ~/.zshrc:\nexport PATH=\"$HOME/.local/bin:$PATH\"\n\n# macOS - usually works out of the box, but if not:\nexport PATH=\"$HOME/.local/bin:$PATH\"\n```\n\n### Alternative: Install from source\n\n```bash\ngit clone https://github.com/mariusei/file-scanner-mcp.git\ncd file-scanner-mcp\nuv sync\n\n# Claude Code\nclaude mcp add --transport stdio scantool -- uv run --directory /path/to/file-scanner-mcp scantool\n\n# Claude Desktop\n# Use command: \"uv\", args: [\"run\", \"--directory\", \"/path/to/file-scanner-mcp\", \"scantool\"]\n```\n\n### Share with your team (.mcp.json)\n\nAdd a `.mcp.json` file to your project root to share the config with your team:\n\n```json\n{\n  \"mcpServers\": {\n    \"scantool\": {\n      \"command\": \"uvx\",\n      \"args\": [\"scantool\"]\n    }\n  }\n}\n```\n\nClaude Code will prompt team members for approval on first use.\n\n## Features\n\n### Multi-language Support\nPython, JavaScript, TypeScript, Rust, Go, C/C++, Java, PHP, C#, Ruby, Zig, Swift, SQL (PostgreSQL, MySQL, SQLite), HTML, CSS, SCSS, Markdown, Plain Text, Images\n\n### Structure Extraction\n- Classes, methods, functions, imports\n- Function signatures with type annotations\n- Decorators and attributes\n- Docstrings and JSDoc comments\n- Precise line numbers (from-to ranges)\n\n### Analysis Tools\n- **preview_directory**: Intelligent codebase analysis with entry points, import graph, call graph, and hot functions (5-10s)\n- **scan_file**: Detailed file structure with signatures and metadata; `focus=` reads one named function/class/section verbatim with parent context\n- **scan_directory**: Compact directory tree with inline function/class names\n- **search_structures**: Filter by type, name pattern, decorator, or complexity\n- **list_directories**: Directory tree (folders only)\n- **find_divergence**: Audit a directory for peer divergence — functions that break a call pattern their siblings follow (peers calling X also call Y, this one doesn't); a review hint, not a verified bug; silent on a consistent codebase. The same section also appears inline in `scan_diff` (changed code) and `preview_directory` (deep)\n\n### Output Formats\n- Tree format with box-drawing characters\n- JSON format for programmatic use\n- Configurable display options\n\n## Usage\n\n### preview_directory - Code analysis (primary tool)\n\nAnalyzes codebase structure including entry points, import graph, call graph, and hot functions.\n\n```python\npreview_directory(\n    directory=\".\",\n    depth=\"deep\",             # \"quick\", \"normal\", or \"deep\" (default: \"deep\")\n    max_files=10000,          # Safety limit (default: 10000)\n    max_entries=20,           # Entries per section (default: 20)\n    respect_gitignore=True    # Honor .gitignore (default: True)\n)\n```\n\n**Depth levels:**\n- `\"quick\"`: Metadata only (0.5s) - file counts, sizes, types\n- `\"normal\"`: Architecture analysis (2-5s) - imports, entry points, clusters\n- `\"deep\"`: Full analysis (5-10s) - includes hot functions and call graph (default)\n\n**Example output (depth=\"deep\"):**\n\n```\nproject/\n\n--- ENTRY POINTS ---\n  main.py:main() @1\n  backend/application.py:Flask app @15\n  frontend/index.ts:export default\n\n--- CORE FILES (by centrality) ---\n  backend/database.py: imports 0, used by 15 files\n  backend/auth.py: imports 1, used by 8 files\n  shared/utils.py: imports 2, used by 12 files\n\n--- ARCHITECTURE ---\n  Entry Points: 25 files\n  Core Logic: 68 files\n  Plugins: 15 files\n  Tests: 42 files\n\n--- HOT FUNCTIONS (most called) ---\n  get_database() (function): called by 41, calls 1 @backend/database.py\n  authenticate() (function): called by 23, calls 5 @backend/auth.py\n  validate_input() (function): called by 15, calls 2 @shared/utils.py\n\nAnalysis: 486 files in 4.82s (layer1+layer2)\n```\n\n**Use cases:**\n- First-time codebase exploration\n- Understanding multi-modality projects (frontend/backend/database)\n- Finding critical functions (hot spots)\n- Identifying entry points\n\n### scan_file - Detailed file analysis\n\n```python\nscan_file(\n    file_path=\"path/to/file.py\",\n    focus=None,                # Read ONE node verbatim by name (\"query\",\n                               # \"DatabaseManager.query\", a markdown heading)\n                               # instead of guessing line ranges — see below\n    show_signatures=True,      # Include function signatures with types\n    show_decorators=True,      # Include @decorator annotations\n    show_docstrings=True,      # Include first line of docstrings\n    show_complexity=False,     # Show complexity metrics\n    condense=True,             # Condensed skeletons (set False for verbatim lines)\n    budget=None,               # Approx token cap for skeletons — least salient\n                               # functions degrade first, output stays predictable\n    output_format=\"tree\"       # \"tree\" or \"json\"\n)\n```\n\n**Example output:**\n\n```\nexample.py (1-57)\n- file-info: 1.4KB modified: 2 hours ago\n- imports: import statements (3-5)\n- class: DatabaseManager (8-26)\n    \"Manages database connections and queries.\"\n  - method: __init__ (self, connection_string: str) (11-13)\n  - method: connect (self) (15-17)\n      \"Establish database connection.\"\n  - method: query (self, sql: str) -\u003e list (24-26)\n      \"Execute a SQL query.\"\n      return self.cursor.execute(sql).fetchall()\n- function: main () (53-57)\n    \"Main entry point.\"\n```\n\nFunctions additionally show their implementation as a condensed method\nskeleton: pseudocode lines without line numbers where control flow with\nconditions, calls and returns are kept and trivial statements fold to `…`\n(verbatim lines always carry `N |` line numbers — that's how you tell them\napart). Skeletons come in two tiers: the most salient functions (by entropy,\nuniqueness and centrality) get full depth, every other function gets a\nshallow depth-2 outline — measured as the best fact-coverage per token.\nMarkers are plain ASCII because box-drawing glyphs cost 2-3 BPE tokens each.\nPass `condense=False` to get line-numbered excerpts (top tier only) instead.\n\nCondensation adapts to the language: imperative languages (Python, TypeScript,\nGo, Rust, Java, ...) get fold-by-default skeletons, declarative ones (CSS,\nSQL, HTML) keep their content and drop only blanks, comments and closing\npunctuation, and prose/config stay verbatim — where there is nothing safe to\nfold, the original excerpt is shown unchanged.\n\n#### focus= — the read step\n\nAfter a scan or search has located a node, pass `focus=` to read exactly\nthat function/class/method/heading verbatim — instead of guessing a line\nrange for Read/cat/sed:\n\n```python\nscan_file(file_path=\"example.py\", focus=\"DatabaseManager.query\")\n```\n\n```\nfocus: DatabaseManager.query @24-26\nexample.py (3-57)\n- import statements @3\n- DatabaseManager @8 # Manages database connections and queries.\n  - __init__ (self, connection_string: str) @11\n  - connect (self) @15 # Establish database connection.\n  - disconnect (self) @19 # Close database connection.\n  - query (self, sql: str) -\u003e list @24 # Execute a SQL query.\n     24 |     def query(self, sql: str) -\u003e list:\n     25 |         \"\"\"Execute a SQL query.\"\"\"\n     26 |         return []\n- UserService @29 # Handles user-related operations.\n- validate_email (email: str) -\u003e bool @48 # Validate email format.\n- main () @53 # Main entry point.\n```\n\nThe rest of the file stays as a depth-1 skeleton, so the node arrives with\nits parent context. Names resolve in three tiers: exact match, qualified\npath (`ClassA.method`, works for markdown headings too), then\ncase-insensitive substring; an ambiguous name returns the qualified\ncandidate list instead of guessing. Measured on real agent episodes\n(`experiments/benchmark/M2C.md`): equal answer quality at 75% fewer\nread tokens than cat/sed line-range guessing.\n\n### scan_file_content - Analyze content directly\n\nScan content without requiring a file path. Works with remote files, APIs, or in-memory content.\n\n```python\nscan_file_content(\n    content=\"def hello(): pass\\n\\nclass MyClass:\\n    pass\",\n    filename=\"example.py\",     # Extension determines parser\n    show_signatures=True,\n    show_decorators=True,\n    show_docstrings=True,\n    show_complexity=False,\n    output_format=\"tree\"\n)\n```\n\n### scan_directory - Compact overview\n\nShows directory tree with inline class/function names.\n\n```python\nscan_directory(\n    directory=\"./src\",\n    pattern=\"**/*\",                 # Glob pattern\n    max_files=None,                 # File limit\n    respect_gitignore=True,         # Honor .gitignore\n    exclude_patterns=None,          # Additional exclusions\n    output_format=\"tree\"            # \"tree\" or \"json\"\n)\n```\n\n**Example output:**\n\n```\nsrc/ (22 files, 15 classes, 127 functions, 89 methods)\n├─ languages/\n│  ├─ python.py (1-329) [11.9KB, 2 hours ago] - PythonLanguage\n│  ├─ typescript.py (1-505) [18.9KB, 1 day ago] - TypeScriptLanguage\n│  └─ rust.py (1-481) [17.6KB, 3 days ago] - RustLanguage\n├─ scanner.py (1-232) [8.8KB, 5 mins ago] - FileScanner\n└─ server.py (1-735) [27.2KB, just now] - scan_file, scan_directory, ...\n```\n\n**Pattern examples:**\n\n```python\n# Specific file types\nscan_directory(\"./src\", pattern=\"**/*.py\")\n\n# Multiple types\nscan_directory(\"./src\", pattern=\"**/*.{py,ts,js}\")\n\n# Shallow scan (1 level deep)\nscan_directory(\".\", pattern=\"*/*\")\n\n# Exclude directories\nscan_directory(\".\", exclude_patterns=[\"tests/**\", \"docs/**\"])\n```\n\n### search_structures - Find and filter\n\n```python\n# Find test functions\nsearch_structures(\n    directory=\"./tests\",\n    type_filter=\"function\",\n    name_pattern=\"^test_\"\n)\n\n# Find classes ending in \"Manager\"\nsearch_structures(\n    directory=\"./src\",\n    type_filter=\"class\",\n    name_pattern=\".*Manager$\"\n)\n\n# Find functions with @staticmethod\nsearch_structures(\n    directory=\"./src\",\n    has_decorator=\"@staticmethod\"\n)\n\n# Find complex functions (\u003e100 lines)\nsearch_structures(\n    directory=\"./src\",\n    type_filter=\"function\",\n    min_complexity=100\n)\n```\n\n### list_directories - Folder structure\n\nShows directory tree without files.\n\n```python\nlist_directories(\n    directory=\".\",\n    max_depth=3,              # Maximum depth (default: 3)\n    respect_gitignore=True    # Honor .gitignore (default: True)\n)\n```\n\n**Example output:**\n\n```\n/Users/user/project/\n├─ src/\n│  ├─ components/\n│  ├─ services/\n│  └─ utils/\n├─ tests/\n│  ├─ unit/\n│  └─ integration/\n└─ docs/\n```\n\n## Output Contract\n\nThe default output format IS the API: LLM agents consume scantool output\ndirectly and uncritically, so format drift is behavior drift in the\nconsumer (measured in `experiments/benchmark/M2B.md`). Two consequences:\n\n- **Defaults are the measured optimum — parameters are escape hatches.**\n  Every default (two-tier condensation, saliency selection, skeleton\n  depth, compact vs verbatim per language) is backed by measurements in\n  `experiments/condensation/`, `experiments/entropy_metrics/` and\n  `experiments/benchmark/`. Override them when a specific situation\n  demands it, not as a style preference.\n- **The default format is frozen by golden tests** (`tests/test_golden.py`,\n  snapshots in `tests/golden/`). A deliberate format change requires a\n  deliberate snapshot update (`UPDATE_GOLDEN=1 uv run pytest\n  tests/test_golden.py`); an accidental change fails CI. Environment-\n  dependent parts (file size/mtime, git churn, delta memory) live outside\n  the frozen layer. Peer divergence is a pure function of the code, so it\n  is frozen too (`tests/golden/consensus.txt`, fixture in\n  `tests/golden/consensus_fixture/`).\n\n## Supported Languages\n\n| Extension | Language | Extracted Elements |\n|-----------|----------|-------------------|\n| `.py`, `.pyw` | Python | classes, methods, functions, imports, decorators, docstrings |\n| `.js`, `.jsx`, `.mjs`, `.cjs` | JavaScript | classes, methods, functions, imports, JSDoc comments |\n| `.ts`, `.tsx`, `.mts`, `.cts` | TypeScript | classes, methods, functions, imports, type annotations, JSDoc |\n| `.rs` | Rust | structs, enums, traits, impl blocks, functions, use statements |\n| `.go` | Go | types, structs, interfaces, functions, methods, imports |\n| `.c`, `.h` | C | functions, structs, enums, includes |\n| `.cpp`, `.hpp`, `.cc`, `.hh` | C++ | classes, functions, namespaces, templates, includes |\n| `.java` | Java | classes, methods, interfaces, enums, annotations, imports |\n| `.php` | PHP | classes, methods, functions, traits, interfaces, namespaces |\n| `.cs` | C# | classes, methods, properties, structs, enums, namespaces |\n| `.rb` | Ruby | modules, classes, methods, singleton methods |\n| `.zig` | Zig | functions, structs, enums, unions, tests |\n| `.swift` | Swift | classes, structs, enums, protocols, functions, extensions |\n| `.sql` | SQL | tables, views, functions, procedures, indexes, columns |\n| `.html` | HTML | document structure, elements, attributes |\n| `.css` | CSS | selectors, properties, media queries |\n| `.scss` | SCSS | selectors, mixins, variables, nesting |\n| `.md` | Markdown | headings (h1-h6), code blocks with hierarchy |\n| `.txt` | Plain Text | sections, paragraphs |\n| `.png`, `.jpg`, `.gif`, `.webp` | Images | format, dimensions, colors, content type |\n\nAll files include metadata (size, modified date, permissions) automatically.\n\n## Use Cases\n\n### Code Navigation\n- Structural overview of unfamiliar codebases\n- File organization understanding\n- Navigation using precise line ranges\n\n### Refactoring\n- Identify class and function boundaries for safe splitting\n- Find implementations of specific patterns\n- Locate functions above complexity thresholds\n\n### Code Review\n- Generate structural diffs\n- Find functions with specific decorators\n- Identify test coverage gaps\n- Peer divergence: spot a changed function that breaks a call pattern its\n  siblings across the repo follow (a likely regression — adjudicate by reading)\n\n### Documentation\n- Auto-generate table of contents with line numbers\n- Extract API signatures\n- Feed structured data to analysis tools (JSON output)\n\n### AI Code Assistance\n- Primary exploration tool (replaces ls/grep/find workflows)\n- Partition large files intelligently for LLM context windows\n- Extract code sections with exact boundaries\n- Search patterns across codebases\n- Reduce token usage: get structure first, read content only when needed\n\n## Architecture\n\n```\nscantool/\n├── server.py        # FastMCP server (stdio + HTTP entry points)\n├── scanner.py       # Core scanning logic using tree-sitter\n├── formatter.py     # Tree formatting with box-drawing characters\n├── code_map.py      # Architecture analysis (Layer 1 + 2)\n├── call_graph.py    # Hot functions, centrality analysis\n├── preview.py       # Quick directory preview\n└── languages/       # Unified language system (one file per language)\n    ├── base.py      # BaseLanguage - all languages inherit from this\n    ├── models.py    # StructureNode, CallInfo, ImportInfo, etc.\n    ├── python.py    # PythonLanguage\n    ├── typescript.py\n    ├── rust.py\n    └── ...          # 20+ languages\n```\n\n## HTTP Transport (advanced)\n\nFor environments where stdio doesn't work, or when sharing a server across multiple clients:\n\n```bash\n# Start the HTTP server\nuvx --from scantool scantool-http\n# Listens on port 8080 by default (set PORT env var to change)\n\n# Connect Claude Code to it\nclaude mcp add --transport http scantool http://127.0.0.1:8080/mcp\n```\n\nNote: The HTTP server must be started separately and kept running. For most users, the stdio transport (default) is simpler and recommended.\n\n## Testing\n\n```bash\n# Run all tests\nuv run pytest\n\n# Run specific tests\nuv run pytest tests/languages/\nuv run pytest tests/python/\nuv run pytest tests/typescript/\n\n# Run with coverage\nuv run pytest --cov=src/scantool\n\n# Run with verbose output\nuv run pytest -v\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for details on adding language support.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Dependencies\n\n- [FastMCP](https://github.com/jlowin/fastmcp) - MCP server framework\n- [tree-sitter](https://tree-sitter.github.io/) - Parsing library\n- [uv](https://github.com/astral-sh/uv) - Python package installer\n\n## Known Limitations\n\n### MCP Tool Response Size Limit\n\nClaude Desktop enforces a 25,000 token limit on MCP tool responses. Claude Code has a configurable limit (set `MAX_MCP_OUTPUT_TOKENS` env var to adjust).\n\n**Built-in mitigations:**\n- `scan_directory()` uses compact inline format\n- Respects `.gitignore` by default (excludes node_modules, .venv, etc.)\n- Shows file metadata with relative timestamps\n\n**Manual controls:**\n- Use `pattern` to limit scope: `\"**/*.py\"` vs `\"*/*\"` (shallow)\n- Use `max_files` to cap number of files processed\n- Use `exclude_patterns` for additional exclusions\n- Scan specific subdirectories instead of entire codebase\n\n**For large codebases:**\n```python\n# Scan specific areas\nscan_directory(\"./src\", pattern=\"**/*.py\")\nscan_directory(\"./tests\", pattern=\"**/*.py\")\n```\n\n### Agent Delegation\n\nWhen using Claude Code, asking to \"explore the codebase\" may delegate to the Explore agent which doesn't have access to MCP tools. Be explicit: \"use scantool to scan the codebase\" to ensure the MCP tool is used directly.\n\n## Support\n\n- [GitHub Issues](https://github.com/mariusei/file-scanner-mcp/issues)\n- [GitHub Discussions](https://github.com/mariusei/file-scanner-mcp/discussions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariusei%2Ffile-scanner-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmariusei%2Ffile-scanner-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariusei%2Ffile-scanner-mcp/lists"}