# How trace_path with data_flow Mode Follows Value Propagation Through Argument Expressions

> Learn how trace_path with data_flow mode tracks value propagation through argument expressions and field sub-expressions. Discover source code easily using BFS and hybrid LSP symbols.

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

---

**In `data_flow` mode, the `trace_path` tool traverses `DATA_FLOWS` edges to track how values move from argument expressions through parameters and field-level sub-expressions, using a breadth-first search that begins at the target function and follows hybrid LSP-resolved symbols to their ultimate source.**

The `codebase-memory-mcp` project provides a `trace_path` MCP tool that can operate in a specialized `data_flow` mode. This mode moves beyond simple call-graph traversal to answer where a specific argument's value originates, following the chain of data dependencies through the codebase.

## The Anatomy of DATA_FLOWS Edges

Value propagation relies on explicit `DATA_FLOWS` edges stored in the code graph. These edges are generated during the indexing phase and encode how data moves between AST nodes.

### Mapping Arguments to Parameters in semantic.c

During semantic analysis, the indexer inspects function calls to create direct mappings between argument expressions and their corresponding formal parameters. In [`src/semantic/semantic.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/semantic/semantic.c), the analysis uses the `w_dataflow` weight to emit `DATA_FLOWS` edges that link the argument's AST node to the parameter name.

- Each argument expression at a call site generates a `DATA_FLOWS` edge pointing to the callee's parameter.
- The edge captures the exact source range of the argument expression for precise traceability.

### Chaining Sub-Expressions in dataflow.c

Argument expressions often contain nested structures such as field accesses (`obj.field`), array indexing, or dereferences. The pipeline in [`src/pipeline/dataflow.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/dataflow.c) decomposes these expressions into leaf identifiers. For every sub-expression that contributes to the final value, an additional `DATA_FLOWS` edge is created, chaining the argument node to the underlying symbols that actually hold the data.

## Hybrid LSP Resolution for Accurate Propagation

Before `DATA_FLOWS` edges are finalized, the system must resolve symbols across file boundaries, imports, generics, and inheritance hierarchies. The Hybrid LSP layer, implemented in [`src/hybrid_lsp/resolution.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/hybrid_lsp/resolution.c), performs this resolution. It ensures that an argument expression is linked to the exact declaration the runtime would use, preventing false positives from name collisions or incomplete type information.

## The trace_path Traversal Algorithm

The implementation in [`src/mcp/tools/trace_path.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/mcp/tools/trace_path.c) handles the `mode` parameter and executes the appropriate traversal strategy.

### BFS with Edge Type Filtering

When invoked with `mode: "dataflow"`, the tool performs a breadth-first search starting from the target function node:

1. It first follows standard `CALLS` edges to reach caller nodes.
2. At each caller, it queries the graph for `DATA_FLOWS` edges associated with the specific `arg_index`.
3. It traverses these edges backward (or forward, depending on `direction`) to the originating symbols.
4. The search recurses through additional `DATA_FLOWS` edges until it reaches source leafs such as variables, constants, or static fields.

The traversal respects the `max_depth` parameter (defaulting to 5) to prevent combinatorial explosion in complex expression trees.

### Handling Argument Expressions

The tool specifically tracks the **argument expression** node rather than just the call site. This allows it to distinguish between different arguments passed to the same parameter across multiple call sites. The graph walk aggregates all unique source symbols discovered along the propagation chain, de-duplicating paths to provide a concise provenance list.

## Practical Usage and Code Examples

You can invoke `trace_path` in `data_flow` mode via the CLI or MCP client to analyze value provenance.

Basic call-graph trace (excludes data flow):

```bash
codebase-memory-mcp cli trace_path '{"project":"my-proj","function_name":"processOrder","direction":"inbound"}'

```

Data-flow mode targeting the first argument (index 0):

```bash
codebase-memory-mcp cli trace_path '{
  "project": "my-proj",
  "function_name": "processOrder",
  "direction": "inbound",
  "mode": "dataflow",
  "arg_index": 0,
  "max_depth": 5
}'

```

The response provides structured provenance paths showing which variables or fields ultimately supply the value:

```json
{
  "paths": [
    {
      "caller": "OrderService.validate",
      "arg_expression": "checkout.cart",
      "source": "checkout.cart.items"
    },
    {
      "caller": "ApiController.postCheckout",
      "arg_expression": "body.cart",
      "source": "request.body.cart"
    }
  ]
}

```

## Summary

- **`DATA_FLOWS` edges** are created in [`src/semantic/semantic.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/semantic/semantic.c) using the `w_dataflow` weight to link arguments to parameters.
- **[`src/pipeline/dataflow.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/dataflow.c)** extends these edges to cover nested sub-expressions like field accesses and array indices.
- **[`src/hybrid_lsp/resolution.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/hybrid_lsp/resolution.c)** resolves symbols across files before edge creation, ensuring accurate type information.
- **[`src/mcp/tools/trace_path.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/mcp/tools/trace_path.c)** implements BFS traversal that filters for `DATA_FLOWS` edges when `mode` is set to `"dataflow"`.
- The tool tracks specific **argument expressions** by index, following chains of value propagation to their source leafs while respecting depth limits.

## Frequently Asked Questions

### How does trace_path identify which argument to track in data_flow mode?

The tool uses the `arg_index` parameter (0-based) provided in the request to filter `DATA_FLOWS` edges, examining only the edges that correspond to the specified argument position at each call site.

### What happens if the argument contains multiple nested field accesses?

The traversal follows the chain of `DATA_FLOWS` edges created by [`src/pipeline/dataflow.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/pipeline/dataflow.c) for each sub-expression, recursively walking from the root argument node down through field accessors, array indices, or pointer dereferences until it reaches terminal identifier nodes.

### Does data_flow mode work across language boundaries?

Yes, provided the Hybrid LSP layer in [`src/hybrid_lsp/resolution.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/hybrid_lsp/resolution.c) can resolve the symbols. The system uses cross-file type resolution to link arguments in one language to parameters in another (e.g., TypeScript to C++ bindings) before creating the `DATA_FLOWS` edges that `trace_path` traverses.

### Is there a limit to how deep the propagation analysis goes?

By default, `trace_path` limits traversal to a depth of 5 edges, configurable via the `max_depth` parameter. This prevents excessive computation when analyzing highly interconnected data flow graphs.