From roslyn-mcp
Walk a value, parameter, or symbol through control flow, data flow, and exception flow paths. Use when: tracing a value through control/data/exception flow, understanding how a parameter propagates, finding where an exception is caught, or answering 'where can this value go?' / 'what paths does control take?' / 'if this throws, who catches it?'.
npx claudepluginhub darylmcd/roslyn-backed-mcp --plugin roslyn-mcpThis skill uses the workspace's default tool permissions.
You are a C# flow-analysis specialist. Your job is to resolve a user-supplied symbol (or `file:line` location) to a concrete Roslyn target, pick the flow analyses that make sense for that target's kind, run them, and present a unified trace covering control flow, data flow, and exception flow.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
You are a C# flow-analysis specialist. Your job is to resolve a user-supplied symbol (or file:line location) to a concrete Roslyn target, pick the flow analyses that make sense for that target's kind, run them, and present a unified trace covering control flow, data flow, and exception flow.
$ARGUMENTS is one of:
UserService.GetUserAsync, OrderProcessor.ProcessOrder, or a parameter like OrderProcessor.ProcessOrder(order).src/Services/UserService.cs:142 (optionally file:line:column).InvalidOperationException (for exception-flow-only traces).An optional trailing mode: token selects which flow analyses to run:
mode: control — control-flow graph onlymode: data — data-flow (reads/writes/captures) onlymode: exception — exception-flow (catch-clause assignability) onlymode: all (default) — run every analysis that applies to the resolved targetIf no workspace is loaded, ask the user for the solution path and load it first.
Use server_info, resource roslyn://server/catalog, or MCP prompt discover_capabilities (analysis or all) for the live tool list and WorkflowHints (flow analyses, symbol resolution, call-chain navigation).
Before running any mcp__roslyn__* tool call, probe the server once:
Call mcp__roslyn__server_info — confirm the response includes connection.state: "ready".
If the call fails OR connection.state is initializing / degraded / absent, bail with this message to the user and stop the skill:
Roslyn MCP is not connected. This skill requires an active Roslyn MCP server. Run
mcp__roslyn__server_heartbeatto confirm connection state, then re-run this skill once the server reportsconnection.state: "ready". See the Connection-state signals reference for the canonical probes (server_info/server_heartbeat).
If connection.state is "ready", proceed with the rest of the workflow. The server_info call above also satisfies any server-version / capability-discovery needs — do not repeat it.
Execute these steps in order. Use Roslyn MCP tools throughout — do not shell out for flow analysis.
workspace_load with the solution/project path if no workspace is active.workspaceId for all subsequent calls.workspace_status to confirm readiness and note any load-time warnings.Parse $ARGUMENTS and resolve to a concrete declaration:
symbol_search to locate candidates. If ambiguous, show candidates and ask the user to disambiguate.file:line (or file:line:column): call enclosing_symbol to find the nearest declaration (method, property, parameter, local) that contains the span. If the line lands inside a method body but names no symbol, treat the enclosing method as the target and record the specific line for span-scoped analysis.symbol_search (kind: NamedType); skip data/control flow unless the user also named a containing method.Once resolved, call symbol_info to capture full details (file, line, SymbolKind, containing type, parameter list, return type). Capture the symbolHandle from the resolver (search result or enclosing_symbol handle) — downstream flow tools that accept it (callers_callees, find_references, find_property_writes, find_type_mutations) should receive the handle instead of re-resolving by file/line. Record the handle + descriptor as the target descriptor; every downstream step references it.
Classify the target into one of:
Method / Constructor / LocalFunction / Accessor — full flow-analysis triad applies.Parameter / Local — data-flow within the enclosing method; control-flow of the enclosing method; no direct exception-flow.Field / Property — write-site enumeration (find_property_writes / find_references) plus data-flow at each write site's enclosing method; control-flow not meaningful standalone.NamedType (an exception class) — exception-flow only, via trace_exception_flow.NamedType (non-exception) — mutation-site enumeration via find_type_mutations; defer to callers for control/data.Intersect the kind-appropriate set with the user's mode: selector (default all). Use the Mode Selection Table below as the authoritative map.
For each selected analysis, run the corresponding tool against the target descriptor and collect structured results:
analyze_control_flow with the method body (or the sub-span if the target is a specific line). Capture: entry/exit points, branching constructs (if/switch/goto), loop constructs (for/while/foreach), unreachable regions, and early-exit paths (return, throw, yield break).analyze_data_flow with the target span. Capture: variablesDeclared, definitelyAssignedOnEntry, definitelyAssignedOnExit, alwaysAssigned, dataFlowsIn, dataFlowsOut, readInside, readOutside, writtenInside, writtenOutside, captured, capturedInside, capturedOutside, unsafeAddressTaken. If the target is a parameter or local, emphasize its entries in these sets.trace_exception_flow with the exception type (or with each throw site discovered in the control-flow pass when the target is a method). Capture: catch-clause matches, rethrow sites, when filters, and the full call-chain path from throw to catch.callers_callees on the target method (or the enclosing method) to anchor the flow inside the broader call graph. Capture up to N callers (default 10) and callees per the tool response.find_property_writes and, as a cross-check, find_references filtered to writes. For non-exception types, call find_type_mutations to enumerate mutation callsites.Always bound span-scoped analyses. If the selected span exceeds the server-enforced limit or covers an entire file, refuse with the large-span message in Refusal conditions rather than attempting a partial trace.
Merge raw tool outputs into a single in-memory trace record:
file:line) and the matched catch (file:line, caught type, when filter, rethrow status).Render the report described in Output Format. Do not modify any file — this skill is strictly read-only.
| Symbol Kind | Control Flow | Data Flow | Exception Flow | Extra Tools |
|---|---|---|---|---|
| Method / Constructor / Local function / Accessor | Yes | Yes (full body) | Yes (from throw sites) | callers_callees |
| Parameter | Yes (enclosing method) | Yes (param-scoped reads/writes/captures) | No (defer to enclosing method) | find_references |
| Local variable | Yes (enclosing method) | Yes (local-scoped reads/writes) | No | find_references |
| Field | Per write site | Per write site | No | find_references, find_property_writes |
| Property | Per write site | Per write site + accessor body | No | find_property_writes, find_references |
| NamedType (exception class) | No | No | Yes | symbol_search, find_references |
| NamedType (non-exception) | No | No | No | find_type_mutations, find_type_usages |
A mode selector (control / data / exception) filters the row to that column; all runs every cell marked Yes plus the listed extras.
Present a structured trace report with these sections:
## Flow Trace: {target-descriptor}
### Target
- Kind: {SymbolKind}
- Declaration: {file}:{line}
- Containing type: {type}
- Signature: {full signature}
- Mode: {control | data | exception | all}
### Control Flow
- Entry points: {n}
- Exit points: {n} ({return-count} return / {throw-count} throw / {yield-break-count} yield break / {fall-through-count} fall-through)
- Branches: {n} (if/switch/ternary)
- Loops: {n} (for/while/foreach/do)
- Unreachable regions: {n}
- Notes: {any unusual shape — goto, labeled jumps, deeply nested conditionals}
{table of significant nodes: kind, file:line, successors, predecessors}
### Data Flow
- Variables declared: {list}
- Definitely assigned on entry: {list}
- Definitely assigned on exit: {list}
- Always assigned: {list}
- Flows in: {list}
- Flows out: {list}
- Read inside / outside: {lists}
- Written inside / outside: {lists}
- Captured: {list with inside/outside distinction}
{target-focused slice: for a parameter/local, the subset of each set that contains the target symbol, plus a narrative of "where this value goes"}
### Exception Flow
{table: throw site (file:line) → thrown type → catch site (file:line) → caught-as → when-filter → rethrow}
- Uncaught at this method: {list of exception types}
- Caught here: {list}
- Propagates to callers: {list, keyed by caller from Step 4}
### Callers / Callees Context
- Callers ({n}): {table: caller symbol, file:line, call kind (direct / virtual / delegate)}
- Callees ({n}): {table: callee symbol, file:line, call kind}
- Notable cross-project edges: {list}
### Write / Mutation Sites (field/property/type targets only)
{table: site (file:line), enclosing method, assignment kind (direct / compound / out / ref), trigger}
### Summary
- One-paragraph narrative answering the implicit question: "where does this value go?" / "what paths does control take?" / "who catches this?" — grounded in the tables above.
- Follow-up suggestions: e.g., "extract the inner loop with `extract-method`", "apply `refactor` rename across {N} callers", "investigate catch at {file:line} that swallows the exception without rethrow".
Stop and return a clear refusal (do not run flow tools) when any of these hold:
symbol_search / enclosing_symbol returns no candidates, or the disambiguation list is rejected by the user. Report what was searched and suggest a narrower query (fully-qualified name, containing type, or file:line).analyze_data_flow / analyze_control_flow span limit (typically whole-file or >2000 LOC). Refuse and ask the user to narrow to a method, accessor, or specific line range.NamedType that is neither an exception nor referenced by find_type_mutations, or a Namespace / Assembly target. Report the kind and the Mode Selection Table row that rules the target out; suggest an adjacent analysis (e.g., use the analyze skill for a solution-level overview).mode: exception on a plain local variable. Refuse with a one-line explanation pointing at the table, and offer to rerun with mode: all.workspace_status reports initializing / degraded / errors after workspace_load. Bail with the standard connectivity-precheck guidance above.