This page describes self-hosted workspace mode, where one MCP
server is started over a workspace directory. Hosted Repowise has its
own workspace endpoint at https://api.repowise.dev/mcp/w/{workspace_id}
with a different federation rule: there is no default repo, every
federatable tool takes repo, and omitting it answers across every
member. See
Connecting your IDE.
In workspace mode, every one of the
core MCP tools takes an extra repo parameter, and
three workspace-only tools appear for questions that have no single-repo
equivalent. The default repo (set by repowise workspace set-default)
is targeted when repo is omitted, just like single-repo mode.
Four ways to address a workspace
| How | Behavior |
|---|---|
repo omitted | get_context, get_symbol, get_risk and get_health route each target to the repo that owns it. Other tools target the default repo. |
"<alias>:<target>" in a target | Names the repo outright, for example web:src/app.ts::App. |
repo="backend" | Targets the repo with that alias. |
repo="all" | Fans the query out across every repo, on the four tools that support it. |
Routing targets to the repo that owns them
With repo omitted, a path or path::Name target goes to the default
repo when the file exists there, else to the one other repo whose
checkout has it. A path found in several other repos returns its
candidates. A path in no repo gets the default repo's usual not-found
answer plus a hint naming search_codebase(repo="all") and the
<alias>:<path> form. Routed results carry repo.
get_context and get_symbol route a bare symbol name (render,
Client.send) the same way, through the workspace symbol index: the
default repo keeps a name it has, one other repo that has it gets the
call, and several return candidates. A repowise#<ref> omission ref
is found in whichever repo holds it.
| Tool | Batch spanning repos |
|---|---|
get_context | One call answers across repos |
get_symbol | One id per call |
get_risk, get_health | One repo per call; the response names the per-repo calls to make |
Routing reads .repowise-workspace/workspace.db, a store derived from
each repo's own index. It is refreshed after every workspace update and
is always safe to delete: it is rebuilt the next time it is needed.
get_context(targets=["src/app.ts::App", "api/handlers.py"]) # each routed to its repo
get_context(targets=["web:src/app.ts::App"]) # repo named outright
get_symbol("Client.send") # bare name, routedrepo="all" is supported by four tools: search_codebase (RRF merge
of the per-repo results), get_dead_code (merged, sorted),
get_overview (a workspace aggregate, not a ranked merge), and get_why
in its workspace search mode.
These calls query up to 4 repos at a time and give each 60 seconds.
A repo that fails to open, errors or times out is listed in
repos_failed with its reason while the other repos still answer. A
repo whose index is behind its checkout is listed in repos_stale with
indexed_commit and live_head, and its rows carry stale: true.
Both keys appear only when non-empty.
| Variable | Default | Meaning |
|---|---|---|
REPOWISE_WORKSPACE_CONCURRENCY | 4 | Repos queried at a time |
REPOWISE_WORKSPACE_REPO_TIMEOUT_S | 60 | Seconds each repo gets |
Every other tool returns an error for repo="all" and asks you to
name one repo. That includes get_answer, get_context,
get_symbol, get_risk, get_change_risk, get_dependency_path,
get_execution_flows, and get_why's reference-lookup and
health-dashboard modes. They each resolve one thing in one repo, so
there is nothing coherent to merge.
Examples
# Get an architecture summary of the whole workspace
get_overview(repo="all")
# Search every repo at once
search_codebase("authentication flow", repo="all")
# Risk assessment in a specific repo
get_risk(targets=["src/auth/service.py"], repo="backend")
# Decision archaeology across repos
get_why("why caching?", repo="all")How federated queries work
Each tool implements repo="all" slightly differently:
get_overview(repo="all"), returns workspace-level totals (repos, files, symbols), per-repo dependency graph, and cross-repo topology / contract links.search_codebase(repo="all"), runs the search in each repo and merges results with Reciprocal Rank Fusion (k=60).get_dead_code(repo="all"), concatenates each repo's findings and sorts the union by confidence, then by lines, and applies a cross-repo confidence adjustment when a "dead" symbol has external consumers.get_why(repo="all"), keyword search across every repo's decision records (capped at 15 merged results).get_contextandget_risk, when the target lives in repo A but has cross-repo co-change partners or contract consumers in repos B and C, append those signals to the response.
Cross-repo directives in get_risk
When you pass changed_files in workspace mode, the
get_risk directive block carries the changed
repo's cross-repo fallout in addition to the in-repo blast radius:
will_break_consumers, services in other repos that depend on this one (structural impact), each withrepo,service,distance,score, and the edge kinds carrying the impact.missing_cross_repo_cochanges, services in other repos that historically co-change with this one but aren't in the diff.breaking_changes, provider contracts in this repo that changed incompatibly since the last index (a removed route or field, a type or field-number change, a newly-required field), each with the impacted consumers it endangers. See Breaking-change guard.conformance_violationsanddependency_cycles, the declared dependency-rule breaches and circular dependencies the diff's repo participates in. See Architecture conformance.
Workspace-only tools
These three tools only exist when the server runs over a workspace. They read the system graph directly.
get_blast_radius
Cross-repo downstream impact: if you change this service, what breaks across the other repos? See Cross-repo blast radius.
| Parameter | Type | Required | Description |
|---|---|---|---|
targets | string[] | Yes | Node ids (repo or repo::service/path), repo aliases, or the symbol id of a published symbol |
max_depth | int | No | Reachability depth (1-8, default 3) |
include_behavioral | bool | No | Include co-change (behavioral) edges (default true) |
Returns: the impacted services ranked by impact score, each with
distance (hops), structural (a real dependency vs co-change only),
and the edge kinds that carried the impact; plus impacted_repos,
structural_count / behavioral_count, total_impacted, and any
unresolved_targets.
When to use: before changing a high-fan-out provider, to see who
consumes it across repo boundaries. Structural impact (will break)
outweighs behavioral co-change (may drift).
get_blast_radius(targets=["backend"])
get_blast_radius(targets=["mono::services/auth"], max_depth=2, include_behavioral=False)get_conformance
Opt-in, off by default alongside generate_refactoring_code to
keep the default tool surface lean. Enable it with repowise mcp --tools +get_conformance (default set plus
this tool) if your agent needs it. Architecture governance: does the live
system graph obey the declared dependency rules, and are there circular
service dependencies? See Architecture conformance.
| Parameter | Type | Required | Description |
|---|---|---|---|
repo | string | No | Limit findings to those involving this repo alias |
Returns: violations (each with the offending source/target
services, the rule_source/rule_target matchers that fired, and the
edge_kind), cycles (each with the participating nodes and
length), and the violation_count / cycle_count / rules_evaluated
rollups.
When to use: before a refactor that changes service boundaries, or
to audit whether the live architecture still matches the intended one.
Rules are declared under conformance: in .repowise-workspace.yaml.
get_conformance()
get_conformance(repo="frontend")get_architecture
The one evaluative read of the whole system: how coupled is it, where is the architectural core, and a single 1-10 architecture score. Deterministic, structural edges only (co-change excluded). See Architecture metrics.
Parameters: none.
Returns: score (1-10), architecture_type (core-periphery or
hierarchical), propagation_cost_pct (share of other services the
average service reaches), core_size / core_ratio / core_members
(the largest cyclic group), cycle_count, conformance_violations, a
role_breakdown (count of Core / Shared / Control / Peripheral
services), and a one-line summary.
When to use: before a cross-service refactor, or to gauge and compare overall system structure over time.
get_architecture()Setting the default
repowise workspace set-default backendThe default determines what repo-less queries hit. Set it to whichever
repo your team works in most often.
Single endpoint, no extra setup
repowise init . at the workspace root writes a single .mcp.json that
points at the workspace MCP server. Your editor doesn't need to know
which repo it's targeting, the tools handle routing.
The server lazy-loads each repo's index on first query and evicts with an LRU policy once more than 5 repos are loaded at once, to bound memory in large workspaces. The default repo is never evicted.
The MCP transport's per-call token budget still applies in workspace
mode. repo="all" results are aggregated and capped; if you need
deeper paging, narrow to a specific repo with repo="<alias>".