# How codebase-memory-mcp Extracts HTTP Route Nodes and Matches Call Sites for Cross-Service Linking

> Discover how codebase-memory-mcp extracts HTTP route nodes from edges and matches them to call sites using canonicalized names for effective cross-service linking and dependency analysis.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: how-to-guide
- Published: 2026-07-11

---

**codebase-memory-mcp extracts HTTP route nodes by scanning HTTP_CALLS edges in [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c), canonicalizing URL paths into deterministic qualified names (QNs), and matching them to call sites through identical QN lookups to enable cross-service dependency analysis.**

codebase-memory-mcp constructs a comprehensive graph representation of repository entities to enable deep cross-service analysis. The system extracts **HTTP Route nodes** from call edges and links them to call sites using canonicalized qualified names, creating a unified dependency graph that maps inter-service HTTP interactions across the entire codebase.

## Extracting HTTP Route Nodes from Graph Edges

The extraction process begins in [`src/pipeline/pipeline.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pipeline.c) within the `cbm_pipeline_create_route_nodes()` function. This orchestration pass invokes the `route_edge_visitor()` callback in [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c) to iterate over the graph edge list and identify HTTP endpoints.

### Filtering HTTP_CALLS and ASYNC_CALLS Edges

The visitor function filters edges by type, processing only **HTTP_CALLS** and **ASYNC_CALLS** relationships. For each matching edge, it extracts the `url_path` and `callee` properties from the edge's JSON metadata using `json_extract()`:

```c
if (strcmp(edge->type, "HTTP_CALLS") != 0 &&
    strcmp(edge->type, "ASYNC_CALLS") != 0) {
    return;
}

const char *url = json_extract(edge->properties_json, "url_path",
                               url_buf, sizeof(url_buf));
const char *callee = json_extract(edge->properties_json, "callee",
                                  callee_buf, sizeof(callee_buf));

```

### Guarding for Literal Routes

For **HTTP_CALLS** edges, the system applies a literal route guard using `cbm_service_pattern_is_http_route_literal()`. This ensures that only endpoints with literal URL paths (not dynamically constructed strings) are processed as route definitions, preventing false positives from variable interpolation.

```c
if (strcmp(edge->type, "HTTP_CALLS") == 0 &&
    !cbm_service_pattern_is_http_route_literal(url, callee))
    return;

```

### Canonicalizing URL Paths

The `cbm_route_canon_path()` function transforms URL paths into a canonical form by replacing path parameters (e.g., `:id`) with uniform placeholders (`{}`). This normalization ensures that `/user/:id` and `/user/123` resolve to the same route identity, enabling accurate cross-service matching regardless of specific argument values.

## Matching Routes to Call Sites via Qualified Names

Route nodes are matched to call sites through a **deterministic qualified name (QN)** strategy that guarantees identity across the graph.

### Generating Deterministic Qualified Names

The system constructs a stable QN by combining the HTTP method (or "ANY" for generic routes) with the canonicalized path:

```c
char route_qn[CBM_ROUTE_QN_SIZE];
snprintf(route_qn, sizeof(route_qn), "__route__%s__%s",
         method ? method : "ANY",
         cbm_route_canon_path(url, cpath, sizeof(cpath)));

```

For **ASYNC_CALLS** edges, the QN incorporates the broker identifier instead of the HTTP method.

### Upserting Route Nodes

The `cbm_gbuf_upsert_node()` function in the graph buffer (`gb`) creates or updates **Route** nodes using the QN as the deduplication key. This guarantees a single node per unique endpoint/method combination:

```c
cbm_gbuf_upsert_node(ctx->gb, "Route", url, route_qn,
                     "", 0, 0, route_props);

```

### Cross-Service Linking Passes

After route creation, several specialized passes complete the cross-service linking:

- **ensure_decorator_routes**: Scans Function nodes for `@route` decorators in [`src/pipeline/pass_semantic.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_semantic.c) and creates corresponding Route nodes with **HANDLES** edges.
- **connect_prefix_to_decorators**: Links prefix routes (e.g., `/api`) to decorator-defined handlers.
- **match_infra_routes**: Joins infrastructure Route nodes (from external configurations) to handler Routes by comparing canonicalized paths.
- **create_data_flows**: Establishes **DATA_FLOWS** edges from callers through Route nodes to handlers, enabling end-to-end flow analysis.

The matching succeeds because both the Route node and the call-site edge share the identical QN derived from the same canonicalization logic.

## End-to-End Pipeline Flow

The complete extraction and linking lifecycle follows five distinct phases:

1. **Discovery Phase**: [`src/pipeline/pass_calls.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_calls.c) parses source files to create `File` → `Function` → **HTTP_CALLS** edges.
2. **Route Extraction**: `cbm_pipeline_create_route_nodes()` scans edges, extracts URLs, and upserts **Route** nodes with deterministic QNs.
3. **Decorator Resolution**: `ensure_decorator_routes()` validates that annotated functions have matching Route nodes.
4. **Route Matching**: `connect_prefix_to_decorators()` and `match_infra_routes()` link Route nodes to their callers and infrastructure definitions.
5. **Data Flow Construction**: `create_data_flows()` adds **DATA_FLOWS** edges, finalizing the cross-service call graph for downstream LSP and security analysis.

## Implementation Details

The following C implementation from [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c) demonstrates the core extraction logic:

```c
static void route_edge_visitor(const cbm_gbuf_edge_t *edge, void *userdata) {
    route_ctx_t *ctx = (route_ctx_t *)userdata;

    if (strcmp(edge->type, "HTTP_CALLS") != 0 &&
        strcmp(edge->type, "ASYNC_CALLS") != 0) {
        return;
    }

    char url_buf[CBM_SZ_512];
    const char *url = json_extract(edge->properties_json, "url_path",
                                   url_buf, sizeof(url_buf));
    if (!url || !url[0]) return;

    char callee_buf[CBM_SZ_256];
    const char *callee = json_extract(edge->properties_json, "callee",
                                      callee_buf, sizeof(callee_buf));
    if (strcmp(edge->type, "HTTP_CALLS") == 0 &&
        !cbm_service_pattern_is_http_route_literal(url, callee))
        return;

    char route_qn[CBM_ROUTE_QN_SIZE];
    char cpath[CBM_SZ_256];
    snprintf(route_qn, sizeof(route_qn), "__route__%s__%s",
             method ? method : "ANY",
             cbm_route_canon_path(url, cpath, sizeof(cpath)));

    cbm_gbuf_upsert_node(ctx->gb, "Route", url, route_qn,
                         "", 0, 0, route_props);
    ctx->created++;
}

```

The pipeline entry point in [`src/pipeline/pipeline.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pipeline.c) orchestrates the sequential execution:

```c
void cbm_pipeline_create_route_nodes(cbm_gbuf_t *gb) {
    route_ctx_t ctx = {.gb = gb, .created = 0};
    cbm_gbuf_foreach_edge(gb, route_edge_visitor, &ctx);

    ensure_decorator_routes(gb);
    connect_prefix_to_decorators(gb);
    match_infra_routes(gb);
    create_data_flows(gb);
    create_grpc_routes(gb);
    create_sveltekit_routes(gb);
}

```

## Summary

- **HTTP Route extraction** occurs in [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c) via the `route_edge_visitor()` callback, filtering for **HTTP_CALLS** and **ASYNC_CALLS** edges.
- **Canonicalization** via `cbm_route_canon_path()` normalizes path parameters to `{}`, ensuring that `/user/:id` and `/user/123` map to identical route identities.
- **Qualified names (QNs)** provide deterministic deduplication keys using the pattern `__route__METHOD__canonicalized_path`.
- **Cross-service linking** relies on matching QNs between Route nodes and call-site edges, with subsequent passes creating **HANDLES** and **DATA_FLOWS** relationships.
- The graph buffer (`cbm_gbuf_t`) persists nodes to [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) for consumption by downstream analysis tools.

## Frequently Asked Questions

### How does codebase-memory-mcp handle path parameters in HTTP routes?

The system canonicalizes path parameters using `cbm_route_canon_path()` in [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c), which replaces dynamic segments like `:id` or `{userId}` with uniform `{}` placeholders. This ensures that different call sites referencing the same endpoint with varying arguments resolve to a single Route node.

### What is the purpose of the qualified name (QN) in route matching?

The **QN** serves as a deterministic, stable identifier that combines the HTTP method and canonicalized path (e.g., `__route__GET__/api/users`). Both Route nodes and call-site edges generate identical QNs, enabling the graph query engine to stitch together cross-service dependencies without ambiguity.

### Which edge types trigger route node extraction?

The `route_edge_visitor()` function processes edges of type **HTTP_CALLS** and **ASYNC_CALLS**. HTTP calls undergo additional literal validation via `cbm_service_pattern_is_http_route_literal()`, while async calls proceed directly to QN generation using their broker identifier.

### How are decorator-based routes linked to HTTP handlers?

The `ensure_decorator_routes()` pass scans Function nodes annotated with `@route` attributes (identified by [`src/pipeline/pass_semantic.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_semantic.c)) and creates corresponding Route nodes if missing. The `connect_prefix_to_decorators()` pass then establishes **HANDLES** edges between prefix routes (e.g., `/api`) and specific handler functions, completing the linkage between infrastructure definitions and implementation code.