# How HTTP Routes and Cross-Service Links Are Detected and Validated in codebase-memory-mcp

> Discover how codebase-memory-mcp detects and validates HTTP routes and cross-service links using AST parsing and import analysis for robust code understanding. Learn more.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: internals
- Published: 2026-07-16

---

**The codebase-memory-mcp engine discovers HTTP routes by parsing framework-specific AST patterns and canonicalizing paths, while cross-service links are identified through import analysis and qualified name resolution, with both undergoing strict validation for completeness, uniqueness, and reachability.**

`codebase-memory-mcp` builds a **graph-based memory** of a codebase by analyzing source files and extracting semantic entities as nodes and edges. Understanding how it detects and validates HTTP routes and cross-service links is essential for navigating microservice architectures and ensuring API consistency. The pipeline uses language-specific extractors and a central graph store to maintain these relationships across JavaScript, TypeScript, Go, Python, Rust, and other supported languages.

## Detecting HTTP Routes in the Pipeline

The detection of HTTP routes begins with **AST extraction**, where language-specific parsers walk the abstract syntax tree looking for framework-specific patterns.

### AST Extraction and Framework Pattern Matching

In [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c), the pipeline walks the AST to identify route declarations such as `app.get('/path', handler)`, `router.post("/path", fn)`, or `http.HandleFunc("/path", fn)`. These patterns are matched regardless of the specific web framework being used, allowing the system to extract the HTTP method, path string, and handler function reference from the source code.

### Route Canonicalization

Before storage, raw route strings are normalized by `cbm_route_canon_path()` in [`src/pipeline/route_canon.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/route_canon.c). This function converts parameter placeholders into a uniform `{}` token, transforming variations like `"/users/:id"`, `"/users/{id}"`, or `"/users/<int:id>"` into a standardized `"/users/{}"` format. This canonicalization removes framework-specific syntax differences and enables reliable duplicate detection across the codebase. The logic is thoroughly tested in [`tests/test_route_canon.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/tests/test_route_canon.c).

### Node Creation and Link Wiring

For each discovered route, the system creates a **node** with the aspect `routes` via `cbm_store_upsert_node()` in [`src/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store.c). Each node stores:
- `method` (GET, POST, etc.)
- `path` (canonicalized)
- `handler` (qualified function name)
- `service` (the package or module containing the handler)

The route node is then linked to its handler function node via an edge of type `defines`, and the handler is linked to its containing service node, creating a complete trace from *service → handler → route*.

## Validating HTTP Routes

The validation phase in [`src/pipeline/pass_route_validate.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_validate.c) ensures route integrity before the graph is considered stable.

**Validation checks include:**
- Every route node must have a non-empty `method` and `path`
- The referenced handler node must exist (otherwise the route is flagged as *dangling*)
- No two route nodes within the same service may share the same canonical path and method (duplicate route detection)

When validation fails, the store flags the node with a `validation_error` aspect, making it queryable through the LSP and CLI interfaces.

## Detecting Cross-Service Links

Cross-service dependencies are discovered through **import analysis** and **qualified name resolution**.

### Import Analysis and Link Edge Creation

In [`src/pipeline/pass_link_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_link_nodes.c), the pipeline parses import statements (`import X from "serviceB"`, `require('serviceB')`, Go `import "serviceB"`, etc.) to identify dependencies between modules. When a symbol is imported from a different service, the system records a **link** edge from the importing module to the imported symbol's defining module.

### Qualified Name Resolution

Symbol resolution builds a **qualified name** string of the form `<service>.<package>.<symbol>` using `cbm_fqn_resolve()` in [`src/fqn.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/fqn.c). This fully qualified name is stored as the node's `qualified_name` field, enabling precise cross-reference tracking. An edge of type `depends_on` (or `calls`) is then inserted between the caller and callee nodes via `cbm_store_upsert_edge()` in [`src/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store.c).

## Validating Cross-Service Dependencies

After the graph is fully constructed, [`src/pipeline/pass_link_validate.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_link_validate.c) performs cross-service validation by walking all `depends_on` edges. The validation ensures that:
- The target node exists and is reachable
- The dependency actually crosses a service boundary (both nodes belong to different services)
- Missing targets are marked with `missing_link`
- Cycles that span multiple services are flagged as potential architectural violations

## Accessing Validation Results

The pipeline exposes validation results through multiple interfaces for developer tooling integration.

### LSP Diagnostics and CLI Queries

**LSP diagnostics** query the store for nodes with a `validation_error` aspect and surface them as diagnostics in the editor. Via the **CLI**, you can retrieve specific validation states:

```c
/* Query all valid routes */
cbm_store_t *store = cbm_store_open(".");
cbm_node_t *routes = cbm_store_query(store,
    "aspect == 'routes' && !validation_error");
for (size_t i = 0; i < routes->len; ++i) {
    printf("%s %s -> %s\n",
        routes[i].method,
        routes[i].path,
        routes[i].handler);
}
cbm_store_close(store);

```

To inspect cross-service boundaries:

```c
/* List all edges that cross service boundaries */
for (edge in store->edges) {
    if (edge.type == DEPENDS_ON &&
        edge.src.service != edge.dst.service) {
        printf("%s (%s) → %s (%s)\n",
            edge.src.name, edge.src.service,
            edge.dst.name, edge.dst.service);
    }
}

```

The **test suite** in [`tests/test_store_arch.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/tests/test_store_arch.c) validates this entire workflow by creating fake route nodes, running `cbm_store_validate()`, and asserting the expected `route_count` and error flags, ensuring the detection and validation pipeline remains consistent across releases.

## Summary

- **HTTP route detection** occurs in [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c) through AST pattern matching, followed by path canonicalization in [`src/pipeline/route_canon.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/route_canon.c) to normalize framework-specific syntax.
- **Route validation** in [`src/pipeline/pass_route_validate.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_validate.c) checks for complete metadata, existing handlers, and duplicate paths within services.
- **Cross-service links** are identified in [`src/pipeline/pass_link_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_link_nodes.c) via import/require analysis and qualified name resolution using `cbm_fqn_resolve()`.
- **Link validation** in [`src/pipeline/pass_link_validate.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_link_validate.c) verifies that dependencies exist, cross service boundaries, and flags architectural cycles.
- All validation results are stored as node aspects (`validation_error`, `missing_link`) and exposed through LSP diagnostics, CLI queries, and the C API.

## Frequently Asked Questions

### How does codebase-memory-mcp handle different web framework syntaxes?

The system uses framework-agnostic AST patterns in [`src/pipeline/pass_route_nodes.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_nodes.c) to recognize common routing idioms across Express.js, Fastify, Gorilla Mux, Flask, and other frameworks. The `cbm_route_canon_path()` function in [`src/pipeline/route_canon.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/route_canon.c) then normalizes parameter syntax variations (such as `:id`, `{id}`, or `<int:id>`) into a uniform `{}` format, allowing the graph to treat routes from different frameworks as comparable entities.

### What happens when a route references a non-existent handler?

During the validation phase in [`src/pipeline/pass_route_validate.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_route_validate.c), the system verifies that each route's handler references an existing function node in the graph. If the handler cannot be resolved, the route node is flagged with a `validation_error` aspect and reported as a *dangling* route through LSP diagnostics or CLI queries, allowing developers to identify broken API endpoints immediately.

### How are circular dependencies between services detected?

The [`src/pipeline/pass_link_validate.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/pass_link_validate.c) validation pass analyzes all `depends_on` edges that cross service boundaries. When it detects cycles where service A depends on service B, which transitively depends back on service A, it flags these as potential architectural violations. This helps maintain clean service boundaries in microservice architectures.

### Can I query the graph store directly for validation errors?

Yes. The store exposes a query interface via `cbm_store_query()` in [`src/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store.c). You can filter specifically for problematic nodes using aspect queries such as `"aspect == 'routes' && validation_error"` to retrieve only routes with validation failures, or query for `missing_link` aspects to find broken cross-service dependencies.