Skip to main content
Glama
EdgeHop

EdgeHop

EdgeHop builds an accurate, durable graph of the symbols in a solution — and the relationships between them — then serves it to an AI assistant over the Model Context Protocol (MCP). It doesn't match text; it understands code. Every relationship is resolved from the compiler's own semantic model, so a call, an implementation, or a reference is the actual one the compiler binds — not a name that happens to look alike. Instead of guessing at call chains from text search, your assistant asks "who calls this method?", "what implements this interface?", or "what breaks if I change this?" and gets answers grounded in that semantic understanding — including across tier boundaries the compiler can't cross: the Web-to-API HTTP call and the C#-to-JavaScript interop bridge.

Project types. EdgeHop is built .NET-first, but it is not limited to .NET. Any directory works as a target: a .sln/.csproj solution, a mixed C#+JS/TS Blazor app, or a pure HTML/JavaScript/TypeScript project with no .NET at all. Additional languages and project types are added through extractor plugins.


What it does

  • Indexes a .sln — or any project directory — into a code graph: C# symbols from Roslyn's semantic model, and JavaScript/TypeScript symbols from a native oxc parse — merged into one graph per git branch. .NET is the primary focus, but the target need not be a .NET project at all: point it at a pure HTML/JS/TS tree (no .sln, no Visual Studio, no .NET involved) and the oxc extractor graphs it while the Roslyn extractor simply no-ops.

  • Captures real relationships, not text matches: calls, interface implementations, inheritance, overrides, type references, containment, Blazor component rendering, and two cross-tier bridges — HTTP client-to-endpoint calls and bidirectional C#↔JS interop.

  • Serves the graph over MCP so an assistant (e.g. Claude Code) can traverse it with five focused tools, and over a plain CLI for scripting.

  • Stays current with your working tree via watch mode and optional git hooks that re-index in the background on commit, merge, and checkout — per branch, without touching your working directory.

Related MCP server: polycodegraph

Why it's different

Most "code intelligence for AI" tooling falls into one of two camps, and EdgeHop deliberately avoids both:

  • Text / Tree-sitter indexers parse syntax without resolving symbols. They can tell you a token named Save appears in twelve files; they can't tell you which Save a given call actually binds to. EdgeHop uses Roslyn's semantic model, so a CALLS edge is a resolved invocation, not a name collision — the difference between a guess and an answer.

  • Monolithic graph.json extractors (e.g. Graphify-style tools) dump the whole graph to a single file that must be regenerated wholesale on every change. EdgeHop stores the graph in an indexed, durable, incrementally-reconciled database and updates only what changed, so it scales and stays truthful as you work.

Beyond that, three things are unusual:

  • Cross-tier edges. Call chains stay walkable straight across boundaries a compiler can't cross:

    • Web tier → API. A Web-tier HttpClient call is linked to the C# method that serves the matching endpoint (by verb + route template).

    • C# ↔ JavaScript interop, both directions. IJSRuntime.InvokeAsync → the JS export it invokes, and JS DotNet.invoke* → the [JSInvokable] C# method it targets.

  • Branch-aware and local-first. The graph is scoped per git branch and lives entirely on your machine. No shared server, no credentials, no telemetry. Switch branches and the next query reflects it.

  • Pluggable storage and extractors. SQLite by default (embedded, zero-config), Neo4j optional. The C# and JS/TS extractors are independent, reflection-loaded plugins — the same seam is how support for other languages and project types will be added over time, without changing the core or the query surface.

Requirements

  • .NET 10 SDK/runtime

  • win-x64, linux-x64, or osx-arm64 — the only platform-specific dependency is the bundled edgehop-oxc JS/TS parser, a native binary shipped for those three platforms. Everything else is portable .NET. See Roadmap — a platform-independent oxc parser is planned, which will drop the native-binary requirement entirely.

  • No database or credentials for the default SQLite backend. Neo4j is opt-in.

Project types. EdgeHop is built .NET-first, but it is not limited to .NET. Any directory works as a target: a .sln/.csproj solution, a mixed C#+JS/TS Blazor app, or a pure HTML/JavaScript/TypeScript project with no .NET at all. Additional languages and project types are added through extractor plugins.

Installation

EdgeHop ships as a single .NET global tool:

dotnet tool install -g EdgeHop --prerelease
dotnet tool update  -g EdgeHop --prerelease   # later, to upgrade

Quick start

1. Index a solution (or a directory):

edgehop index C:\path\to\YourApp.sln

2. Query it from the CLI:

edgehop find-symbol OrderService
edgehop get-callers <symbolId> --depth 3
edgehop get-relationships <symbolId> --edge-type IMPLEMENTS
edgehop get-path <fromId> <toId>
edgehop stats

Add --json to any query verb for machine-readable output.

3. Wire it into your AI assistant — point an MCP client at the edgehop mcp command. For Claude Code, add to .mcp.json:

{
  "mcpServers": {
    "edgehop": {
      "command": "edgehop",
      "args": ["mcp"],
      "env": { "EDGEHOP_REPO": "C:\\path\\to\\your\\solution" }
    }
  }
}

4. Keep it fresh — watch mode, or install background git hooks:

edgehop index C:\path\to\YourApp.sln --watch
edgehop install-hooks C:\path\to\YourApp.sln   # re-index on commit / merge / checkout

What the graph captures

Node kinds: namespaces, types (class/struct/interface/enum), methods, properties, fields, Blazor components, and JS/TS functions.

Edge types:

type

meaning

CONTAINS

namespace → type, type → member

CALLS

method invocation (resolved via the semantic model)

IMPLEMENTS

class/struct implements interface

INHERITS

derived type → base type

OVERRIDES

override → overridden method

REFERENCES

a symbol uses a type (parameter, return, field type, …)

RENDERS

a Blazor component renders a child component in its markup

HTTP_CALLS

a Web-tier HttpClient call → the C# method serving that endpoint

JS_CALLS

C# IJSRuntime interop call → the JS function it invokes

JS_INVOKES

JS DotNet.invoke* → the [JSInvokable] C# method it targets

The MCP query surface

tool

answers

find_symbol

where a symbol lives; whether it's a component; which route it serves

get_callers

who calls a method, N hops deep — across HTTP and JS interop too

get_relationships

everything related to a symbol by any edge type; filter by direction/type

get_path

the shortest directed path between two symbols (reachability/impact)

graph_stats

per-branch totals, counts by kind and edge type, and the busiest nodes

Text and content search stays your assistant's grep job — EdgeHop indexes structure, not text.

Configuration

All configuration is environment variables (no config file, no stored credentials):

variable

purpose

EDGEHOP_BACKEND

sqlite (default) or neo4j

EDGEHOP_SQLITE_PATH

override the store file (default is derived per repo under %LOCALAPPDATA%\EdgeHop\stores\)

EDGEHOP_REPO

which repo's current branch the MCP server follows

EDGEHOP_BRANCH

force a branch (otherwise resolved from git)

EDGEHOP_EXTRACTORS

subset the loaded extractors (default: all)

EDGEHOP_JS_INTEROP

C#↔JS interop match mode: precise (default) / broad / off

NEO4J_URI etc.

Neo4j connection info, read only when EDGEHOP_BACKEND=neo4j

The SQLite store is per-solution and derived from the repo, so multiple solutions index side by side with zero configuration.

How it works

 C#/Razor ──▶ Roslyn extractor ─┐
                                 ├─▶ reconcile (per-branch diff) ─▶ graph store ─▶ MCP / CLI
 JS/TS ─────▶ oxc extractor  ────┘                                   (SQLite/Neo4j)

Extraction is whole-solution; storage is incremental — each index run reconciles the new graph against the stored one for that branch and applies only the difference. Stores and extractors are reflection-loaded plugins, so neither the core nor the host depends on a specific database driver or on MSBuild.

A worked example

The commands below run against the in-repo sample Blazor Server app at tests/samples/EdgeHopExplorer.BlazorServer — a small app whose Blazor UI calls a typed HttpClient that hits a minimal-API endpoint, so it exercises the cross-tier edges. First index it:

$ edgehop index tests/samples/EdgeHopExplorer.BlazorServer/EdgeHopExplorer.BlazorServer.sln
Extraction complete: 115 nodes, 168 edges.
oxc: 2 module(s)  11 nodes, 12 edges.
JS interop (precise): 2 C# call site(s), 3 JS export(s), 2 JS_CALLS edge(s).
DotNet interop (precise): 2 JS call site(s), 2 [JSInvokable] method(s), 2 JS_INVOKES edge(s).

1. Find a symbol — locate the Web-tier client method and its stable id:

$ edgehop find-symbol GetAllAsync
Method     Task<IReadOnlyList<FeatureInfo>> FeatureApiClient.GetAllAsync()
           id:  Method:System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<EdgeHopExplorer.BlazorServer.Domain.FeatureInfo>> EdgeHopExplorer.BlazorServer.Services.FeatureApiClient.GetAllAsync()
           doc: Services/FeatureApiClient.cs

1 match on branch 'main'.

2. Look up its relationships — what does this method reach? Note the HTTP_CALLS edge: EdgeHop resolved this client call to the minimal-API method that serves the matching route, across a tier boundary the compiler can't cross:

$ edgehop get-relationships "Method:...FeatureApiClient.GetAllAsync()" --direction out

HTTP_CALLS out
Method     IEndpointRouteBuilder FeatureEndpoints.MapFeatureEndpoints(IEndpointRouteBuilder app)
           id:  Method:...EdgeHopExplorer.BlazorServer.Endpoints.FeatureEndpoints.MapFeatureEndpoints(...)
           doc: Endpoints/FeatureEndpoints.cs
           routes: GET /api/features/all, GET /api/features/{name}, POST /api/features/search

REFERENCES out
NamedType  FeatureInfo
           id:  NamedType:EdgeHopExplorer.BlazorServer.Domain.FeatureInfo
           doc: Domain/FeatureInfo.cs

2 relationships on branch 'main'.

3. Find a path from one call to another — trace how the Blazor page's init handler reaches the API endpoint. The shortest directed path walks a CALLS edge and then the cross-tier HTTP_CALLS edge in a single traversal:

$ edgehop get-path "Method:...Features.OnInitializedAsync()" "Method:...FeatureEndpoints.MapFeatureEndpoints(...)"
Path ... (2 hops):

Task Features.OnInitializedAsync() --CALLS--> Task<IReadOnlyList<FeatureInfo>> FeatureApiClient.GetAllAsync() --HTTP_CALLS--> IEndpointRouteBuilder FeatureEndpoints.MapFeatureEndpoints(IEndpointRouteBuilder app)

That's a Blazor UI handler → typed HTTP client → API endpoint chain, reconstructed from the graph rather than guessed from text.

4. See which routes that endpoint serves — the path lands on the minimal-API method; inspect it and EdgeHop reports the concrete, verb-prefixed HTTP routes it registers, so the trace ends at the actual URLs the UI ultimately reaches:

$ edgehop find-symbol MapFeatureEndpoints
Method     IEndpointRouteBuilder FeatureEndpoints.MapFeatureEndpoints(IEndpointRouteBuilder app)
           id:  Method:...EdgeHopExplorer.BlazorServer.Endpoints.FeatureEndpoints.MapFeatureEndpoints(...)
           doc: Endpoints/FeatureEndpoints.cs
           routes: GET /api/features/all, GET /api/features/{name}, POST /api/features/search

1 match on branch 'main'.

Add --json to any query verb for the exact MCP tool shape.

Roadmap

  • Platform-independent JS/TS parser. EdgeHop ships the native edgehop-oxc binary for win-x64, linux-x64, and osx-arm64 today. A cross-platform oxc parser is planned, which will drop the native-binary requirement entirely and let EdgeHop run anywhere .NET 10 does.

  • More extractor plugins. The reflection-loaded extractor seam is designed to grow beyond C# and JS/TS to additional languages and project types.

Contributing

Contributions are welcome — see CONTRIBUTING.md for how to build, test, and submit changes.

License

Licensed under the Apache License 2.0.

Built on oxc (JS/TS parsing) and Roslyn (C#/Razor analysis). Bundled third-party components and their licenses are listed in THIRD-PARTY-NOTICES.md.

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EdgeHop/EdgeHop'

If you have feedback or need assistance with the MCP directory API, please join our Discord server