Skip to main content
Glama

jscpd

npm version npm downloads skills.sh installs Crates.io Version NPM License jscpd CI Coverage Duplication in rust/ Socket Badge OpenSSF Scorecard OpenSSF Best Practices Follow on X

Duplicate code detector for 220+ languages — plus dead code, complexity hotspots, duplication and health trends over git history, and one health score for the whole codebase. Rust engine, self-contained binary, AI-ready with an MCP server and a token-efficient reporter.

Documentation: https://jscpd.dev

jscpd tokenizes each of its 224 supported formats the way that language defines it — its own comment and string rules, not generic text — then finds duplicated token sequences across files with a rolling Rabin-Karp hash. Opt-in passes catch copies that differ only in names or values (Type-2) or that have a few edited lines (Type-3), and an experimental one uses a code embedding model for functions that do the same thing written differently (Type-4). See How detection works for the full mechanism, and Supported formats for the full list.

Beyond duplicates, jscpd also finds dead code (--dead-code), ranks files by complexity (--complexity), tracks duplication and health over git history (--history), and rolls it all into one health score (--health) — see Features below.

Quick Start

# macOS / Linux
curl -fsSL https://jscpd.dev/install.sh | bash

# Windows (PowerShell)
irm https://jscpd.dev/install.ps1 | iex

# No install — run once with npx (Node.js)
npx jscpd .

Then scan a project:

jscpd /path/to/code

Other install methods

Method

Command

Notes

npm

npm install -g jscpd

Installs the jscpd command; prebuilt binary, no Node.js at runtime

npm (cpd command)

npm install -g cpd

Same binary, exposed as cpd

PyPI

pip install jscpd

Platform wheels with both commands; also pipx install jscpd, uv tool install jscpd, or uvx jscpd . to run without installing

Cargo

cargo install jscpd

Builds from crates.io; installs both jscpd and cpd

Homebrew

brew install jscpd

macOS / Linux

Nix

nix run github:kucherenko/jscpd -- /path/to/code

Or nix profile install github:kucherenko/jscpd

Docker

docker run --rm -v "$PWD:/src" ghcr.io/kucherenko/jscpd .

Multi-arch image built from the release binaries

GitHub Action

- uses: kucherenko/jscpd@v5
  with:
    threshold: 5

Uploads SARIF results to GitHub Code Scanning by default. See CI & Pre-Commit Hooks for all inputs and outputs.

Related MCP server: tree-sitter-analyzer

Documentation

Document

Description

Rust engine

Installation, CLI reference, reporters, baseline, summary, complexity, dashboard, blame, config file

AI-Ready

AI reporter, agent skills, MCP server

Editors

jscpd --lsp, the language server: setup for Neovim, Helix, Sublime Text, Emacs and JetBrains IDEs

Programming API

Rust API (cpd-finder crate)

CI & Pre-Commit Hooks

GitHub Action, Docker image, pre-commit hooks

Packages

npm packages and crates that make up a release

Supported formats

All 224 formats with their file extensions

Runnable demos

One fixtures/<feature>-demo/ directory per feature, each README lists the commands with their expected output

Features

jscpd v5 is a Rust engine that ships as a self-contained binary — no runtime required — under two npm names (jscpd installs the jscpd command, cpd installs cpd), on PyPI, crates.io, Homebrew, Nix, Docker, and as a GitHub Action.

Duplicate detection

  • Language-aware tokenization — per-format comment and string syntax for all 224 formats, the oxc parser for JavaScript/TypeScript/JSX/TSX, embedded-language extraction for Vue, Svelte, Astro, Markdown and Razor, and keyword/identifier/literal classification, so a clone is a repeated sequence of language tokens, never a repeated run of text (see How detection works)

  • 224 language formats, with cross-format detection (Vue SFC, Svelte, Astro, Markdown) and --cross-formats groups to match clones across JavaScript and TypeScript

  • Type-2 clones — --ignore-identifiers, --ignore-literals and --ignore-annotations find blocks that differ only in names, literal values or annotations, reported as renamed. A name must stand for one name on the other side, so x = x + x does not match d = a + b; --ignore-identifiers=blind matches any names, as 5.4 did (see docs)

  • Type-3 near-miss clones — --max-gap-lines N merges a copy with a few inserted or changed lines into one similar clone with a similarity score; --similarity compares whole functions of JavaScript, TypeScript, Python, Java, Kotlin, Scala, C#, Go, Rust, C, C++, PHP, Ruby, Swift and Clojure by the subtrees of their normalized syntax trees, in code blocks of Markdown and components as well: renamed locals (each standing for one name on the other side) and other literals match, other called functions or operators do not, and test files are left out; the edn reporter lists every pair with its score (see docs)

  • Type-4 semantic clones (experimental) — --semantic embeds the functions of JavaScript, TypeScript, Vue, Svelte, Astro, Python, Rust, Go, Java, Kotlin, C#, C, C++, PHP, Ruby, Scala and Swift files with a code embedding model, either one jscpd runs itself (after jscpd --semantic-download once) or any OpenAI-compatible API, and reports functions that do the same thing written differently: the same feature implemented twice in one language, or a rule your Rust backend enforces and your Svelte frontend repeats (see Semantic clones below)

  • Port progress and parity (experimental): jscpd --compare python/ typescript/ pairs the functions of two folders with the same model and lists which functions of each have a counterpart in the other: what is left to port to another language or platform, or what the Android version of an app has that the iOS one lacks (see Comparing two codebases below)

  • Boundaries: rules in .jscpd.json keep the code of a module, a folder, a file or a method inside its boundary, such as money that only the backend may calculate. A copy of it in a place a rule keeps it out of fails the run, whether someone copied it, edited the copy or wrote the logic again in another language (see Boundaries below)

  • Clone kinds everywhere — exact, renamed or similar in the console, JSON (kind, similarity, method), XML, HTML, Xcode, SARIF (jscpd/duplicate-code, jscpd/renamed-code, jscpd/similar-code, jscpd/similar-function, jscpd/semantic-code) and Code Climate output; default runs still report only exact clones

  • --kind — keep only the clone kinds you care about: --kind renamed, or --kind gap,ast for near-miss clones only. Statistics and --threshold follow the filter; a kind whose detector is off warns, an unknown kind errors (see docs)

  • 15 reporters: console, console-full, json, xml, csv, html, markdown, badge, sarif, codeclimate, openmetrics, ai, xcode, threshold, silent

  • Clone baseline — gate CI on new duplication only. --baseline .jscpd-baseline.json --fail-on-new-clones[=N] tolerates legacy clones and fails the build on regressions; --baseline-from-ref origin/main does the same without a committed file (see docs)

  • Only the files you changed — jscpd --changed . reports the clones of the files git status lists, matched against the whole project, and marks the ones HEAD didn't have as new; --changed-only compares the changed files only with one another. The baseline of HEAD is saved on the first run and built again after a commit (see docs)

  • Exit codes you can gate on — an unknown --format, a missing scan path or a reporter that can't write its file now exit 1 instead of passing with an empty report; --fail-on-empty fails a scan that analyzed no files (see Exit codes)

  • GitLab-ready reporters — codeclimate (gl-code-quality-report.json) and openmetrics (jscpd-metrics.txt) plug into artifacts:reports

  • Git blame with side-by-side author comparison (--blame --reporters console-full)

  • --skip-local — report only clones that cross the scan roots: jscpd packages/api packages/web --skip-local drops pairs inside either tree, keeping only api-to-web duplication

  • --skip-isolated — ignore duplication between monorepo folders owned by different teams (--skip-isolated "packages/team-a|packages/team-b")

Beyond duplication

  • --history — duplication and health trend over git history: jscpd --history scans the current folder over the last 30 commits of the branch, jscpd src --history v5.0.0..HEAD the commits of a range, a merged branch as its merge commit. It prints bar charts of the duplication percentage and the health score, a per-commit table with the change between points, the trends with the score of each health dimension at both ends, and how far --threshold could be tightened; --health and --dashboard print the series too (see docs)

  • --dead-code — find code nothing runs, not just code written twice: unused files, exports, declarations and imports across JavaScript, TypeScript and Python. Builds the import graph from your entry points (package.json, pyproject.toml, framework conventions) and walks it, so dead code cascades — a helper whose only caller is dead gets reported too, each finding with a confidence score and, below 100, why it might be wrong. Also ships standalone as basta (see docs)

  • --summary — refactoring hotspots straight from the scan: top files and folders by tokens, lines, size, and a complexity estimate (see docs)

  • --complexity — the complexity ranking alone, without clone detection: most complex files and folders from one tokenizing pass, in the console, ai or json (see docs)

  • --health — one 0-100 score with a grade, from the share of code that's duplicated, dead, or concentrated in complex files; size-aware, calibrated on 42 open-source projects, extensible with coverage, test or security metrics via --health-input. Console badge, JSON, SVG badge (see docs)

  • --dashboard — the whole picture on one screen, under the health badge: project size with the largest code files, duplication by clone kind with the most duplicated files, the most complex files, and dead code by category for JavaScript, TypeScript and Python (see docs)

AI and operations

  • --mcp — built-in MCP server over stdio with fully described tools: point your AI assistant at the binary and it can check a snippet against your codebase for all four types of clone (exact, renamed, near-miss and semantic), list a file's clones, and compare two folders function by function (see docs)

  • --lsp: a language server over stdio. Clones, similar functions, semantic clones, dead code and complexity show up as diagnostics in the files you edit and follow the text as you type, each analysis with a switch of its own (see Editors below)

  • AI reporter — token-efficient output for LLM pipelines (~79% fewer tokens than console)

  • Prebuilt for 8 platforms — macOS arm64/x64, Linux arm64/x64 (glibc and musl), Windows arm64/x64

  • --workers — control parallelism for file tokenization and detection (default: all CPU cores)

  • Config discovery — .jscpd.json, .config/jscpd.json, or the jscpd key in package.json

  • Symbolic links are skipped unless --follow-symlinks — v4 followed them by default. With the flag, a file reached through a link is reported by the path it was found at, and a file reachable through several paths is counted once

  • Quiet in pipelines — tips and sponsor lines print only on an interactive terminal; --no-tips, CI or JSCPD_NO_TIPS switch them off everywhere

See the Rust docs for the full CLI reference and rust/CHANGELOG.md for release notes.

Looking for v4?

jscpd v4 (TypeScript engine, Node.js API, LevelDB/Redis stores) is maintained on the master-v4 branch and published as jscpd@4 / the latest-4 dist-tag. README-v4.md describes it in one page (install, CLI, API, packages, maintenance policy); the same content is at https://jscpd.dev/getting-started/v4.

Packages

Package

Registry

Description

jscpd

npm

Installs the jscpd command (prebuilt binary via platform packages)

cpd

npm

Installs the cpd command (same binary)

jscpd-<platform>

npm

Platform binary packages pulled in as optional dependencies: jscpd-darwin-arm64, jscpd-darwin-x64, jscpd-linux-x64-gnu, jscpd-linux-arm64-gnu, jscpd-linux-x64-musl, jscpd-linux-arm64-musl, jscpd-windows-x64-msvc, jscpd-windows-arm64-msvc

jscpd

PyPI

Platform wheels repacked from the release binaries; installs both jscpd and cpd commands

jscpd

crates.io

CLI crate; installs both jscpd and cpd binaries

cpd-core

crates.io

Detection algorithm (Rabin-Karp rolling hash), data models

cpd-tokenizer

crates.io

Source code tokenization (224 formats)

cpd-similarity

crates.io

Structural similarity (--similarity): functions from tree-sitter syntax trees and a Clojure reader, normalized trees and their subtree fingerprints, and the exact search for pairs

cpd-finder

crates.io

File walking, orchestration, git blame — the library entry point

cpd-reporter

crates.io

Output formatting (15 reporters, duplication and dead code)

cpd-semantic

crates.io

Semantic clones (--semantic, experimental): function extraction, code embeddings from a model run in-process or an API, pairing

basta

npm / crates.io

Dead code detection — unused files, exports, symbols and imports for JavaScript, TypeScript and Python. Installs the basta command; the same engine backs jscpd --dead-code

Who Uses jscpd

The jscpd npm package is downloaded 10M+ times per month, and ~5,000 repositories declare it on GitHub's dependents graph.

Bundled by analysis platforms:

  • GitHub Super Linter — official GitHub linter aggregator, bundles jscpd as its copy/paste detector and runs it by default; 15,500+ workflow files on GitHub reference Super Linter (as of Sep 2026)

  • MegaLinter — open-source linter aggregator for CI, ships jscpd in every flavor including ci_light

  • Codacy — automated code analysis platform, jscpd powers the duplication engine

Explicitly enabled in Super Linter (VALIDATE_JSCPD: true) by dozens of public repositories, including:

  • A2A — Google's Agent2Agent protocol (25k+ stars)

  • RimSort — mod manager for RimWorld (1.2k+ stars); also runs jscpd directly with its own .jscpd.json

  • Contact Center AI samples — official Google Cloud samples, with a dedicated jscpd config

  • Drifty — open-source download manager

Used in notable projects:

Super Linter and MegaLinter both run jscpd with threshold: 0 by default, which fails a build on any duplication at all, including clones that were already there. That is the most common reason projects end up setting VALIDATE_JSCPD: false. Gate on new duplication instead, and leave the threshold out:

jscpd . --baseline-from-ref origin/main --fail-on-new-clones 0

--baseline-from-ref scans the base ref's tree with the same configuration and marks the clones that are absent from it as new, and --fail-on-new-clones 0 fails the run when there is one. Every clone is still reported, and --threshold still compares the duplication of the whole tree, so keep threshold: 0 out of the config, or the old clones fail the build as before. The base ref has to be in the checkout: with actions/checkout set fetch-depth: 0, or run git fetch origin main first, otherwise jscpd stops with an error. jscpd needs the whole tree to find clones, so VALIDATE_ALL_CODEBASE: false does not narrow the scan.

Super Linter takes the same gate from .github/linters/.jscpd.json, on v9.0.0 or later: see Using jscpd with Super Linter.

When several linters write into one reports directory, give jscpd its own file name so parallel runs cannot overwrite each other:

jscpd . --reporters json --output reports --report-name megalinter-jscpd
# -> reports/megalinter-jscpd.json

--report-name sets the base name for the json, xml, csv, html, markdown, sarif and edn reports, and defaults to jscpd-report. It can also be set as reportName in .jscpd.json, or with the report-name input of the GitHub Action. The name is a plain file name, so a path, an extension or an empty name is an error. The badge, OpenMetrics and CodeClimate files (jscpd-badge.svg, jscpd-metrics.txt, gl-code-quality-report.json) keep their names, so the pipelines that read them keep working. When two runs write those too, give each run its own --output.

Benchmark

Compared against other copy/paste detectors on the fixtures/ corpus (547 files, 150+ formats), default thresholds, wall-clock time on Apple Silicon:

Tool

Time

Files

Clones

Dup Lines

jscpd

84ms

347

212

9,133

jscpd-rs

111ms

360

222

10,317

Duplo

162ms

319

518

13,049

Fallow dupes

164ms

34

10

3,137

Simian

964ms

547

424

15,351

PMD CPD

35.980s

71

56

2,267

Methodology, cross-format detection and AI-token-efficiency comparisons: benchmark/BENCHMARK.md. Re-run with benchmark/benchmark.sh.

Semantic clones (experimental)

Token matching finds code that someone copied. It cannot find two functions that do the same job with different code, such as a validation rule that a Rust backend enforces and a Svelte frontend writes again, or two helpers that two people wrote for the same task. --semantic looks for these pairs with a code embedding model. jscpd turns every function into a vector and reports two functions as a semantic clone when each is the other's closest match and their vectors are similar enough.

jscpd --semantic-download                                    # once: CodeRankEmbed, 548 MB, into the jscpd cache
jscpd --semantic src/                                        # pairs within one language and across languages
jscpd --semantic --semantic-scope cross backend/ frontend/   # only pairs across languages
jscpd --semantic --kind semantic -r ai .                     # only semantic clones, one line each

The model runs inside jscpd on the CPU, so a scan makes no network call. The default model is CodeRankEmbed (MIT), and jscpd can also run jina-embeddings-v2-base-code. jscpd --semantic-models lists nine models with the thresholds jscpd calibrated for each one, and --semantic-model picks one of them. To use a model that jscpd does not run itself, point --semantic-url at an OpenAI-compatible embeddings API such as Ollama, LM Studio or llama-server. jscpd reads an API key only from the JSCPD_SEMANTIC_API_KEY environment variable.

jscpd compares the functions of JavaScript, TypeScript, JSX, TSX, Vue, Svelte, Astro, Python, Rust, Go, Java, Kotlin, C#, C, C++, PHP, Ruby, Scala and Swift files. A pair within one language needs a higher similarity than a pair across languages, because code in one language resembles other code in that language whatever it does. With CodeRankEmbed the two thresholds are 0.4125 and 0.6375, and --semantic-threshold and --semantic-same-threshold change them. jscpd caches the vectors, so a second run embeds only the functions whose code changed.

The console, ai, JSON, SARIF and Code Climate reporters mark these clones as kind semantic with their similarity. The mode is experimental. Besides real duplicates it reports related code, such as a client function and the server endpoint it calls, so review a pair before you merge the two functions. The docs describe the rules, fixtures/semantic-demo is a runnable example with a Rust backend and a SvelteKit frontend, and Embedding Models compares the nine models.

Comparing two codebases (experimental)

--compare takes two folders and pairs their functions with the --semantic model. During a port, such as a library moving to another language or an iOS app moving to Android, it shows which functions of the source already have a version in the target and which are still to port. For two implementations of one app, such as the Android and the iOS one, it shows what both have and what only one of them has.

jscpd --compare python typescript        # progress of a port: the source first, the target second
jscpd --compare ios android -r console-full  # parity, with every pair and its similarity
Code
 71% 5 of 7 functions in python have a counterpart in typescript
 80% 4 of 5 functions in typescript have a counterpart in python

Paired under other names (1):
  python                        typescript              similarity
  billing.py:28 tax_for_region  billing.ts:27 salesTax  0.87 high

Only in python (2):
  billing.py (1)
    46  due_date                6 lines
  shipping.py (1)
    18  estimate_delivery_days  8 lines

Tests
 75% 3 of 4 tests in python have a counterpart in typescript
100% 3 of 3 tests in typescript have a counterpart in python

A function pairs with its counterpart when the model finds them each other's closest match. A short function the model cannot place pairs by name when the names match once case and underscores are ignored (encodeBinary, encode_binary) and the code is similar enough. jscpd measures tests and code in two blocks and pairs a test only with a test. It tells a test by the conventions of its language, such as *_test.go, test_*.py, *.test.ts, src/test/ or Rust's #[cfg(test)]. Every pair has its similarity and a level, high, medium or low, on the scale of the model, and the report lists the pairs under other names on their own, since nobody finds those by searching for a name. The console, JSON and Markdown reporters print the totals per side and per file with the mean similarity, the functions with no counterpart, and the pairs. -r html writes a migration map, a page that draws both sides as dependency graphs with the pairs bridging them and marks the functions ready to port, the ones whose callees all have a counterpart already. A second tab lists the same pairs as a table you can sort. The docs describe the rules and how they did on two real codebases, and fixtures/compare-demo is a runnable example.

Boundaries

Some code must stay where it is. In a bank or a shop only the backend calculates money, and a frontend that calculates it too shows one price and charges another as soon as the formula changes. A boundary rule names that code and the places its copies must stay out of:

{
  "boundaries": [
    {
      "name": "money",
      "code": ["backend/billing", "backend/loans/Interest.kt#monthlyPayment"],
      "notIn": ["web/**", "mobile/**"],
      "allow": ["web/e2e/**"]
    }
  ]
}

code takes modules, folders, files or methods, by name (#monthlyPayment) or by a pattern of names (#(*Payments)). Without notIn, every place outside code counts. Every clone run checks the rules with every method jscpd has: token clones for copy-paste, --similarity for an edited copy, and the model of --semantic for the same logic written again in another language, such as the annuity formula of a Kotlin backend in a TypeScript widget. A copy fails the run with exit code 1:

Boundaries:
money: 1 copy outside the boundary
  web/src/loan/payment.ts:4-14 monthlyPayment
    looks like backend/loans/Interest.kt:8-15 monthlyPayment (semantic ~0.82)

The logic written again in another language needs the embedding model, so run jscpd --semantic-download once, or point --semantic-url at an embeddings API. Without it jscpd prints a warning and still finds the copies and the edited copies. Each rule can set its own thresholds, and disable turns kinds of copies off: "disable": ["semantic"] for a rule that needs no model, or ["ast", "semantic"] for one that reports copy-paste only. The docs describe the rules, and fixtures/boundaries-demo is a runnable example.

Editors

jscpd --lsp runs jscpd as a language server. An editor starts it for a workspace, and the files you edit get what jscpd finds as diagnostics, updated as you type: clones by default, and similar functions, semantic clones, dead code and complexity when --lsp-analyses or the lsp section of .jscpd.json turns them on. A clone comes with "Go to the other copy" and "Ignore this clone" actions. In Neovim 0.11:

vim.lsp.config('jscpd', { cmd = { 'jscpd', '--lsp' }, root_markers = { '.jscpd.json', '.git' } })
vim.lsp.enable('jscpd')

Editors has the setup for Helix, Sublime Text, Emacs and JetBrains IDEs too, and fixtures/lsp-demo is a project that shows each analysis. Clients for VS Code and Zed will follow in a repository of their own.

AI-Ready Features

jscpd integrates into AI-powered workflows through three mechanisms:

AI Reporter

Token-efficient output for LLM pipelines (~79% fewer tokens than the default console reporter):

jscpd --reporters ai /path/to/source              # compact clone list
jscpd --reporters ai --summary /path/to/source    # + compact codebase summary
jscpd --reporters ai --complexity /path/to/source # most complex files, no clone detection

Agent Skills

Installable skills that teach AI coding assistants how to use jscpd, refactor detected duplications, and clean up a codebase more broadly:

Skill

Purpose

Install

jscpd

Tool reference — CLI options, AI reporter format, config syntax

npx skills add kucherenko/jscpd --skill jscpd

dry-refactoring

Guided refactoring workflow — read clones, choose strategy, apply, verify

npx skills add kucherenko/jscpd --skill dry-refactoring

compare-codebases

How --compare pairs the functions of two folders, and a step-by-step way to compare two folders and check the result

npx skills add kucherenko/jscpd --skill compare-codebases

code-migration

Port a codebase to another language or framework, tests first and code second, with a coverage map binding functions to their tests and --compare as the progress measure; or check two implementations for parity

npx skills add kucherenko/jscpd --skill code-migration

codebase-refactoring

Broader health pass — fix duplication, then remove/refactor dead code, then simplify the biggest/most complex files, prioritized from --health

npx skills add kucherenko/jscpd --skill codebase-refactoring

After installation, ask your agent to "find and fix code duplication" and it will invoke jscpd with the right options and act on the results — or "clean up this codebase" for the broader pass, or "port this Python library to Rust" for a migration.

MCP Server

jscpd --mcp /path/to/project scans the project and serves the Model Context Protocol over stdio. An assistant can check a snippet against the codebase before writing it, list a file's clones, scan the working directory again and compare two folders function by function. The tools that find clones can look for exact (Type-1), renamed (Type-2), near-miss (Type-3) and semantic (Type-4) ones.

See AI-Ready docs for full details.

Citation

If jscpd is part of your research, cite it via the repository's CITATION.cff (GitHub's "Cite this repository" button produces BibTeX and APA) or with:

@software{jscpd,
  title        = {jscpd: copy/paste detector for programming source code},
  author       = {Kucherenko, Andrey},
  year         = {2026},
  version      = {5.3.0},
  license      = {MIT},
  url          = {https://github.com/kucherenko/jscpd},
}

Contributing

See CONTRIBUTING.md for the development setup, test policy, and pull request requirements. In short:

cd rust
cargo nextest run --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check

Security issues go through the security policy, not public issues.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

MIT © Andrey Kucherenko

Available Tools

5 tools
check_current_directoryScan the project againA
Read-onlyIdempotent

Scan the paths the server was started with again and return the fresh clone list and counts. Use it after creating, editing or deleting files, so that the other tools answer from current content. Returns {files, kinds, clones, returned, duplicatedLines, percentage, byKind, duplications[]} with the duplications of get_file_clones, biggest first. Reads the files only, and replaces the previous scan; it can take a few seconds on a large project.

NameRequiredDescriptionDefault
kindsNoThe kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.
limitNoMaximum number of clones in the response. 'clones' always carries the full count, so a small limit still tells you how much was found.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already establish read-only, idempotent, non-destructive, closed-world behavior. The description adds meaningful context beyond that: it reads files only, replaces the previous scan, and can take a few seconds on a large project.

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

Conciseness5/5

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

The description is front-loaded with the action and purpose, then covers usage, return shape, and side effects without filler. Every sentence adds useful information for invoking or interpreting the tool.

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

Completeness5/5

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

There is no output schema, but the description explicitly lists the return shape and notes that duplications are biggest first. For a two-parameter scan tool with annotations covering safety, the description is complete enough to call and interpret correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters in detail, including the kinds enum and limit behavior. The description does not add parameter-specific semantics beyond what the schema provides, so the baseline 3 is appropriate.

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

Purpose5/5

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

States a specific verb and resource: scanning the paths the server was started with and returning a fresh clone list and counts. It also distinguishes itself by tying its duplication output to get_file_clones and by explaining that other tools should answer from current content after a scan.

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

Usage Guidelines4/5

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

Explicitly says to use it after creating, editing, or deleting files so other tools answer from current content. It does not state when not to use it, which keeps it below a full 5, but the usage context is clear.

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

check_duplicationCheck a snippet for duplicationA
Read-onlyIdempotent

Check whether a code snippet duplicates code that already exists in the scanned project. Use it before writing or committing a function, class or block, to find the existing code you should reuse instead; pass kinds ["exact", "renamed", "similar"] to find copies with other names or edited lines as well. Returns {format, kinds, count, returned, duplications[]}, each duplication with 'kind', 'format' (the language of the code that matched), 'file', 'fileStartLine', 'fileEndLine', 'lines' (how many of those lines count as duplicated, as in jscpd's reports: fewer when the match runs over other blocks of the file), 'snippetStartLine', 'snippetEndLine' and 'tokens'; similar and semantic ones add 'similarity' (and 'method': gap or ast), and ast and semantic ones add 'name' (the name of the project's function) and 'snippetName'. Exact matches come first, then renamed, similar and semantic ones. A request without 'kinds' gets its ast matches under 'similar' with 'similarCount', as earlier versions answered. A Markdown, Vue, Svelte or Astro snippet is split into blocks the way a scan splits such a file, so the code of a fence or a script matches code in its language; by meaning, only the functions in a component's scripts are compared. A snippet or a block of code in it shorter than the server's --min-tokens (50 by default) cannot match, and a 'note' says so. Kinds that could not be searched are listed under 'unavailable' with the reason. The snippet is compared with the last scan: call check_current_directory first if files changed.

NameRequiredDescriptionDefault
codeYesThe source code to check, verbatim. Whole functions or blocks work best.
kindsNoThe kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.
limitNoMaximum number of duplications in the response. 'count' always carries the full count, so a small limit still tells you how much was found.
formatYesLanguage of the snippet: a jscpd format name such as 'javascript', 'typescript', 'python', 'java', or a file extension such as 'js', 'py' (`jscpd --list` lists all 224).
similarityNoThe share of subtrees two functions' normalized syntax trees must have in common to be an ast match: 1 finds copies with other names, each standing for one name, and other literals only, 0.8 also one-line edits, 0.7 a couple of added or removed statements. Giving it asks for ast matches. Defaults to the server's --similarity, or 0.8. Functions of JavaScript, TypeScript, Python, Java, Kotlin, Scala, C#, Go, Rust, C, C++, PHP, Ruby, Swift and Clojure. In ast matches each function's syntax tree is normalized: the names of the functions and methods it calls and its operators count, local names, field names and literals do not, as long as each name stands for one name on the other side, and two functions score the share of subtrees their trees have in common. Test files are left out.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only cover the safe-read profile; the description adds substantial behavior: results are ordered exact → renamed → similar → semantic, a --min-tokens threshold (50 default) prevents short snippets from matching, unfindable kinds appear under 'unavailable', semantic search runs an embedding model that is slow the first time, and renamed/similar may need an extra scan. It also documents the legacy no-'kinds' response shape, which is real behavioral variance.

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

Conciseness4/5

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

Purpose and usage are front-loaded in the first sentence, and the dense return-format detail is justified because no output schema exists. It does read as one long wall of text bundling edge cases (Markdown/Vue/Svelte/Astro splitting, threshold notes) that could be sectioned, but little is truly wasted.

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

Completeness5/5

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

With no output schema, the description takes on the full burden and delivers: it enumerates every returned field, explains the 'lines' vs match-span distinction, and covers degraded responses ('note', 'unavailable'). An agent has everything needed to call this and interpret the result.

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

Parameters4/5

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

Schema coverage is 100%, so the schema already carries most parameter meaning. The description still adds cross-parameter semantics the schema does not: supplying 'similarity' implicitly requests ast matches, and omitting 'kinds' changes how ast results are reported ('similar' with 'similarCount'), plus the note that ast matching only covers a listed set of languages.

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

Purpose5/5

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

States a specific verb and resource ('Check whether a code snippet duplicates code that already exists in the scanned project') and scopes it to the last scan. It is clearly distinguishable from siblings like get_file_clones (project-wide listing) and compare_folders (folder-to-folder).

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

Usage Guidelines5/5

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

Gives an explicit trigger ('Use it before writing or committing a function, class or block, to find the existing code you should reuse instead') and an explicit prerequisite/alternative: 'call check_current_directory first if files changed'. Both when-to-use and when-to-refresh are covered.

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

compare_foldersCompare two folders function by functionA
Read-onlyIdempotent

Compare two folders function by function, in one language or across languages: a port and its original (the source first, the target second), or two implementations of one app (iOS and Android). Every function of one folder is paired with the function of the other that does the same job, by the embedding model, and what has no counterpart is listed. Returns the JSON report of jscpd --compare: 'code' and 'tests' sections, each with 'sides' (per folder: 'functions', 'matched', 'percentage', 'files', 'unmatched', 'readyToPort': unported functions whose callees are all ported) and 'pairs' (each with both functions, 'similarity', 'level' high/medium/low, 'renamed' and 'matchedBy' code or name). Read a few low pairs and the pairs matched by name before relying on them. Needs the embedding model; the first comparison of two folders embeds every function and can take minutes, later ones reuse the cached vectors.

NameRequiredDescriptionDefault
leftYesThe first folder (or file): the source of a port, or one of two implementations. It must lie inside the scanned folders: give it relative to one of them, or absolute.
limitNoMaximum number of entries of each list ('pairs', 'unmatched', 'readyToPort', 'files') in the response. 'functions' always carries the full count, so a small limit still tells you how much was found.
rightYesThe second folder (or file): the target of a port, or the other implementation. It must lie inside the scanned folders too, and must not contain the first or lie inside it.

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, the description discloses the operational cost ('needs the embedding model', 'the first comparison ... can take minutes, later ones reuse the cached vectors') and describes the full returned report. It also flags correctness risk by warning that name-matched and low-level pairs should be spot-checked, which the annotations cannot convey.

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

Conciseness4/5

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

It is front-loaded with purpose and argument ordering and every sentence carries information. The long parenthetical enumeration of returned sections is dense but justified because no output schema exists, though it could be tightened.

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

Completeness5/5

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

With no output schema, the description fully carries the return-value burden: it names the 'code'/'tests' sections, the per-side fields including 'readyToPort', and the 'pairs' fields including 'similarity', 'level', 'renamed' and 'matchedBy'. Combined with model requirements and caching behavior, an agent has what it needs to call this correctly.

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

Parameters4/5

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

Schema coverage is already 100%, so the baseline is 3, but the description adds the semantic ordering rule (left is the source, right the target) and implies the left/right containment constraint the schema also states. The 'limit' parameter's truncation behavior is left entirely to the schema, so it isn't a full 5.

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

Purpose5/5

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

The description gives a specific verb and resource — compare two folders function by function — and immediately names the two scenarios it serves (a port and its original, or two implementations of one app such as iOS and Android). That is enough to distinguish it from the sibling tools get_statistics, check_duplication and get_file_clones, which operate on duplication statistics or clone lists rather than cross-folder function pairing.

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

Usage Guidelines4/5

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

It spells out both intended scenarios and the argument ordering (source first, target second), and it adds a concrete interpretation rule: read a few low-similarity pairs and the pairs matched by name before relying on them. It never explicitly states when not to use it or names a sibling as the alternative for plain clone or duplication queries, so a 4 rather than a 5.

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

get_file_clonesList the clones of one fileA
Read-onlyIdempotent

List every clone of the last scan that involves one file, to see which other files share code with it. Use it before refactoring, splitting or deleting a file. Returns {file, kinds, clones, returned, duplications[]}, each duplication with 'kind', 'format', 'fileA', 'startA', 'endA', 'fileB', 'startB', 'endB', 'lines' and 'tokens' ('similarity' and 'method' for similar and semantic ones), biggest first; the file may be fileA or fileB. A path that was not part of the scan gets clones 0 and a 'note'.

NameRequiredDescriptionDefault
pathYesThe file, relative to the scan root as other results show paths (e.g. 'src/cart.js'), or absolute.
kindsNoThe kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.
limitNoMaximum number of clones in the response. 'clones' always carries the full count, so a small limit still tells you how much was found.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare read-only, idempotent, non-destructive behavior, and the description goes beyond them: it discloses the ordering (biggest first), the edge case where an unscanned path returns 0 clones plus a 'note', and the cost/latency caveats for semantic clones and extra scans.

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

Conciseness4/5

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

Purpose, usage, and return shape are front-loaded in that order with no filler sentences. The long enumeration of return fields is dense but earns its place given there is no output schema.

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

Completeness5/5

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

With no output schema, the description fully compensates by specifying the response envelope, per-clone fields, ordering, and the not-found shape. An agent has everything needed to call and interpret it.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3; the description adds meaning by explaining that results may place the requested file as either fileA or fileB, and by describing the unscanned-path outcome that affects the 'path' parameter. It does not elaborate on kinds/limit beyond the schema, so not a 5.

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

Purpose5/5

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

Specific verb and resource — 'List every clone of the last scan that involves one file' — plus a scoping phrase ('which other files share code with it') that separates it from siblings like check_duplication and get_statistics.

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

Usage Guidelines4/5

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

Gives a concrete usage context ('before refactoring, splitting or deleting a file'), which is clear guidance on when to reach for it. It does not name an alternative tool or state when not to use it, so it falls short of a 5.

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

get_statisticsProject duplication statisticsA
Read-onlyIdempotent

Report the duplication statistics of the last scan, for the clones of the kinds asked: for the whole project and per format, the files, lines and tokens analyzed, the clones, and the duplicated lines and tokens with their percentages, plus the number of clones of each kind ('byKind'). Use it to judge overall duplication, or to compare before and after a refactoring (call check_current_directory in between). It reflects the last scan, not the files on disk now.

NameRequiredDescriptionDefault
kindsNoThe kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.

TDQS

A3.9/5.0
Behavior4/5

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

Beyond the annotations, the description discloses important snapshot semantics: it reflects the last scan, not the files currently on disk. It also enumerates the reported statistics, including the 'byKind' breakdown. It does not cover cost or timing details, though those appear in the parameter schema.

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

Conciseness4/5

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

The description is front-loaded with the core purpose and the key caveat about the last scan. The first sentence is dense and long, but each part carries useful information and the later sentences add workflow guidance efficiently.

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

Completeness4/5

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

With no output schema, the description does a good job listing the returned statistics and explaining the stale-scan behavior. It omits precise output shape details, but gives enough for an agent to understand what the call yields and when to use it.

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

Parameters3/5

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

Schema description coverage is 100% and the sole 'kinds' parameter is fully documented in the schema, including defaults, enum meanings, and performance notes. The description only alludes to 'the clones of the kinds asked' and does not add meaning beyond the schema.

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

Purpose4/5

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

The description states a specific verb and resource ('Report the duplication statistics of the last scan') and clarifies the aggregate scope ('whole project and per format'), which helps distinguish it from per-file tools like get_file_clones. It does not explicitly contrast with check_duplication, so sibling differentiation is good but not complete.

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

Usage Guidelines4/5

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

It gives clear usage contexts: judging overall duplication and comparing before/after a refactoring, with the concrete instruction to call check_current_directory in between. It does not state when not to use it or name get_file_clones as the alternative for per-file clone data.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv5.4.2
    • Changedcheck_current_directory2 fields changed
      • addedInput schema / properties / kinds
        Added value: +{
        +  "description": "The kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.",
        +  "examples": [
        +    [
        +      "exact",
        +      "renamed",
        +      "similar"
        +    ],
        +    [
        +      "semantic"
        +    ]
        +  ],
        +  "items": {
        +    "enum": [
        +      "exact",
        +      "renamed",
        +      "similar",
        +      "gap",
        +      "ast",
        +      "semantic",
        +      "type1",
        +      "type2",
        +      "type3",
        +      "type4"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array",
        +  "uniqueItems": true
        +}
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of clones to include in the response. 'clones' always carries the untruncated total, so a small limit still tells you how much was found."New value: +"Maximum number of clones in the response. 'clones' always carries the full count, so a small limit still tells you how much was found."
    • Changedcheck_duplication7 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / code / description
        Previous value: -"The source code to check, verbatim (whole functions or blocks work best; it must reach the server's --min-tokens threshold, 50 tokens by default)"New value: +"The source code to check, verbatim. Whole functions or blocks work best."
      • changedInput schema / properties / format / description
        Previous value: -"Language of the snippet: a jscpd format name such as 'javascript', 'typescript', 'python', 'java', or a file extension such as 'js', 'py' (run `jscpd --list` for all 224). Unknown values return an error naming the problem."New value: +"Language of the snippet: a jscpd format name such as 'javascript', 'typescript', 'python', 'java', or a file extension such as 'js', 'py' (`jscpd --list` lists all 224)."
      • addedInput schema / properties / kinds
        Added value: +{
        +  "description": "The kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.",
        +  "examples": [
        +    [
        +      "exact",
        +      "renamed",
        +      "similar"
        +    ],
        +    [
        +      "semantic"
        +    ]
        +  ],
        +  "items": {
        +    "enum": [
        +      "exact",
        +      "renamed",
        +      "similar",
        +      "gap",
        +      "ast",
        +      "semantic",
        +      "type1",
        +      "type2",
        +      "type3",
        +      "type4"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array",
        +  "uniqueItems": true
        +}
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of duplications to include in the response. 'count' always carries the untruncated total, so a small limit still tells you how much was found."New value: +"Maximum number of duplications in the response. 'count' always carries the full count, so a small limit still tells you how much was found."
      • changedInput schema / properties / similarity / description
        Previous value: -"Also return project functions whose syntax-tree structure is similar to the snippet's functions, when the similarity ratio reaches this value. 1 means exact matches only (no 'similar' section); 0.85 catches renames, literal changes and one-line edits; 0.7 tolerates a couple of added or removed statements. Defaults to the server's --similarity setting (1 unless configured). JavaScript/TypeScript only; other formats ignore it."New value: +"The share of subtrees two functions' normalized syntax trees must have in common to be an ast match: 1 finds copies with other names, each standing for one name, and other literals only, 0.8 also one-line edits, 0.7 a couple of added or removed statements. Giving it asks for ast matches. Defaults to the server's --similarity, or 0.8. Functions of JavaScript, TypeScript, Python, Java, Kotlin, Scala, C#, Go, Rust, C, C++, PHP, Ruby, Swift and Clojure. In ast matches each function's syntax tree is normalized: the names of the functions and methods it calls and its operators count, local names, field names and literals do not, as long as each name stands for one name on the other side, and two functions score the share of subtrees their trees have in common. Test files are left out."
      • changedInput schema / properties / similarity / examples
        Previous value: -[
        -  0.85
        -]New value: +[
        +  0.8
        +]
    • Addedcompare_folders
    • Changedget_file_clones4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / kinds
        Added value: +{
        +  "description": "The kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.",
        +  "examples": [
        +    [
        +      "exact",
        +      "renamed",
        +      "similar"
        +    ],
        +    [
        +      "semantic"
        +    ]
        +  ],
        +  "items": {
        +    "enum": [
        +      "exact",
        +      "renamed",
        +      "similar",
        +      "gap",
        +      "ast",
        +      "semantic",
        +      "type1",
        +      "type2",
        +      "type3",
        +      "type4"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array",
        +  "uniqueItems": true
        +}
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of clones to include in the response. 'clones' always carries the untruncated total, so a small limit still tells you how much was found."New value: +"Maximum number of clones in the response. 'clones' always carries the full count, so a small limit still tells you how much was found."
      • changedInput schema / properties / path / description
        Previous value: -"The file to inspect, either relative to the scan root exactly as paths appear in other tool results (e.g. 'src/cart.js') or absolute"New value: +"The file, relative to the scan root as other results show paths (e.g. 'src/cart.js'), or absolute."
    • Changedget_statistics1 field changed
      • addedInput schema / properties / kinds
        Added value: +{
        +  "description": "The kinds of clone to look for: exact (type1), renamed (type2), similar (type3; 'gap' or 'ast' for one of its two mechanisms) and semantic (type4). Without it: exact, what jscpd reports with this server's options. Renamed and similar clones may need one scan more, and semantic ones run an embedding model, which takes a while the first time.",
        +  "examples": [
        +    [
        +      "exact",
        +      "renamed",
        +      "similar"
        +    ],
        +    [
        +      "semantic"
        +    ]
        +  ],
        +  "items": {
        +    "enum": [
        +      "exact",
        +      "renamed",
        +      "similar",
        +      "gap",
        +      "ast",
        +      "semantic",
        +      "type1",
        +      "type2",
        +      "type3",
        +      "type4"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array",
        +  "uniqueItems": true
        +}
  2. 4 tool updatesv5.2.0
    • Changedcheck_current_directory3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / default
        Added value: +100
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of clones to include in the response (default 100); 'clones' always carries the untruncated total"New value: +"Maximum number of clones to include in the response. 'clones' always carries the untruncated total, so a small limit still tells you how much was found."
    • Changedcheck_duplication6 fields changed
      • changedInput schema / properties / code / description
        Previous value: -"Source code snippet to check"New value: +"The source code to check, verbatim (whole functions or blocks work best; it must reach the server's --min-tokens threshold, 50 tokens by default)"
      • changedInput schema / properties / format / description
        Previous value: -"Language format (javascript, python, ...) or file extension (js, py, ...); see `cpd --list`"New value: +"Language of the snippet: a jscpd format name such as 'javascript', 'typescript', 'python', 'java', or a file extension such as 'js', 'py' (run `jscpd --list` for all 224). Unknown values return an error naming the problem."
      • addedInput schema / properties / format / examples
        Added value: +[
        +  "javascript",
        +  "python",
        +  "ts"
        +]
      • addedInput schema / properties / limit / default
        Added value: +100
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum matches to include in the response (default 100); 'count' always carries the untruncated total"New value: +"Maximum number of duplications to include in the response. 'count' always carries the untruncated total, so a small limit still tells you how much was found."
      • addedInput schema / properties / similarity
        Added value: +{
        +  "description": "Also return project functions whose syntax-tree structure is similar to the snippet's functions, when the similarity ratio reaches this value. 1 means exact matches only (no 'similar' section); 0.85 catches renames, literal changes and one-line edits; 0.7 tolerates a couple of added or removed statements. Defaults to the server's --similarity setting (1 unless configured). JavaScript/TypeScript only; other formats ignore it.",
        +  "examples": [
        +    0.85
        +  ],
        +  "exclusiveMinimum": 0,
        +  "maximum": 1,
        +  "type": "number"
        +}
    • Changedget_file_clones4 fields changed
      • addedInput schema / properties / limit / default
        Added value: +100
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum clones to include in the response (default 100); 'clones' always carries the untruncated total"New value: +"Maximum number of clones to include in the response. 'clones' always carries the untruncated total, so a small limit still tells you how much was found."
      • changedInput schema / properties / path / description
        Previous value: -"File path, relative to the scan root (as shown in other tool results) or absolute"New value: +"The file to inspect, either relative to the scan root exactly as paths appear in other tool results (e.g. 'src/cart.js') or absolute"
      • addedInput schema / properties / path / examples
        Added value: +[
        +  "src/cart.js"
        +]
    • Changedget_statistics1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
  3. 4 tool updatesv0.1.0
    • First observedcheck_current_directory
    • First observedcheck_duplication
    • First observedget_file_clones
    • First observedget_statistics

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

The five tools target clearly distinct inputs and outputs: snippet check, file clone listing, folder comparison, statistics reporting, and rescanning. The descriptions explicitly clarify boundaries, such as 'last scan' vs 'fresh scan', leaving little room for misselection.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern (get_statistics, check_duplication, get_file_clones, check_current_directory, compare_folders). No mixed conventions or vague verbs.

Tool Count5/5

Five tools neatly cover the duplication analysis domain: scan, stats, snippet check, file clones, and folder comparison. Each tool has a clear role, and the set is neither thin nor bloated.

Completeness4/5

Core workflows are covered, but there is no tool to retrieve the full clone list from the last scan without rescanning (check_current_directory always rescans), and no way to adjust parameters like min-tokens. These are minor gaps that agents can work around.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Framework-aware code intelligence MCP server that builds a cross-language dependency graph from source code. 53 integrations (Laravel, Django, Rails, Spring, NestJS, Next.js, and more) across 68 languages. 100+ tools for navigation, impact analysis, refactoring, security scanning, session memory, and CI/PR reports — up to 97% token reduction.
    29
    7,155 npm
    198
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    An MCP code-intelligence server for AI agents with pre-indexed AST cache, 62 MCP tools, and TOON-compressed output, enabling token-efficient code analysis and project health grading entirely locally.
    9
    1,170 PyPI
    61
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A local MCP server that indexes TypeScript/JavaScript projects and returns budget-aware, dependency-optimized context packs for AI coding assistants.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Token-efficient MCP server for multi-language project analysis (Java, TypeScript, JavaScript, Markdown, Python) with plugins, semantic search, and static analysis.
    MIT