Version
codebase-memory-mcp 0.8.1
Platform
Linux (x64)
Install channel
GitHub release archive / install.sh / install.ps1
Binary variant
standard
What happened, and what did you expect?
I wanted to cross index 3 different related microservices and it failed to create the edges
Reproduction
Summary
index_repository(mode="cross-repo-intelligence") produces 0 CROSS_HTTP_CALLS edges for a real HTTP integration between two indexed repos. Root cause is on the caller side: the URL extractor only resolves URLs that appear as string literals at the call site. When the caller passes a module-level constant (or any Name / string-concatenation / env-derived value), no url_path is attached to the call, so no HTTP_CALLS edge is created — and the cross-repo matcher then has nothing to link against the callee's Route nodes.
This is a false negative: cross_http_calls: 0 reads as "no integration" when the integration exists.
Observed behavior (anonymized)
- Callee repo: FastAPI service that defines routes via
@app.post("/<path>").
- Caller repo: Python service that calls those routes via
requests.post(...).
The callee's routes are indexed correctly as Route nodes with literal paths. The caller's calls are not captured as HTTP edges, so cross-repo matching yields nothing.
Callee side is fine — Route nodes exist with literal paths
MATCH (r:Route) RETURN r.qualified_name, r.method
Returns the expected __route__POST__/<path> nodes (literal paths preserved).
Caller side — HTTP_CALLS edges only appear for literal-path arguments
MATCH (a)-[e:HTTP_CALLS]->(b) RETURN e.url_path, e.via, e.callee
Every surviving edge has via = "arg_url" and a concrete url_path — i.e. it survived only because the path was passed as a literal string argument at the call site.
Calls with a variable URL are downgraded to plain CALLS with empty url_path
MATCH (a)-[e:CALLS]->(b)
WHERE e.callee = 'requests.post'
RETURN e.callee, e.via, e.url_path, e.strategy
For call sites that pass a constant/variable URL:
callee = requests.post via = "" url_path = "" strategy = "unique_name"
The extractor resolved the callee symbol but extracted no URL.
cross-repo-intelligence result
index_repository(mode="cross-repo-intelligence", target_projects=[...])
=> { cross_http_calls: 0, total_cross_edges: 0 }
Root cause
The caller passes a variable, not a literal — the common pattern of centralizing endpoint URLs:
API_URL = API_BASE_URL + "some/path" # base often env-derived
...
requests.post(API_URL, json=payload, ...)
The first argument is a Name bound to base_var + "literal". The URL extractor does literal reading only (via=arg_url); it does not do constant folding or interprocedural value resolution for Name → (base_var + "literal"). With no literal in hand it emits a generic CALLS edge and discards the path.
Impact
- Any service-to-service integration where the caller centralizes endpoint URLs in constants/config (a near-universal pattern) is invisible to
cross-repo-intelligence.
- Users cannot trust
cross_http_calls: 0 as "not integrated."
trace_path(mode="cross_service") likewise misses these hops.
Proposed fixes (in rough priority)
- Intra-file constant folding for URL args. When a call argument is a
Name, resolve it to a same-module assignment and fold simple str + str / f-string / .format concatenations where at least one operand is a literal. Recover the literal suffix even when the base is an env var, and store it as a partial url_path.
- Suffix/contains matching in the cross-repo matcher. Even a partial path (no host) should match a Route by path-suffix + method, with reduced confidence on the edge.
- Emit a low-confidence HTTP_CALLS edge for unresolved client calls. When the callee is a known HTTP client (
requests.post, httpx, fetch, axios) but the URL is unresolved, still create an HTTP_CALLS edge with url_path=null and confidence="unresolved", so callers can see "this function makes an outbound HTTP call we couldn't pin to a route."
- Report unresolved client calls in the index result. Add
unresolved_http_calls: N to the cross-repo-intelligence response so 0 cross edges isn't silently misleading.
Minimal repro
- Repo A:
@app.post("/foo") (FastAPI/Express).
- Repo B:
URL = BASE + "foo"; requests.post(URL).
- Index both, run
cross-repo-intelligence from B targeting A → 0 edges.
- Change B to
requests.post(BASE + "foo") or a literal → edge appears (literal/arg_url path).
Logs
Diagnostics trajectory (memory / performance / leak issues)
Project scale (if relevant)
No response
Confirmations
Version
codebase-memory-mcp 0.8.1
Platform
Linux (x64)
Install channel
GitHub release archive / install.sh / install.ps1
Binary variant
standard
What happened, and what did you expect?
I wanted to cross index 3 different related microservices and it failed to create the edges
Reproduction
Summary
index_repository(mode="cross-repo-intelligence")produces 0CROSS_HTTP_CALLSedges for a real HTTP integration between two indexed repos. Root cause is on the caller side: the URL extractor only resolves URLs that appear as string literals at the call site. When the caller passes a module-level constant (or anyName/ string-concatenation / env-derived value), nourl_pathis attached to the call, so noHTTP_CALLSedge is created — and the cross-repo matcher then has nothing to link against the callee'sRoutenodes.This is a false negative:
cross_http_calls: 0reads as "no integration" when the integration exists.Observed behavior (anonymized)
@app.post("/<path>").requests.post(...).The callee's routes are indexed correctly as
Routenodes with literal paths. The caller's calls are not captured as HTTP edges, so cross-repo matching yields nothing.Callee side is fine — Route nodes exist with literal paths
Returns the expected
__route__POST__/<path>nodes (literal paths preserved).Caller side — HTTP_CALLS edges only appear for literal-path arguments
Every surviving edge has
via = "arg_url"and a concreteurl_path— i.e. it survived only because the path was passed as a literal string argument at the call site.Calls with a variable URL are downgraded to plain CALLS with empty url_path
For call sites that pass a constant/variable URL:
The extractor resolved the callee symbol but extracted no URL.
cross-repo-intelligence result
Root cause
The caller passes a variable, not a literal — the common pattern of centralizing endpoint URLs:
The first argument is a
Namebound tobase_var + "literal". The URL extractor does literal reading only (via=arg_url); it does not do constant folding or interprocedural value resolution forName → (base_var + "literal"). With no literal in hand it emits a genericCALLSedge and discards the path.Impact
cross-repo-intelligence.cross_http_calls: 0as "not integrated."trace_path(mode="cross_service")likewise misses these hops.Proposed fixes (in rough priority)
Name, resolve it to a same-module assignment and fold simplestr + str/ f-string /.formatconcatenations where at least one operand is a literal. Recover the literal suffix even when the base is an env var, and store it as a partialurl_path.requests.post,httpx,fetch,axios) but the URL is unresolved, still create anHTTP_CALLSedge withurl_path=nullandconfidence="unresolved", so callers can see "this function makes an outbound HTTP call we couldn't pin to a route."unresolved_http_calls: Nto thecross-repo-intelligenceresponse so0 cross edgesisn't silently misleading.Minimal repro
@app.post("/foo")(FastAPI/Express).URL = BASE + "foo"; requests.post(URL).cross-repo-intelligencefrom B targeting A → 0 edges.requests.post(BASE + "foo")or a literal → edge appears (literal/arg_urlpath).Logs
Diagnostics trajectory (memory / performance / leak issues)
Project scale (if relevant)
No response
Confirmations