Skip to main content
Glama
astrograph
by Thaylo

ASTrograph

CI Release Docker Arch License MCP

An MCP server that helps AI agents detect duplicate code before writing it. It provides write and edit tools that compare new code against existing functions in your codebase using AST graph isomorphism — powered by algorithms, not LLM tokens. When a structural duplicate is found, the operation is blocked with a pointer to the existing code. Variable names, formatting, and comments are ignored — if two pieces of code share the same abstract structure, ASTrograph flags them as duplicates.

Installation

Add .mcp.json to your project root:

{
  "mcpServers": {
    "astrograph": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i", "--pull", "missing",
        "--add-host", "host.docker.internal:host-gateway",
        "-v", ".:/workspace",
        "thaylo/astrograph:latest"
      ]
    }
  }
}

The image is multi-arch (amd64, arm64). The codebase is indexed at startup. Metadata is stored outside the project directory (in the user data dir) so it never interferes with your codebase.

To update to a new release:

docker pull thaylo/astrograph:latest

The running version is always visible in the MCP serverInfo.version field on connect.

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "astrograph": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i", "--pull", "missing",
        "--add-host", "host.docker.internal:host-gateway",
        "-v", "/absolute/path/to/project:/workspace",
        "thaylo/astrograph:latest"
      ]
    }
  }
}

~/.codex/config.toml:

[mcp_servers.astrograph]
command = "docker"
args = [
  "run", "--rm", "-i", "--pull", "missing",
  "--add-host", "host.docker.internal:host-gateway",
  "-v", "/absolute/path/to/project:/workspace",
  "thaylo/astrograph:latest"
]

~/.config/wmark/.mcp.json (user-level, applies to all projects on macOS):

{
  "mcpServers": {
    "astrograph": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i", "--pull", "missing",
        "--add-host", "host.docker.internal:host-gateway",
        "-v", "/Users:/Users:rw",
        "thaylo/astrograph:latest"
      ]
    }
  }
}

Mounting /Users makes all macOS home paths accessible inside the container unchanged. Call set_workspace with the full host path (e.g. /Users/yourname/project) to index a project.

For Linux, replace /Users:/Users:rw with /home:/home:rw.

pip install .
{
  "mcpServers": {
    "astrograph": {
      "command": "python",
      "args": ["-m", "astrograph.server"],
      "cwd": "/path/to/astrograph"
    }
  }
}

Related MCP server: CodeWalker

How it works

Your codebase already contains:

# src/math.py
def calculate_sum(a, b):
    return a + b

An AI agent tries to write:

# src/utils.py
def add_numbers(x, y):
    return x + y

ASTrograph detects the duplicate and blocks the write:

BLOCKED: Cannot write - identical code exists at src/math.py:calculate_sum (lines 1-2).
Reuse the existing implementation instead.

Different variable names, identical structure. Source code is converted into labeled directed graphs and compared using Weisfeiler-Leman hashing with VF2 isomorphism verification — all algorithmic, no LLM tokens spent on the search.

Detection types

ASTrograph detects four types of structural duplication:

Type

What it catches

How it works

Exact

Identical AST structure with renamed variables or different formatting

WL hash identity + VF2 graph isomorphism verification

Pattern

Same control flow with different operators or constants

Operator-normalized graph hashing

Block

Duplicate inner blocks (for/if/while/try) within functions

Block-level AST extraction + hash matching

Near-duplicate

~80% structural similarity — copy-paste-modify patterns

Hierarchy hash prefix matching at 4/5 depth levels

Near-duplicate detection catches Type-3 clones that exact and pattern detection miss. For example, Flask's TagBytes, TagDateTime, TagTuple, and TagUUID classes share 80%+ identical structure but differ in leaf-level details.

Language support

Python, JavaScript, and TypeScript work out of the box. C, C++, Java, and Go attach to an already-running language server over TCP.

Language

Versions

Mode

Default endpoint

Python

3.11 -- 3.14

bundled

pylsp

JavaScript

ES2021+, Node 20/22/24 LTS

bundled

typescript-language-server --stdio

TypeScript

TypeScript 5.x, Node 20/22/24 LTS

bundled

typescript-language-server --stdio

Go

1.21 -- 1.25

attach

tcp://127.0.0.1:2091

C

C11, C17, C23

attach

tcp://127.0.0.1:2087

C++

C++17, C++20, C++23

attach

tcp://127.0.0.1:2088

Java

11, 17, 21, 25

attach

tcp://127.0.0.1:2089

The Docker image bundles Python and JS/TS LSP runtimes. For attach-based languages, expose the language server on a TCP port using socat and configure via your MCP JSON:

{
  "mcpServers": {
    "astrograph": {
      "command": "docker",
      "args": ["run", "--rm", "-i", "--add-host", "host.docker.internal:host-gateway", "-v", ".:/workspace", "thaylo/astrograph:latest"],
      "env": {
        "ASTROGRAPH_CPP_LSP_COMMAND": "tcp://host.docker.internal:2088",
        "ASTROGRAPH_GO_LSP_COMMAND": "tcp://host.docker.internal:2091",
        "ASTROGRAPH_JAVA_LSP_COMMAND": "tcp://host.docker.internal:2089",
        "ASTROGRAPH_C_LSP_COMMAND": "tcp://host.docker.internal:2087"
      }
    }
  }
}

Language

Env var

Socat bridge example

C

ASTROGRAPH_C_LSP_COMMAND

socat TCP-LISTEN:2087,reuseaddr,fork EXEC:clangd

C++

ASTROGRAPH_CPP_LSP_COMMAND

socat TCP-LISTEN:2088,reuseaddr,fork EXEC:clangd

Java

ASTROGRAPH_JAVA_LSP_COMMAND

socat TCP-LISTEN:2089,reuseaddr,fork EXEC:jdtls

Go

ASTROGRAPH_GO_LSP_COMMAND

socat TCP-LISTEN:2091,reuseaddr,fork EXEC:"gopls serve"

Python

ASTROGRAPH_PY_LSP_COMMAND

(bundled, override if needed)

JS

ASTROGRAPH_JS_LSP_COMMAND

(bundled, override if needed)

TS

ASTROGRAPH_TS_LSP_COMMAND

(bundled, override if needed)

Run lsp_setup(mode='inspect') to see which languages are available and what's missing.

Real-world results

Tested on popular open-source projects:

Project

Language

Files

Code Units

Duplicates Found

Redis

C

208

18,272

556 groups

TypeORM

TypeScript

492

7,107

511 groups

Express.js

JavaScript

141

3,866

468 groups

nlohmann/json

C++

488

9,103

959 groups

Gin

Go

99

1,557

141 groups

Flask

Python

24

910

48 groups

Spring PetClinic

Java

47

270

17 groups

Exact, pattern, and block findings are verified via VF2 graph isomorphism. Near-duplicates are matched via hierarchy hash prefix similarity (~80% structural identity).

Star History

Star History Chart

License

MIT

Available Tools

12 tools
analyzeA
Read-onlyIdempotent

Find duplicate code (verified via graph isomorphism). Returns summary inline. Full details available via the astrograph://analysis/latest resource. File paths in responses are server-internal — use the resource URI instead.

Inputs: auto_reindex.

editA
Destructive

Edit file. Blocks if new code duplicates existing, warns on similarity.

Inputs: file_path (required), new_string (required), old_string (required).

generate_ignoreA
Idempotent

Auto-generate .astrographignore with reasonable defaults for excluding files from indexing.

Inputs: no named parameters.

list_suppressionsA
Read-onlyIdempotent

List suppressed hashes.

Inputs: no named parameters.

lsp_setupB

Inspect and configure deterministic LSP command bindings for bundled language plugins. Returns a guided recommended_actions plan for search/install/config workflows.

Inputs: mode, command, language, observations, +3 more.

metadata_eraseA
DestructiveIdempotent

Erase all persisted metadata. Resets server to idle.

Inputs: no named parameters.

metadata_recompute_baselineB
Idempotent

Erase metadata and re-index the codebase from scratch.

Inputs: no named parameters.

set_workspaceA

Set or change the workspace directory. Re-indexes the codebase at the new path.

Inputs: path (required).

statusA
Read-onlyIdempotent

Check server readiness. Returns instantly even during indexing.

Inputs: no named parameters.

suppressA
Idempotent

Suppress a duplicate by WL hash (from analyze output). Only suppress AFTER confirming the duplication is intentional (e.g. API symmetry, test isolation). Refactoring should be the default action for duplicates.

Inputs: wl_hash (required).

unsuppressC
Idempotent

Unsuppress a hash.

Inputs: wl_hash (required).

writeA
Destructive

Write file. Blocks if duplicate exists, warns on similarity.

Inputs: content (required), file_path (required).

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 12 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes: analyze finds duplicates, suppress/unsuppress/list manage suppressions, write/edit handle file operations. However, metadata_erase and metadata_recompute_baseline overlap (both erase metadata) and write/edit are similar in behavior, creating minor boundary ambiguity.

    Naming Consistency3/5

    Tool names mix single verbs (analyze, status, edit) with verb_noun patterns (list_suppressions, generate_ignore) and noun-verb patterns (metadata_erase, metadata_recompute_baseline). This inconsistency in naming structure makes the set feel less cohesive.

    Tool Count5/5

    12 tools is an appropriate scope for a code duplication analysis server, covering detection, suppression management, file enforcement, and configuration without excess.

    Completeness4/5

    The server covers the core duplication lifecycle well: detect (analyze), manage (suppress/unsuppress/list), enforce (write/edit), plus setup and maintenance tools. Minor gaps exist, such as no configuration for detection thresholds, but the overall surface is comprehensive.

    Maintenance

    ActivityNo data
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      Not graded
      maintenance
      An MCP server that indexes Python codebase structures to help AI assistants discover and reuse existing functions instead of duplicating code. It enables real-time searching of function metadata, duplicate detection, and structural analysis across multiple projects.
      -