aicb-roslyn-mcp
Use this server as a local Roslyn/MCP code-intelligence backend for C#/.NET solutions to answer semantic code questions, prepare agent context, and review changes.
Analyze
.sln/.slnx/.slnfsolutions with Roslyn and maintain reusable sessions.Navigate code: find symbols, usages, call graphs, implementations, overrides, hierarchies, signatures.
Assess change impact, blast radius, review context, and verify claims like removed-unused or no-new-API.
Find tests, coverage gaps, dead code, instantiation sites, and DI registrations/injection paths.
Inspect side effects, external API calls, event subscriptions, circular dependencies, concurrency/resource risks.
Analyze XAML/AXAML bindings and resource usages, including unresolved bindings.
Get architecture overviews, public API surface, solution metrics, complexity metrics, and code insights.
Pack task-focused context (
get_context,explain_symbol,pack_for_task,prepare_task) with token budgets.Measure answer sizes, batch read-only queries, export Markdown, and manage snapshots/config.
Install agent hooks/skills, refresh sessions, read docs, and report server/tool usage.
Analyzes C#/.NET solutions (.sln/.slnx/.slnf) using MSBuild and Roslyn semantic models to build a symbol graph of declarations, calls, type references, DI registrations, tests and side effects, then answers caller/implementation/impact questions and renders budgeted, task-focused Markdown context packages for coding agents.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@aicb-roslyn-mcpWhat could be affected if I change ColorMixerService?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
AIContextBuilder (aicb)
Give coding agents a Roslyn-accurate map of your C#/.NET solution. aicb is
a code intelligence server for C# and .NET: it answers questions about callers,
implementations, dependency injection, tests, side effects and change impact,
then packs the relevant code into compact Markdown for an LLM. It runs locally as
an MCP server and CLI; a Windows desktop app adds visual context selection,
analysis and editing.
The software is closed source. This public repository contains its documentation, license and releases. It is free for individuals, education and organizations below the license thresholds.
This page is a short tour, not the reference. It names 35 of the 54 tools an agent sees by default; the three manuals run to 35 chapters, about 37 times the length of this page.
See it answer a code question
Ask your coding agent:
What could be affected if I change
ColorMixerService? Use AICB.
Or call the same tool from a terminal:
aicb call impact_of_change --sln C:/repo/App.sln --arg symbol=ColorMixerServiceAbridged output from the bundled ColorMixer.SelectionLab sample:
{
"symbol": "ColorMixerService",
"resolvedKind": "type",
"directCount": 1,
"transitiveCount": 2,
"risk": "low",
"productionImpactCount": 2,
"directImpact": {
"items": [
{
"name": "DemoCompositionRoot",
"file": "ColorMixer.SelectionLab.ConsoleApp/DemoCompositionRoot.cs",
"line": 9
}
]
}
}The desktop app's MCP Usage page records calls locally and separates guided refusals from suspected defects:

That answer comes from the Roslyn symbol graph, not a substring search. AICB distinguishes overloads, follows interface and override relationships, understands partial types and records DI construction paths.
Related MCP server: Kivgraph
Build context that fits the task
AICB does more than answer individual symbol questions. It can assemble a focused, task-specific context package for an agent instead of sending an unfiltered source dump:
Need | Tool | What it returns |
Read one symbol in context |
| The symbol plus its direct dependencies and callees |
Explore a named symbol with selected surroundings |
| Callers, callees, implementations, tests or other requested dimensions |
Pack context for a natural-language goal |
| Goal-named symbols and their semantic neighborhood |
Prepare to edit |
| The goal-focused context plus covering tests and likely siblings such as a factory or validator |
Check the response cost first |
| The exact token count of one or more planned tool answers, without returning their large payloads |
The focused context tools accept a token budget, so a package fits the room your agent has. The symbols you name stay in; when the budget is tight, the package becomes less detailed around them instead of being cut off in the middle of a block, and a leading note says which types, tests or siblings were left out. AICB can therefore tell you that a bundle was reduced or capped; it cannot certify that what remains is enough to solve the task correctly. Whole-document rendering can use the same budget through a pipeline profile, with an allowance for overshoot and an optional report of what was trimmed.
The result is AI-Builder-MD: structured Markdown for an LLM, containing the selected code together with symbol relationships, architecture graphs, semantic metadata and provenance. It can use the established tag notation or YAML. See the context-document guide and the task-packing tools.
Add explicit meaning with AI Tags and semantic annotations
AICB works without annotations. Where source structure and conventions are not
enough, optional <ai> tags in XML documentation let a developer state the intended
role of a type or method explicitly:
/// <ai
/// role="service"
/// layer="Application"
/// responsibility="Coordinates order validation and submission."
/// stability="Stable"
/// />
public sealed class OrderServiceAnnotations can describe semantics such as role, domain, architectural layer,
priority, stability, responsibility and side effects. Explicit values take
precedence over heuristic inference; sentinel values such as none can deliberately
suppress inference for one field. AICB preserves provenance so an agent can
distinguish source-derived facts, author-provided meaning and inferred hints. The
AI annotation reference
documents the supported forms and fields.

How analysis and memory work
.sln / .slnx / .slnf + C# + XAML/AXAML
↓
MSBuild + Roslyn semantic models
↓
AICB facts and consolidated semantic indexes
↓
individual answers or budgeted AI-Builder-MDAICB is more than a response cache around Roslyn. During analysis it walks the solution's C# documents, records declarations, calls, type references and other facts, then consolidates caller and type fan-in, implementations, resolved markup references and transitive side-effect classifications. Tools traverse or project that warm model for a particular question; context tools select and render a task-specific slice. This does not mean that every possible answer or runtime relationship is precomputed.
An MCP session belongs to one aicb mcp process and pins both the analyzed graph
and its Roslyn workspace. A second server process builds its own session. The
desktop app, CLI and MCP server use the same analysis and rendering engine and can
share configuration and persisted snapshots through the local database, but they
do not share one live in-memory graph. Within one session, only one refresh runs at
a time; concurrent callers join it. A source-only edit can take the incremental
path, replaying changed document text without reloading the workspace. When that
path is unavailable, or when force: true is requested, AICB fully reloads it.
Live sessions, snapshots and persistent codebase memory
These states serve different purposes and should not be treated as interchangeable:
State | Lifetime and purpose | Important boundary |
Live MCP session | In-memory graph and Roslyn workspace reused by one server process | Sees saved files, not unsaved editor buffers; another server process has a separate session |
Remembered codebase |
| A recalled session has no live workspace, no reliable line numbers and a reduced insight contract; use |
Saved snapshot | Named baseline used by | A comparison baseline, not a live workspace |
| Git-trackable solution configuration | Contains rules and choices, never analysis results, sessions or credentials |
remember_codebase, recall_codebase and refresh_remembered are opt-in tools: no
MCP profile exposes them, so start the server with AICB_MCP_TOOLS naming them (or
AICB_MCP_TOOLS=all). recall_codebase reports whether the persisted model still matches the source,
payload schema and analyzer identity. It deliberately returns the recalled model
even when it is stale, with metadata that tells the agent when a live re-analysis
is necessary. See sessions, recall and staleness.
What the model can and cannot prove
AICB analyzes statically visible C# and selected XAML/AXAML relationships. Code reached only through reflection, runtime assembly scanning, dynamic configuration or an external consumer can remain invisible.
DI analysis recognizes statically readable Microsoft-DI-shaped registrations; runtime-produced registrations are disclosed as dynamic or unknown rather than invented.
XAML binding analysis resolves paths only where the source and data type are safe to establish. Unknown scopes are skipped conservatively.
A reported side effect is a conservative static contact classification propagated through known call edges. It is not general data-flow, taint or runtime state analysis.
Responses disclose stale sessions, unresolved projects and capped result sets. Read
staleness,incompleteProjects,totalFoundandtruncatedbefore treating an empty or short answer as proof.
How an agent should judge an answer
An AICB response is evidence together with its limits. Before acting on an empty, short or apparently definitive result, inspect the accompanying signals:
Signal | Meaning | Typical response |
| Saved source changed after the analysis, or an automatic refresh ran or failed | Save the files and refresh if the response is not current |
| Project references could not be resolved well enough for a complete semantic graph | Restore or build, then call |
| More matches exist than were returned | Narrow the scope, paginate or raise the documented cap |
Bundle manifest or leading omission note | A token budget removed surrounding types, tests or sibling implementations | Increase the budget or request the missing axis explicitly |
| A name did not resolve to one unique symbol | Repeat the query with a qualified symbol name |
| A value is measured, author-supplied, inferred or not statically knowable | Preserve the uncertainty and verify the relevant runtime configuration when needed |
| The answer came from persisted memory rather than a live Roslyn workspace | Use |
The MCP profile controls automatic refresh. Off only discloses drift,
Reactive refreshes before a reading tool answers and is the normal shipped
setting, while Proactive starts analysis after saved edits settle. Automatic
refresh never sees unsaved editor buffers. Staleness is also different from
reference incompleteness: the first needs a refresh; the second normally needs a
restore or build followed by a forced refresh.
AICB also distinguishes unknown from verified absent. Tools such as
assert_absence return confirmed, refuted or indeterminate rather than
turning missing evidence into a false negative.
The question-first architecture, limits and evidence guide explains what lives in memory, how refresh and context selection work, which claims are measured, and where the published scale benchmark stands.
Where it helps
Question | Tool |
Who calls or uses this? |
|
What is the blast radius of a change? |
|
Where is this interface implemented or overridden? |
|
Which tests exercise this symbol? |
|
What gets injected here? |
|
Which code has side effects or calls an external API? |
|
What context does an agent need for this task? |
|
How large would these answers be before I pull them? |
|
Where is this property or resource used in XAML/AXAML? |
|
Which markup bindings cannot be resolved safely? |
|
What changed between two analyzed states? |
|
Does this change set violate a policy or public contract? |
|
Is the claim that this symbol is unused, untested or absent actually supported? |
|
What evidence should a reviewer see for these changed symbols? |
|
Where are concurrency, resource-lifetime or event-subscription risks? |
|
Where did repeated structures, conventions or documentation drift apart? |
|
The default profile exposes every tool in this table except semantic_diff,
diff_review, find_by_concurrency_risk, find_by_resource_leak,
find_structural_twins, check_pattern_drift and check_doc_drift, which need the
Full Select profile, and compare_public_api, which is opt-in (see
Tool sets and Agent Skills).
These tools form a broader capability map rather than a flat search catalog:
Capability | Examples |
Semantic navigation | usages, implementations, overrides, hierarchy, DI and XAML |
Change safety | impact, tests, diagnostics, review context and public API comparison |
Runtime-risk indicators | concurrency, resources, events, external calls and side effects |
Architecture and consistency | layers, cycles, structural twins, pattern drift and documentation drift |
Verification | negative claims, baseline-to-changed claims and change-set policy |
Context economy | task packing, measurement, token budgets and compression |
The desktop app turns code-quality, security, design and architecture findings into an actionable review queue:

AICB is most useful for non-trivial C#/.NET solutions and semantic questions that plain text search cannot answer reliably. It analyzes C#; selected XAML/AXAML relationships supplement that graph. Other programming languages are out of scope.
Multi-targeted projects are loaded once per target framework by default, while
query surfaces generally deduplicate them to one logical project. Setting
analyzePreferredTfmOnly in <Solution>.aicb.json reduces analysis and export work
to the newest target-framework instance. The symbol inventory remains available,
but fan-in edges that exist only in another target can disappear, so this is a
documented precision-versus-cost choice rather than a transparent optimization.
A safe agent workflow
An agent can use AICB without memorizing the tool catalog:
Call
server_infoto verify the connection and detect binary or configuration drift. Uselist_skillsfor the complete capability map ordocs()for the built-in operating manual.Start an edit task with
prepare_taskto collect the named symbols, relevant context, covering tests and likely sibling implementations within one budget.Before changing a symbol that other code names, call
impact_of_change; usefind_tests_forwhen the task bundle does not give enough test evidence.Read uncertainty and completeness signals before treating an empty result as proof. Qualify ambiguous symbol names; restore and force-refresh incomplete projects.
Make and save the change. Then call
refresh_sessionbeforeget_diagnostics. Under the normalReactiveprofile this is usually redundant, but it remains correct in every mode and makes the intended boundary explicit.Use
review_context,evaluate_change_setorverify_claimwhen the task makes a review or policy claim; do not infer absence merely from a short search result.Finish with the repository's real build and test commands.
get_diagnosticsreports Roslyn compiler diagnostics, not third-party analyzer or runtime results.
For several independent read-only questions, batch reuses one session and returns
one bounded response. Use measure first when the likely response size matters.
Reproducible analysis, CI and review
Need | AICB workflow |
Version the portable solution rules | Commit |
Enforce a quality threshold in CI | Run |
Compare an in-place change with a baseline | Call |
Review two live analyzed states |
|
Reuse an analyzed model across processes |
|
Curate context visually | The Windows app adds a solution tree, manual context selection, detail and token controls, AI-Builder-MD preview/export, snapshots, Insights, LLM runs and a source editor. |
In GitHub Actions the gate is one step. The action at the root of this repository sets up
the .NET 10 SDK, installs the published tool, restores the solution and runs
aicb analyze; a failed gate fails the step with exit code 6, and the document is still
written:
- uses: gregordadera/aicb-roslyn-mcp@v0.5.503.1
with:
version: 0.5.503.1
solution: App.sln
output: artifacts/context.md
fail-on: "critical>0 OR debt>120min"The example pins both halves: @v0.5.503.1 fixes the action, version fixes the package it
installs. Without version the action installs the newest published package, and @main
follows every change to the action, so neither belongs in a build you depend on. A release
tag can in principle be moved; the full commit SHA of that tag is the immutable form. Further
inputs are dotnet-version, restore and args for other
aicb analyze options; the outputs are output and exit-code. See
action.yml.
Configuration precedence is axis- and surface-specific. For example, headless layer
mapping can fall back to the sidecar, while headless test detection currently resolves
from the database or built-in rules rather than the sidecar's test axis. The exact
matrix is in the
configuration guide.
A running MCP session keeps the configuration it was analyzed with; after editing the
sidecar, start a new analysis instead of assuming refresh_session re-reads it.
Suppressions hide accepted findings from suppression-aware reading surfaces, but
solution_metrics and the CLI quality gate continue to count them. A shared
suppression is therefore an explicit review decision, not a way to lower the gate.
From semantic engine to human-in-the-loop workspace
The MCP server is currently AICB's most complete and operationally mature integration surface. Its 82 registered tools cover semantic navigation, change impact, dependency injection, test discovery, architecture, quality, context packing, review and session management. Profiles expose a curated 54-tool default or the 72-tool Full Select set, while sessions, staleness signals and bounded responses make the surface practical for coding agents. These numbers describe the available product surface; they are not a published benchmark of agent outcome quality.
The active MCP profile also selects task-oriented facets: each facet connects agent
guidance, a context-template slot and the corresponding tool subset. list_skills
is the runtime source of truth for which tools are exposed, which are callable, and
which additional registered tools sit outside the active pool.
The Windows app complements that agent-facing surface with a visual workspace for people: solution navigation, manual context selection, detail and token controls, AI-Builder-MD preview and export, snapshots, Insights, reusable configuration and manual LLM runs.
Quality and solution-specific analysis profiles
A Quality Profile controls which insight producers run and the thresholds they use, such as method length, cyclomatic complexity and class size. It does not by itself define finding severity or the CLI quality gate.

Each solution also has three independent analysis axes:
Axis | Question it answers | What it controls |
Layer Profile | Where does this code belong architecturally? | Ordered namespace-pattern-to-layer mappings for layers such as Domain, Application and Infrastructure. The first matching rule wins. The profile also determines whether a detected cross-layer violation is |
Exclude Namespaces | What should stay outside the analysis? | Named namespace patterns skipped by the analyzer, using |
Test Profile | What counts as test code? | Project-name rules plus method-attribute markers. The built-in profiles recognize xUnit, NUnit and MSTest conventions, and production-focused tools can exclude the detected test code by default. |
The desktop app presents these three pickers side by side for the selected solution. The Settings pages are the library editors; the Workspace pickers choose which library entry applies to this particular solution. A per-solution choice wins over the global default.

Initialize the three axes
For a freshly registered solution, all three auto-init flags start enabled. The next time the desktop Context Builder loads it, AICB attempts each still-unconfigured axis. If a sidecar already covers an axis, the GUI offers to restore it without a model call. Otherwise, with a usable default model profile, one LLM request proposes layer rules and exclusions from declared and referenced namespace lists; test detection is derived locally from the analyzed projects and test attributes. The confirmation dialog decides whether the proposal is applied - the LLM request has already happened at that point. A missing model profile, no detected tests, or declining the proposal can leave an axis unconfigured. Existing choices are never overwritten.
Successful GUI auto-initialization stores the chosen profiles in the local database.
It does not create <SolutionName>.aicb.json automatically. Use Workspace → Profiles → Export Config to write that portable sidecar, then commit it. A later GUI
can restore the supported axes from it without an LLM call; headless consumers apply
the per-axis rules described in the configuration matrix. Initialize Now performs
only an immediate sidecar restore - it does not call a model or analyze the solution.
An agent can guide the same setup explicitly:
solution_config_statusreports which axes are initialized and whether their active values come from the local database, the sidecar or neither.init_solution_configreturns proposal material: declared namespaces for the layer map, referenced namespaces for exclusions, and detected test projects and attributes for the test profile.After reviewing or adapting that proposal,
apply_solution_configcreates and activates the custom entries, marks the axes initialized and writes both the local configuration database and<SolutionName>.aicb.jsonbeside the solution.Commit the sidecar so the portable solution configuration travels with the repository. Each consumer applies the supported axes described above; do not assume every surface resolves every field identically. Later,
check_solution_config_driftreports namespaces or test projects no longer covered by that configuration.
aicb init is a different operation: it connects a repository to the MCP server
and installs the agent skill and optional symbol guard. It does not initialize
these three solution axes or create <SolutionName>.aicb.json.
See profiles and solution configuration for precedence, the sidecar schema and the full initialization behavior.
Context templates and run templates
The two template types have different responsibilities:
Template type | Purpose |
Context Template ( | Defines what goes into an export: prompt, Markdown profile, detail presets, expansion strategies, compression, quality settings and export switches |
Run Template ( | Defines how a task is executed: run type, selected context template, model defaults and run-specific options |
Detail Presets, Markdown Profiles, Expansion Strategies, Compression Rules, Pipeline Profiles and Quality Profiles are reusable building blocks referenced by a context template; a run template selects that context template.

Product direction, not a release commitment
The direction for the desktop app is a human-facing orchestration workspace: a
developer selects and constrains context, inspects intermediate results, approves
decisions and controls what an AI model runs next. Manual is the released run
type today. Iteration is intended to process selected nodes one by one, and
Preselection to let a model narrow the relevant context before the main run;
both are represented in the application but are not released yet. Pipeline
currently exists only as a placeholder in the data model and executes nothing.
Install
Install one form per machine:
You want | Install | Platform |
MCP server and CLI | Windows, Linux, macOS | |
Desktop app plus the same MCP server and CLI | Windows |
The .NET tool needs the .NET 10 SDK. Without .NET 10 it runs on the next newer .NET on the machine and needs that version's SDK. A machine that has only .NET 8 or .NET 9 cannot start it.
dotnet tool install -g aicb-roslyn-mcp
aicb --versionUp to 0.5.465.1 the package was called AIContextBuilder. An update does not cross that
rename: remove the old package first, then install the new one as above.
dotnet tool uninstall -g AIContextBuilderUpdate it later with dotnet tool update -g aicb-roslyn-mcp. For a container, the
repository's Dockerfile
installs the same .NET tool and serves MCP over stdio. The container runs as a non-root
user, and analysis writes obj/ into the mounted solution, so run it as the owner of the
mount and restore the solution inside the container first:
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/src" \
-v aicb-nuget:/home/aicb/.nuget/packages --entrypoint dotnet aicb restore /src/App.sln
docker run --rm -i --user "$(id -u):$(id -g)" -v "$PWD:/src" \
-v aicb-nuget:/home/aicb/.nuget/packages aicbThe Dockerfile header explains why the restore has to run in the container.
If the tool reports that MSBuild could not be registered, the .NET it runs on found no SDK it
can use: an SDK newer than that .NET does not count (for example a .NET 10 runtime next to only
the .NET 11 SDK). Install the .NET 10 SDK; beside a .NET 10 runtime the .NET 8 and .NET 9 SDKs
work as well. Or set the environment variable DOTNET_ROLL_FORWARD=LatestMajor so that the tool
runs on the newest .NET - a preview .NET additionally needs
DOTNET_ROLL_FORWARD_TO_PRERELEASE=1.
The Windows downloads are self-contained, but analyzing a solution still needs MSBuild from a .NET SDK or Visual Studio. The installer and the programs are code-signed (publisher: Gregor Dadera); Windows SmartScreen can still warn about a new release until it has enough download history. Every release provides SHA-256 checksums.
Connect a coding agent
Run this from the project you want the agent to work on:
aicb initIt writes .mcp.json, the MCP configuration Claude Code reads, and the
aicb-csharp-context agent skill under .claude/skills/, without overwriting
existing files. If the project uses Codex or OpenCode (a .codex/ or .opencode/
folder), it also registers the server in that client's own configuration and
writes the skill to .agents/skills/, where both read skills. If it detects
Claude Code, Codex or OpenCode project configuration, it also installs a
symbol guard that blocks C# symbol searches by grep and redirects the agent
to the semantic tool. This intentionally changes agent behavior. Opt out with:
aicb init --hooks none--hooks none skips only the guard; the server is still registered. To wire a
client whose folder does not exist yet, name it: aicb init --hooks codex or
aicb init --hooks opencode.
Client-specific status:
Client | MCP setup | Skill and guard |
Claude Code |
| Skill and optional guard installed |
Codex |
| Skill in |
OpenCode |
| Skill in |
Cursor / Cline / other stdio clients | Add command | Use the published skill if the client supports Agent Skills |
Manual .mcp.json configuration for clients that read it:
{
"mcpServers": {
"aicb": {
"command": "aicb",
"args": ["mcp"]
}
}
}Verify the connection by asking the client to call server_info. Every analysis
tool accepts an absolute .sln, .slnx or .slnf path as its session, so no
separate analyze step is required. See the five-minute guide
for setup, first questions and troubleshooting.
Tool sets and Agent Skills
Set | Size | Purpose |
Default MCP profile | 54 tools | Curated semantic and structural tools for normal agent work |
Full Select profile | 72 tools | Default set plus the measured long tail |
Complete server surface | 82 tools | Full Select plus the opt-in session-memory, database and API-comparison tools |
This README names 35 of the 54 default tools; the references below describe all of them.
Start the Full Select profile with
aicb mcp --mcp-profile mcp-profile/full. Set AICB_MCP_TOOLS=all to add
the opt-in tools as well. The generated tool reference documents
the default set; the MCP server manual
documents all 82 tools and their parameters, and alongside them sessions and
staleness, profiles, pools and facets, and what aicb init writes - twelve
chapters in Markdown, readable in the browser and by an agent, and also
published as a PDF.
The three published counts are starting points, not fixed editions. In the
desktop MCP Profiles editor you can create or duplicate a profile, enable only
the task facets you want, and select individual core and facet tools. Every core
tool can be removed except the locked diagnostic server_info, so even a very
small task-specific tools/list is possible. The server's fixed lead-in is
standing agent guidance, not another selectable tool group. For headless setup,
AICB_MCP_TOOLS=methods:<tool>,<tool>,... exposes exactly the named functions;
class lists, lean and all are also supported. Profile and environment changes
take effect at the next server start. list_skills shows the resulting in-pool and
out-of-pool tools. See profiles, pools and facets.
Four Agent Skills ship in skills/:
aicb-csharp-contextroutes semantic C# questions to the right tool.aicb-code-reviewchecks a completed change for correctness.aicb-code-simplifierlooks for unnecessary complexity.aicb-usage-checkreports what this server was actually reached for.
The last three are opt-in: aicb init --skills=all.
Scale, releases and compatibility
AICB has no published hard project-count limit. Initial cost and peak memory are
solution-specific and grow with loaded projects, documents, target-framework
instances and graph density. The first analysis can take seconds to minutes;
subsequent questions reuse the warm graph, and eligible saved-source edits use the
incremental refresh path. For a very large repository, use a .slnf to reduce what
MSBuild loads and optionally set analyzePreferredTfmOnly to avoid analyzing every
target-framework instance. summaryOnly, query scopes and token budgets reduce
response volume; they do not necessarily reduce the underlying solution analysis.
The desktop load-perf.log and MCP usage_report provide local phase and latency
measurements. A standardized cold/warm time and RAM benchmark on three public
.NET solutions (≈ 25k, ≈ 55k and ≈ 1.8M lines of C#) is published in the
architecture and evidence guide;
these controls are still not a universal performance claim, but there is now a
measured boundary.
Public releases currently have no declared LTS window, response-time SLA or promise
that every MCP response and persisted schema remains unchanged across versions.
Operational safeguards are explicit instead: the changelog records releases;
server_info reports version, build and configuration drift; persisted analyses
carry payload-schema and analyzer identities and fall back to a live analysis when
they are incompatible; and the desktop refuses to write a database created by a
newer schema. Database migrations can be one-way, so a reliable rollback means
backing up before an update and using the older build with a separate or restored
pre-migration database. Commercial agreements can define stronger support,
response-time and version-maintenance commitments where required; see
Support.
CLI at a glance
aicb init Connect a project to the MCP server and install the agent skill.
aicb analyze Analyze a solution and emit context Markdown.
aicb export Re-render Markdown from an existing session database.
aicb import Import a constellation JSON.
aicb list List built-in and custom profiles and presets.
aicb mcp Start the stdio MCP server.
aicb call Invoke one MCP tool without an MCP client.Run aicb <command> --help for options.
Local by default
The CLI and MCP server have no outbound network capability and do not modify the source code they analyze.
There is no outbound telemetry, analytics, update check, account or license server. The MCP server records its tool calls locally for
usage_reportand the desktop app's MCP Usage page; that log never leaves the machine.The desktop app can contact only an LLM endpoint you configure: for a manual run, a model-profile connection test, or first-load proposals for Layer Profile and Exclude Namespaces when those auto-init flags are armed. The endpoint may be a local model. The Details tab is also a real editor and saves a file only when you explicitly use Save.
Opening a solution runs its MSBuild logic to resolve references, and building its compilation runs the source generators its projects reference, as in an IDE or
dotnet build. Analyze only solutions you trust. AICB does not run third-party Roslyn analyzers.
A small number of explicitly named tools can write configuration or an export;
their tool descriptions state this. The complete threat model and private
reporting route are in SECURITY.md.
License at a glance
Use is free for:
private, hobby and educational use by natural persons,
accredited educational institutions for teaching, learning and non-commercial research,
organizations that reach none of these thresholds: 100 employees, EUR 10 million annual turnover, 21 developers.
The thresholds apply to your organization, not to your clients. After first
reaching any one threshold, you have 90 days to agree a commercial license; use
remains free during that period. The 90 days are contractual text only: AICB
starts no license timer, sends no threshold or deadline data, blocks no feature
and does not technically stop working when the period ends. Commercial licenses
start at EUR 25 per licensed developer per month; the exact price and scope depend
on the number of users, the requested support level and any agreed priority for
improvement requests. A commercial agreement can include support, defined response
or maintenance commitments, prioritized consideration or
implementation of improvements - for example, making a generally useful analyzer
handle patterns found in the customer's code more accurately. Such work improves
the general AICB product; it does not create a customer-specific fork or specialize
AICB to one codebase. Customer code is never collected or used for improvement
automatically; examining it requires material or access deliberately provided by
the customer and a separate agreement on scope and confidentiality. Exact
deliverables, priorities and guarantees exist only when written into the individual
agreement. Connecting AICB to MCP clients, agent harnesses, scripts, build systems
and CI through its documented interfaces is permitted. Redistributing, modifying,
repackaging, reselling or offering the AICB binaries as a hosted service is not.
Contact aicb@dadera.de. See the plain-language guide,
LICENSE.txt and the full bilingual EULA.md.
Support and continued development
AICB is under active development: the changelog records every release, and published releases appear on the Releases page.
Support follows the license:
Free | Commercial agreement | |
Who | Everyone below the thresholds | Organizations at or above a threshold, or anyone who wants stronger terms |
Channel | Direct contact plus the public channels | |
Response target | Best effort | ≤ 2 business days |
Security fixes | Shipped through public releases | Fix target ≤ 10 business days for confirmed vulnerabilities |
Version maintenance | Current release | Individually agreed maintenance window |
Improvement requests | Community-driven | Prioritized consideration; agreed priorities are written into the contract |
Source access | None | Code review under NDA can be agreed |
The targets in this table are typical values an individual agreement can include;
they bind only when written into the agreement, and payment alone creates no
unstated SLA. Prices are in License at a glance. Contact
aicb@dadera.de.
Questions and feature requests are welcome in
GitHub Discussions. Report bugs
through GitHub Issues and include
aicb --version and, for MCP problems, the output of server_info. Report security
issues privately as described in SECURITY.md.
Documentation
Everything above is the short version. The three manuals below hold the full reference - 35 chapters, each manual 70,000 to 80,000 words, together about 37 times the length of this README.
Getting started - install, connect and ask the first question
Tool reference - generated reference for the default MCP profile
Architecture, limits and evidence - in-memory model, refresh, context selection, static-analysis boundaries and benchmark status
MCP server manual - the full reference in twelve Markdown chapters: connecting a client,
aicb init, sessions and staleness, profiles and facets, every tool, troubleshootingGeneral reference manual - the full reference in twelve Markdown chapters, with the printable PDF in the same folder
Desktop app reference manual - the full reference in eleven Markdown chapters, with the printable PDF in the same folder
"AIContextBuilder" and "AIContextBuilder for .NET" are product names used by Gregor Dadera; no registration is claimed.
Available Tools
54 toolsanalyze_solutionAnalyze a SolutionA
Analyze a C#/.NET solution (.sln, .slnx or .slnf) with Roslyn and cache the result as an in-memory session - the entry point of this server: it returns the session_id the other tools take as sessionId.
Calling it is optional: every tool that takes a sessionId also accepts the absolute solution path and analyzes on first use, so do not call it just to run a query. Call it to read this answer first or to pass layerProfile / dbPath. After editing .cs files call refresh_session, not this: a second analyze_solution is a full reload into a new session.
Returns JSON: sessionId, solutionPath, solutionName, projectCount, fileSetHash, layerProfile, lastAccessUtc, origin, lineNumbersAvailable - plus, only when they apply, analyzePreferredTfmOnly, incompleteRun, configInit (config axes still to set up; see solution_config_status) and agentWiring (the agent's guard hooks are missing here).
When a scanned project could not bind even its core framework types (for example a missing targeting pack), the answer carries incompleteRun - how many, which, and the repair - because every later answer of the session inherits that shortfall. Its absence is no all-clear: an unrestored project that still binds its framework is not flagged here; get_diagnostics names its errors.
It changes no source or project file: it opens the solution through MSBuild (whose design-time build can write generated files under obj/), reads the files as they are on disk (uncommitted edits included) and keeps the model in server memory - by default for 90 minutes after the last use, at most 8 sessions. A large solution can take minutes; with a client progress token it reports progress.
Parameters: normally pass only solutionPath; layer profile, namespace exclusions and test profile then come, per axis, from the server's config DB, else the committed .aicb.json beside the solution, else built-in heuristics. layerProfile overrides the layer axis only; dbPath reads all three from another config DB.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional absolute path to a config/master DB. When given, the DB's CONFIGURED namespace-exclusion list (per-solution row, else app-global default) is applied during analysis, same as the CLI; where the DB configured none, the committed .aicb.json sidecar's list applies, and only without a sidecar the DB's built-in default (a built-in default is not configuration - solution_config_status names the list in force and its source); the DB's active test-detection profile (per-solution > global > default) is resolved for the session so the test-aware tools (find_dead_code / coverage_gaps / symbol_metrics / find_tests_for / find_by_side_effects / assert_absence / prepare_task / list_insights / get_insight / solution_metrics) honor it; AND - unless an explicit layerProfile is given - the DB's active layer-mapping profile (per-solution > app-global) drives the analysis (dependency-graph layers + LAYER_MAP), matching the insights/metrics/CLI-gate path. All three travel with the session, so downstream tools honor them without re-passing dbPath. Omit to use the server's default config DB (the same one the GUI uses), if the server resolved one - so the GUI's per-solution exclusions + test + layer profile apply automatically; else the DB-free default (the built-in exclusion list, default test heuristic, role-based layers). When a config DB is resolved and a config axis (layer/exclusions/test) is not yet initialized via the guided setup, the response carries a configInit hint pointing to solution_config_status. | |
| layerProfile | No | Optional absolute path to a layer-mapping profile JSON. Omit to use the config DB's active layer profile (per-solution > app-global) when a config DB is resolved, else the .aicb.json sidecar's profile, else role-based heuristics. | |
| solutionPath | Yes | Absolute path to the solution file to analyze (.sln, .slnx or .slnf). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only supply boolean hints; the description explains the non-read-only hint by disclosing that MSBuild design-time builds can write generated files under obj/, that sources are read as-is on disk, and that the model lives in server memory (90-minute idle TTL, max 8 sessions). It also adds cost/latency context (minutes on large solutions, progress token) and the non-idempotency rationale (a second call is a full reload into a new session), which is exactly the context the hints alone cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then call-avoidance, return shape, edge-case flag, behavior, and parameters in a sensible order; each paragraph carries distinct information. It is dense and long for a 3-parameter tool, with some clauses (the incompleteRun and configInit passages) that take effort to parse, but little is genuinely redundant with the structured fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description correctly enumerates the returned JSON fields, flags which are conditional (analyzePreferredTfmOnly, incompleteRun, configInit, agentWiring) and warns that an absent incompleteRun is not an all-clear, routing the agent to get_diagnostics. For an entry-point tool with three-way config resolution this is complete enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real decision guidance beyond the schema: 'normally pass only solutionPath' and the per-axis precedence chain (config DB > committed .aicb.json > built-in heuristics), plus the scoping note that layerProfile overrides only the layer axis. It largely consolidates what the verbose schema descriptions already say, which keeps it short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Analyze a C#/.NET solution (.sln, .slnx or .slnf) with Roslyn') and pins its identity as 'the entry point of this server', explicitly contrasted with refresh_session and with the tools that accept sessionId. An agent can place it among 50+ siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-not guidance ('Calling it is optional... do not call it just to run a query'), explicit when ('Call it to read this answer first or to pass layerProfile / dbPath'), and names the alternative for the edit case ('After editing .cs files call refresh_session, not this'). Nothing about selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
apply_solution_configApply a Solution ConfigurationADestructive
Apply a proposed Layer Profile + Exclude-Namespaces + Test Profile configuration for a solution. Creates a new custom layer profile / exclusion list / test profile (tagged with the source solution for provenance), activates them, and marks each touched slot initialized. proposalJson is a JSON object {"layerRules":[{"pattern":".Application.","matchType":"Contains","layer":"Application"}],"exclusions":[{"pattern":"System.","matchType":"StartsWith"}]}; the test axis is given via testProposalJson {"testProjectRules":[{"pattern":".Tests","matchType":"EndsWith"}],"testAttributeNames":["Fact","Theory"]} (rules match PROJECT names) OR via testPreset = xunit|nunit|mstest|default. At least one axis must be non-empty (empty arrays/slots are skipped). matchType is Contains|StartsWith|EndsWith|Exact (an invalid matchType is rejected, not silently defaulted). An exclusion with "keep":true is a keep rule: a namespace it matches is never excluded; exclusions that are all keep rules leave the built-in list in force; the sidecar stores keep rules under "keepNamespaces". Writes to the config/master DB (the given dbPath, or the server's default - the GUI's - if omitted; created if missing) AND to the git-tracked .aicb.json sidecar next to the .sln (returned as sidecarPath - commit it so the config travels with the repo). An axis this call does not name keeps what the existing sidecar holds for it, and keys it does not know stay as they are. An existing sidecar that cannot be read (malformed, locked) is never rewritten: the call is refused before anything is written, and a file that becomes unreadable while the DB is written is left as it is too (the DB keeps the configuration, a warning says so); a keep rule the file puts inside 'exclusions' is moved to 'keepNamespaces'. A keep flag that is not a JSON boolean is rejected.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Absolute path to the aicb config/master SQLite DB to write the configuration into (created if missing). Omit to use the server's default config DB (the same one the GUI uses), if the server resolved one. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| testPreset | No | Optional shortcut: clone a built-in test profile (xunit|nunit|mstest|default) into a custom per-solution profile. Mutually exclusive with testProposalJson. | |
| proposalJson | No | Optional layer/exclusion proposal as a JSON object with 'layerRules' and/or 'exclusions' arrays (see tool description). Omit for a test-only apply. | |
| layeringPolicy | No | Layer-mapping policy for the new profile: 'Advisory' (default) or 'Strict'. | |
| testProfileName | No | Optional display name for the created test profile. Omit for an auto-generated name. | |
| layerProfileName | No | Optional display name for the created layer profile. Omit for an auto-generated name. | |
| testProposalJson | No | Optional test-axis proposal as a JSON object {"testProjectRules":[{"pattern":".Tests","matchType":"EndsWith"}],"testAttributeNames":["Fact","Theory"]}. testProjectRules match PROJECT names. Mutually exclusive with testPreset. | |
| exclusionListName | No | Optional display name for the created exclusion list. Omit for an auto-generated name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare destructive/not-readOnly/not-idempotent; the description goes well beyond by disclosing dual writes to the DB and the git-tracked sidecar (with sidecarPath and a commit recommendation), refusal-before-write semantics for malformed or locked sidecars, a warning path when the file becomes unreadable mid-write, and keep-rule relocations between 'exclusions' and 'keepNamespaces'. It also states validation behavior (invalid matchType rejected, non-boolean keep flag rejected).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence front-loads the action well, but the remainder is one very long unbroken paragraph mixing core behavior, JSON examples, and edge-case error handling. Some JSON example content duplicates what the schema property descriptions already show for testProposalJson, so a portion of the text does not earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, dual-target write tool with nine parameters and no output schema, the description covers what an agent needs: what gets created and activated, where it is written, the returned sidecarPath, the commit obligation, and the failure modes that abort or partially succeed. The remaining gaps (naming parameters, layeringPolicy) are fully carried by the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so a 3 is the baseline, but the description genuinely adds meaning the schema lacks: literal JSON shapes for proposalJson and testProposalJson, the matchType value set (Contains|StartsWith|EndsWith|Exact) even though no schema enum exists, the fact that test rules match PROJECT names, and the keep/keepNamespaces semantics. Only the naming parameters (layerProfileName, exclusionListName) and layeringPolicy get no extra treatment.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: it applies a proposed layer/exclusion/test configuration and creates plus activates the corresponding profiles and sidecar entries. The scope (DB + git-tracked <SolutionName>.aicb.json, slots marked initialized) is concrete. It never names a sibling such as init_solution_config or check_solution_config_drift to draw the boundary explicitly, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives operational rules for using the tool correctly (at least one axis must be non-empty, testPreset is mutually exclusive with testProposalJson, an axis not named retains the existing sidecar value), which implies when it is applicable. However, it never says when to prefer this over siblings like init_solution_config or solution_config_status, nor does it state prerequisites or exclusions relative to alternatives. Usage is inferable but not routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
architecture_overviewGet Architecture OverviewARead-onlyIdempotent
Orient on a whole solution WITHOUT the firewall of full source. When anything was cut, the document LEADS with a block: how many sections were capped, how many entries are shown of how many in total, and one 'SECTION: shown of total' row per capped section - read it before the sections, because the per-section '+N more' lines below state one section's loss each and never the whole. Absent = nothing was cut. Renders a structural-only AI-Builder-Markdown overview: the macro/architecture graphs (layer map, service & class dependency graphs, role graph, entry points + entry-point flow, architecture flow, interface relations) plus a domain summary and a quality-hotspots section (the most complex methods + most-coupled types) - but NO per-type/per-file source-code blocks, so it stays bounded where export_markdown is a 27-29 MB firehose. BOUNDED AT SCALE: each macro section is capped at 80 entries with a '+N more' note; the layer map lists every type up to 2000 and per-layer counts above, so even a 200+-project monolith returns a usable orientation instead of overflowing the token cap (use export_markdown for the full set, or find_symbol / call_graph / get_context to drill in). PRODUCTION-FOCUSED: test projects are excluded by default (an architecture overview is otherwise dominated by every test method listed as an entry point + its flow trace, which is not part of the production architecture) - set includeTests=true to include .Tests/.Spec projects. Method-level call graphs are deliberately omitted (use call_graph / explain_symbol for a specific symbol). Multi-TFM solutions are deduplicated to one logical project per name, keeping the NEWEST TFM's instance (without it every hotspot/edge appears once per TFM). Recall-safe: works on live AND recalled sessions (on a recalled session quality-hotspot line counts are unavailable, complexity is still shown). Use this FIRST to understand a codebase's shape, then get_context / explain_symbol to drill into a symbol.
| Name | Required | Description | Default |
|---|---|---|---|
| lean | No | Lean mode (default TRUE): drop the <AI_CONTEXT_SPEC>/<AI_CONTEXT_META> format-rules preamble and any empty graph sections. Set false for the full AI-Builder-MD document contract. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| summaryOnly | No | Summary mode (default FALSE): collapse each macro-section to a count + top-N entries instead of up to 80. Use on EXTREME/very-large solutions (200+ projects, heavy generics) where even the bounded overview exceeds the token cap and would otherwise return nothing. | |
| includeTests | No | Include test projects (default FALSE - production focus: an architecture overview is otherwise flooded by every test method listed as an entry point + its flow trace, bloating the output with scaffolding that is not part of the production architecture). Set true to include *.Tests/*.Spec projects in the graphs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description is free to disclose traits the annotations cannot: the LEADING <TRUNCATION> block and how to read it, the 80-entry-per-section cap with '+N more' rows, the 2000-type layer-map ceiling, multi-TFM deduplication to the newest TFM, and degraded behaviour on recalled sessions. That is genuinely useful context beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the single most important fact (whole-solution orientation, bounded output) and organized with emphatic labels (BOUNDED AT SCALE, PRODUCTION-FOCUSED, Recall-safe). It is dense and parenthetical-heavy, with some restatement of schema-level guidance, but little of it is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the burden of describing the return shape and does so in detail: truncation block semantics, section list, domain summary, quality-hotspots contents, and what is absent. Combined with the token-cap and capping behaviour, an agent has everything needed to call it and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema, including the same rationales for lean/includeTests/summaryOnly. The description mostly restates those defaults and conditions rather than adding new syntax or semantics, so the baseline 3 for schema-carried parameters is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Orient on a whole solution', 'Renders a structural-only AI-Builder-Markdown overview') and enumerates exactly which graphs are included and which are deliberately not (no per-type/per-file source blocks, no method-level call graphs). It explicitly distinguishes itself from siblings export_markdown, call_graph, explain_symbol and get_context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit ordering: 'Use this FIRST to understand a codebase's shape, then get_context / explain_symbol to drill into a symbol.' It names alternatives with the condition that selects them (export_markdown for the full set, find_symbol/call_graph/get_context to drill in, includeTests for test projects, summaryOnly for 200+ project monoliths).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
assert_absenceCheck a Negative ClaimARead-onlyIdempotent
Check a NEGATIVE claim against the analyzed model and return confirmed / refuted / indeterminate with evidence. Supported: 'no_tests:' (the symbol has no detected covering test), 'absent:.' (the semantic axis is verified-absent - developer declared 'none', NOT merely unknown), and 'unknown:.' (the axis has no provenance entry at all). is a bare name or the qualified Type.Member form - the same strings find_usages / find_tests_for / impact_of_change resolve, so the pre-edit gate's tools accept one vocabulary; a name that resolves to nothing declared says so ('resolves to no declared type or member'), which is a statement about the name, not a claim the code lacks it. axis is e.g. role/layer/domain/context/responsibility; an axis name not recorded anywhere in the solution returns 'indeterminate' with the actual recorded axes as evidence (a typo'd/invented axis is NOT silently 'confirmed'). Conservative in BOTH directions: a claim the model cannot prove is 'indeterminate', never falsely confirmed - and 'refuted' for a no_tests claim requires at least one STRONG covering test, as find_tests_for defines its tiers; the reason states the split between the strong tiers and the name-only matches, matching find_tests_for's invokesTotal. Tests that merely carry the symbol in their NAME yield 'indeterminate' with that split disclosed, not a refutation - a test named after a symbol is not proof it exercises it. Use to validate 'this service is untested' or 'role is explicitly unset' before relying on it.
| Name | Required | Description | Default |
|---|---|---|---|
| claim | Yes | The negative claim: 'no_tests:<Symbol>', 'absent:<Symbol>.<axis>', or 'unknown:<Symbol>.<axis>'. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds substantial behavioral context beyond them: conservatism in both directions, that refutation requires a STRONG covering test per find_tests_for tiers, that name-only matches yield indeterminate with the tier split, and that typo'd/invented axes return indeterminate rather than a false confirm.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and return values, and most sentences carry distinct information. It is dense with parenthetical qualifications that border on overload, but almost none is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description spells out return values (confirmed/refuted/indeterminate with evidence) and the edge-case returns (unresolved names, unrecorded axes). With 2 fully-covered params and annotations supplying safety, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds real meaning beyond it: it decodes each claim token ('absent' means developer-declared none, NOT unknown; 'unknown' means no provenance entry), explains the Symbol vocabulary shared with find_usages/find_tests_for/impact_of_change, and defines what an axis is with examples (role/layer/domain/context/responsibility).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (check/assert) and a specific resource (a NEGATIVE claim against the analyzed model), and enumerates the three supported claim tokens with their precise meanings. It is clearly distinguishable from the positive-verification sibling verify_claim.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ('validate this service is untested or role is explicitly unset before relying on it') and defines which claim shapes are in scope. It does not, however, name verify_claim as the positive-claim alternative, so the sibling routing is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
batchRun Several Queries at OnceARead-onlyIdempotent
Run several read-only query tools in ONE round-trip against one shared session. measure is the sibling that reports what each answer would cost instead of returning it.
Use it whenever two or more questions do not depend on each other's answers; a solution path as sessionId is analyzed once.
queries is an array of {tool, args}: args is that tool's own arguments as a JSON object WITHOUT sessionId (omit it for a tool that takes none). Example: queries=[{"tool":"find_usages","args":{"symbol":"Foo"}},{"tool":"find_tests_for","args":{"symbol":"Foo"}}]. At most 16 per call: more fails the whole call, as does a sessionId that does not resolve.
Returns { results: [{tool, ok, result | error}], count, okCount }, in query order. A failing sub-query answers ok:false + error and the rest still return. A JSON tool's result is nested as an object, a Markdown tool's is the string. The answers share a response budget of about 9000 tokens: one that no longer fits is omitted with ok:false and a pointer to call that tool directly - after its work was done. 'note' on an item names arguments the tool does not have; they are ignored, not rejected.
Dispatchable is a fixed registry of read-only queries about the analyzed code, among them find_*/get_*/impact_of_change/symbol_signature/explain_symbol/calls_external/resolve_injection/symbol_metrics/list_insights. Refused per item, with the registry's names listed - call these directly where the profile exposes them: tools that mutate session state or write (such as analyze_solution/refresh_session/apply_solution_config/save_session/remember_codebase/export_markdown/install_agent_hooks), poor batch members (evaluate_change_set/init_solution_config/prepare_task/review_context), tools needing a second session or snapshot (semantic_diff/diff_review/verify_claim/compare_with_previous) and the session, configuration and server tools. A tool the active MCP profile does not expose is refused per item too, as a direct call would be - also when a refusal's list names it.
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | The read-only sub-queries: an array of { tool, args } objects. 'tool' is a read-only tool name; 'args' is that tool's argument object (without sessionId), omittable when the tool needs no arguments. Max 16. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. Shared by ALL sub-queries - do NOT repeat it inside each query's args. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnly/idempotent/non-destructive, but the description adds constraints they cannot convey: max 16 sub-queries (over-limit fails the whole call), an unresolved sessionId failing the whole call, per-item refusal semantics, partial success (ok:false + error while the rest still return), a ~9000-token shared response budget with omission behavior pointing to direct invocation, and the 'note' field for unrecognized args being ignored not rejected. This is rich behavioral disclosure well beyond the annotation set.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose then usage then return shape then failure modes then the dispatchable/refused registry. Dense and mostly waste-free for the surface area covered, though the sessionId-omission point is stated twice and the refused-tool list is long.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description supplies the return shape ({results:[{tool,ok,result|error}], count, okCount} in query order), per-item vs whole-call failure behavior, and budget-driven omission semantics. For a dispatcher with a nested query registry, this is complete enough to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real meaning: the required {tool, args} shape, that args must omit sessionId, a concrete worked example, the max-16 bound, and that sessionId accepts an absolute .sln/.slnx/.slnf path analyzed on first use. It goes well beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Run several read-only query tools in ONE round-trip against one shared session.' It also explicitly distinguishes itself from its sibling measure, which 'reports what each answer would cost instead of returning it.' An agent can tell what this does and what it is not without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit trigger: 'Use it whenever two or more questions do not depend on each other's answers.' It also enumerates what must NOT be batched — mutating tools, poor batch members (evaluate_change_set, init_solution_config, prepare_task, review_context), tools needing a second session/snapshot, and session/config/server tools — with the registry's names. When/when-not coverage is unusually complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
call_graphBuild a Call GraphARead-onlyIdempotent
Build a depth-limited call graph rooted at a method NAME. direction='callees' follows project-internal calls outward; direction='callers' follows the inverse (who calls this). Returns (caller, callee) edges using method-lookup keys, cycle-safe and capped at 500 edges (truncated flag). Rooted at the name, NOT at one symbol: EVERY same-named declaration in the solution is a root and the graph is their union, so a common name (e.g. 'ExecuteAsync') can pull in unrelated members and inflate the payload. 'rootedAt' lists the declarations actually walked - check it when the result looks too big (then re-query a rarer name) and when it is empty (the name resolved to nothing, which an empty edge list alone does not tell you).
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Max traversal depth (1-10). Default 2. | |
| method | Yes | The root method's name. | |
| direction | No | 'callees' (default) or 'callers'. | callees |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe read-only/idempotent profile, and the description adds substantial context beyond them: the 500-edge cap with a truncated flag, cycle-safe traversal, edge key format, and the critical name-resolution behavior (every same-named declaration is a root, unioned together). This is exactly the kind of behavior an agent cannot infer from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then progressively adds depth-limit, truncation, and root-resolution caveats. Dense but every sentence carries information; only the length keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description must cover return values, and it does: (caller, callee) edges, lookup keys, cycle safety, truncation flag, and the 'rootedAt' diagnostic. Complete enough for an agent to call and interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it explains the semantic difference between direction values and, crucially, that 'method' resolves to all same-named declarations rather than one symbol, which materially changes how the parameter should be chosen.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Build a depth-limited call graph rooted at a method NAME') and immediately distinguishes direction modes ('callees' vs 'callers'). An agent can tell exactly what this produces without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operational guidance: which direction to choose, and what to do when the result is too big (re-query a rarer name) or when 'rootedAt' is empty. It does not explicitly name alternative sibling tools (e.g. find_usages, impact_of_change) for comparison, so it stops short of full when-not routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calls_externalFind Calls to External APIsARead-onlyIdempotent
Find the code that calls an EXTERNAL member - BCL or package - whose key contains a pattern. find_usages answers for solution symbols only; find_by_side_effects classifies the same calls into effect tokens.
Use it for 'who calls the risky or external API X?': AOT and trimming readiness, security surface, dependency footprint (pattern 'Process.Start', 'Assembly.Load', 'DateTime.UtcNow').
Returns scope, pattern, methodsScanned, matches - a capped envelope of at most 200 hits, sorted by type and name, not ranked - and testMatchesFiltered when the test filter removed hits. A hit carries name, declaringType, namespace, matchedCalls (invoked methods and method groups, keys like 'System.IO.File.ReadAllText(string)') and matchedReads (external properties read or written, like 'System.DateTime.UtcNow'). The units scanned are methods plus every accessor and constructor with a body, under their metadata names (get_X, set_X, .ctor); an initializer counts toward the constructor that runs it.
The pattern is a case-insensitive substring of the whole key, parameter list included, so a type name also hits the units that only pass that type to another API. It is an open vocabulary: there is no did-you-mean, and empty is now a strong statement, though not absolute. Not recorded: an external field read ('string.Empty'), a bare 'new X()', operators and conversions, indexers, event subscriptions and compiler-lowered calls (using, foreach, await). Cross-check a surprising empty against the declaring type ('DateTime' instead of 'DateTime.UtcNow'). A 'note' leads the answer when it is empty - it says when only the test filter emptied it - and when a project's core references did not resolve: an unresolved call records no key.
Read-only; works on a recalled session. Test-project code is excluded by default; includeTests=true includes it. testMatchesFiltered counts the filtered-out units, which methodsScanned does not include. scope is 'solution' or a namespace prefix, matched case-insensitively on segment boundaries.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default) or a namespace prefix (e.g. 'MyApp.Infrastructure') to narrow scope. | solution |
| pattern | Yes | A substring of the external (BCL/third-party) call key to match (case-insensitive), e.g. 'Process.Start', 'File.', 'Assembly.Load', 'System.Reflection', 'JsonSerializer'. Required - a very broad pattern (e.g. 'System') truncates at 200. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test-project methods (default false - production focus; test setup/assertions calling external APIs would otherwise drown the signal). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover only safety (readOnly/idempotent/non-destructive), but the description goes far beyond: it defines the scanned units (methods, accessors, constructors with bodies under metadata names), declares the open vocabulary with no did-you-mean, warns that empty is a strong but not absolute statement, and enumerates exactly what is NOT recorded (field reads, bare constructors, operators, indexers, event subscriptions, compiler-lowered calls).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and usage scenario are front-loaded, and the dense caveat list is justified by the tool's many non-obvious edge cases. It is long and could be tightened, but nearly every sentence carries operational information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description fully specifies the return envelope (scope, pattern, methodsScanned, matches, 200-hit cap sorted not ranked, testMatchesFiltered, the note field) and the per-hit structure (name, declaringType, namespace, matchedCalls, matchedReads).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real meaning: the pattern is a case-insensitive substring of the whole key including the parameter list, that type names also hit units merely passing that type, that broad patterns truncate at 200, and how testMatchesFiltered relates to methodsScanned.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource+scope ('Find the code that calls an EXTERNAL member - BCL or package - whose key contains a pattern') and explicitly differentiates from siblings, noting find_usages covers solution symbols only and find_by_side_effects classifies the same calls into effect tokens.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use scenarios ('who calls the risky or external API X?': AOT/trimming readiness, security surface, dependency footprint) with concrete example patterns, and names the alternatives (find_usages, find_by_side_effects) that answer different questions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_solution_config_driftCheck Solution Configuration DriftARead-onlyIdempotent
Check whether a solution's active Layer Profile, Exclude-Namespaces and Test Profile still FIT the code. solution_config_status tells you WHICH configuration is active and where it comes from.
Use it on a solution configured a while ago, or when layer or exclusion results look off; a stale axis is rebuilt with init_solution_config and apply_solution_config. Do not use it on a never-configured solution: nothing is evaluated there.
Three conservative signals: layer - declared (own) namespaces that no rule of the active layer profile maps; exclusion - EXTERNAL referenced namespaces that the active exclusion list does not cover; test - projects the default heuristic classifies as test projects that the active custom test profile's rules do not match.
Returns JSON with layer, exclusion and test, each carrying source (db / sidecar / built-in / none), name, status, stale, considered (the denominator), sample (the drifted names as items/count/totalFound/truncated, max 50) and reason, which states the drifted count against considered. status is 'stale' from 3 drifted names on for layer and exclusion, and for test when more than a quarter of the considered projects drifted; else 'ok', and an 'ok' with a sample is still worth reading. 'built-in-preset' and 'not-configured' mean the axis was NOT evaluated: only a custom config is judged (a generic preset is a choice, not drift). sidecarProblem appears when the .aicb.json could not be read.
It changes no configuration and creates no solution row; a dbPath that does not exist is refused with an error, and an older one is upgraded on open (schema, built-in rows), as the server's own DB is at startup. It judges the configuration a plain analyze_solution resolves NOW, not a layerProfile the session was analyzed with. It needs a live session, not a recalled one.
Parameters: normally pass only sessionId (an absolute .sln path works too). Pass dbPath only if the session was analyzed with that same dbPath; otherwise this judges a configuration the analysis did not use.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional absolute path to the aicb config/master DB. If given, the config the DB holds for the solution (per-solution row, then app-global default) takes precedence over the .aicb.json sidecar; a built-in default in the DB does not. Omit to fall back to the server's default config DB (the GUI's, if resolved), else only the .aicb.json sidecar next to the .sln. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive; the description adds genuinely new behavior: it changes no configuration, creates no solution row, refuses a nonexistent dbPath with an error, upgrades an older DB on open, judges the config a plain analyze_solution resolves now, and requires a live (not recalled) session. The only gap is no note on performance or rate characteristics, but the behavioral surface is well covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core question and the sibling contrast before the details; every sentence carries information. It is dense and long, but the length is justified by the absence of an output schema and the non-obvious dbPath precedence rules.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return shape (layer/exclusion/test axes, source/name/status/stale/considered/sample/reason fields, status thresholds, built-in-preset and not-configured semantics, sidecarProblem). An agent has everything needed to call and interpret it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (baseline 3), but the description adds decision guidance beyond the schema: 'normally pass only sessionId' and pass dbPath only if the session was analyzed with that same dbPath, otherwise the judgment is meaningless. That is real added meaning, not a restatement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Check whether a solution's active Layer Profile, Exclude-Namespaces and Test Profile still FIT the code') and explicitly differentiates from the sibling solution_config_status by contrasting 'which config is active' vs 'does it still fit'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit triggers ('a solution configured a while ago, or when layer or exclusion results look off'), an explicit exclusion ('Do not use it on a never-configured solution: nothing is evaluated there'), and names the remedial siblings init_solution_config and apply_solution_config.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_with_previousCompare with a Saved SnapshotARead-onlyIdempotent
Diff the current session against a previously saved snapshot of the SAME solution - the newest by default, or the N-th previous via snapshotsBack (0=newest saved, 1=the one before, ...). Optionally narrow the diff to a single type and/or method. Returns added/removed types plus, per changed type, added/removed methods and signature changes. Requires a sessionId and at least one earlier save_session; dbPath is optional and defaults to the server's standard config DB when omitted. Name-based, syntactic (no method-body diff).
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional absolute path to the aicb SQLite DB holding the saved snapshots. Omit to use the server's standard config DB. | |
| typeName | No | Optional: restrict the diff to this type (simple name, case-insensitive). Omit for the whole-solution diff. A simple name ALSO matches the namespace-qualified form the diff renders for a type whose simple name collides in the solution - then the answer spans every type of that name and 'note' says which; pass one of those qualified names to narrow to a single type. Not a substring match: 'MyApi' never matches 'MyApiExtensions'. When a filter EMPTIES a diff that did have changes, 'note' says so and names the axis that missed, because 'isIdentical: true' then describes the filtered view and not the solution. On a diff that was ALREADY empty there is no note and none is owed: 'your filter matched nothing' and 'nothing changed' are the same state there, so a typo'd name and a real one answer identically - check the spelling with find_symbol rather than reading that agreement as confirmation. | |
| sessionId | Yes | The current session_id (the 'after' side of the diff). Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| methodName | No | Optional: within that type, restrict to this method name (case-insensitive). Omit for all methods of the type. Same disclosure rule as typeName: if the type matched and this name matches none of its added/removed/signature-changed methods, the type is dropped from the answer and 'note' says which of the two filters came up empty - an empty view here is never evidence that the method is unchanged. | |
| snapshotsBack | No | 0 = newest saved snapshot, 1 = the one before it, etc. (index into the per-solution history, newest first). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly/idempotent/non-destructive/openWorld=false), and the description adds real behavioral detail on top: the exact return shape (added/removed types, per-type added/removed methods and signature changes), the dbPath default, and the important limitation that the diff is name-based and syntactic with no method-body diff.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads the core purpose before defaults, filtering, return shape and the syntactic-only caveat. Every sentence contributes, though the block is information-heavy and could be more scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description carries the full burden and does so by enumerating the returned structure and the syntactic-only scope. It also covers the optional dbPath default and prerequisite, so nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and its parameter descriptions are already highly detailed (snapshotsBack indexing, typeName/methodName disclosure rules), so the schema does the heavy lifting. The description adds the cross-parameter constraint that an earlier save_session must exist, but otherwise largely restates what the schema documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (diff) and both operands (current session vs. a previously saved snapshot of the SAME solution), which cleanly separates it from save_session and other siblings. The scope of what is compared is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the concrete prerequisite ('Requires a sessionId and at least one earlier save_session') and the default behavior (newest snapshot, or N-th via snapshotsBack), plus a redirect to find_symbol for spelling checks. It stops short of explicitly naming alternative tools or when-not-to-use cases, so it is clear but not fully routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
coverage_gapsFind Test Coverage GapsARead-onlyIdempotent
List what is NOT covered in a scope: 'uncovered' - production methods no test code calls directly - and 'verifiedAbsent' - semantic axes a developer explicitly declared as 'none'. find_tests_for asks the opposite question for one symbol.
Use it to find untested code before claiming coverage. THE LIST IS ONE HOP, NOT A COVERAGE MEASUREMENT: a method a test reaches THROUGH another method (a CLI verb behind its command builder) is listed although it is exercised - on this server's own solution that is most of the list. So read each entry's testReachDepth: the hops to the nearest directly called method (1 = one of those calls it), ABSENT when no test reaches the method at all. Those are the real gaps. The walk follows interface and abstract dispatch; an entry reached only that way carries viaDispatch.
Returns scope, a 'note' when uncovered is non-empty or no namespace matched, symbolsScanned, uncovered and verifiedAbsent (at most 200 items each), transitivelyReached, judgedUnits, testProjectsExcluded, testFixtureTypesExcluded and reachedOnlyThroughDispatch. uncovered is sorted by type and name, not by depth, so on a large scope the cap cuts alphabetically: narrow the scope to see the rest.
What counts: test code is every method of a test project, every test-attributed method and every method or constructor of a type that declares one. Only ordinary methods are judged. A constructor is a hop: new X(...) reaches the bound overload and its callees. A call from an accessor is not read. Abstract and interface declarations are excluded, and a weak test-name match does not count.
THE POPULATION IS DISCLOSED: judgedUnits is the methods the uncovered list is drawn from, out of symbolsScanned; testProjectsExcluded and testFixtureTypesExcluded count what was set aside as test code. A gap count without its denominator is meaningless. symbolsScanned 0 means the scope matched no namespace.
Read-only. scope is 'solution' or a namespace prefix, case-insensitive, matched on segment boundaries. There is no test switch.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default) or a namespace prefix to narrow which symbols are checked. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds substantial context beyond them: the one-hop limitation, testReachDepth/viaDispatch semantics, the alphabetical 200-item cap, the definition of test code, constructor-as-hop behavior, accessor calls not read, and the judgedUnits denominator. This is exactly the behavioral disclosure an agent needs to interpret results correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the critical one-hop caveat are front-loaded, and the sections (returns, what counts, population) are logically ordered. It is long and carries some rhetorical filler ('A gap count without its denominator is meaningless', 'THE LIST IS ONE HOP'), but the density is largely justified by the absent output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so thoroughly, naming every field (scope, note, symbolsScanned, uncovered, verifiedAbsent, transitivelyReached, judgedUnits, testProjectsExcluded, testFixtureTypesExcluded, reachedOnlyThroughDispatch) plus the edge cases for symbolsScanned 0 and the note field.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: scope is case-insensitive and matched on segment boundaries, 'solution' is the default, and there is no test toggle. It also notes sessionId accepts an absolute .sln/.slnx/.slnf path analyzed on first use.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List what is NOT covered in a scope') and enumerates the two result categories, uncovered and verifiedAbsent. It also explicitly distinguishes itself from find_tests_for ('asks the opposite question for one symbol'), so an agent can route between the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use ('find untested code before claiming coverage') and names the alternative sibling with the condition that selects it. It also warns about the primary misuse case (treating the one-hop list as a coverage measurement) and tells the agent to narrow scope when the 200-item cap bites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_api_surfaceDescribe Public API SurfaceARead-onlyIdempotent
List the PUBLIC API SURFACE of a solution or namespace - every externally-visible type with its externally-visible members (constructors, properties, fields, events, methods, user-defined operators), each as a compact declaration signature. The "header"/contract view: what a consumer of this assembly can actually reference, WITHOUT the source bodies (like a public-API digest, not a firehose). A type is included when its OWN declared accessibility is externally visible - public or the protected family (reachable by a subclass in another assembly); its members likewise. A property renders only the accessors that are themselves visible (a { get; private set; } shows as { get; }), a const carries its value, an enum is listed as a type (its values are not in the model). includeInternal=true additionally surfaces the internal family. PRODUCTION-FOCUSED: test projects are excluded by default (a shipped API surface is production code) - set includeTests=true to include .Tests/.Spec projects. scope='solution' (default) covers everything; a namespace prefix narrows it, and one that matches no namespace gets a 'note' ahead of typesScanned 0. The type list is capped (the true total travels in the envelope; narrow by namespace or filter to see the rest); members per type are whole. Recall-safe (reads persisted accessibility + signature facts) → works on live AND recalled sessions. Known v1 simplifications: accessibility is the type's OWN declared modifier (effective accessibility through the nesting chain is not computed - a public member of a type nested in an internal type is still listed); a type declared with NO access modifier is stored as private by the analyzer, so a modifier-omitted (compiler-internal) top-level type is not surfaced even with includeInternal. Use it to review a public contract before changing it, or as the baseline for a contract comparison - save_session then compare_with_previous, or diff_public_contract, which is outside the default profile's pool.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default - the whole solution) or a namespace prefix (e.g. 'MyApp.Contracts') to narrow the surface. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test projects (default FALSE - a shipped API surface is production code). Set true to include *.Tests/*.Spec projects. | |
| includeInternal | No | Include the internal family (internal / private-protected) types + members too (default FALSE = only the externally-visible public/protected surface). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description adds substantial beyond-schema behavior: how property accessors, consts, and enums render, that the type list is capped with the true total in the envelope, that it works on live AND recalled sessions, and honest "Known v1 simplifications" about accessibility computation and modifier-omitted types.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence, and most sentences carry load-bearing detail. However, the volume is high for a 4-param read-only tool, with heavy ALL-CAPS emphasis and stacked parentheticals that reduce scannability and add redundancy (accessibility/rendering rules are stated twice).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-shape burden and does so well: it explains declarations are compact signatures, that member lists are whole while types are capped, and that the envelope carries the true total. Combined with the simplification caveats, an agent has everything needed to call and interpret it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics the schema lacks: includeInternal surfaces the internal/private-protected family, and a namespace prefix matching no namespace yields a 'note' ahead of typesScanned 0. It reinforces the defaults for scope and includeTests rather than merely restating them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb ("List") and resource ("PUBLIC API SURFACE of a solution or namespace") and immediately clarifies scope (externally-visible types with their members). It differentiates itself from siblings by naming compare_with_previous and diff_public_contract, plus the "public-API digest, not a firehose" framing that separates it from a full-documentation tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit use cases ("review a public contract before changing it, or as the baseline for a contract comparison") and names the chaining alternatives (save_session then compare_with_previous, or diff_public_contract, noting the latter is outside the default profile). It does not state an explicit when-not condition beyond the firehose contrast, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
detect_circular_dependenciesDetect Circular DependenciesARead-onlyIdempotent
Detect circular NAMESPACE dependencies: groups of namespaces that depend on each other in a cycle - a modularity smell the compiler allows, unlike project-reference cycles. The layer-violation insight in list_insights checks the direction rule; this answers the orthogonal 'who is mutually entangled?'.
Use it before splitting an assembly or moving types between namespaces.
Returns scope, namespacesScanned, cyclesFound and cycles, at most 100. Each cycle is a strongly connected component of two or more namespaces and carries namespaces, size, projects, spansMultipleProjects, edgeCount, edgesTruncated and edges: one 'witness' type -> type reference per directed namespace pair (fromNamespace, toNamespace, fromType, toType, typeEdgeCount). Read the witnesses as EXAMPLES, not as a work list: edgeCount counts directed namespace pairs, and typeEdgeCount says how many distinct type references cross that one boundary. Where it is above 1, removing the shown reference leaves the edge standing. Cycles that span assemblies come first, then the largest. Witness edges are capped per cycle, and edgesTruncated says when; the namespace list is complete. A cycle inside one assembly is namespace organisation; one that spans assemblies means a namespace is reused across DLL boundaries.
Edges come from the type references a type's facts record by full name - member, field, parameter, return and typeof types, base class and interfaces among them - so a same-named type in two namespaces is never conflated, and external references are ignored.
cyclesFound 0 under scope 'solution' means no cycle among the scanned namespaces. Under a prefix it only means no cycle touches a namespace starting with that text, and an unknown prefix answers the same zero.
Read-only; works on a recalled session. Test projects are excluded by default (includeTests=true includes them). scope is 'solution' or a plain case-insensitive namespace prefix: it narrows the report, not the graph, and returns a whole cycle when one of its namespaces matches.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default - all cycles) or a namespace prefix to report only cycles whose members include that prefix. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test projects (default FALSE - production focus: a test->production reference is one-way and not an architecture cycle). Set true to include them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only/idempotent, but the description goes well beyond them: it discloses the 100-cycle cap, ordering (solution-spanning first, then largest), witness edges being EXAMPLES not a work list, edgeCount/typeEdgeCount semantics, edgesTruncated capping (with the namespace list still complete), and how edges are derived from recorded type facts. This is exactly the extra behavioural context a caller needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose in the first clause, then alternatives, then return semantics. It is long, and the witness-edge paragraph is dense, but with no output schema every sentence is doing load-bearing work; only minor tightening is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description must carry return semantics and it does: field list, caps, ordering, truncation flag, and the interpretation rule for a zero count under each scope. Combined with annotations covering safety, an agent has everything needed to call and read this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description genuinely adds meaning: scope 'narrows the report, not the graph' and returns a whole cycle when any member matches the prefix; includeTests is justified (test->production is one-way, not an architecture cycle); sessionId accepts a .sln/.slnx/.slnf path analyzed on first use. This exceeds what the schema alone conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Detect circular NAMESPACE dependencies') and immediately scopes it as cycles among groups of namespaces, explicitly contrasting with the 'layer-violation insight in list_insights'. An agent can distinguish it from that sibling and from other architecture tools without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('Use it before splitting an assembly or moving types between namespaces') and a precise division of labour with list_insights (direction rule vs mutual entanglement). It also explains the interpretation of results under each scope value, including that an unknown prefix likewise answers zero, which is real guidance, not just context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
docsRead the Operating ManualARead-onlyIdempotent
The aicb operating manual - how to USE this server, as opposed to what it can tell you about your code. Call it with no arguments for the directory (each page with a one-line summary and a token estimate, so you can budget); pass one or more page ids to read them, or the route id 'init' for the whole first run in order. Pages: 'overview' (what aicb is and is not, the three ways to run it), 'install' (getting the dotnet tool, aicb init, and what it writes - the client's .mcp.json entry and the agent skill a tool install cannot deliver; for setting aicb up somewhere else, or finishing a half-done setup), 'first-context' (from a .sln to your first context - and why the full export is rarely the right call), 'navigation' (which tool answers which question about the code, the blast-radius call before editing shared code, and where plain text search is still right), 'solution-config' (layers / exclusions / test detection and the .aicb.json sidecar), 'glossary' (session, facet, MCP profile, snapshot, insight, AI-Builder MD). Start here if you have not used aicb before. No session and no solution needed.
| Name | Required | Description | Default |
|---|---|---|---|
| topics | No | Optional page or route ids. Omit for the directory. A route id ('init') expands to its pages in reading order; repeats collapse, so asking for a route and one of its pages yields one copy. Unknown ids are named back to you rather than silently dropped. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds real behavioral detail beyond them: token estimates per page for budgeting, route expansion into reading order, deduplication of repeats, and unknown ids being named back rather than dropped.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads what it is, then how to call it, then the page catalog. The page enumeration is long but each entry earns its place as a routing aid; only minor tightening is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single optional-array parameter tool with rich annotations and no output schema, the description covers invocation modes, valid values, edge behavior, and prerequisites. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description goes further by enumerating every valid page id with its content summary ('overview', 'install', 'first-context', 'navigation', 'solution-config', 'glossary') plus the 'init' route — effectively documenting the valid value domain beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names the specific resource (the aicb operating manual) and explicitly demarcates its scope: 'how to USE this server, as opposed to what it can tell you about your code.' That contrast cleanly separates it from the ~50 sibling code-analysis tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states explicit routing conditions: 'Start here if you have not used aicb before', explains that a bare call returns the directory, and gives per-page when-to-use cues (e.g. 'for setting aicb up somewhere else, or finishing a half-done setup'). It also notes 'No session and no solution needed', removing a common prerequisite question.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
evaluate_change_setCheck an Edit Before Writing ItARead-onlyIdempotent
Advisory policy gate: which code-quality / design-smell / layer-violation findings would this edit INTRODUCE? Ask BEFORE writing it. Cheapest form - the edit you are about to make anyway: changes: [{filePath, oldText, newText}], the snippet being replaced and what it becomes (the shape an editor takes). The full file is rebuilt here from the analyzed document, so the payload is the size of the CHANGE, not of the file, and 'operation' defaults to 'modify'. oldText must occur EXACTLY ONCE - a missing or ambiguous anchor is an error, never a silently different edit; line endings are reconciled for you; an empty newText deletes the snippet. Full-text form still works and is required for add/delete: {filePath, operation: 'modify'|'add'|'delete', newContent}. Findings are a delta against the current session, so pre-existing debt is never blamed. The changeset is applied as an in-memory Roslyn overlay (NO disk write, the session is untouched) and the amended solution is re-analyzed. Verdict: pass / warn / block. Policy: 'block_on_critical' (default) | 'block_on_warning' | 'advisory' (an unknown policy is rejected, not silently treated as advisory). Advisory only - an MCP tool cannot block; the real blocking gate is the CLI '--fail-on'. The findings delta honors the session's explicit layer profile (analyze_solution(layerProfile) / sidecar) and its resolved test-detection profile on both sides; pass dbPath to also use that DB's active QualityProfile (producer thresholds + toggles) and its configured default layer profile (per-solution > app-global; the explicit session profile still wins) - same semantics as list_insights, so the gate judges by the same configured thresholds as the CLI gate. apply_change_set is out of scope. Pass absolute file paths matching the analyzed documents.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND its configured default layer profile (per-solution > app-global) drives the layer-violation analysis on BOTH delta sides (an explicit analyze_solution(layerProfile) wins); omit to fall back to the server's default config DB (the GUI's, if the server resolved one), else the default profile + session axes, and the layer profile to the config DB the session was analysed against - the one its renders read. | |
| policy | No | Policy: 'block_on_critical' (default) | 'block_on_warning' | 'advisory'. | |
| changes | Yes | The proposed file changes. Per change: filePath (absolute), plus EITHER the anchor patch oldText + newText (preferred - 'operation' may be omitted, it defaults to 'modify') OR the full new file text newContent with operation 'modify'/'add' ('delete' takes neither). | |
| sessionId | Yes | The session_id returned by analyze_solution (the baseline). Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the annotations: states the changeset is applied as an in-memory Roslyn overlay with NO disk write and the session untouched, that the gate is advisory only because an MCP tool cannot block (real gate is CLI --fail-on), that oldText must occur exactly once or it is an error, and how layer/quality profiles are resolved on both delta sides.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and most sentences carry non-redundant behavioral detail, but the prose is extremely dense and long for a four-parameter tool, packing profile-resolution and precedence caveats into a single flowing paragraph that is hard to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description covers the verdict shape (pass/warn/block), the delta-vs-session finding semantics, the available policy values, and the advisory-only caveat, so an agent has everything needed to call and interpret it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: the oldText/newText anchor-patch shape, operation defaulting to 'modify', empty newText deleting, and precisely what dbPath changes (QualityProfile thresholds + default layer profile with precedence rules).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('which findings would this edit INTRODUCE') with a clear noun: an advisory policy gate over a proposed change set. It also proactively rules out the confusingly-named sibling by declaring 'apply_change_set is out of scope', so an agent can separate the preview from the write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to ask BEFORE writing, names the cheapest form (anchor patch) versus the full-text form required for add/delete, and rules out apply_change_set. It stops short of naming which sibling to use instead for the adjacent 'what will my change impact' question, so selection against impact_of_change/review_context is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_symbolExplain a SymbolARead-onlyIdempotent
Explain a symbol: its source PLUS a chosen environment, as ONE dense AI-Builder-Markdown slice - the cold-read in a single call instead of 4-6 (get_context + find_usages + find_implementations + find_tests_for + ...). 'include' selects the environment axes (any combination): callers (the members that reference it, with their bodies, and their owner types as structure - not the calling types whole), callees (what it calls/depends on, depth 1), implementations (the types implementing it, if it's an interface), tests (its covering test cases), siblings (naming/file-convention kin), quality (complexity / efferent-coupling hotspot metrics). A partial type renders as ONE block (its declaration fragments are folded, a leading comment says which files) instead of one identical block per file. An empty include returns just the symbol's source - and then the manifest names the axes you could have asked for, so that answer is a stated choice rather than a silent default; an include token that names no axis is reported as dropped, whether or not a sibling token was valid. A leading manifest comment discloses what each merge axis actually found - so '(none)' is an honest negative (no impl / no caller / no test), not 'not asked'. Pass a type or method simple name (use find_symbol to disambiguate). Recall-safe (reads persisted facts); prefer it over export_markdown for one symbol's world. Multi-TFM solutions are deduplicated to one logical project per name (NEWEST TFM's instance, matching find_symbol's view).
| Name | Required | Description | Default |
|---|---|---|---|
| lean | No | Lean slice (default TRUE): drop the <AI_CONTEXT_SPEC>/<AI_CONTEXT_META> format-rules preamble and omit enabled-but-empty graph sections. Set false for the full AI-Builder-MD document with the format contract. | |
| budget | No | Optional token budget (floored at 8000). Compacts/drops method bodies and, when the neighborhood overflows, drops the least-relevant types. The center symbol is always kept - with its full source when that fits, otherwise as STRUCTURE (identity, members, every method signature) plus a leading note that names the measured size of the full-code render and the budget that would hold it, so a 2000-line type under budget:8000 costs ~2000 tokens, not ~24000. The bundled environment (callers / tests / siblings / implementations) is BUDGET-BOUND - under a tight budget it is dropped to fit (a leading comment names the drops so you can ask for one by name). Omitted, the slice still renders against a ceiling (the active MCP profile's token budget, else a ~10000-token default budget) that bounds the merged environment - relevant above all with include=["callees"], whose outward neighborhood is the widest slice this server produces. | |
| symbol | Yes | The type or method simple name to center on (use find_symbol to disambiguate), or the qualified Type.Member form to focus ONE declaration of a shared method name - the same string find_usages / find_tests_for / impact_of_change resolve. A bare name that matches several declarations seeds them all (a whole family can then be budget-capped), and the manifest says so and names the qualified form. | |
| include | No | Which environment axes to include (any combination, case-insensitive): callers, callees, implementations, tests, siblings, quality. Empty/omitted = just the symbol's source. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a safe, idempotent, non-destructive read, so the bar is lower; the description nonetheless adds rich behavior: empty include returns only source and names available axes, unknown include tokens are reported as dropped, '(none)' is an honest negative rather than 'not asked', multi-TFM solutions are deduplicated to the newest TFM, and the read is recall-safe from persisted facts. These are meaningful traits not expressible in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Content is front-loaded with the core purpose and almost every clause carries non-redundant information (dedup, manifest honesty, budget fallback). However, it is an extremely long single paragraph with heavy nested parentheticals, which harms parseability despite the density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-shape burden and does so: it explains the manifest, the folded single-block partial-type rendering, the structural fallback under budget, and the honesty semantics of empty results. Given 100% schema coverage and annotations covering safety, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so a baseline of 3 applies, but the description adds real meaning beyond the schema: it defines the empty-vs-dropped-token semantics of 'include', the qualified Type.Member focus form for 'symbol', and the honest-negative behavior of the manifest. The budget semantics are already largely in the schema, so the added value is real but partly overlapping.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Explain') and resource ('a symbol') and defines the deliverable precisely as 'ONE dense AI-Builder-Markdown slice.' It explicitly distinguishes itself from siblings by naming the 4-6 calls it replaces (get_context + find_usages + find_implementations + find_tests_for) and from export_markdown. An agent can tell exactly what this does without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use ('the cold-read in a single call instead of 4-6'), an alternative preference ('prefer it over export_markdown for one symbol's world'), and a prerequisite workaround ('Pass a type or method simple name (use find_symbol to disambiguate)'). The selection logic against named siblings is fully stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_markdownExport Solution as MarkdownADestructiveIdempotent
Render the cached analysis of a session as AI-Builder Markdown. No re-analysis - instant. NOTE: this renders the WHOLE solution - on a large codebase that is many megabytes, and an answer over the server's message ceiling (16,000,000 bytes as JSON unless AICB_MCP_MAX_RESPONSE_BYTES says otherwise) is not sent: the call is refused with its size, because MCP clients drop larger messages. Pass outputPath for anything but a small solution. For a bounded view prefer architecture_overview (whole-solution orientation, structural-only, no per-type source) or get_context / explain_symbol (one symbol's world). When the server has a config DB (the default: a plain 'aicb mcp' resolves the standard one), the active MCP profile drives the render: the chosen facet's template (detail presets, graphs, line numbers, quality metrics) is used; otherwise the full default render is used. Returns the Markdown; if outputPath is given it writes the file and returns a short confirmation (not the full content), so a large render does not flood the response.
| Name | Required | Description | Default |
|---|---|---|---|
| facet | No | Optional facet to render through - the task axis of this call: General (default), Exploration, Refactoring, Debugging, Review, Testing, Documentation, Architecture, or Performance. The facet picks the active MCP profile's matching template and appends a short work-style trailer with suggested next tools. Unknown/empty falls back to General; a facet whose slot has no template assigned falls back to the active context template. (The former name 'slot' is still accepted.) | |
| format | No | Optional inner notation of the rendered Markdown: 'tag' (the established AI-Builder tag format) or 'yaml' (idiomatic YAML - a lossless re-notation, not a different selection of content). Pick whichever notation you parse more reliably. When given, this explicit value wins; when omitted, the active MCP profile's OutputFormat is used (profile-aware path), else yaml (the DB-free default). The .md branding is unchanged. Any other value counts as omitted: the profile's format (else yaml) applies, and the response starts with a note naming the ignored value. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| outputPath | No | Optional absolute path to write the Markdown to (UTF-8, no BOM). When given, the tool writes the file and returns a short confirmation (path + size) instead of the full markdown - so a large (whole-solution) render does not flood the response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=true, and idempotentHint=true, so the write profile is already partly known; the description still adds real value by disclosing the 16,000,000-byte response ceiling, the refusal-with-size behavior, the profile-driven rendering path, and the file-vs-inline return difference. The main gap is that it never warns that writing outputPath overwrites an existing file, which is exactly the behavior destructiveHint=true implies.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with purpose before constraints, and the long size-ceiling and profile-fallback sentences each carry operational information. It is on the verbose side and could be tightened, but nothing is pure filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly explains return values (Markdown content vs a short confirmation when outputPath is set) and covers defaults, fallbacks, size limits, and alternatives. Only the overwrite/destructive side of writing outputPath is left implicit, which matters given destructiveHint=true.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents facet, format, sessionId, and outputPath in detail (including fallbacks and accepted path forms). The description mostly restates those semantics ('the chosen facet's template ... is used'), adding only the practical hint to use outputPath for anything but a small solution, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource ('Render the cached analysis of a session as AI-Builder Markdown') and immediately adds the distinguishing trait 'No re-analysis - instant.' It also names the sibling tools that serve adjacent needs (architecture_overview, get_context, explain_symbol), so an agent can separate this from other export/overview tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states explicit routing conditions: 'Pass outputPath for anything but a small solution', and 'For a bounded view prefer architecture_overview ... or get_context / explain_symbol'. When-not conditions are also covered via the size-ceiling refusal for whole-solution renders.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_binding_usagesFind XAML Binding UsagesARead-onlyIdempotent
List the {Binding ...} sites in the solution's .xaml and .axaml markup that name a member path, with what each one resolves against. find_usages carries a markup edge for a root member bound against the DataContext; this tool lists every site, redirected bindings included. find_unresolved_bindings checks whether a bound member exists on its view-model.
Use it before renaming or deleting a view-model member.
With a path: sites (view, line, path, form), siteCount, byForm, deeperSegmentSites + deeperSegmentSiteCount, pathlessBindingCount, scannedFileCount, sitesTruncated and a note. form is dataContext (no redirect), elementName, relativeSource or source. A path matches as the whole path or as its ROOT segment: 'Foo' finds {Binding Foo} and {Binding Foo.Bar}. The 'Bar' of {Binding Foo.Bar} is a member of Foo's type and is reported apart in deeperSegmentSites. On an elementName or relativeSource binding a leading 'DataContext.' is the hop to the element's view-model: {Binding DataContext.Cmd, RelativeSource=...} is a site of 'Cmd'.
Without a path: the inventory - members (member, siteCount, byForm), most-bound first, with distinctMemberCount and totalSiteCount. Lists are capped at 200; the counts are true totals. pathlessBindingCount is every binding without a plain member root (an empty {Binding}, {Binding Mode=OneWay}, an attached-property path); it counts the whole solution, whatever scope and form say.
The markup is read from disk at every call, so a markup edit needs no refresh_session. Only the {Binding} markup extension is read ({CompiledBinding} too in .axaml): a binding built in code-behind, element-syntax , {x:Bind}, {TemplateBinding} and a path assembled at runtime are invisible here - zero sites means 'verify before renaming or deleting', not proof.
Read-only; test projects are scanned too. path is a case-sensitive markup path and is not resolved as a symbol. An unknown form matches nothing, and the note says so. scope is 'solution' or a substring of the view path.
| Name | Required | Description | Default |
|---|---|---|---|
| form | No | Optional form filter: 'dataContext', 'elementName', 'relativeSource' or 'source'. Omit for all forms. Applies to both views. | |
| path | No | The exact (case-sensitive) bound member path, e.g. 'GestureLabel' or 'Foo.Bar'. Omit for the inventory view (every bound root member with its site counts). | |
| scope | No | 'solution' (default) or a view-path substring (e.g. 'AIContextBuilder.UI/Views/Dialogs') to narrow which markup files are reported. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent/non-destructive, and the description adds substantial context beyond them: markup is re-read from disk each call so no refresh_session is needed, only the {Binding} markup extension (plus {CompiledBinding} in .axaml) is visible and code-behind/element-syntax/{x:Bind} bindings are invisible, lists are capped at 200 while counts are true totals, and test projects are scanned. This is rich disclosure well beyond the annotation set.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is long, but front-loaded with purpose and routing first, then output shape with/without path, then caveats, then param notes – each block carries distinct information. The final paragraph mildly restates schema content (case-sensitivity, scope values), which costs a point but does not obscure the structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry the return contract, and it does: it enumerates sites/siteCount/byForm/deeperSegmentSites/pathlessBindingCount/scannedFileCount/sitesTruncated for the path view and members/distinctMemberCount/totalSiteCount for the inventory view, plus the truncation caveat. Nothing needed to invoke or interpret the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning the schema lacks: path matches the whole path or its ROOT segment ('Foo' finds {Binding Foo} and {Binding Foo.Bar}), the 'Bar' of Foo.Bar is reported separately in deeperSegmentSites, a leading 'DataContext.' on elementName/relativeSource is a hop, path is not resolved as a symbol, and an unknown form matches nothing. Some overlap with the schema's own field descriptions keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource – listing {Binding ...} sites in the solution's .xaml/.axaml markup that name a member path. It immediately distinguishes itself from find_usages ('carries a markup edge for a root member bound against the DataContext; this tool lists every site, redirected bindings included') and find_unresolved_bindings, so an agent can select it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit routing rules against two named siblings and a concrete trigger: 'Use it before renaming or deleting a view-model member.' It also states when zero results are meaningful ('zero sites means verify before renaming or deleting, not proof'), which is exactly the exclusion guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_by_attributeFind Symbols by AttributeARead-onlyIdempotent
Find symbols (types, methods, properties or fields) that carry a given ATTRIBUTE - a cross-cutting query that find_symbol (name-only) cannot do. The attribute name is matched format-independently: the last name segment, with an optional 'Attribute' suffix stripped, case-insensitive. So 'Obsolete', 'ObsoleteAttribute' and 'System.ObsoleteAttribute' all match the same symbols (types store the fully-qualified attribute class, methods/properties/fields store the source-syntax name - this reconciles both). The raw stored attribute list travels with each hit so you see the ground truth. kinds = 'all' (default - types + methods + properties + fields) / 'type' / 'method' / 'property' / 'field'. Member scanning surfaces a member-level attribute like a CommunityToolkit '[ObservableProperty]' (on a backing field or a modern partial property) or a '[JsonProperty]' that a type/method-only scan misses. Use it for '[Obsolete]', '[ApiController]', '[Authorize]', test attributes, etc. The 'method' axis includes constructors and accessors with a body (named .ctor / get_X / set_X), so a [JsonConstructor] or an [Obsolete] setter is found. Deterministic from Roslyn - works on recalled sessions. Capped at 200.
| Name | Required | Description | Default |
|---|---|---|---|
| kinds | No | Which symbol kinds to search: 'all' (default - types + methods + properties + fields), 'type', 'method', 'property', or 'field'. | all |
| scope | No | 'solution' (default) or a namespace prefix (e.g. 'MyApp.Api') to narrow scope. | solution |
| attribute | Yes | The attribute to find (e.g. 'Obsolete', 'ApiController', 'Fact'). Suffix/namespace are normalized away - required. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, non-open-world), yet the description adds substantial behavior beyond that: deterministic Roslyn evaluation, validity on recalled sessions, the 200-result cap, and the fact that the raw stored attribute list is returned with each hit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose then matching semantics, with zero filler sentences. It is dense and slightly long, but nearly every clause carries actionable detail, so it stays close to the top of the range.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description explains that the raw stored attribute list travels with each hit, and it covers matching, kinds, member scanning, the method-axis nuance, determinism, and the result cap. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: the attribute param's format-independent normalization (last segment, optional 'Attribute' suffix, case-insensitive, fully-qualified vs source-syntax storage) and the nuanced 'method' axis including .ctor/get_X/set_X. It leaves 'scope' semantics entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Find symbols ... that carry a given ATTRIBUTE') and immediately differentiates from the sibling find_symbol by noting it is a 'cross-cutting query that find_symbol (name-only) cannot do'. An agent can route between the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative (find_symbol) and the condition selecting this tool, plus concrete use cases ('[Obsolete]', '[ApiController]', '[Authorize]', test attributes). It also flags the value-add case where member scanning surfaces attributes a type/method-only scan misses.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_by_event_subscriptionFind Event SubscriptionsARead-onlyIdempotent
Find the TYPES that subscribe to a C# event: a '+=' whose left side resolves to an event, anywhere in the type (constructor, method, accessor, lambda). find_usages on an event the solution declares lists the subscribing, unsubscribing and raising METHODS; this tool works at type level and also sees external events ('Button.Click').
Use it for 'who listens to this event?' and to find where handlers are wired. Only subscriptions ('+=') are read, not '-='; a '+=' on a number, a string or a delegate field is not a subscription and is skipped.
Returns scope, event, typesScanned, subscriptionSitesChecked, subscriptionSitesUnresolved, matches - a capped envelope of at most 200 types (name, namespace, events), sorted by namespace and name - and when they apply 'note', availableEvents and testMatchesFiltered. A hit lists ALL event keys the type subscribes to ('DeclaringType.EventName'), not only the one filtered on.
Reading an empty answer: on zero matches availableEvents lists the events subscribed in scope. When testMatchesFiltered is present, read it first - the name was right and only its subscribers were tests. An EMPTY availableEvents means no subscription was RECORDED, which is not the same as none being present: recognition needs a resolved left side, so in a project whose types do not resolve every subscription is missing. The two site counts settle it: subscriptionSitesChecked is every '+=' the rule was applied to, subscriptionSitesUnresolved those whose left side could not be resolved. '0 of 0' is nothing to see, '0 of 7, 0 unresolved' a real absence, '0 of 7, 7 unresolved' an unmeasured scope - and that one carries a note.
Read-only; works on a recalled session. eventName is matched exactly, never as a substring; omit it to list every subscribing type. Test-project types are excluded by default (includeTests=true includes them).
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default) or a namespace prefix (e.g. 'MyApp.UI') to narrow scope. | solution |
| eventName | No | Filter to types subscribing to this event - the event name ('Click') or the qualified 'DeclaringType.EventName' key ('Button.Click'), case-insensitive. Omit to list every type with any subscription. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test-project types (default false - production focus; test setup that wires events would drown the signal). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower. The description still adds substantial behavior beyond that: a 200-type cap, exact-match semantics, default test exclusion, and detailed interpretation of empty results via subscriptionSitesChecked/Unresolved and the availableEvents/note/testMatchesFiltered fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and sibling differentiation before the dense return-shape guidance. The empty-result interpretation (the three site-count scenarios) is verbose, but with no output schema present, explaining the return envelope earns its place. Slightly long but well organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description responsibly documents the return envelope (scope, event, counts, matches, note, availableEvents, testMatchesFiltered). Combined with the read-only annotations and full param coverage, an agent has everything needed to call and interpret the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds real meaning: eventName is matched exactly, never as a substring, and omitting it lists every subscribing type; includeTests rationale is also explained. This goes beyond what the schema fields state.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: finding TYPES that subscribe to a C# event via '+='. It explicitly distinguishes itself from the closest sibling, find_usages, by noting that tool lists subscribing/unsubscribing/raising METHODS while this works at type level and also sees external events like 'Button.Click'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit use cases ('who listens to this event?', finding handler wiring), names the alternative (find_usages), and states exclusions ('+=' only, not '-='; a '+=' on a number, string or delegate field is skipped). When and when-not are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_by_semanticsFind Symbols by Layer, Role or DomainARead-onlyIdempotent
Find types and methods by their resolved semantics: layer, role, domain, responsibility. Filters combine with AND, and each hit names where a matched value came from.
Use it for 'list the services of the Infrastructure layer' or 'which types carry role X?'. At least one filter is required.
layer and role match the WHOLE value, case-insensitively: role='View' is one view, not every ViewModel. Values that merely contain the query are counted in nearMisses (axis, value, symbols) and named in a leading 'note', never listed as matches. domain and responsibility are free text and match as a case-insensitive substring; responsibility exists on types only, so setting it matches no method. The echoed criteria show the mode ('role=View' vs 'domain~order').
Returns criteria, a 'note' when there are near misses, minConfidence, matches - at most 200 items (kind, name, declaringType, namespace, matched), types first - and when they apply availableAxisValues and nearMisses. matched lists per filtered axis the field, the value and its source: 'fact', 'ai', 'inferred' or 'none'.
The layer and role values the built-in inference assigns are listed on those parameters; there is no 'Repository' role and an enum gets none. A layer profile or an annotation adds values in its own spelling ('viewmodel-item' beside 'ViewModel'). Nothing infers a domain: that axis matches only where an annotation set one.
On zero matches availableAxisValues lists, for the queried axes, the values present under the same minConfidence (up to 50 per axis; the key is absent when there are none). A queried value missing from it is unknown at that confidence; if it is listed, the AND of your filters was empty.
Read-only; test-project symbols are matched like production ones.
| Name | Required | Description | Default |
|---|---|---|---|
| role | No | Match symbols whose resolved Role EQUALS this (whole value, case-insensitive). Inferred TYPE roles: Service, Helper, Model, Record, Interface, Builder, ViewModel, Converter, Controller, Middleware, Attribute, Exception, EntryPoint, ContractModel, Type - there is NO 'Repository' (a repository class is mostly 'Service'), and an enum gets no role. Methods use a category role (e.g. Query, Command, Mapping, Validation, Orchestration). <ai>-asserted roles add values of their own. Omit to not filter on role. | |
| layer | No | Match symbols whose resolved Layer EQUALS this (whole value, case-insensitive). The built-in inference assigns Domain / Application / Infrastructure / Presentation / Contracts; a layer profile adds its own names. Omit to not filter on layer. | |
| domain | No | Match symbols whose resolved Domain contains this (free text, set by an <ai> annotation - nothing infers it). Omit to not filter on domain. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| minConfidence | No | Confidence floor: 'any' (default - include inferred guesses) or 'asserted' (only fact/ai). Any other value is rejected (not silently treated as 'any'). | any |
| responsibility | No | Match TYPES whose resolved Responsibility contains this (types only; free text). Omit to not filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false), so the bar is low, and the description far exceeds it: it discloses max 200 items and types-first ordering, whole-value vs substring match modes, near-miss behavior, zero-match behavior of availableAxisValues, the fact that domain/responsibility are never inferred, that there is no 'Repository' role, and that test-project symbols are matched like production ones.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is long, but front-loaded with purpose and usage before the matching mechanics, return shape and edge cases, and nearly every sentence adds operational information an agent needs. Slightly dense across eight paragraphs rather than ruthlessly trimmed, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description carries the return-value burden and does so fully – criteria, note, minConfidence, matches (kind, name, declaringType, namespace, matched), matched source provenance, plus availableAxisValues and nearMisses when applicable. Nothing an agent needs to call and interpret it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: filters combine with AND, layer/role match the whole value case-insensitively while domain/responsibility match as substrings, responsibility applies to types only, minConfidence rejects unknown values, and the echoed criteria encode the mode ('role=View' vs 'domain~order').
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource – find types and methods by their resolved semantics (layer, role, domain, responsibility) – which is a clear, distinctive capability. Concrete usage examples ('list the services of the Infrastructure layer', 'which types carry role X?') sharpen the intent. It does not name a sibling such as find_by_attribute or find_symbol to draw the boundary explicitly, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use examples and a hard precondition ('At least one filter is required'). It does not, however, state when to prefer an alternative tool or when this is the wrong choice, so the routing guidance to siblings is incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_by_side_effectsFind Methods by Side EffectsARead-onlyIdempotent
Find code by its side-effect profile: what a method touches in the outside world. Each unit carries effect tokens from a closed set - io, network, database, serialization, logging, cache, messaging, unknown ('unknown' = an external call the analysis could not classify) - or none, which makes it pure. calls_external lists the external calls and property accesses behind a token; an effect that comes from a 'new X()' or is inherited from a callee has no row there.
Use it for 'what hits the database or the network?' and to find pure methods. Effects are propagated along calls and creations: calling a method or building an object that writes a file counts as 'io'.
With neither effect nor purity, only impure units are listed. An effect or a purity outside its vocabulary is rejected with the valid values, never answered with a silent zero; effect together with purity='pure' is rejected too.
Returns scope, effect, purity, methodsScanned, matches - a capped envelope of at most 200 hits (name, declaringType, namespace, effects), sorted by type and name - and when they apply 'note', availableEffects and testMatchesFiltered. The units are methods plus every accessor and constructor with a body, under their metadata names (get_X, set_X, .ctor, .cctor); the purity='pure' listing is methods-only. A hit does not say which of its effects are direct and which inherited.
On zero matches availableEffects lists the tokens present in scope, so an empty result reads 'valid token, nothing in scope records it'; the note quotes what the token means ('cache' = calls into an external cache API, not a cache held in memory). availableEffects is omitted when methodsScanned is 0: nothing was scanned. A 'note' leads the answer when a project's core references did not resolve: an unresolved run reports methods as PURE that are not.
Read-only; works on a recalled session. Test-project code is excluded by default (includeTests=true includes it); testMatchesFiltered counts what the filter removed, units methodsScanned does not include.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default) or a namespace prefix (e.g. 'MyApp.Infrastructure') to narrow scope. | solution |
| effect | No | Filter to methods carrying this effect token - exactly one of: io, network, database, serialization, logging, cache, messaging, unknown (case-insensitive; any other value is rejected, not answered with zero). Omit to not filter on a specific effect. | |
| purity | No | 'any' (default), 'pure' (only side-effect-free methods), or 'impure' (only methods with at least one effect). | any |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test-project methods (default false - production focus: a 'what hits the DB?' query is otherwise drowned by Seed*/Migrate_*/*RepositoryTests). Set true to also list the methods of test projects. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the read-only/idempotent annotations: it discloses the 200-hit cap and sort order, the rejection semantics for out-of-vocabulary tokens and the effect+purity='pure' combination, the empty-result behavior via availableEffects, the unresolved-reference warning that can falsely report methods as pure, and that a hit does not distinguish direct from inherited effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in sentence one, and the dense prose largely earns its place by carrying behavioral detail no other field provides. It is on the long side and could be tightened (token meanings in a note could be shorter), but there is little outright waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite there being no output schema, the description fully covers the return envelope (scope, effect, purity, methodsScanned, matches, note, availableEffects, testMatchesFiltered), the units included (methods, accessors, constructors, .ctor/.cctor), and caveats like the unresolved-reference purity warning. An agent has everything needed to call and interpret this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the 3 baseline is met by the schema alone, but the description adds real meaning: effect tokens are a closed set where an invalid value is rejected rather than answered with zero, effect combined with purity='pure' is rejected, purity='pure' restricts the listing to methods only, and includeTests excludes test code by default with a stated rationale.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Find code by its side-effect profile: what a method touches in the outside world.' It defines the closed token vocabulary and what a hit contains, so an agent can distinguish this from siblings like find_by_semantics, find_usages, or usage_report without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use framing: "Use it for 'what hits the database or the network?' and to find pure methods," plus the fallback behavior when neither filter is supplied. It gives clear context but never names an alternative tool or an exclusion (e.g., when to prefer calls_external or find_binding_usages instead).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_dead_codeFind Dead CodeARead-onlyIdempotent
List dead-code suspects on two axes. kinds='type': types with no incoming reference in the reverse type fan-in, the source find_usages reads. kinds='method' (the default): PRIVATE methods whose recorded caller list is empty. kinds='all': both.
The default axis skips a private method a framework may call ([RelayCommand] or other framework attributes, partial methods, markup or designer event handlers, static Main, record PrintMembers, ShouldSerialize/Reset) or whose callers were not measured (unresolved references, explicit interface implementations). A nameof in a method's attribute (CanExecute) is a call. *.Designer.cs and *.g.cs files are read for references, never judged.
Returns scope, a 'note' first when there is one, methodsScanned, deadMethods and - when the type axis ran - typesScanned and deadTypes: at most 200 items each (methods: name, declaringType, namespace; types: name, kind, accessibility, namespace). Counters, each omitted at zero: what was not judged - methodsIneligible (split into methodsIneligibleNotPrivate, methodsIneligibleFrameworkInvoked and methodsIneligibleUnanalyzedCallers), typesIneligible (split into typesIneligibleStructural, typesIneligibleTestScaffolding, typesIneligibleFrameworkActivated, typesIneligibleMarkupReferenced), typesUnexamined (types the type axis would have judged had it run) - and the candidates the test filter removed, testMethodsFiltered and testTypesFiltered.
A listed candidate is a suspect: the note names what a zero fan-in does not prove and how to confirm one. The type axis exempts what it cannot see being used: interfaces, static classes, types named *Extensions, test scaffolding, framework- or reflection-activated types and markup-referenced types. An empty answer without a note means at least one axis judged an eligible population and found nothing; for the method axis read methodsIneligible against methodsScanned.
Read-only; works on a recalled session. Test projects are excluded by default. Any other non-blank kinds value runs both axes.
| Name | Required | Description | Default |
|---|---|---|---|
| kinds | No | 'method' (default): private methods with a measured, empty caller list - see the description for what that axis does not judge; 'type': types with no incoming reference; 'all': both. | method |
| scope | No | 'solution' (default) or a namespace prefix (e.g. 'MyApp.Core') to narrow scope. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test-project methods/types (default false - production dead-code; a private test-helper without callers is not production dead code). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry read-only/idempotent/non-destructive, and the description goes well beyond them: it discloses the 200-item cap, that a listed candidate is only a suspect rather than proof, the exact exemptions (framework attributes, partial methods, Designer/generated files, static Main, PrintMembers, ShouldSerialize/Reset), which caller scenarios are not measured, and how to read an empty result against methodsIneligible. That is rich behavioral context rather than a restatement of the hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and organizes the body by axis, exemptions, then return shape, so the structure is sound. It is nonetheless dense and uses long run-on sentences (the eligibility/exemption sentence in particular), which costs some readability even though most sentences carry distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry the return contract, and it does: it names every returned field (scope, note, methodsScanned, deadMethods, typesScanned, deadTypes), the per-item shape, the counters and their zero-omission behavior. Combined with the exemption rules and the semantics of an empty result, an agent has enough to invoke and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents kinds, scope, sessionId and includeTests; baseline is 3. The description adds only marginal meaning beyond that — notably that an empty answer without a note implies an eligible population was judged, and that any other non-blank kinds value runs both axes — while not adding scope syntax or sessionId behavior beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List dead-code suspects') and enumerates the two distinct axes it operates on (types with no incoming reference vs. private methods with empty caller lists). It also names the related sibling 'find_usages' as the source of the reverse type fan-in, letting an agent place it relative to siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear selection guidance for the `kinds` axis, states the default (method), explains when to widen to 'all', and documents that test projects are excluded by default and what happens when other kinds values are passed. It does not, however, explicitly contrast the tool against plausible alternatives such as coverage_gaps or impact_of_change for a 'is this safe to delete' decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_implementationsFind ImplementationsARead-onlyIdempotent
List the types that implement an interface, declared in the solution or external (IDisposable, IEquatable). The interface counterpart to get_type_hierarchy (class inheritance) and find_overrides (methods).
Use it before changing an interface member, to find every type that has to follow.
Returns items [{name, isAbstract, kind, isTestProject, namespace, declaration, via}], count, totalFound, truncated - at most 100 items, sorted by name. kind is class, struct, record or interface; isAbstract marks an abstract base ('FooBase : IFoo'); 'declaration' is a generic implementer's arity-qualified form ('PolicyWrap'); via:'back-edge' marks an item known only from the interface's own implementer list, via:'inherited' one that gets an external interface through a solution base class or interface.
A closed query ('IHandler') lists the types closing it with those arguments, via bases and generic interfaces too; typeArgumentFilter counts the arity-matching types (tests too) closing it otherwise (otherClosings) or only over their own type parameters (openClosings). An unreadable closing stays, marked closing:'unresolved'.
Test-project implementers are excluded by default; testImplementationsFiltered: N says how many (absent = none), so a short list is never silently short.
An empty answer carries a 'hint' when the name is not an interface (use get_type_hierarchy or find_overrides) or no indexed type carries it (a did-you-mean when one is close; a delegate counts as undeclared), and a 'generatedCodeNote' when a source generator that did not run may have added the interface. When a project's core references did not resolve, a leading 'note' marks the inventory as partial until restore or build, then refresh_session.
Read-only. interfaceName is the simple name, case-sensitive: a namespace-qualified name matches nothing. Two interfaces that share a simple name answer as one list.
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include test-project implementers (default false - production focus). | |
| interfaceName | Yes | The interface's simple name, e.g. 'ICodeAnalyzer'. An arity suffix ('IConsumer`1' / 'IConsumer<T>', or 'IConsumer`0' for the non-generic namesake) filters to that arity; a bare name keeps the merged view of every arity. A concrete type argument ('IConsumer<OrderPlaced>') keeps only the types that close it with that argument. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (read-only, idempotent, non-destructive); the description goes well beyond them, disclosing the 100-item cap and name sort, the default exclusion of test implementers plus the testImplementationsFiltered counter ('so a short list is never silently short'), unresolved-closing marking, partial-inventory notes, generatedCodeNote, and hint behaviour. This is exactly the operational context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and the sibling routing before the edge-case detail, and each sentence carries information. It is dense to the point of being long for a 3-parameter tool, but there is little outright waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return contract itself: field list {name, isAbstract, kind, isTestProject, namespace, declaration, via}, count/totalFound/truncated, and the meaning of kind and via values. Nothing an agent needs to interpret or trust the result appears missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the arity suffix and concrete-type-argument forms, so the baseline is 3. The description nonetheless adds non-obvious semantics the schema omits: the name is case-sensitive, a namespace-qualified name matches nothing, and two interfaces sharing a simple name answer as one merged list.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb+resource: 'List the types that implement an interface.' It also positions itself against named siblings — 'the interface counterpart to get_type_hierarchy (class inheritance) and find_overrides (methods)' — so an agent can discriminate without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('Use it before changing an interface member, to find every type that has to follow') and routes elsewhere when the query is wrong ('when the name is not an interface (use get_type_hierarchy or find_overrides)'). Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_overridesFind OverridesARead-onlyIdempotent
List the override-to-base relationships for methods of a given name - the class-inheritance counterpart to find_implementations (which covers interfaces). Each row pairs an overriding method with the nearest ancestor in its base-class chain that declares the virtual/abstract method it overrides: 'Derived.M(params) overrides Base'.
One call answers both 'who overrides this virtual/abstract method?' (impact, before you change a base method) and 'what does this override?' (comprehension). For a type's base and derived types use get_type_hierarchy; for the callers of a method use find_usages.
Returns a capped envelope: items (the rows, sorted), count, totalFound, truncated - at most 100 rows. Empty items means no method of that name is an override. When the overridden base is a BCL/framework virtual outside the solution (object.ToString, Stream.Dispose) the row reads '... overrides (external base)'.
Types render in their DECLARATION FORM ('Strategy.M(...) overrides ResilienceStrategy', the render get_type_hierarchy uses), so a generic and a non-generic namesake stay separate rows. A row carries no namespace: two same-named types that differ only by namespace collapse into one row, so read a row as the relationship, not as one attributed type; 'mergedNamesakes' names each such row and its types.
Read-only: it reads persisted facts and also works on a recalled session. Parameters: a qualified methodName ('Widget.ToString') matches nothing. There is no type filter, and each overload is a row of its own. An empty answer carries 'nearest' when a close declared method name exists - for a qualified methodName the bare method name.
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| methodName | Yes | The method's exact (case-sensitive) simple name, e.g. 'ToString' or 'Dispose'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the full safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds real behavior beyond that: a hard 100-row cap with a truncated flag, external-BCL bases rendering as '(external base)', declaration-form rendering, and namespace-based row collapsing via mergedNamesakes. It does not mention auth or rate limits, but for a read-only query tool the added result-shaping behavior is substantial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then use cases, then alternatives, then return shape - a sensible order with little padding. It runs long for a 2-parameter tool and the final sentence about 'nearest' in empty answers is dense, but each sentence carries distinct information rather than restating structured fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-shape burden and does so: it names the envelope fields (items, count, totalFound, truncated), the row format, the 100-row cap, the empty-items meaning, and the empty-answer 'nearest' hint. Edge cases (external bases, merged namesakes, qualified names) are all covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: a qualified name like 'Widget.ToString' matches nothing (schema only says 'simple name'), there is no type filter, and each overload is its own row. It also clarifies that sessionId accepts a recalled session. These are genuine usage constraints beyond the field docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the override-to-base relationships for methods of a given name') and immediately distinguishes itself from the closest sibling by naming find_implementations and the axis of difference (class inheritance vs interfaces). An agent can tell this apart from interface-implementation and hierarchy tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use framings ('who overrides this virtual/abstract method?' before changing a base method; 'what does this override?' for comprehension) and routes to two named alternatives with conditions: get_type_hierarchy for base/derived types and find_usages for callers. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_resource_usagesFind XAML Resource UsagesARead-onlyIdempotent
Resource-key fan-in across the solution's XAML/AXAML markup AND its C# sources - the question the C# symbol graph cannot answer because resources are wired by string key, not by symbol. With a key: where it is DEFINED (x:Key, file:line), every REFERENCE (file:line + kind - 'static'/'dynamic' for the markup extension, since a theme-swapped brush must be dynamic, and 'code' for a C# string literal equal to the key), and same-file duplicate definitions (in a compiled resource dictionary a duplicate silently shadows a neighboring key; a same-named key in DIFFERENT files is usually a legitimate theme pair, so only same-file counts as a collision). Without a key: the audit view - every never-referenced key (deletion candidates; deleting a still-referenced key compiles clean and throws only at runtime) + all same-file collisions. Reads the CURRENT .xaml/.axaml/.cs files on disk (bin/obj/.vs excluded, same discovery as the analyzer) - never stale after an edit, no refresh_session needed, works on recalled sessions. STRING keys only (a structural x:Key="{x:Type ...}" is out of scope); the forms that name the key - {StaticResource ResourceKey=...} and the element - are read. XML-commented markup is ignored. Fan-in comes from TWO channels: the solution's markup ({StaticResource}/{DynamicResource}) and C# string literals equal to the key - the TryFindResource channel, reported as kind 'code' with its file:line because a matching literal is not by itself proof of a resource lookup (it may be a test assertion, or a doc-comment cref naming a same-named converter type). Still invisible: a key ASSEMBLED at runtime (interpolated or concatenated), a source file that is not .cs, and a third-party library template resolving the key from ITS OWN dll (e.g. a theme library's DynamicResource re-key) - zero references means 'verify before deleting', not proof. Lists capped at 200.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | The exact (case-sensitive) resource key, e.g. 'TextPrimaryBrush'. Omit for the audit view (never-referenced keys + same-file collisions). | |
| scope | No | 'solution' (default) or a view-path substring (e.g. 'AIContextBuilder.UI/') to narrow which files are reported. In the audit view the scope narrows the DEFINITIONS under audit; references still count solution-wide, so a key referenced outside the scope is not a false orphan. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly/idempotent/non-destructive), yet the description adds substantial context beyond them: it reads current files on disk with bin/obj/.vs excluded, is never stale so no refresh_session is needed, works on recalled sessions, only handles string keys (not {x:Type ...}), ignores XML-commented markup, and caps lists at 200. The 'code' kind caveat (a matching literal is not proof of a lookup) is exactly the kind of nuance annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and the key-vs-audit branching, and nearly every sentence carries real information. It is a dense wall of text, though, and the C# string-literal caveat is restated in the fan-in paragraph after already being introduced in the reference-kind sentence, which costs some clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-value burden and does so: it describes definitions as x:Key file:line, references as file:line + kind ('static'/'dynamic'/'code'), same-file duplicate definitions, and the 200-item list cap. Combined with the stated blind spots, an agent has everything needed to call it and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents key (case-sensitive exact match, omit for audit view), scope (solution vs view-path substring, references still counted solution-wide), and sessionId. The description reinforces the key/no-key split but adds no syntax or format detail beyond what the schema provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (find resource-key fan-in across XAML/AXAML markup and C# sources) and explicitly positions itself against the sibling capability ('the question the C# symbol graph cannot answer because resources are wired by string key, not by symbol'). An agent can distinguish it from find_usages and find_binding_usages without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use branching: with a key -> definition/reference lookup; without a key -> audit view of never-referenced keys and same-file collisions. It also states when the tool is insufficient (runtime-assembled keys, non-.cs source files, third-party dll templates) and what a zero-reference result actually means ('verify before deleting', not proof).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_symbolFind a Symbol by NameARead-onlyIdempotent
Find types, methods, properties, fields, events, enum members and operators whose name contains the query (case-insensitive). Returns each match with kind ('type'/'method'/'property'/'field'/'event'/'enum_member'/'operator'), name, declaring type, namespace, a signature, and 'project' where two hits would read alike. Use this to locate a symbol before calling find_usages / call_graph / get_context - every kind listed here is one find_usages / impact_of_change resolve, an operator by its metadata name with its uses (a == b, a cast, an implicit conversion) as the fan-in. Types are listed first, then methods, then properties (handwritten + source-generated - a generated property carries a '// source-generated' note in its signature), then fields, events and enum members (an enum member's signature is its qualified Enum.Member form, the string the fan-in tools take), then user-defined operators + conversions. A user-defined operator is found by its METADATA name (query 'op_Equality' / 'op_Addition' / 'op_Implicit'; 'op_' lists them all). Not indexed, so an empty answer is expected for them: local variables, parameters, labels, namespaces, and C# generated into obj/ that carries real declarations (protobuf/Grpc.Tools, T4, Refit), and a Blazor component written only in a .razor file - a zero-hit answer says which in 'generatedSourcesNote'. Results are ranked by match quality FIRST - exact name, then case-insensitive exact, then prefix, then substring - and only within one rank by the kind order above; an exact match is therefore never hidden by the cap behind weaker substring hits (a symbol named 'Type' used to sit at position 1026 of 1102). Returns a capped envelope (items/count/totalFound/truncated), max 100 - if truncated, the exact/prefix matches are the ones you got; narrow the query (a longer substring) to see the weaker rest. If the query matches nothing, the response carries a 'nearest' suggestion - the closest declared symbol name (a likely typo/case-mismatch); a matched symbol never carries one.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | A substring of the symbol name to search for (type, method, property, field, event, enum member or operator). | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description still adds substantial behavioral context: what is deliberately not indexed (locals, parameters, labels, namespaces, generated obj/ declarations, .razor-only components) surfaced via 'generatedSourcesNote', the ranking algorithm (exact > case-insensitive > prefix > substring, then kind order), the 100-item cap and truncation semantics, and the 'nearest' suggestion on zero hits. These are genuinely beyond what the annotations provide, though the density makes some details hard to parse.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in sentence one, but the body is a single very dense paragraph that mixes ranking rules, kind ordering, non-indexed cases, truncation and typo handling. Anecdotes like the 'Type at position 1026 of 1102' history and the parenthetical asides inflate length without helping selection or invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description fully describes the return shape (items/count/totalFound/truncated, max 100), per-item fields (kind, name, declaring type, namespace, signature, project), and edge-case payloads ('generatedSourcesNote', 'nearest'). Nothing an agent needs to interpret or act on the response is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description nonetheless adds meaning beyond the schema: case-insensitive substring semantics, the operator metadata-name convention ('op_Equality', 'op_Implicit', 'op_' lists all), and what an enum member signature looks like. That is real added value over the two documented params.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Find types, methods, properties, fields, events, enum members and operators whose name contains the query') and enumerates exactly what the search covers. It is clearly distinguishable from siblings like find_usages, call_graph and get_context, which it explicitly positions itself as a precursor to.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use rule ('locate a symbol before calling find_usages / call_graph / get_context') and explains the handoff mechanism (every kind listed is one those tools resolve; operators by metadata name). It also tells the agent what to do when results are truncated or empty, which is actionable routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_tests_forFind Tests for a SymbolARead-onlyIdempotent
Find the test cases that likely cover a symbol: test methods that call it, read it, build it or are named after it. Static evidence, not a coverage run; coverage_gaps asks the reverse for a scope.
Use it before changing a symbol, to see what pins it, and after, to pick tests. Only a method that itself carries a test attribute counts (by default Fact, Theory, Test, TestMethod, TestCase).
Returns items [{testType, testMethod, project, matchReason}], count, totalFound, truncated (at most 50), invokesTotal, dispatchTotal (omitted at 0) and an optional 'note' after the list. matchReason is one of nine tiers, in sort order: 'invokes' (the test calls the target), 'invokes-via' (through one method or constructor it calls), 'accesses' (it reads or writes the target property or field; for a type, a static one), 'accesses-via', 'constructs' (it builds the target type; type and constructor queries only), 'constructs-via', 'dispatch' (it calls an interface or abstract member the target implements; a test double may have run instead), 'dispatch-via' and 'name' (a guess: the test's or its class's name mentions the symbol - for Type.Member, both names). The first six are strong. invokesTotal counts the strong rows and dispatchTotal the contract rows over the whole result, so totalFound minus both is the name guesses.
The evidence reaches two hops at most - the test and one method or constructor it calls or getter it reads - so a deeper chain is not counted, and an empty answer is not 'nothing pins this'. The 'note' says so on an empty answer, and names the other cases where numbers mislead: an undeclared name or type segment (every hit is name noise), an event or enum member (only the name tier can match), a nested type in the 'Outer.Inner' form, a constructor query, contract rows, construction rows (matched on the type's simple name, so a namesake counts too).
Read-only. symbol is case-sensitive: a type's simple name, a member name bare or as 'Type.Member' (only that type's member), or 'Type.Type' for the constructor.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | The type name, or the member name - bare or in the qualified Type.Member form - to find covering tests for. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), but the description adds substantial context beyond them: the two-hop evidence limit, the truncation cap of 50, the meaning of an empty answer, and the specific cases where the returned numbers mislead (undeclared names, event/enum members, nested types, constructor queries). This is unusually rich disclosure for a read-only tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and the sibling distinction, and each sentence carries information an agent needs. The middle paragraph enumerating nine matchReason tiers is dense, but with no output schema this return-value semantics has to live somewhere. Slightly heavy, though nearly every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the full burden of explaining the return shape, and it does: the item fields, count/totalFound/truncated, invokesTotal/dispatchTotal, the optional note, and the tier taxonomy in sort order. Combined with the case-sensitivity rule for the input, an agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real meaning beyond the schema: 'symbol is case-sensitive' and the three accepted forms including 'Type.Type' for a constructor, which the schema does not spell out. The added constraint materially affects how an agent passes the argument.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('find the test cases that likely cover a symbol') and immediately scopes what counts as evidence ('static evidence, not a coverage run'). It explicitly distinguishes itself from the sibling coverage_gaps ('asks the reverse for a scope'), so an agent can route between the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance in both directions of a workflow: 'before changing a symbol, to see what pins it, and after, to pick tests.' It also names the alternative tool and the condition that selects it, and states what the tool is NOT (a coverage run).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_unresolved_bindingsFind Unresolved XAML BindingsARead-onlyIdempotent
List silently broken XAML bindings: a {Binding X} whose root member does NOT exist on its confidently resolved DataContext view-model (typo, removed/renamed member, or wrong DataContext) - the defect class that NEITHER the compiler NOR render-smoke tests catch.
Use it after renaming or removing view-model members. It judges the ROOT member of a binding path only. To see where a member or a resource key is bound use find_binding_usages / find_resource_usages.
Covers WPF/WinUI .xaml (view-model via d:DesignInstance or a unique FooView->FooViewModel convention) and Avalonia .axaml ({Binding}/{CompiledBinding}, only via x:DataType). Conservative BY SKIPPING, and the skip is what carries the accuracy claim: a binding whose DataContext scope cannot be typed with certainty (ControlTemplate/Style, runtime DataContext, keyed resources, a DataType-less template unless - WPF only - its host's ItemsSource types it), or whose view-model has an unverifiable external base, is never flagged - a recall miss, never a false report. Source-generated ([ObservableProperty]/[RelayCommand]) and inherited members count as resolved. One false-report class was measured: a HierarchicalDataTemplate's own ItemsSource mis-pinned onto its content read 8/8 false on MahApps.Metro and is fixed + fixture-pinned (0 after). So read a hit as high-confidence evidence to verify at its file and line, not as proof.
Returns JSON: count and unresolvedBindings (view, viewModel, member, line; one entry per site), plus markupFilesScanned and bindingSitesInMarkup from a live disk walk, which tell a clean zero from 'no markup at all'. The denominator of count: sitesJudged (root member checked on a resolved type) and sitesSkipped, by reason in sitesSkippedBy; judgementNote names any gap to bindingSitesInMarkup. Both null on a recalled session.
Read-only. The findings come from the LIVE analysis: call refresh_session after edits. A recalled DB snapshot reports none, and a 'note' says so when the session looks recalled.
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations covering the safety profile (readOnly/idempotent/non-destructive/closed-world), the description still adds substantial behavioral context the annotations cannot: the conservative 'skip carries the accuracy claim' recall-vs-precision contract, the single measured false-report class with its fixture-pinning, the caveat that a hit is evidence to verify not proof, and the live-analysis requirement ('call refresh_session after edits') plus the recalled-snapshot failure mode.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and routing before drilling into coverage mechanics, returns, and caveats, and each paragraph has a distinct role. It is nonetheless very long and dense for a one-parameter tool, with the skip/accuracy rationale restated, so it stops short of maximal conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description fully specifies the return shape (count, unresolvedBindings with view/viewModel/member/line, markupFilesScanned, bindingSitesInMarkup, sitesJudged, sitesSkipped, sitesSkippedBy, judgementNote) and how to interpret a zero. Nothing an agent needs to call or correctly read the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
One parameter with 100% schema coverage, so the schema fully documents sessionId (session_id from analyze_solution, or an absolute .sln/.slnx/.slnf path). The description adds no additional syntax or format meaning beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List silently broken XAML bindings: a {Binding X} whose root member does NOT exist on its confidently resolved DataContext view-model') and pins the exact defect class ('neither the compiler nor render-smoke tests catch'). It distinguishes itself from find_binding_usages and find_resource_usages by name, so an agent can route without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('Use it after renaming or removing view-model members'), states its scope limit ('judges the ROOT member of a binding path only'), and names the alternatives for the adjacent task ('To see where a member or a resource key is bound use find_binding_usages / find_resource_usages'). When-to-use, when-not, and alternatives are all present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_usagesFind Usages of a SymbolARead-onlyIdempotent
List who uses a symbol: its direct fan-in. impact_of_change adds the closure and risk; calls_external covers external members.
Use it before changing or deleting a symbol, instead of grepping a C# name. What is listed depends on resolvedKind: 'type' - the types that reference it (a doc cref too, unmarked), plus markup views; 'method' - its callers, overloads unioned; 'property' or 'field' - its readers and writers; 'event' - its raisers and (un)subscribers; 'enum_member' - its references; 'operator' ('op_Equality') - its uses, casts too; 'constructor' ('Type.Type') - the type's construction and injection sites. Test users included.
Returns symbol, resolvedKind and usedBy, a capped envelope (items, count, totalFound, truncated; at most 100). An item is {name, file, line}, one per user: file is solution-relative, line where its declaration starts (not the reference); 'files' [{file, line}] for a type declared in several; absent if unknown; users sharing a name add 'fullName' (a type), 'project'. Optional members qualify it: 'note' ahead of the list (an empty answer, a constructor answer, or unresolved core references), 'namesakes' (several types share the name; usedBy unions them), 'collision' (a bare name: a same-named symbol of another kind, not counted), 'viaContract' + 'viaContractNote' (a qualified method: its contracts' callers), 'selfReferences' (users of a member on its own type), 'textuallyInvisibleUsers' (users whose source never names it), 'nearest' (on 'not_found': a close declared name).
An empty usedBy on a resolved symbol is not proof of dead code: an entry point, DI, reflection, a source generator and unrecorded markup forms leave no reference. 'not_found' is not 'undeclared': a delegate type and a qualified or nested type name answer it too; 'note' may say why.
Read-only. symbol is case-sensitive. A type takes its simple name. A member takes 'Type.Member' for one type's, or a bare name: that answers for ONE kind, the first in the order above with users, unioned over its same-named members.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | The exact (case-sensitive) type, method, property, field, event, enum-member or operator (metadata) name - the qualified Type.Member form for a member - or 'Type.Type' for a type's CONSTRUCTOR (see the tool description: the answer is the type's construction/injection sites, overloads unioned). | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, non-destructive), and the description goes well beyond them: the capped envelope (at most 100, truncated flag), the meaning of empty results, namesake/collision semantics, selfReferences and textuallyInvisibleUsers, and not_found caveats. This is unusually rich disclosure for a read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and routing are correctly front-loaded, and most clauses carry genuine behavioral content, but the middle is a dense run-on of semicolon-chained enumerations (resolvedKind branches, envelope fields, optional members) that is hard to scan. It is informative but over-sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry return semantics — and it does fully: top-level fields, the usedBy envelope, per-item shape {name, file, line}, multi-file declarations, fullName/project disambiguation, and all optional qualifier members. Nothing an agent needs to interpret the response is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters, but the description adds real meaning: how symbol resolves differently by resolvedKind (type/method/property/field/event/enum_member/operator/constructor) and the case-sensitivity constraint. It goes beyond the schema's restatement of the Type.Member/Type.Type forms.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 'List who uses a symbol: its direct fan-in.' It immediately distinguishes itself from siblings by naming impact_of_change (closure/risk) and calls_external (external members), so an agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States explicit when-to-use ('before changing or deleting a symbol'), when-not (instead of grepping a C# name), and the alternatives for the adjacent cases. It even covers edge conditions — empty usedBy is not proof of dead code, 'not_found' is not 'undeclared' — so the agent knows how to interpret negative results.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_contextGet Code Context for a SymbolARead-onlyIdempotent
Return a dense, token-budgeted AI-Builder-Markdown slice of the code around a symbol: the symbol's source plus its expanded neighborhood (direct dependencies + callees, depth 1). Pass a type or method simple name (use find_symbol first to disambiguate). budget caps the output in tokens (floored at 8000); omit for full bodies. The fastest single-symbol retrieval - prefer it over export_markdown (which renders the WHOLE solution) when you only need one symbol's context. Multi-TFM solutions are deduplicated to one logical project per name, keeping the NEWEST TFM's instance (matching find_symbol's view; export_markdown keeps the unfiltered per-TFM render). Need a CHOSEN environment of one symbol (callers / tests / implementations / quality)? use explain_symbol. Bundling a whole task from a natural-language goal? use pack_for_task (read) or prepare_task (edit-ready: + covering tests & siblings).
| Name | Required | Description | Default |
|---|---|---|---|
| lean | No | Lean slice (default TRUE): drop the repeated <AI_CONTEXT_SPEC> format-rules preamble and the <AI_CONTEXT_META> block, and omit any enabled-but-empty graph section (the ones that would otherwise render just '- none'). On a focused single-symbol slice that boilerplate is >4x the actual signal. The PATH_LEGEND, COMPRESSION_LEGEND (decoding keys) and all non-empty sections are kept. Set false to get the full AI-Builder-MD document with the format contract. | |
| budget | No | Optional token budget (floored at 8000). Caps the slice TWO ways: it compacts/drops method bodies AND - when the expanded neighborhood still overflows - drops the least-relevant non-seed types entirely, ranked by closeness to the seed and in-slice fan-in. The seed itself is never dropped: it renders with its full source when that fits the budget, otherwise as STRUCTURE (identity, members, every method signature) with a leading note naming the measured size of the full-code render and the budget that holds it. A leading comment discloses how many types were dropped. Omitted, the slice still renders against a ceiling (the active MCP profile's token budget, else a ~10000-token default budget) that bounds the neighborhood; pass a value for a tighter slice. | |
| symbol | Yes | The type or method simple name to center the slice on. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeQualityMetrics | No | When true, also emit the <QUALITY_HOTSPOTS> section plus complexity=""/ce="" tag attributes for the sliced symbols (cyclomatic complexity, efferent coupling). Default false (leaner slice). Set true when reviewing code quality / picking refactor targets. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds substantial non-obvious behavior: the 8000-token budget floor, the two-way budget compaction, that the seed is never dropped and degrades to STRUCTURE, disclosure comments for dropped types, and Multi-TFM dedup keeping the NEWEST TFM's instance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose in the first sentence, then routing. The routing paragraph is long and slightly dense with parentheticals, but each clause carries actionable routing or behavioral information rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description explains the return shape (AI-Builder-Markdown, kept legends, dropped sections, optional QUALITY_HOTSPOTS) and the constraints that govern it. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the parameter docs are already rich, but the description still adds decision value beyond the schema, e.g. when to pass includeQualityMetrics (reviewing quality / picking refactor targets) and the practical meaning of omitting budget versus tightening it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: returns a dense, token-budgeted Markdown slice of the code around a symbol, including its depth-1 neighborhood. It also explicitly differentiates itself from export_markdown (whole solution) and explain_symbol (chosen environment), so an agent can pick it apart from siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: prefer over export_markdown for a single symbol, use explain_symbol for callers/tests/implementations/quality, use pack_for_task or prepare_task for whole-task bundling. It also states the prerequisite (use find_symbol first to disambiguate).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_diagnosticsGet Compiler DiagnosticsARead-onlyIdempotent
Compiler errors and warnings without a build: every C# project of the session is compiled in memory, in seconds. list_insights reports design findings instead.
Use it after editing .cs files: refresh_session, THEN this - the diagnostics come from the session's snapshot, not from disk, and an answer known to be behind the disk leads with verdict:'stale'. After a restore or build call refresh_session(force: true): an unforced refresh can answer 'unchanged'.
Returns verdict (only when stale or inconclusive), projectsScanned, errorCount, warningCount, infoCount and diagnostics: at most 200 items (id, severity, message, location, category, project), while the counts cover the full set. A multi-targeted project reports a diagnostic once; #pragma-suppressed ones are excluded. No analyzer runs, the SDK's included; source generators that load do run.
Disclosures say what the counts leave out:
incompleteProjects, incompleteRatio, suppressedDiagnosticsTotal: projects whose core references did not resolve (e.g. no targeting pack). Their diagnostics are counted, not listed. Read that total as a MAGNITUDE, not as one half of a ratio with errorCount. verdict:'inconclusive' + reliable:false fire only when a strict majority of projects is incomplete, because a judgement that triggers on every partly-restored solution is one a caller learns to ignore.
cascadeFromIncomplete:true on an item: inherited from an incomplete project.
generatedCodeGaps: code a source generator or the WPF markup compiler writes is missing.
designTimeBuildFailures: MSBuild reported a failure loading a project (a warning reads alike); its compiler options may be incomplete.
Needs a live session (a recalled one is rejected); writes nothing. scope: 'solution' or a case-insensitive substring of an item's location - for a file under the solution folder its relative path, with the OS separator (backslash on Windows). It filters the ANSWER, not the work: every project is compiled either way. Use scope to save context tokens, never to save time.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default) or a file-path substring (e.g. 'MyApp.Core' or 'Settings.cs') that filters the RESULT. It is matched against a diagnostic's location as the answer prints it, so a directory separator is a backslash on Windows. It does not reduce the work: all projects are compiled either way (see the tool description) - it saves response tokens, not latency. | solution |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| severityFloor | No | Minimum severity to include: 'error', 'warning' (default), 'info', or 'hidden'. | warning |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so safety is covered. The description builds on that with rich behavior no structured field captures: snapshot-based rather than disk-based results, verdict:'stale' semantics, the #pragma exclusion, the 200-item cap with full counts, incompleteProjects magnitude caveat, cascadeFromIncomplete propagation, generatedCodeGaps, and designTimeBuildFailures. This is well beyond the annotation bar.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the primary purpose, then sequencing, then the verdict/return contract, then disclosures. Dense but the disclosures block is a long list of caveats that, while valuable, makes the description heavy. Structure is logical and every clause earns its place, but the volume is near the upper limit for one tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 params, no output schema, and complex return semantics, the description supplies the return shape (verdict, projectsScanned, counts, up-to-200 diagnostics), the meaning of stale/inconclusive verdicts, and the caveats behind the counts. An agent has everything needed to call it and interpret the result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds real meaning for scope beyond the schema: it filters the answer not the work, every project compiles either way, and the token-saving intent is stated. severityFloor is left entirely to the schema, which is fine given full coverage, but the scope nuance is a genuine addition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: compiler errors and warnings, compiled in memory without a build. It explicitly distinguishes itself from sibling list_insights, which reports design findings instead. An agent can tell what this tool does and how it differs from adjacent tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use sequencing: 'after editing .cs files: refresh_session, THEN this'. Names the stale-answer failure mode, tells the agent to call refresh_session(force:true) after restore/build, and warns that an unforced refresh may answer 'unchanged'. Also states the tool needs a live session and rejects a recalled one. This is strong routing and prerequisite guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_insightGet Insight DetailsARead-onlyIdempotent
Get the full detail of one insight (incl. the per-item Details list) by its id. Discover ids via list_insights (the producers that found issues). Ids are producer-level. An unknown/typo'd id is rejected with the known producer ids; a registered producer that found nothing this session reports that explicitly (distinct from a typo - list_insights lists only producers WITH findings, so a 0-finding id is not discoverable there). Details default to the top 20 items (a '(... and N more)' marker discloses the rest); pass maxDetails to raise that cap for a full per-item drill-down. Pass dbPath to use the active QualityProfile from that DB (same semantics as list_insights, incl. the explicit-layerProfile precedence). Triage-filtered like list_insights, on BOTH axes: detail lines removed by a suppression ('by design', DB + sidecar) or by a dismissal ('seen', solution record) are gone, and 'suppressedDetailCount' reports the two ADDED TOGETHER (absent = none) - so it is not a count of sidecar entries. A producer silenced outright reports as 'registered but 0 hits'.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND the configured default layer profile (DefaultLayerProfileName / per-solution) drives the layer-violation analysis (an explicit analyze_solution(layerProfile) wins). Omitted, the QualityProfile falls back to the server's default config DB (the GUI's, if resolved), else the default profile, and the layer profile to the config DB the session was analysed against - the one its renders read. | |
| insightId | Yes | The producer-level insight id, e.g. 'quality-long-methods' (discover via list_insights; an unknown id is rejected WITH the known ids). | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| maxDetails | No | Optional cap on the returned Details list (default 20). Raise it (e.g. 200) for a full per-item drill-down of this insight; a '(... and N more)' marker still discloses any remainder beyond the value. Applies only to this call; ignored (default cap) when omitted or <= 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds substantial behavior beyond them: the default 20-item cap and '(... and N more)' remainder marker, the error contract for unknown ids (rejected WITH the known producer ids), the 0-findings reporting case, and the triage-filtering semantics where 'suppressedDetailCount' sums suppression + dismissal counts and is absent when zero. None of this is derivable from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and the discovery route, and every sentence carries operational information. It is dense to the point of heavy nesting (multiple stacked parentheticals in the triage sentence), which costs some readability, but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-shape burden and does so: it describes the Details list, the truncation marker, and 'suppressedDetailCount' presence/absence semantics. For a 4-param read tool with annotations covering safety, nothing needed to invoke or interpret the call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real meaning: insightId is characterized as producer-level with a concrete example shape, maxDetails is framed as call-scoped with an explicit drill-down intent, and dbPath is condensed to a reference ('same semantics as list_insights') rather than restated. It stops short of 5 because much of the dbPath/maxDetails text parallels the schema wording.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'Get the full detail of one insight ... by its id', and explicitly names the payload ('incl. the per-item Details list'). It distinguishes itself from the sibling list_insights ('the producers that found issues') so an agent can route correctly without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the discovery path explicitly ('Discover ids via list_insights'), explains the when-not edge case (a registered producer with 0 findings is not discoverable via list_insights), and gives concrete conditions for the optional params (pass maxDetails for a full drill-down, pass dbPath for DB-scoped thresholds). Alternatives and their selection conditions are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_type_hierarchyGet Type HierarchyARead-onlyIdempotent
Walk one type's inheritance in both directions: baseChain upward, derivedTypes downward, plus the interfaces the type declares. The type-level counterpart to find_overrides; for the types that implement an interface use find_implementations.
Use it before changing a base class.
Returns type, resolvedKind (class, record, struct, interface, enum or 'not_found'), baseChain, interfaces and derivedTypes, a capped envelope (items, count, totalFound, truncated; at most 100). baseChain lists the nearest base first; when the chain leaves the solution the last entry NAMES the external base ('ObservableObject (external)'). derivedTypes is transitive, one entry per type, reading 'Derived : DirectBase'; test-project types are included, unmarked. interfaces holds what the type itself declares - one inherited through a base class is not repeated - and for an interface query its base interfaces. Every link is arity-qualified ('Foo' vs 'Foo'); types sharing a name are written by full name ('Ef.User : Core.User'), adding '[Project]' where the full name is shared too.
Optional members ahead of the lists qualify them: 'mergedNamesakes' (several declared types share the simple name; the view merges them), 'separatedNamesakes' (derivations from a same-named type that is NOT the resolved one, typically a framework base shadowed by an in-solution namesake, were excluded and are counted here), 'hint' (an interface query: derivedTypes covers class inheritance only), 'note' (unresolved core references: partial until restore or build, then refresh_session).
'not_found' answers three empty lists: no type of that name is declared - also for an external base, a delegate type, a namespace-qualified name, a nested 'Outer.Inner' form, or an arity suffix no declaration has. A trailing 'nearest' gives a close declared type name, for a qualified form the simple name.
Read-only; works on a recalled session. typeName is the simple name, case-sensitive. A bare name merges a generic type with its non-generic namesake ('mergedArities' says so).
| Name | Required | Description | Default |
|---|---|---|---|
| typeName | Yes | The type's exact (case-sensitive) simple name, e.g. 'GraphSectionRendererBase'. Add an arity suffix ('Repository<T>' or 'Repository`1') to disambiguate a generic from a same-named non-generic type. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, but the description goes well beyond them: a capped envelope (items, count, totalFound, truncated; max 100), transitive derivedTypes semantics, external-base naming, the not_found contract, and refresh/restore caveats. These are behaviors an agent cannot infer from the annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded correctly: purpose first, then return shape, then edge cases, then the not_found contract. It is long and dense, but with no output schema most of the return-value detail is load-bearing rather than filler; a few clauses (arity-qualification, '[Project]' marking) push toward over-explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and a conceptually complex return, the description fully specifies the response fields, the truncation limit, ordering rules, namesake merging/separation, and the three-empty-list not_found behavior. Nothing an agent needs to interpret or call the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are already documented in the schema (case-sensitivity, arity suffix, session_id sourcing). The description nonetheless adds meaning beyond the schema: a bare name merges a generic with its non-generic namesake and 'mergedArities' signals it, plus the recalled-session requirement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a precise verb+resource: 'Walk one type's inheritance in both directions' naming baseChain, derivedTypes and declared interfaces. It explicitly differentiates from siblings, calling itself the type-level counterpart to find_overrides and directing interface-implementation queries to find_implementations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states a concrete situation ('Use it before changing a base class') and names two alternatives with the condition that selects them (find_overrides for overrides, find_implementations for interface implementers). When-to-use and when-to-use-something-else are both explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
impact_of_changeEstimate Impact of a ChangeARead-onlyIdempotent
Estimate the blast radius of changing a symbol: its direct users plus their dependents, with a risk level.
Call it first, before any edit to a symbol other code names (a rename, signature, default value): a compile checks names, not what a consumer assumes.
Returns directCount and transitiveCount (one per declaration, tests included), productionImpactCount (transitive, without tests), risk and directImpact (at most 20; items {name, file, line} as in find_usages). risk reads productionImpactCount: 0 none, 1-4 low, 5-20 medium, above 20 high; it counts dependents, not what the change means. Where one cycle dominates a high closure, a 'saturation' block leads the counts and risk reads the direct production fan-in.
Per kind: a type - the closure of the types that reference it; a method or operator - its caller closure through interface and abstract dispatch; a property, field, event or enum member - the code that touches it (transitive = direct). A qualified method also counts its contracts' callers ('viaContract', as in find_usages).
An interface or abstract method or type adds 'implementers' per contract (count, testCount, typeCount, testTypeCount, members): what a signature change breaks. Then risk reads 'riskBasis'.total = closure + implementers (production implementing types; on a type only direct ones the closure lacks; 'indirect' lists those via a base class). 'namesakes' splits an entry same-named contracts share; 'riskBasis'.note flags no production caller.
A 'note' ahead of the counts flags misleading numbers: directCount 0 on a resolved symbol (DI or reflection may reach it), unresolved core references, productionImpactCount 0 on an all-test solution, and 'not_found' (risk 'none' is no measurement; 'nearest' gives a close name). 'collision' names a same-named symbol of another kind, not counted.
Read-only. symbol is case-sensitive and resolves as in find_usages: a type by its simple name, a member bare (one kind) or as 'Type.Member'. A constructor ('Type.Type') is not resolved here: use find_usages.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | The exact (case-sensitive) type, method, property, field, event, enum-member or operator (metadata) name to assess - or the qualified Type.Member form for a member. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint and no destruction, so safety is covered; the description goes far beyond that with return fields (directCount, transitiveCount, productionImpactCount, directImpact, risk), the risk thresholds tied to productionImpactCount, per-kind closure semantics, implementers/riskBasis behavior, and the note/not_found/collision caveats that flag misleading counts.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long and dense, but front-loaded (purpose, then call-order guidance, then return/behavior details) and nearly every clause carries distinct information. The remaining cost is readability: the risk-threshold and note/collision material is packed tightly enough that it slows scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry return-value meaning, and it does: exact field names, risk mapping, per-kind closure definitions, and edge-case blocks (saturation, implementers, namesakes, note, collision). Little an agent needs to interpret results is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description meaningfully extends the symbol parameter: case-sensitivity, simple-name vs bare-member vs 'Type.Member' resolution, and that constructors are not resolved. That is genuine semantic value beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Estimate the blast radius of changing a symbol: its direct users plus their dependents, with a risk level') and immediately scopes it as the pre-edit step. It also distinguishes itself from find_usages by adopting its resolution rules while carving out constructors, so an agent can tell what it does and does not cover.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit use trigger ('Call it first, before any edit to a symbol other code names (a rename, signature, default value)') with the reason (compile checks names, not consumer assumptions). It names the alternative for an excluded case: a constructor 'is not resolved here: use find_usages'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
init_solution_configPropose a Solution ConfigurationARead-onlyIdempotent
Collect the raw material for the guided setup of a solution's Layer Profile, Exclude-Namespaces and Test Profile - step 1 of 2; apply_solution_config is the step that writes.
Use it when solution_config_status or the configInit hint of analyze_solution reports an axis as not initialized, or when check_solution_config_drift reports one as stale. Propose a mapping from the returned material, then call apply_solution_config with it. To only see what is configured, use solution_config_status.
Returns JSON: solutionPath; declaredNamespaces - the solution's own namespaces, the source for layer-mapping rules (test-project and framework namespaces are left out); referencedNamespaces - every namespace a using directive names, the solution's OWN included: only the external/framework ones are exclusion material, never exclude your own; testProjects - what the default heuristic classifies as test projects; detectedTestAttributes - the test attributes present in the code; proposalFormat - the JSON shape apply_solution_config expects. The first three lists are capped envelopes (items/count/totalFound/truncated, max 300); detectedTestAttributes is a plain array.
Read-only: it writes no configuration and no DB row and marks nothing as initialized. It walks the warm session workspace (no re-analysis), so it needs a live session; a recalled one is rejected with an error.
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint, but the description adds context beyond them: it writes no config or DB row, marks nothing initialized, walks a warm session workspace without re-analysis, requires a live session, and rejects a recalled one with an error. These are real operational traits not derivable from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose and the step-1-of-2 routing, then handles returns. It is dense and long, but with no output schema the return-format sentences earn their place; a few clauses (e.g., the envelope field enumeration) run long for the value added.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully documents the return JSON (solutionPath, declaredNamespaces, referencedNamespaces, testProjects, detectedTestAttributes, proposalFormat), the capping of the three envelope lists, and the asymmetry between solutions' own vs external namespaces. Nothing needed to call or interpret the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter (sessionId) with 100% schema description coverage; the schema already documents that it accepts a session_id or an absolute .sln/.slnx/.slnf path. The description adds no further meaning about the parameter itself, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: collecting raw material for guided setup of a solution's Layer Profile, Exclude-Namespaces and Test Profile. It explicitly positions itself as 'step 1 of 2' and names apply_solution_config as the writing step, distinguishing it from siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives precise trigger conditions: use when solution_config_status or the configInit hint of analyze_solution reports an axis as not initialized, or when check_solution_config_drift reports one as stale. Names two alternatives (apply_solution_config for writing, solution_config_status for viewing) with the exact conditions selecting each.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
install_agent_hooksInstall Agent HooksADestructiveIdempotent
Install the aicb symbol guard into this project for an agent harness, so a C#-symbol question is REFUSED on a text search and redirected to the tool that answers it. Writes the guard script plus the harness's wiring entry (.claude/settings.json, .codex/hooks.json or opencode.json) and nothing else - no .mcp.json, no skills, and only inside the directory of the session's own solution. Omit 'harness' to install for the harness that is calling. An existing guard or wiring is kept unless force=true. Restart or reconnect the client afterwards, then call refresh_session so the session stops reporting the guard as missing.
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | Overwrite an existing guard script and rewrite an existing wiring entry. | |
| harness | No | Which harness to install for: claude-code, codex or opencode. Omit to use the harness the calling MCP client belongs to. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, and the description adds substantive context beyond them: the exact write footprint, the containment rule (only inside the session's own solution directory), the non-destructive default that force overrides, and the operational requirement to restart the client and then call refresh_session so the guard stops being reported missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and the write footprint before the operational caveats, and every clause carries information. The single dense paragraph is slightly heavy, but there is little that could be cut without losing routing or safety detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating installer with no output schema, the description covers the write scope, the safety default, the containment boundary, and the post-install recovery step. It stops short of describing failure modes (e.g. what happens if sessionId is unknown or the harness is unsupported), but nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are already documented, including the harness enumeration values and the force overwrite semantics. The description largely restates the schema's 'omit harness' and 'kept unless force=true' behavior rather than adding format or edge-case detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (install), resource (the aicb symbol guard), and precisely scopes what is written: the guard script plus one harness wiring entry, explicitly excluding .mcp.json and skills. It even names the concrete target files (.claude/settings.json, .codex/hooks.json, opencode.json), so the agent can distinguish it from every sibling at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage conditions: omit 'harness' to target the calling harness, existing guard/wiring is preserved unless force=true, and it names the follow-up sequence (restart/reconnect, then call refresh_session). It does not explicitly contrast against sibling config tools like apply_solution_config or init_solution_config, so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instantiation_sitesFind Instantiation SitesARead-onlyIdempotent
Find where a type is constructed and where it is injected: the narrow 'who creates or obtains an instance of X?' that find_usages (every reference) cannot answer. resolve_injection answers the other half - what is registered for a type.
Use it before changing a constructor, and to see whether anything but a test builds a type.
'created': a method, constructor or accessor that runs 'new X(...)', a target-typed new or a record 'with'; a field or property initializer is attributed to the constructor the compiler runs it in, so such a site is named '.ctor' ('.cctor' for a static one). 'injected': a type that takes X as a constructor parameter - no container is consulted. A parameter wrapped in another type (IEnumerable, Lazy) is recorded under the outer type, and an array of X is not a creation of X.
Returns typeName, a 'note' when there is one, createdByCount, createdByTests, injectedIntoCount, injectedIntoTests, sites - at most 200 items (name, declaringType, namespace, kind, isTestProject), created sites first - and 'nearest'. The four counts are true totals within scope. Test-project sites are included, not filtered: isTestProject marks each, and createdByTests == createdByCount with a non-zero total means every recorded construction site is in a test project. A type the DI container builds has no recorded production site, so that reading is not proof.
A 'note' covers two zeros: with no site at all it names the construction paths this fact cannot see and the markup views naming the type; with injectedIntoCount 0 it names those of its interfaces something is injected under - a DI consumer takes the interface, so query that name. 'nearest' gives a close declared name when no site was found and the name matches no declaration.
Read-only; works on a recalled session. typeName is matched on its simple name: namespace and generic arguments are dropped, namesakes are unioned, and an external type ('List', 'HttpClient') is a valid query. scope is 'solution' or a namespace prefix on the SITE's namespace.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | 'solution' (default) or a namespace prefix (e.g. 'MyApp.Core') to narrow which sites are scanned. | solution |
| typeName | Yes | The type whose instantiation/injection sites to find (simple name; namespace + generic args are normalized away, e.g. 'OrderService' or 'List'). | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/no-open-world, but the description goes well beyond them: it defines 'created' vs 'injected', states no container is consulted, notes test-project sites are included not filtered, explains the two-zero 'note' cases and 'nearest'. It does not spell out pagination/ordering guarantees beyond 'created first, max 200', so a 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and the sibling contrast, then organized into labeled sections for the two kinds of site and the return shape. It is dense and long, but nearly every sentence carries distinct semantic payload; only marginal trimming is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description enumerates the returned fields (typeName, note, the four counts, sites, nearest) and explains how to read the counts and the zero-site 'note'. An agent has everything needed to call and interpret it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema carries the parameters; the description still adds real meaning by defining scope as a prefix on the SITE's namespace and by explaining typeName's simple-name matching, namesake unioning, and external-type validity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('find where a type is constructed and injected') and immediately distinguishes itself from siblings: find_usages answers 'every reference' and resolve_injection answers 'what is registered'. An agent can route between all three without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('before changing a constructor', 'to see whether anything but a test builds a type') and names the two alternative tools with the exact question each answers instead. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_insightsList Code InsightsARead-onlyIdempotent
List code-quality / async / design-smell insights for a session (long methods, fat interfaces, unused types, missing async suffixes, many-parameter methods, ...). Runs against the live analyzed solution; each insight is aggregated per producer with a Details list. Pass dbPath to use the active QualityProfile (producer thresholds + toggles) from that DB; omit it for the default profile (DB-free). Honors the session's active test-detection profile (resolved by analyze_solution(dbPath)) for the production-focused producers. An explicit analyze_solution(layerProfile) drives the layer-violation insight and wins over the DB-configured profile (same precedence as solution_metrics and the CLI gate). THIS ANSWER IS TRIAGE-FILTERED, on BOTH triage axes: findings the solution marked intentional (a suppression - in the DB or in the git-tracked .aicb.json sidecar) AND findings a user dismissed as seen (in the solution record, NOT in the sidecar) are removed, and an insight whose findings are all gone does not appear at all. Every insight that lost lines carries 'suppressed' with the count of what BOTH axes removed together (absent = nothing filtered), so a shrinking number is never mistaken for a codebase that improved - but do not read that count as a sidecar entry count, because some of it is dismissal. Note 'title' is producer text computed BEFORE filtering, so on a partially filtered insight it still names the pre-filter total - 'detailsCount' + 'suppressed' are the real split. 'remediationCostMinutes' is a coarse order-of-magnitude estimate from fixed per-finding rules, not measured effort.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND the configured default layer profile (DefaultLayerProfileName / per-solution) drives the layer-violation analysis (an explicit analyze_solution(layerProfile) wins). Omitted, the QualityProfile falls back to the server's default config DB (the GUI's, if resolved), else the default profile, and the layer profile to the config DB the session was analysed against - the one its renders read. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/idempotent/non-destructive annotations: it discloses that results are triage-filtered on BOTH axes (intentional suppressions and user dismissals), that fully-filtered insights disappear, how the 'suppressed' count combines both axes, and that 'title' is pre-filter producer text while detailsCount+suppressed is the real split. It also flags remediationCostMinutes as a coarse estimate. This is exactly the behavioral context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded, which is good, but the description is dense and winding — the triage-filtering and profile-precedence passages are convoluted and could be tightened. Given the tool's complexity most content earns its place, but the structure is heavier than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-shape burden and does reasonably well: it explains per-producer aggregation with a Details list and the meaning of suppressed, detailsCount, title, and remediationCostMinutes. A bit more on the overall shape would make it fully complete, but it is close.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented in the schema, including dbPath's profile-resolution behavior. The description largely restates that precedence nuance rather than adding new syntax or format detail, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with concrete scope: 'List code-quality / async / design-smell insights for a session', reinforced by named example categories (long methods, fat interfaces, unused types). It clearly reads as the list-side counterpart to get_insight, but it never explicitly differentiates itself from that sibling, so an agent still has to infer list-vs-single.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real conditional guidance for the dbPath parameter (pass to use the DB's QualityProfile, omit for the default DB-free profile) and explains precedence against analyze_solution(layerProfile). However, it offers no explicit when-to-use-this-vs-alternatives routing against siblings like get_insight or solution_metrics; usage is implied rather than directed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_mcp_profilesList MCP ProfilesARead-onlyIdempotent
List the MCP profiles in the server's config DB - each with its id, name, the slots that have a template assigned (General appears exactly when a profile-wide template is set), the profile-wide templateId (null = none), whether it carries a skill, its effective tool-set (toolSelection: the class-level CSV, or a 'methods:'-prefixed function-name list when the profile curates individual tool functions; null = lean core), whether it is the active one, AND the render config it applies (tokenBudget / outputFormat / overflowPolicy - a null tokenBudget/overflowPolicy means inherit: the template then the active PipelineProfile decides). Requires the server to be started with --db-path. Use the ids with 'aicb mcp --mcp-profile ' to pin the profile at server start - that is the only way to change it; there is no runtime switch tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety bar is low; the description instead adds real behavioral context — the --db-path prerequisite and the fact that profile selection is immutable at runtime. Null-handling rules (null templateId, null tokenBudget means inherit through template then active PipelineProfile) are disclosed, though some of this drifts into return-shape territory rather than behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, but the body is a single sprawling sentence with stacked parentheticals and an ALL-CAPS 'AND' joining two unrelated payload descriptions (identity fields vs. render config). Splitting the return-field inventory from the usage note would make it far more scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of explaining the return shape — and it does, field by field, including null semantics and the two toolSelection encodings. Combined with the stated prerequisite and the 'no runtime switch' constraint, an agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the rubric the baseline is 4. The description correctly adds no parameter guidance because none is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('List the MCP profiles in the server's config DB') and enumerates the exact fields returned. No sibling tool in the list covers MCP profile configuration, so it is unambiguously distinguishable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the prerequisite ('Requires the server to be started with --db-path') and explains what to do with the results ('Use the ids with aicb mcp --mcp-profile <id> to pin the profile at server start'). It also pre-empts a fruitless search by stating there is no runtime switch tool. It never frames when to call this versus another tool, but no viable alternative exists.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_skillsList Tools and FacetsARead-onlyIdempotent
The server's capability map: a tools INDEX naming EVERY tool this server has - each exactly once, grouped into three lists by pool state (inPool.core = the tools every profile exposes, in reach-for-them order; inPool.extras = the rest of the active pool, alphabetical; outOfPool = exists but the active tool set does not expose it) - plus the sections that group them by name: the always-on navigation CORE (listed in no menu because it needs none), the task FACETS (id + guidance + template slot + the facet's tool menu), the cross-cutting guidance styles, and the legacy functional skill bundles. Use it to discover specialized long-tail tools (e.g. get_insight, find_by_concurrency_risk, coverage_gaps, find_unresolved_bindings) beyond that core - and to check whether ANY tool you want is merely in outOfPool rather than nonexistent. Tools outside the active pool become reachable via an MCP profile whose facet menu or bundle names them (see list_mcp_profiles / 'aicb mcp --mcp-profile '), or via the AICB_MCP_TOOLS override. By default the answer omits the per-tool descriptions, which is what makes it cheap; pass detail="full" when you need them. No session needed.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | How much per-tool text to include: "lean" (default) - bare names in their pool groups; "full" - additionally each tool's one-line description. Case-insensitive. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, closed-world, non-destructive), so the bar is lower. The description adds genuinely useful behavior: by default per-tool descriptions are omitted for cheapness, detail="full" includes them, and no session is needed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The intent is front-loaded ('capability map'), but the body is one very long sentence with deeply nested parentheses enumerating pool states and sections, which hurts scannability. It is information-dense but not efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of describing the return shape, and it does: three pool-state lists, the navigation CORE, task FACETS, guidance styles, and legacy bundles. Nothing needed to call or interpret the result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single `detail` parameter is fully documented in the schema, so baseline is 3. The description reinforces the lean-vs-full tradeoff and its cost rationale, but adds little format or syntax detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource - an index naming every tool the server has - and even enumerates the three pool groupings it returns. It distinguishes itself from the similar-sounding list_mcp_profiles and list_insights by describing a capability map rather than profiles or insights.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use cases: discovering specialized long-tail tools (name examples) and checking whether a wanted tool is merely in outOfPool rather than nonexistent. It also explains the alternative paths (an MCP profile that names the tool, or the AICB_MCP_TOOLS override).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
measureMeasure Answer SizesARead-onlyIdempotent
Report how BIG a read-only query's answer would be - its exact token count - WITHOUT returning the answer. Use it to decide before you pull: whether a call is worth making, what 'budget' to pass a slice tool (get_context/explain_symbol/pack_for_task), or whether to narrow 'scope' first. Same shape as batch: pass the shared session_id once plus 'queries', an array of {tool, args} where 'args' is that tool's own arguments WITHOUT the sessionId. Example: queries=[{"tool":"explain_symbol","args":{"symbol":"OrderService","include":["callees"]}}] → {tool, ok, tokens, chars, returned, totalFound, truncated, budgetNote}. 'tokens' is the real tokenizer count (cl100k_base) of the exact text the tool would return; 'returned/totalFound/truncated' are passed through when the tool answers with a capped envelope, so you also see whether you would be seeing everything. The Markdown slice tools (get_context / explain_symbol / pack_for_task) have no such envelope - they disclose budget pruning in prose, so 'budgetNote' carries that disclosure verbatim: if it says types were dropped, the answer you are pricing is already CUT (an axis you asked for can be missing entirely), and a larger 'budget' is what buys it back. IMPORTANT: measure does NOT make the query cheaper to RUN - the server does the full work either way; it makes the answer cheap to INSPECT (you pay ~50 tokens instead of the answer). So measure to DECIDE, then call once - do not measure every call by reflex. Dispatches the same read-only tools as batch, and refuses the same ones for the same four reasons - mutation is only the first of them; the refusal message names which one applies. Like batch, sub-queries follow the ACTIVE POOL: an out-of-pool tool is refused per item. Max 16 queries per call.
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | The read-only queries to measure: an array of { tool, args } objects, exactly as for batch. Max 16. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. Shared by ALL queries - do NOT repeat it inside each query's args. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), but the description adds substantial context beyond them: it does not reduce query execution cost, it costs ~50 tokens instead of the full answer, it enforces a 16-query cap, it follows the active pool, and it refuses the same tools as batch for four named reasons. The only minor gap is that it doesn't detail per-item failure semantics beyond 'the refusal message names which one applies'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded – the core 'token count without the answer' claim and the decide-then-call usage rule come first, followed by mechanics. It is long, and the 'Max 16 queries per call' statement duplicates the schema description, but nearly every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description fully specifies the return payload ({tool, ok, tokens, chars, returned, totalFound, truncated, budgetNote}) and explains the semantics of the ambiguous fields, including how budgetNote surfaces prose-level budget pruning. An agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further: it clarifies that sessionId is shared once and must NOT be repeated inside each query's args, describes the {tool, args} item shape, and supplies a worked example with real args. That is meaningfully more than the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource: it reports the exact token count of a read-only query's answer without returning it. It explicitly distinguishes itself from sibling batch ("Same shape as batch") and from the actual answering tools it prices, so an agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use conditions (decide whether a call is worth making, what budget to pass get_context/explain_symbol/pack_for_task, whether to narrow scope first) and an explicit when-not ("measure to DECIDE, then call once - do not measure every call by reflex"). It also explains what it refuses and why, which is strong alternative-routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pack_for_taskPack Context for a TaskARead-onlyIdempotent
Goal-driven context packing: given a natural-language task, seed on every symbol the goal names (type or method), expand the neighborhood, and return a token-budgeted AI-Builder-Markdown bundle - with goal-aware trimming that keeps the most task-relevant methods when the budget is tight. Name the symbols you care about in the goal (e.g. 'refactor OrderService.Cancel and Validate'). budget caps output tokens (floored at 8000). Multi-TFM solutions are deduplicated to one logical project per name (NEWEST TFM's instance, matching find_symbol's view). For an EDIT-ready bundle that also pulls in the covering tests + naming/file siblings (and, on a profile-aware server, renders through the facet's template), use prepare_task instead.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | Yes | The task description (name the relevant types/methods in it). Once the goal names a symbol exactly, its other words only steer the trimming and seed nothing of their own; a goal naming no symbol is matched by name segments instead ('cancel order' -> CancelOrder). | |
| lean | No | Lean slice (default TRUE): drop the repeated <AI_CONTEXT_SPEC>/<AI_CONTEXT_META> preamble and omit enabled-but-empty graph sections ('- none'). Keeps PATH_LEGEND / COMPRESSION_LEGEND and all non-empty sections. Set false for the full AI-Builder-MD document. | |
| facet | No | Optional facet - the task axis of this call: General, Exploration, Refactoring, Debugging, Review, Testing, Documentation, Architecture, or Performance. pack_for_task always renders the lean bundle (its render deliberately stays template-free - use prepare_task for a template-shaped bundle); the facet appends a short work-style trailer with suggested next tools. (The name 'slot' is accepted too.) | |
| budget | No | Optional token budget (floored at 8000). Caps the slice TWO ways: it compacts/drops method bodies AND - when the expanded neighborhood still overflows - drops the least-relevant non-seed types entirely. Exact type names and exact method names with one owner are pinned; broad subword/ambiguous same-name families may be capped by closeness and in-slice fan-in. A leading comment discloses how many types were dropped. Omitted, the bundle still renders against a ceiling (the active MCP profile's token budget, else a ~10000-token default budget) that bounds the neighborhood; pass a value for a tighter bundle. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeQualityMetrics | No | When true, also emit the <QUALITY_HOTSPOTS> section plus complexity=""/ce="" tag attributes (cyclomatic complexity, efferent coupling) for the packed symbols. Default false. Set true when the task is a refactor/quality pass. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds substantial non-obvious behavior: the 8000-token budget floor, two-way budget enforcement (body compaction plus dropping least-relevant non-seed types), pinned exact names, a dropped-types comment, multi-TFM dedup to the NEWEST TFM, and the default ~10000-token ceiling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior in the first sentence, then progressively narrower detail. It is dense and on the long side, with some parenthetical tangents (the 'slot' alias, the profile-token-budget aside), but nearly every clause carries actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by describing the return shape (lean vs full AI-Builder-MD, PATH/COMPRESSION legends, quality hotspots section), so an agent knows what it will receive. Combined with the routing to prepare_task and the session/prerequisite context, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description genuinely enriches it: the goal's symbol-matching semantics (exact names suppress other words; segment matching for 'cancel order' -> CancelOrder), the lean default's effect on preamble/sections, and budget's dual enforcement. Only the facet enum values are left entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource: 'Goal-driven context packing' that seeds on goal-named symbols, expands the neighborhood, and returns a token-budgeted Markdown bundle. It explicitly distinguishes itself from the closest sibling by routing edit-ready/template work to prepare_task.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use conditions (name symbols in the goal to steer seeding; use prepare_task for an EDIT-ready or template-shaped bundle; set includeQualityMetrics for refactor/quality passes). Alternatives and exclusions are named rather than implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_taskPrepare Context for an EditARead-onlyIdempotent
Build an EDIT-ready context bundle for a task goal: the source of the symbols the goal names, their dependency neighborhood, the test methods that cover them and 1-2 naming/file-convention siblings (the test, the factory, the validator you'd otherwise miss) - as one token-budgeted AI-Builder-MD document.
Prefer this over pack_for_task when you're about to EDIT, not just read. pack_for_task packs the goal-seeded neighborhood alone, without covering tests and siblings. For one symbol use get_context or explain_symbol; for blast radius and test coverage as numbers use review_context.
Returns text, not JSON. It starts with a manifest comment (goal | seeds | tests | siblings | render) so you can see what was covered - and what was NOT ((none)); after a source edit a staleness comment precedes it. 'render' names the path that produced the body. 'template' is the default, because a plain 'aicb mcp' resolves the standard config DB: the chosen facet's template (graphs, detail, line numbers, quality) in the active profile's notation - YAML under the built-in profiles. 'lean' is the fallback of a server without a config DB: tag Markdown. Multi-TFM solutions are deduplicated to one logical project per name (NEWEST TFM's instance, matching find_symbol's view).
Read-only. Parameters: a tight budget drops neighborhood types, tests and siblings first. A type the goal names, or the one owner of a method it names, is never dropped (too large, it renders as structure: members and signatures); the owners of a method name several types share can be dropped. A leading note names the drops. lean and includeQualityMetrics act on the lean render only, so not on a default server.
| Name | Required | Description | Default |
|---|---|---|---|
| goal | Yes | The task description - name the relevant types/methods in it (e.g. 'refactor OrderService.Cancel and its validation'). Once the goal names a symbol exactly, its other words only steer the trimming and seed nothing of their own; a goal naming no symbol is matched by name segments instead ('cancel order' -> CancelOrder). | |
| lean | No | Lean slice (default TRUE): on the lean-render path, drop the repeated <AI_CONTEXT_SPEC>/<AI_CONTEXT_META> preamble and omit enabled-but-empty graph sections ('- none'); keeps PATH_LEGEND / COMPRESSION_LEGEND, the manifest and all non-empty sections. Set false for the full AI-Builder-MD document. (Ignored on the profile-aware slot-template render path, which the active profile controls.) | |
| facet | No | Optional facet to work under - the task axis of this call: General (default), Exploration, Refactoring, Debugging, Review, Testing, Documentation, Architecture, or Performance. On a server with a config DB (the default: a plain 'aicb mcp' resolves the standard one) the facet's template shapes the render; it always appends a short work-style trailer with suggested next tools. (The former name 'slot' is still accepted.) | |
| budget | No | Optional token budget (floored at 8000). Applies to BOTH the lean and the profile-aware template render path: it compacts/drops method bodies AND drops the least-relevant types when the neighborhood overflows. A type the goal names, and the one owner of a method name it names, is never dropped - one whose own source does not fit renders as structure (members and signatures). The owners of a method name several types share are capped like the neighborhood: some are reduced to structure, some dropped. The bundled covering tests/siblings are BUDGET-BOUND - under a tight budget they are dropped to fit (a leading comment names the drops so you can ask for one by name). Overrides any MCP-profile/template token budget. Omitted, the bundle still renders against a ceiling (the MCP profile's token budget, else the facet template's, else a ~10000-token default budget) that bounds the neighborhood. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include the test methods that cover the seeded symbols (default true). | |
| includeSiblings | No | Include 1-2 naming/file-convention siblings of the seeded types (default true). | |
| includeQualityMetrics | No | When true, also emit the <QUALITY_HOTSPOTS> section plus complexity=""/ce="" tag attributes for the bundled symbols (lean path). Default false. Set true for a refactor/quality pass. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent/non-destructive, but the description goes well beyond them: return format is text not JSON, the leading manifest comment reveals coverage and gaps ((none)), staleness precedes it after a source edit, multi-TFM solutions dedupe to the newest TFM, and tight budgets drop neighborhood/tests/siblings with a leading note naming the drops. It also documents the never-dropped guarantees for named types and single method owners.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded correctly, with purpose first and usage routing second. However it is long, and substantial portions (the template vs lean render path, facet trailer, budget behavior) duplicate the parameter descriptions already present in the schema, which is padding for a reader who has the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry the return-value burden and does: it explains the manifest comment, staleness line, render/template/lean distinctions, and the text-vs-JSON format. For an 8-parameter, complex bundle-builder, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: the precise drop order under a tight budget, the never-drop rules, the fact that lean/includeQualityMetrics act only on the lean render path, and the interaction between budget and the profile/template ceiling. These cross-parameter behaviors are not in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 'Build an EDIT-ready context bundle for a task goal', then enumerates exactly what the bundle contains (symbol source, dependency neighborhood, covering tests, convention siblings). It actively distinguishes itself from siblings by naming pack_for_task, get_context, explain_symbol, and review_context with the conditions that separate them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: 'Prefer this over pack_for_task when you're about to EDIT, not just read', 'For one symbol use get_context or explain_symbol', 'for blast radius and test coverage as numbers use review_context'. Both when-to-use and when-not-to-use are stated, with alternatives named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_sessionRefresh a SessionAIdempotent
Re-analyze the session's solution after YOUR code edits - call it once you have changed .cs files, otherwise find_usages / impact_of_change / list_insights / get_context may keep answering from the STALE pre-edit graph (a silent source of wrong results). Cheap to call speculatively: a W0 file-set-hash check skips the expensive Roslyn re-run when nothing actually changed, and a C# file whose timestamp moved while its text stayed the snapshot's (a save without an edit) does not count as a change either. That check reads SOURCE files, so it cannot see a restore or build - after one of those, an analysis that reported unresolved references retries once by itself, and 'force' is the deterministic way to demand it. Reuses the warm workspace. Returns { changed, reason, session, mode } - 'mode' names the path the re-analysis took ('incremental' = document texts replayed into the warm snapshot without an MSBuild reload, else 'full-reload') and is absent when nothing was re-analyzed. The incremental path can stop engaging without any visible symptom - answers stay correct, calls just get slow again - so 'mode' is how you notice.
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | Re-analyze even when no source file has changed. Use it after a restore/build that was meant to repair unresolved references - those live in build output the file-set hash does not cover, so an ordinary call can legitimately answer 'unchanged'. Costs a full MSBuild reload; leave false for the normal after-an-edit refresh. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly=false, idempotent=true, destructive=false), but the description goes far beyond: it discloses the cheap W0 hash pre-check, the source-file-only blind spot (misses restore/build), the automatic single retry, and the reuse of a warm workspace. These are non-obvious behavioral traits the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and the stale-graph warning, then caching, then return shape - a logical order with no filler sentences. It is dense and long, packing several distinct concerns into one paragraph, which costs a little scannability but every clause carries actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description fully documents the return object ({changed, reason, session, mode}) and the meaning of 'mode' and its absence. Combined with annotations, an agent has everything needed to call it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning to 'force' (deterministic demand for re-analysis after a restore/build, full MSBuild cost) and reinforces sessionId semantics. It exceeds the schema rather than merely restating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Re-analyze the session's solution after YOUR code edits') with the triggering condition (changed .cs files). It explicitly distinguishes itself from the read-only analysis siblings that would otherwise answer from a stale graph, so an agent can pick it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when (after editing .cs files), when-not (a save without an edit, an unchanged file-set hash), and the exact alternatives that go stale (find_usages / impact_of_change / list_insights / get_context). It also names the escalation path 'force' for restore/build scenarios, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_injectionResolve Dependency InjectionARead-onlyIdempotent
Resolve a Microsoft DI registration: what is registered for a service, with lifetime and site. Not usage (find_usages), implementers (find_implementations), construction (instantiation_sites).
It reads Add{Singleton,Scoped,Transient}, TryAdd*, descriptor adds built at the call, AddHostedService, project-local helpers registering their own type arguments (note 'via '), and a foreach over a static new(typeof(Service), typeof(Impl)) table. A key, and a closing, is a service of its own (IRepo, IRepo); open IRepo<> is read. Not read: a descriptor built elsewhere, AddHttpClient-style helpers, Scrutor, other containers.
Returns JSON: registrations (serviceType, implementationType [= its service for a self/instance form], lifetime, note, location, project, declaringMethod, key; note 'inferred, not read' = from a package helper's call shape AddSingletonAs().As(): lifetime from its name, body unseen; not in ambiguous or a winner) and: multiRegistration / registrationSites; ambiguous (ONE site registers several implementations of one service, not consumed as a collection); effectiveRegistration (2+ calls: the winner a single-service resolve gets, read only in ONE straight-line site; else null + reason); consumedAsCollection; constructorConsumerCount (plain constructor parameters; not a usage verdict); optionalDependencies (optional constructor parameters, each judged yes/no/unknown).
An empty list says why: resolvedKind 'not_found' plus 'nearest' = nothing in the solution names it; else a 'note' names the forms not read and which of them the solution holds (package helpers, conventions, runtime types) - empty means 'not statically visible', never 'not registered'.
Needs a live session. Test-project registrations and consumers count only with includeTests=true; testRegistrationsFiltered counts what that hid. interface is the SERVICE type (an interface, or a class registered as itself); a closed form (IRepo) lists that closing and IRepo<> (typeArgumentFilter: the rest); site narrows by file path.
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | Optional: narrow to registrations whose file path contains this substring. | |
| interface | Yes | The interface simple or fully-qualified name, e.g. 'ICodeAnalyzer'. A closed generic form ('IHandler<Saved>') lists only the registrations serving that closing; 'IHandler' or 'IHandler<T>' lists every closing. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | Include registrations declared in test projects (default false - production focus). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare read-only/idempotent/non-destructive; the description goes far beyond, enumerating exactly which registration forms are read (Add{Singleton,Scoped,Transient}, TryAdd*, AddHostedService, foreach static table) and which are not (Scrutor, other containers, AddHttpClient-style). It also discloses the 'inferred, not read' provenance, the 'needs a live session' requirement, and the 'never not registered' caveat for empty results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded correctly (purpose first, exclusions second), and given there is no output schema nearly every clause earns its place. It is, however, extremely dense—the return-shape enumeration is a run-on separated by semicolons that is hard to parse on a first read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden and does so: it documents the JSON keys (registrations, ambiguous, effectiveRegistration, consumedAsCollection, constructorConsumerCount, optionalDependencies), the empty-list semantics, session requirements, and test filtering. An agent has what it needs to call and interpret it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds semantics the schema does not: 'interface is the SERVICE type (an interface, or a class registered as itself)' and the typeArgumentFilter distinction for closed vs open generics. Some of the site/includeTests text duplicates the schema, keeping it below 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Resolve a Microsoft DI registration: what is registered for a service, with lifetime and site.' It then explicitly names the sibling tools it is NOT (find_usages, find_implementations, instantiation_sites), so an agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States when to use it versus three named alternatives, defines the empty-result case ('not_found' + 'nearest' vs a note naming unread forms), and specifies the includeTests=true condition with testRegistrationsFiltered. Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
review_contextGet Review ContextARead-onlyIdempotent
Assemble review context for a set of changed symbols in ONE call: per symbol its fan-in, the transitive change impact with a risk level, the types that implement it (if an interface) and the test methods that likely cover it. It bundles what find_usages, impact_of_change, find_implementations and find_tests_for answer one symbol at a time.
Use this before reviewing or refactoring to see blast radius + test coverage at a glance. It does not name the callers (use find_usages or impact_of_change for that list) and returns no code (use explain_symbol).
Returns a JSON array ordered by symbol NAME - index it by 'symbol', never by request position. Per entry: symbol, resolvedKind, directUsages, transitiveImpact, risk (none/low/medium/high), implementations (names; test doubles are listed too, find_implementations filters them by default), coveringTests (testType, testMethod, project, matchReason), coveringTestsTotal, coveringTestsTruncated. An unresolved name reads resolvedKind 'not_found' with a 'note' and no risk; a 'note' also flags a risk graded on the direct fan-in or on implementers alone. For a bare name several types share, the counts are their union and no note says so - find_usages names the namesakes.
'coveringTests' is find_tests_for's list: strongest evidence first, capped at 50 per symbol. The cap keeps the 50 strongest rows: name guesses go first, strong rows too once there are more than 50. find_tests_for stops at the same 50, so narrow the symbol rather than re-query. 'invokesTotal' (strong rows) and 'dispatchTotal' (rows reaching the symbol through an interface or abstract member) count the WHOLE list and can exceed the rows shown; coveringTestsTotal minus both is the name guesses. For a qualified method, directUsages and transitiveImpact include callers credited through such a member - see 'viaContract' / 'viaContractNote'.
Read-only. Parameters: symbols must not be empty and takes the strings find_usages resolves - a type's simple name, or a member bare or as Type.Member.
| Name | Required | Description | Default |
|---|---|---|---|
| symbols | Yes | The changed type/method names to assemble review context for. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (read-only, idempotent, non-destructive), yet the description adds substantial behavioral detail: results are ordered by symbol NAME and indexed by 'symbol' rather than request position, the 50-row cap and its retention policy, invokesTotal/dispatchTotal semantics, 'not_found' handling with notes, union counting for shared bare names, and test doubles included. Very little about runtime behavior is left implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and nearly every sentence carries unique semantics (ordering key, cap policy, count attribution, namesake caveat). It is, however, a dense unformatted block without headers or bullets, which makes the return-shape details harder to scan than they need to be given the volume.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden and does so: every returned field (symbol, resolvedKind, directUsages, transitiveImpact, risk, implementations, coveringTests and its subfields, coveringTestsTotal/Truncated) is documented along with edge cases like not_found and unioned counts. Nothing an agent needs to interpret the response is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description goes beyond it by stating that symbols must not be empty and that it accepts the exact strings find_usages resolves (a type's simple name, or a member bare or as Type.Member). It does not elaborate on sessionId beyond what the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope ('Assemble review context for a set of changed symbols in ONE call') and enumerates exactly what is bundled: fan-in, transitive impact with risk level, implementers, covering tests. It explicitly names the four siblings it consolidates (find_usages, impact_of_change, find_implementations, find_tests_for), so an agent can place it precisely in the toolset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the triggering situation ('Use this before reviewing or refactoring to see blast radius + test coverage at a glance') and gives explicit exclusions with routing alternatives: it does not name callers (use find_usages or impact_of_change) and returns no code (use explain_symbol). When-to-use, when-not-to-use, and alternatives are all present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_sessionSave a Session SnapshotA
Persist the current session's analyzed model as a named Manual snapshot in an aicb DB, so a later session can diff against it with compare_with_previous.
Use it BEFORE a bulk mechanical change (a rename sweep, a signature migration) and call compare_with_previous afterwards. An ordinary edit needs no snapshot: git diff and the tests cover it.
Returns JSON: snapshotId, sessionId, solutionId, name, lineNumbersAvailable and totalSnapshots (the snapshots that DB now holds for this solution).
It writes to the aicb DB, not to the solution's source or configuration: one new snapshot row, plus the solution's record when the DB does not know the solution yet; a DB file that does not exist is created. Nothing is overwritten: every call adds a snapshot under a fresh id, and name is a label, not a key. The snapshot keeps the line spans, but a session recalled from it reports lineNumbersAvailable false: its lines mean 'as analyzed', not the current working tree.
Parameters: sessionId is a live or recalled session's id or an absolute .sln path. Omit dbPath to use the server's standard config DB (the same one the GUI uses); when the server resolved none, the call fails with 'dbPath is required'.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Human-readable name for this snapshot (e.g. 'before refactor'). | |
| dbPath | No | Optional absolute path to the aicb SQLite DB to persist into. Omit to use the server's standard config DB. | |
| sessionId | Yes | The session_id whose current state to snapshot. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), and the description goes well beyond them: it scopes the write to the aicb DB rather than source/config, enumerates the rows created, states a missing DB file is created, and stresses nothing is overwritten with name as a label not a key. It also discloses a subtle downstream behavior (lineNumbersAvailable false on recalled sessions).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, then usage, then return shape, then side effects, then parameters — a logical progression with no filler. It is on the long side for a three-parameter tool, but each paragraph carries distinct information rather than restating the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return contract itself (snapshotId, sessionId, solutionId, name, lineNumbersAvailable, totalSnapshots) and covers the DB-write side effects and the dbPath failure mode. Nothing an agent needs to call and interpret this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: sessionId may be a live or recalled session id OR an absolute .sln path, and omitting dbPath uses the server's standard config DB with the explicit failure mode 'dbPath is required' when none was resolved. That failure-mode detail is not derivable from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource+destination: 'Persist the current session's analyzed model as a named Manual snapshot in an aicb DB.' It explicitly frames the artifact against the sibling that consumes it (compare_with_previous), so an agent can place it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('BEFORE a bulk mechanical change'), the follow-up action (call compare_with_previous afterwards), and an explicit non-trigger ('An ordinary edit needs no snapshot: git diff and the tests cover it'). This is the strongest form of when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
server_infoGet Server InfoARead-onlyIdempotent
Report this SERVER's own identity and health: name, version, build commit, the config DB's schema version, and drift warnings about the server binary. Needs no session - a reachability smoke-check.
Call it first after connecting and after an update or restart: the commit answers the question the version number cannot - 'is the binary I am talking to built from the code I just landed?'. It says nothing about a solution's configuration (solution_config_status: what is active; check_solution_config_drift: does it still fit the code), about which tools exist (list_skills) or about how they were used (usage_report).
Returns plain text, not JSON. Line 1 is the identity: 'aicb MCP server (AIContextBuilder) v (commit )'. Compare the commit against git rev-parse HEAD (the full sha is reported, so a short hash is a prefix of it): one version number can cover DIFFERENT builds. A build with no resolvable git revision omits the commit. 'Config DB schema: user_version=N ()' follows when a config DB is resolved.
Then, only when they apply: ANALYZER DRIFT - this build's commit against the HEAD of the repo holding the analyzed solution; it also reports in-sync and ahead, and is silent without an analyzed session and on a repo that does not know this commit (any foreign solution). SCHEMA DRIFT - the config DB's schema is newer than this binary: rebuild or reinstall. PENDING MIGRATION - the reverse: the DB is older; the line says how to migrate it. TOOL POOL DRIFT - the active profile lists tools this binary does not register: a newer build wrote it (rebuild or reinstall) or the tool was retired (re-save the profile). That check is tool-NAME level; a new parameter on an existing tool is not detected, the commit is the finer signal. CONFIG DRIFT - the active MCP profile changed since this server started: restart or reconnect to load the current tools and instructions.
Read-only: it reads the config DB's schema version and, for the analyzer line, queries git in the analyzed solution's repository.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds substantial behavioral context beyond that: it needs no session, is a reachability smoke-check, returns plain text not JSON, documents the exact line-1 format, and explains exactly when each drift line appears or stays silent. This is rich operational detail that annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and usage in the first sentence, but the body is dense and grows into a long enumeration of drift lines and format rules. Each sentence carries content, yet the whole is closer to a reference block than a tightly edited summary, which hurts scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a zero-parameter, no-output-schema tool and an idempotent read-only annotation set, the description covers everything needed: why to call it, what it returns, every drift line's meaning and firing condition, and the exact text format to parse. Nothing material is missing for an agent to invoke and interpret it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline per rubric is 4. The description does not invent any parameter discussion, which is correct, and its complete output-format documentation compensates fully for the absent parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ("Report this SERVER's own identity and health") and enumerates exactly what is returned: name, version, build commit, config DB schema version, drift warnings. It explicitly distinguishes itself from siblings (solution_config_status, check_solution_config_drift, list_skills, usage_report) by naming what it does NOT cover.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use: "Call it first after connecting and after an update or restart," plus the specific question it answers that the version number cannot. Names sibling alternatives (solution_config_status, check_solution_config_drift, list_skills, usage_report) and the boundary of what each covers, so routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solution_config_statusGet Solution Configuration StatusARead-onlyIdempotent
Check whether a solution's Layer Profile, Exclude-Namespaces and Test Profile have been initialized via the guided setup, and which Layer Profile / Exclusion List / Test Profile is currently active. 'initialized' is an explicit marker for all three slots (stamped by apply_solution_config - it is NOT inferred from having an active id, which a user can also set manually via the Settings panel); the testProfile slot additionally reports the effective per-solution active test-detection profile. Pass the session_id; dbPath is optional - omit it to use the server's default config DB (the same one the GUI uses), if the server resolved one. Each slot names the config IN FORCE for the analysis - resolved exactly as analyze_solution resolves it - and its source: 'db' (the per-solution row or the app-global default), 'sidecar' (the committed .aicb.json applies, which it does whenever the DB configured nothing for the axis - a built-in default is not configuration), 'built-in' (the built-in exclusion list, applied when nothing configured one and no sidecar names one) or 'none' (the heuristic). A repo with a valid .aicb.json sidecar but no DB row reads initialized=true, source:sidecar, not a misleading uninitialized. Use this on solution start: if a slot is not initialized, offer to run init_solution_config + apply_solution_config.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Absolute path to the aicb config/master SQLite DB that holds the per-solution configuration. Omit to use the server's default config DB (the same one the GUI uses), if the server resolved one. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, yet the description adds substantial non-obvious semantics: 'initialized' is an explicit marker stamped by apply_solution_config and NOT inferred from an active id set manually. It also explains source provenance ('db', 'sidecar', 'built-in', 'none'), including the important edge case that a repo with a valid .aicb.json sidecar but no DB row still reads initialized=true / source:sidecar.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded, but the body is a single dense paragraph with deeply nested parentheticals and semicolon-chained clauses that make it hard to scan. Much of the content earns its place (no output schema exists, so return-value semantics matter), but the structure could be broken up without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so fully: it defines the three slots, their initialized flags, the active configuration per slot, the effective test-detection profile, and the four possible source values. It also covers the sidecar edge case and prescribes the follow-up action, so an agent has everything needed to call and act on it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents sessionId (including that it accepts a .sln/.slnx/.slnf path) and dbPath. The description largely restates the dbPath default behavior ('omit it to use the server's default config DB'), adding little beyond the structured field. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (check) and resource (solution configuration status), enumerating exactly which three slots are inspected (Layer Profile, Exclude-Namespaces, Test Profile) and what 'active' means for each. It is clearly distinguishable from siblings apply_solution_config and init_solution_config, which it explicitly references as the write-side counterparts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger ('Use this on solution start') plus a concrete conditional workflow: if a slot is not initialized, offer init_solution_config + apply_solution_config. That names both the when and the alternative tools, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solution_metricsGet Solution MetricsARead-onlyIdempotent
The solution-wide quality rollup in one call - the numbers the CLI '--fail-on' quality gate evaluates. symbol_metrics ranks single methods; list_insights shows the findings behind the severity counts.
Use it for a before/after number, or to try a gate expression.
Returns metrics {typeCount, methodCount, complexityMax, complexityAvg, methodsOverComplexityThreshold, ceMax, caMax}, scope (always 'production'), testMethodCount, testTypeCount, severities {critical, warning, info, ok}, debtMinutes, debtApprox, debtRating, complexityThreshold, qualityProfile, layerProfile (when one is in force), knownGateMetrics and, with failOn, gate {expression, passed, violatedClauses}. degradedProducers appears when an insight producer failed; severities and debt are then incomplete. debtMinutes is a coarse estimate from fixed per-finding rules, not measured effort; debtApprox rounds it (1 d = 8 h).
PRODUCTION code only - test projects, per the session's test profile, are excluded from every number, and testMethodCount / testTypeCount give the excluded side. Types are logical (partial fragments merged, multi-TFM deduplicated); methods exclude constructors and accessors. methodsOverComplexityThreshold counts STRICTLY greater than complexityThreshold, while symbol_metrics' minComplexity is inclusive. ceMax / caMax: coupling maxima (caMaxNote: same-named types could raise caMax). severities count insights - one per producer that found something - not findings. The rollup is NOT triage-filtered: suppressed and dismissed findings still count, as in the CLI gate, so debt and severities can be higher than what list_insights shows.
failOn takes the tokens in knownGateMetrics; this gate is advisory, the blocking one is the CLI's.
Profiles: the active QualityProfile of the config DB in force (see dbPath); the session's layer profile, else the one dbPath (or, omitted, the session's analysis DB) configures. Writes nothing of its own; an older dbPath DB is upgraded on open, as the server's own is at startup. Works on a recalled session.
| Name | Required | Description | Default |
|---|---|---|---|
| dbPath | No | Optional path to an AIContextBuilder SQLite DB. When set, the complexity threshold and producer toggles come from that DB's active QualityProfile (same semantics as list_insights); omit to fall back to the server's default config DB (the GUI's, if resolved), else the default profile. Omitted, the layer profile comes from the config DB the session was analysed against. | |
| failOn | No | Optional quality-gate expression to evaluate against the rollup (CLI '--fail-on' syntax, e.g. 'critical>0 OR debt>120min OR ce-max>50'). An invalid expression or unknown metric is rejected with the known tokens. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover only the read-only/idempotent safety profile; the description adds substantial behavior: production-only scope with test counts reported separately, degradedProducers signalling incomplete severities/debt, debtMinutes being a coarse per-finding estimate, severities counting insights not findings, strict vs inclusive threshold semantics, and non-triage-filtered counting of suppressed findings.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing, and nearly every sentence carries a distinct behavioral fact. It is dense to the point of strain in the closing profiles paragraph, where nested parentheticals ('the one dbPath (or, omitted, the session's analysis DB) configures') slow parsing, but little is genuinely expendable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description enumerates the returned fields (metrics, scope, severities, debt, gate, degradedProducers) and their caveats, plus scope/profile behavior and the DB-upgrade side effect. An agent has everything needed to call it and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description still adds meaning: failOn must use tokens from knownGateMetrics and is rejected with the known tokens on error, and dbPath controls which QualityProfile supplies the threshold. sessionId's .sln path acceptance is only restated from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: the 'solution-wide quality rollup in one call' that the CLI '--fail-on' gate evaluates. It explicitly distinguishes itself from symbol_metrics (single methods) and list_insights (findings behind severity counts), so an agent can pick it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use conditions ('a before/after number, or to try a gate expression') and names the two nearest alternatives with the axis that separates them. It also warns that this gate is advisory while the blocking one is the CLI's, which prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
symbol_metricsMeasure Method ComplexityARead-onlyIdempotent
Report method complexity: McCabe CYCLOMATIC complexity (independent paths) and COGNITIVE complexity (how hard the method is to follow: nesting is penalised, boolean-operator runs collapse), plus the parameter count - for one method by name, or as a ranking of the hotspots. solution_metrics gives the solution-wide rollup.
Use it before touching an unfamiliar method, and to find where the complexity sits. Both metrics measure CODE SHAPE, not runtime cost; for a hot path use a profiler.
With symbol (mode 'symbol'): every method unit of that exact, case-sensitive name - bare for all same-named ones, 'Type.Member' for one type's. scope, includeTests, minComplexity and rankByCognitive are ignored. Accessors, constructors and operators answer by metadata name ('get_Items', '.ctor', 'op_Equality'); '.ctor' is every constructor unit of the solution, 'Type..ctor' one type's. Without symbol (mode 'ranked'): methods only, sorted by cyclomatic complexity descending - by cognitive with rankByCognitive=true - and filtered to complexity >= minComplexity (inclusive; 0 = no floor).
Returns scope, mode, metricMeaning, minComplexity, methodsScanned, methods - at most 200 items (name, declaringType, namespace, cyclomaticComplexity, cognitiveComplexity, parameterCount; project when two projects compile one type) - and when they apply 'note', minComplexityBoundary, 'nearest' (a close declared name when a lookup matched no method) and testMethodsFiltered. In a ranking, test-project methods are excluded by default (includeTests=true includes them); testMethodsFiltered counts those that cleared the floor, and the note names the strongest one when it would have ranked inside the shown list. The note also says when the two axes would have listed different methods.
An empty ranking means nothing cleared the floor - or the scope matched nothing: methodsScanned 0, plus a note. An empty lookup means no METHOD of that name; a bare property or type name gets a note saying so.
Read-only; works on a recalled session.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | When ranking: 'solution' (default) or a namespace prefix to narrow scope. Ignored when symbol is given. | solution |
| symbol | No | Exact (case-sensitive) method name to report - bare (every same-named method) or in the qualified Type.Member form (that type's member only). Omit to rank all methods by complexity. | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. | |
| includeTests | No | When ranking: include test-project methods (default false - production hotspots; CC-heavy test harnesses would otherwise skew the top-N). Ignored in the by-name symbol lookup (which always returns the named method). | |
| minComplexity | No | When ranking (no symbol): only include methods whose ranking complexity (cyclomatic, or cognitive when rankByCognitive=true) >= this. 0 (default) = no filter. | |
| rankByCognitive | No | When ranking: rank + filter by COGNITIVE complexity instead of cyclomatic (default false). Both numbers are always present per method; this only changes the sort + minComplexity axis. Ignored in the by-name symbol lookup. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive/non-open-world, yet the description adds substantial behavior: a 200-item cap, default exclusion of test-project methods with a rationale, empty-ranking vs empty-lookup semantics, nearest-name notes, and testMethodsFiltered accounting. This is rich context beyond what structured fields provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded: the first sentence delivers the core purpose and metrics, then modes and return shape follow. It is dense and long with some redundancy against the schema (mode-ignore rules restated), but nearly every sentence carries distinct information for a genuinely complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-shape burden and does so fully: it enumerates every returned field (scope, mode, metricMeaning, methodsScanned, methods, note, minComplexityBoundary, nearest, testMethodsFiltered) and explains edge-case returns for empty rankings and lookups.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds mode-interaction semantics (scope/includeTests/minComplexity/rankByCognitive are ignored in symbol mode) and the metadata-name convention for accessors/constructors/operators ('get_Items', '.ctor', 'op_Equality') that the schema does not explain. Some of the ignore-when text overlaps the schema's own 'Ignored when symbol is given' notes, capping it below 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: reports McCabe cyclomatic and cognitive complexity plus parameter count for a method or as a ranking. It explicitly distinguishes itself from the sibling solution_metrics (solution-wide rollup) and from profilers (runtime cost).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('before touching an unfamiliar method, and to find where the complexity sits') and when-not (for runtime cost use a profiler). Mode selection is spelled out with the exact triggering parameter (symbol present vs absent), so the agent knows which sibling and which mode to pick.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
symbol_signatureGet Symbol SignatureARead-onlyIdempotent
Return a symbol's signature(s) WITHOUT the body: the type declaration, the method/operator signature or a member's declaration (property, field, event, enum member - the last as its qualified Enum.Member form), plus its XML doc and its declaring file + start line - for understanding an API without reading the whole file/body, and for navigating straight to it. 'file' is the fragment's OWN file (for a partial type a method points at the file the METHOD lives in, not at the first type fragment); it is omitted only when the snapshot carries no path. 'line' is where the declaration starts, a leading attribute included; it is null for an enum member and a source-generated property (no line fact is modeled for them). Exact (case-sensitive) name match; multiple results for overloads or name collisions; one declaration compiled in two projects is two results, each with its 'project'. A member also takes 'Type.Member' (that type's only) and a type a qualified name ('Ns.Type', 'Outer.Inner'). A user-defined operator matches by its METADATA name ('op_Equality' / 'op_Implicit' / …). Leaner than get_context (which returns the full source). Returns a capped envelope (items/count/totalFound/truncated), max 50. Matching is EXACT, so a typo or case-mismatch returns an empty list rather than an error - when nothing matched, the response therefore carries a 'nearest' suggestion (the closest declared name), which distinguishes 'you spelled it differently' from 'this symbol genuinely has no signature' - and, where the run skipped generated C# under obj/, a 'generatedSourcesNote' naming the third possibility: the declaration exists in code this index never read.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | The exact (case-sensitive) type, method, property, field, event, enum-member or operator name (e.g. 'op_Equality'), bare or qualified ('Type.Member', 'Ns.Type'). | |
| sessionId | Yes | The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only covering safety (readOnly/idempotent/closed-world/non-destructive), the description carries the substantive behavioral load: capped envelope (items/count/totalFound/truncated, max 50), multiple-results semantics for overloads/cross-project duplicates, exact-match behavior returning an empty list rather than an error, plus the 'nearest' suggestion and 'generatedSourcesNote' that disambiguate why nothing matched. This is unusually rich disclosure beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded, and most edge-case detail earns its place, but it is delivered as one dense wall of text thick with parentheticals, which hurts scannability for an agent. The information is valuable yet not efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter read tool with no output schema, the description supplies everything needed: the return envelope shape and cap, result multiplicity, null-line cases, and the failure-mode explanations (nearest suggestion, generatedSourcesNote). Nothing an agent needs to interpret results or handle misses is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics beyond the schema: the exact-match/case-sensitivity consequence (empty list vs error), the overload and dual-project result behavior, and the 'Type.Member' member-only and qualified-type name forms. Some of this overlaps the schema's own symbol description, keeping it from a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with precise scope: 'Return a symbol's signature(s) WITHOUT the body: the type declaration, the method/operator signature or a member's declaration.' It explicitly distinguishes itself from a sibling by noting it is 'Leaner than get_context (which returns the full source).' An agent can tell exactly what this returns versus a full-source tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear use cases ('for understanding an API without reading the whole file/body, and for navigating straight to it') and names the alternative route (get_context for full source). It stops short of stating explicit exclusion conditions or the full set of sibling tools it competes with (find_symbol, explain_symbol), so it is strong but not complete routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
usage_reportReport Tool UsageARead-onlyIdempotent
Report the server-side tool-call telemetry: what the CallTool filter recorded into the config DB's tool_calls table, across every client that used this DB - not this conversation's transcript. list_skills shows the pool; this shows what was called.
Use it to see how heavily, how reliably and at what cost each tool is used. READ THE SCOPE FIRST: the filter sits on the tools/call pipeline. A one-shot aicb call writes the same row under the client name 'aicb-call' when given a --db-path, and nothing without one. A sub-query inside batch or measure records the PARENT call and no child row - measured with a planted probe. So every count here is a LOWER BOUND, and a tool at 0 was not called THROUGH THIS DOOR rather than not called. A batch parent's row does carry a tally of its sub-queries, returned as subQueries: read it before calling a tool unused.
Returns totals (totalCalls, errorCalls, errorRatePct, distinctTools, distinctSessions, firstTs, lastTs, clients, serverVersions); tools, ranked by calls, each with errors, duration (ms) and result size (chars) as average, p50, p90 and max, plus - when non-zero - errorClasses (exception type names; McpException is a failure the tool raised on purpose), argumentBindingErrors (the caller named an argument the tool does not have) and aliasApplied; protocolVersions and clientEras (who called, on which protocol revision); facets; subQueries; recordedVia; and poolCoverage (poolSize, poolToolsFired, poolToolsNeverCalled, outOfPoolTools). Read coverage THERE, not from distinctTools: that figure counts every tool called including ones outside the pool, so holding it against the pool size overstates coverage.
The answer carries shapes only - names, counts, exception type names - no code, no argument values and no session reference. Without a readable config DB it answers available:false.
Read-only and session-less. sinceDays narrows every figure to the last N days (1..3650, so 0 means one day; omit it for the whole log); the cutoff comes back as windowSinceIso.
| Name | Required | Description | Default |
|---|---|---|---|
| topTools | No | Cap on the per-tool breakdown, ranked by call count (default 30; clamped to 1..200). | |
| sinceDays | No | Only count calls from the last N days (omit for the whole log; clamped to 1..3650). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description goes well beyond: session-less, no code or argument values or session references returned, available:false without a readable DB, and the crucial lower-bound semantics of every count. That is exactly the kind of interpretive disclosure annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the scope warning, then the return shape and the window parameter, so an agent can stop reading early. It is long for a two-parameter read-only tool and some sentences (batch vs. measure phrasing) are dense, but each carries distinct scope semantics rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry the return contract - and it does, enumerating totals fields, per-tool ranking with duration/result-size percentiles, errorClasses, aliasApplied, facets, subQueries, recordedVia, and poolCoverage with a warning to read coverage there rather than from distinctTools. Nothing needed to call or interpret it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so baseline is 3, but the description adds meaning: sinceDays narrows every figure to the last N days, the 0-thus-one-day quirk and the omitted-for-whole-log behavior, and that the cutoff returns as windowSinceIso. topTools is left to the schema, which documents it fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: reports server-side CallTool-filter telemetry from the config DB's tool_calls table, across every client that used the DB. It explicitly distinguishes itself from the sibling list_skills ('shows the pool; this shows what was called'), which most siblings would not infer on their own.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('see how heavily, how reliably and at what cost each tool is used') and, unusually, a when-NOT-to-trust-it section ('READ THE SCOPE FIRST' - the filter only sees tools/call, batch sub-queries record the parent, so counts are lower bounds and a 0 means 'not called through this door'). This routes the agent's interpretation correctly and names the alternative (list_skills) for the population question.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_claimVerify a Claim About a ChangeARead-onlyIdempotent
Verify a structured claim about a change by diffing two analyzed sessions (baseline → changed). Supported claim types (MVP): 'no_new_api' (no types/methods were ADDED AND no method signatures changed) and 'symbol_removed_unused' (the named symbol was removed AND had no usages in the baseline's static fan-in graph). Returns a verdict of confirmed / refuted / indeterminate with a reason + evidence. NOTE THE SCOPE OF 'no_new_api': it is about ADDITIONS and SIGNATURE CHANGES, so a REMOVAL does not refute it - a change set that only deletes public API is legitimately 'confirmed'. Removals are therefore never silent: the reason states the boundary and every removal the same diff records is listed as evidence, prefixed '-'. For the removal question ask verify_claim(symbol_removed_unused), or diff_public_contract (outside the default profile's pool). Conservative in BOTH directions: what the diff cannot prove is never falsely confirmed - and never falsely refuted either, because 'was not removed' is a claim about the change that is only made once the string resolves to something this diff could report on. A name that resolves to nothing, a property/field/event/enum member (the diff models types and methods only), and the simple name of a removed type the diff had to render by its FULL name because it is ambiguous, each return 'indeterminate' naming that cause - not a confident 'was not removed'. A removed method whose only baseline callers called an interface or abstract member it implemented (find_usages' viaContract) is 'indeterminate' too: such a call ran its body only when the instance was of its type, and the reason says whether that credit was exact. Unsupported claim types return indeterminate.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | No | The symbol name the claim is about (required for symbol_removed_unused) - a bare name or the qualified Type.Member form, the same strings find_usages / impact_of_change / find_tests_for resolve. A removed type whose simple name is ambiguous solution-wide is recorded under its FULL name; pass that full name for it. A namespace-qualified TYPE name is accepted here even when nothing was removed - this tool resolves it against the baseline's declared type identities, which the fan-in tools (simple name only) do not, and the answer then names the simple name to carry on with. A dotted name no namespace declares stays unresolved rather than falling back to whatever type carries its last segment. | |
| claimType | Yes | Claim type: 'no_new_api' or 'symbol_removed_unused'. | |
| changedSessionId | Yes | The changed session_id (after the change). | |
| baselineSessionId | Yes | The baseline session_id (before the change). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the safety profile is covered. The description goes further by detailing indeterminate conditions (unresolved symbols, non-type/method members, viaContract ambiguity) and the conservative-verdict policy, which is valuable behavioral context. It could specify output format details, but the return shape is described.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loads the core purpose, but it is lengthy and includes detailed edge-case explanations that could be moved to a separate doc. The structure is logical but not optimally concise for quick scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and complex domain logic, the description covers return values (verdict + reason + evidence), supported claim types, indeterminate causes, and conservative reasoning. It is nearly complete, though it could mention session ID requirements more explicitly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by clarifying what 'symbol' accepts (bare or qualified name, full name for ambiguous removed types) and the exact resolution semantics relative to sibling tools. This exceeds the schema's own documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Verify a structured claim about a change by diffing two analyzed sessions') and enumerates the two supported claim types with precise semantics. It clearly distinguishes its scope (additions/signature changes) from sibling tools like verify_claim(symbol_removed_unused) and diff_public_contract.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use guidance is given: supported claim types are listed with their meanings, and the tool routes to alternatives for the removal question ('For the removal question ask verify_claim(symbol_removed_unused), or diff_public_contract'). It also states the boundary of 'no_new_api' to prevent misapplication.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.5.46514- Changed
analyze_solution1 field changed- changed
Input schema / properties / dbPath / descriptionPrevious value: -"Optional absolute path to a config/master DB. When given, the DB's CONFIGURED namespace-exclusion list (per-solution row, else app-global default) is applied during analysis, same as the CLI; where the DB configured none, the committed .aicb.json sidecar's list applies, and only without a sidecar the DB's built-in default (a built-in default is not configuration - solution_config_status names the list in force and its source); the DB's active test-detection profile (per-solution > global > default) is resolved for the session so the test-aware tools (find_dead_code / coverage_gaps / symbol_metrics / find_tests_for / find_by_side_effects / assert_absence / prepare_task / list_insights / get_insight / solution_metrics) honor it; AND - unless an explicit layerProfile is given - the DB's active layer-mapping profile (per-solution > app-global) drives the analysis (dependency-graph layers + LAYER_MAP), matching the insights/metrics/CLI-gate path. All three travel with the session, so downstream tools honor them without re-passing dbPath. Omit to use the server's default config DB (the same one the GUI uses), if the server resolved one - so the GUI's per-solution exclusions + test + layer profile apply automatically; else the DB-free default (no exclusions, default test heuristic, role-based layers). When a config DB is resolved and a config axis (layer/exclusions/test) is not yet initialized via the guided setup, the response carries a configInit hint pointing to solution_config_status."New value: +"Optional absolute path to a config/master DB. When given, the DB's CONFIGURED namespace-exclusion list (per-solution row, else app-global default) is applied during analysis, same as the CLI; where the DB configured none, the committed .aicb.json sidecar's list applies, and only without a sidecar the DB's built-in default (a built-in default is not configuration - solution_config_status names the list in force and its source); the DB's active test-detection profile (per-solution > global > default) is resolved for the session so the test-aware tools (find_dead_code / coverage_gaps / symbol_metrics / find_tests_for / find_by_side_effects / assert_absence / prepare_task / list_insights / get_insight / solution_metrics) honor it; AND - unless an explicit layerProfile is given - the DB's active layer-mapping profile (per-solution > app-global) drives the analysis (dependency-graph layers + LAYER_MAP), matching the insights/metrics/CLI-gate path. All three travel with the session, so downstream tools honor them without re-passing dbPath. Omit to use the server's default config DB (the same one the GUI uses), if the server resolved one - so the GUI's per-solution exclusions + test + layer profile apply automatically; else the DB-free default (the built-in exclusion list, default test heuristic, role-based layers). When a config DB is resolved and a config axis (layer/exclusions/test) is not yet initialized via the guided setup, the response carries a configInit hint pointing to solution_config_status."
- Changed
evaluate_change_set1 field changed- changed
Input schema / properties / dbPath / descriptionPrevious value: -"Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND its configured default layer profile (per-solution > app-global) drives the layer-violation analysis on BOTH delta sides (an explicit analyze_solution(layerProfile) wins); omit to fall back to the server's default config DB (the GUI's, if the server resolved one), else the default profile + session axes."New value: +"Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND its configured default layer profile (per-solution > app-global) drives the layer-violation analysis on BOTH delta sides (an explicit analyze_solution(layerProfile) wins); omit to fall back to the server's default config DB (the GUI's, if the server resolved one), else the default profile + session axes, and the layer profile to the config DB the session was analysed against - the one its renders read."
- Changed
export_markdown1 field changed- changed
Input schema / properties / format / descriptionPrevious value: -"Optional inner notation of the rendered Markdown: 'tag' (the established AI-Builder tag format) or 'yaml' (idiomatic YAML - a lossless re-notation, not a different selection of content). Pick whichever notation you parse more reliably. When given, this explicit value wins; when omitted, the active MCP profile's OutputFormat is used (profile-aware path), else yaml (the DB-free default). The .md branding is unchanged; an unrecognized explicit value falls back to tag."New value: +"Optional inner notation of the rendered Markdown: 'tag' (the established AI-Builder tag format) or 'yaml' (idiomatic YAML - a lossless re-notation, not a different selection of content). Pick whichever notation you parse more reliably. When given, this explicit value wins; when omitted, the active MCP profile's OutputFormat is used (profile-aware path), else yaml (the DB-free default). The .md branding is unchanged. Any other value counts as omitted: the profile's format (else yaml) applies, and the response starts with a note naming the ignored value."
- Changed
find_implementations1 field changed- changed
Input schema / properties / interfaceName / descriptionPrevious value: -"The interface's simple name, e.g. 'ICodeAnalyzer'. An arity suffix ('IConsumer`1' / 'IConsumer<T>', or 'IConsumer`0' for the non-generic namesake) filters to that arity; a bare name keeps the merged view of every arity."New value: +"The interface's simple name, e.g. 'ICodeAnalyzer'. An arity suffix ('IConsumer`1' / 'IConsumer<T>', or 'IConsumer`0' for the non-generic namesake) filters to that arity; a bare name keeps the merged view of every arity. A concrete type argument ('IConsumer<OrderPlaced>') keeps only the types that close it with that argument."
- Changed
find_usages1 field changed- changed
Input schema / properties / symbol / descriptionPrevious value: -"The exact (case-sensitive) type, method, property, field, event or enum-member name - the qualified Type.Member form for a member - or 'Type.Type' for a type's CONSTRUCTOR (see the tool description: the answer is the type's construction/injection sites, overloads unioned)."New value: +"The exact (case-sensitive) type, method, property, field, event, enum-member or operator (metadata) name - the qualified Type.Member form for a member - or 'Type.Type' for a type's CONSTRUCTOR (see the tool description: the answer is the type's construction/injection sites, overloads unioned)."
- Changed
get_insight1 field changed- changed
Input schema / properties / dbPath / descriptionPrevious value: -"Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND the configured default layer profile (DefaultLayerProfileName / per-solution) drives the layer-violation analysis (an explicit analyze_solution(layerProfile) wins); omit to fall back to the server's default config DB (the GUI's, if resolved), else the default profile + the explicit session layer profile."New value: +"Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND the configured default layer profile (DefaultLayerProfileName / per-solution) drives the layer-violation analysis (an explicit analyze_solution(layerProfile) wins). Omitted, the QualityProfile falls back to the server's default config DB (the GUI's, if resolved), else the default profile, and the layer profile to the config DB the session was analysed against - the one its renders read."
- Changed
impact_of_change1 field changed- changed
Input schema / properties / symbol / descriptionPrevious value: -"The exact (case-sensitive) type, method, property, field, event or enum-member name to assess - or the qualified Type.Member form for a member."New value: +"The exact (case-sensitive) type, method, property, field, event, enum-member or operator (metadata) name to assess - or the qualified Type.Member form for a member."
- Changed
list_insights1 field changed- changed
Input schema / properties / dbPath / descriptionPrevious value: -"Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND the configured default layer profile (DefaultLayerProfileName / per-solution) drives the layer-violation analysis (an explicit analyze_solution(layerProfile) wins); omit to fall back to the server's default config DB (the GUI's, if resolved), else the default profile + the explicit session layer profile."New value: +"Optional path to an AIContextBuilder SQLite DB. When set, producer thresholds + toggles come from that DB's active QualityProfile AND the configured default layer profile (DefaultLayerProfileName / per-solution) drives the layer-violation analysis (an explicit analyze_solution(layerProfile) wins). Omitted, the QualityProfile falls back to the server's default config DB (the GUI's, if resolved), else the default profile, and the layer profile to the config DB the session was analysed against - the one its renders read."
- Changed
resolve_injection1 field changed- changed
Input schema / properties / interface / descriptionPrevious value: -"The interface simple or fully-qualified name, e.g. 'ICodeAnalyzer'."New value: +"The interface simple or fully-qualified name, e.g. 'ICodeAnalyzer'. A closed generic form ('IHandler<Saved>') lists only the registrations serving that closing; 'IHandler' or 'IHandler<T>' lists every closing."
- Changed
solution_metrics1 field changed- changed
Input schema / properties / dbPath / descriptionPrevious value: -"Optional path to an AIContextBuilder SQLite DB. When set, the complexity threshold and producer toggles come from that DB's active QualityProfile (same semantics as list_insights); omit to fall back to the server's default config DB (the GUI's, if resolved), else the default profile."New value: +"Optional path to an AIContextBuilder SQLite DB. When set, the complexity threshold and producer toggles come from that DB's active QualityProfile (same semantics as list_insights); omit to fall back to the server's default config DB (the GUI's, if resolved), else the default profile. Omitted, the layer profile comes from the config DB the session was analysed against."
48 tool updates
v0.5.46513- Changed
analyze_solution1 field changed- changed
Input schema / properties / solutionPath / descriptionPrevious value: -"Absolute path to the .sln file to analyze."New value: +"Absolute path to the solution file to analyze (.sln, .slnx or .slnf)."
- Changed
apply_solution_config1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
architecture_overview1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
assert_absence1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
batch1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution (or an absolute .sln path to self-init once). Shared by ALL sub-queries - do NOT repeat it inside each query's args."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. Shared by ALL sub-queries - do NOT repeat it inside each query's args."
- Changed
call_graph1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
calls_external1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
check_solution_config_drift1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
compare_with_previous1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The current session_id (the 'after' side of the diff)."New value: +"The current session_id (the 'after' side of the diff). Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
coverage_gaps1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
describe_api_surface1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
detect_circular_dependencies2 fields changed- changed
Input schema / properties / includeTests / descriptionPrevious value: -"Include test projects (default FALSE - production focus: a test->production reference is one-way and not an architecture cycle). Set true to include *.Tests/*.Spec projects."New value: +"Include test projects (default FALSE - production focus: a test->production reference is one-way and not an architecture cycle). Set true to include them." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
evaluate_change_set1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution (the baseline)."New value: +"The session_id returned by analyze_solution (the baseline). Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
explain_symbol1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
export_markdown1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_binding_usages2 fields changed- changed
Input schema / properties / path / descriptionPrevious value: -"The exact (case-sensitive) bound member path, e.g. 'GestureLabel' or 'Foo.Bar'. Omit for the inventory view (every bound path with its site counts)."New value: +"The exact (case-sensitive) bound member path, e.g. 'GestureLabel' or 'Foo.Bar'. Omit for the inventory view (every bound root member with its site counts)." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_by_attribute1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_by_event_subscription1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_by_semantics4 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"Match symbols whose resolved Domain contains this (free text - derived from naming/namespace). Omit to not filter on domain."New value: +"Match symbols whose resolved Domain contains this (free text, set by an <ai> annotation - nothing infers it). Omit to not filter on domain." - changed
Input schema / properties / layer / descriptionPrevious value: -"Match symbols whose resolved Layer EQUALS this (whole value, case-insensitive). Clean-Architecture layers: Domain / Application / Infrastructure / Presentation / Contracts. Omit to not filter on layer."New value: +"Match symbols whose resolved Layer EQUALS this (whole value, case-insensitive). The built-in inference assigns Domain / Application / Infrastructure / Presentation / Contracts; a layer profile adds its own names. Omit to not filter on layer." - changed
Input schema / properties / role / descriptionPrevious value: -"Match symbols whose resolved Role EQUALS this (whole value, case-insensitive). Inferred TYPE roles (closed set): Service, Helper, Model, Record, Interface, Enum, Builder, ViewModel, Converter, Controller, Middleware, Attribute, Exception, EntryPoint, ContractModel, Type - there is NO 'Repository' (repositories are 'Service'). Methods use a category role (e.g. Query, Command, Mapping, Validation). <ai>-asserted roles may differ. Omit to not filter on role."New value: +"Match symbols whose resolved Role EQUALS this (whole value, case-insensitive). Inferred TYPE roles: Service, Helper, Model, Record, Interface, Builder, ViewModel, Converter, Controller, Middleware, Attribute, Exception, EntryPoint, ContractModel, Type - there is NO 'Repository' (a repository class is mostly 'Service'), and an enum gets no role. Methods use a category role (e.g. Query, Command, Mapping, Validation, Orchestration). <ai>-asserted roles add values of their own. Omit to not filter on role." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_by_side_effects2 fields changed- changed
Input schema / properties / includeTests / descriptionPrevious value: -"Include test-project methods (default false - production focus: a 'what hits the DB?' query is otherwise drowned by Seed*/Migrate_*/*RepositoryTests). Set true to also list methods in *.Tests/*.Spec projects."New value: +"Include test-project methods (default false - production focus: a 'what hits the DB?' query is otherwise drowned by Seed*/Migrate_*/*RepositoryTests). Set true to also list the methods of test projects." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_dead_code2 fields changed- changed
Input schema / properties / kinds / descriptionPrevious value: -"'method' (default) private methods with no caller · 'type' types with no incoming reference · 'all' both."New value: +"'method' (default): private methods with a measured, empty caller list - see the description for what that axis does not judge; 'type': types with no incoming reference; 'all': both." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_implementations1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_overrides1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_resource_usages1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_symbol1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_tests_for1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_unresolved_bindings1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
find_usages1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
get_context1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
get_diagnostics2 fields changed- changed
Input schema / properties / scope / descriptionPrevious value: -"'solution' (default) or a file-path substring (e.g. 'MyApp.Core' or 'Services/') that filters the RESULT. It does not reduce the work: all projects are compiled either way (see the tool description) - it saves response tokens, not latency."New value: +"'solution' (default) or a file-path substring (e.g. 'MyApp.Core' or 'Settings.cs') that filters the RESULT. It is matched against a diagnostic's location as the answer prints it, so a directory separator is a backslash on Windows. It does not reduce the work: all projects are compiled either way (see the tool description) - it saves response tokens, not latency." - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
get_insight1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
get_type_hierarchy1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
impact_of_change1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
init_solution_config1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
install_agent_hooks1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"Session id, or the absolute .sln/.slnx/.slnf path (self-init)."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
instantiation_sites1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
list_insights1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
measure1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution (or an absolute .sln path to self-init once). Shared by ALL queries - do NOT repeat it inside each query's args."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use. Shared by ALL queries - do NOT repeat it inside each query's args."
- Changed
pack_for_task1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
prepare_task3 fields changed- changed
Input schema / properties / budget / descriptionPrevious value: -"Optional token budget (floored at 8000). Applies to BOTH the lean and the profile-aware template render path: it compacts/drops method bodies AND drops the least-relevant types when the neighborhood overflows. The goal-named seeds are never dropped - one whose own source does not fit renders as structure (members and signatures); the bundled covering tests/siblings are BUDGET-BOUND - under a tight budget they are dropped to fit (a leading comment names the drops so you can ask for one by name). Overrides any MCP-profile/template token budget. Omitted, the bundle still renders against a ceiling (the MCP profile's token budget, else the facet template's, else a ~10000-token default budget) that bounds the neighborhood."New value: +"Optional token budget (floored at 8000). Applies to BOTH the lean and the profile-aware template render path: it compacts/drops method bodies AND drops the least-relevant types when the neighborhood overflows. A type the goal names, and the one owner of a method name it names, is never dropped - one whose own source does not fit renders as structure (members and signatures). The owners of a method name several types share are capped like the neighborhood: some are reduced to structure, some dropped. The bundled covering tests/siblings are BUDGET-BOUND - under a tight budget they are dropped to fit (a leading comment names the drops so you can ask for one by name). Overrides any MCP-profile/template token budget. Omitted, the bundle still renders against a ceiling (the MCP profile's token budget, else the facet template's, else a ~10000-token default budget) that bounds the neighborhood." - changed
Input schema / properties / facet / descriptionPrevious value: -"Optional facet to work under - the task axis of this call: General (default), Exploration, Refactoring, Debugging, Review, Testing, Documentation, Architecture, or Performance. On a profile-aware server (aicb mcp --db-path) the facet's template shapes the render; it always appends a short work-style trailer with suggested next tools. (The former name 'slot' is still accepted.)"New value: +"Optional facet to work under - the task axis of this call: General (default), Exploration, Refactoring, Debugging, Review, Testing, Documentation, Architecture, or Performance. On a server with a config DB (the default: a plain 'aicb mcp' resolves the standard one) the facet's template shapes the render; it always appends a short work-style trailer with suggested next tools. (The former name 'slot' is still accepted.)" - changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
refresh_session1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
resolve_injection1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
review_context1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
save_session1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id whose current state to snapshot."New value: +"The session_id whose current state to snapshot. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
solution_config_status1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
solution_metrics1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
symbol_metrics1 field changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use."
- Changed
symbol_signature2 fields changed- changed
Input schema / properties / sessionId / descriptionPrevious value: -"The session_id returned by analyze_solution."New value: +"The session_id returned by analyze_solution. Also takes an absolute .sln/.slnx/.slnf path, analyzed on first use." - changed
Input schema / properties / symbol / descriptionPrevious value: -"The exact (case-sensitive) type, method, property, field, event, enum-member or operator name (e.g. 'op_Equality')."New value: +"The exact (case-sensitive) type, method, property, field, event, enum-member or operator name (e.g. 'op_Equality'), bare or qualified ('Type.Member', 'Ns.Type')."
54 tool updates
- First observed
analyze_solution - First observed
apply_solution_config - First observed
architecture_overview - First observed
assert_absence - First observed
batch - First observed
call_graph - First observed
calls_external - First observed
check_solution_config_drift - First observed
compare_with_previous - First observed
coverage_gaps - First observed
describe_api_surface - First observed
detect_circular_dependencies - First observed
docs - First observed
evaluate_change_set - First observed
explain_symbol - First observed
export_markdown - First observed
find_binding_usages - First observed
find_by_attribute - First observed
find_by_event_subscription - First observed
find_by_semantics - First observed
find_by_side_effects - First observed
find_dead_code - First observed
find_implementations - First observed
find_overrides - First observed
find_resource_usages - First observed
find_symbol - First observed
find_tests_for - First observed
find_unresolved_bindings - First observed
find_usages - First observed
get_context - First observed
get_diagnostics - First observed
get_insight - First observed
get_type_hierarchy - First observed
impact_of_change - First observed
init_solution_config - First observed
install_agent_hooks - First observed
instantiation_sites - First observed
list_insights - First observed
list_mcp_profiles - First observed
list_skills - First observed
measure - First observed
pack_for_task - First observed
prepare_task - First observed
refresh_session - First observed
resolve_injection - First observed
review_context - First observed
save_session - First observed
server_info - First observed
solution_config_status - First observed
solution_metrics - First observed
symbol_metrics - First observed
symbol_signature - First observed
usage_report - First observed
verify_claim
TDQS
Scored across 54 tools
Most tools carve out a distinct question and the descriptions explicitly cross-reference siblings (coverage_gaps vs find_tests_for, instantiation_sites vs resolve_injection, find_overrides vs find_implementations, find_by_side_effects vs calls_external), which is unusually good disambiguation. The weak spot is a family of overlapping context-bundlers — get_context, explain_symbol, pack_for_task, prepare_task, review_context, architecture_overview, export_markdown — whose boundaries are only separated by prose hints like 'prefer X when you are about to EDIT'.
Every name is snake_case with no casing mix, and the majority follow a verb_noun pattern (find_*, get_*, list_*, analyze_*, apply_*, check_*, describe_*, save_*, refresh_*, detect_*, verify_*). The deviations are consistent-ish but real: a whole cluster of noun-phrase names (coverage_gaps, impact_of_change, review_context, symbol_signature, architecture_overview, symbol_metrics, solution_metrics, usage_report, instantiation_sites, call_graph) plus bare verbs (measure, batch, docs), so the verb is missing where an agent might expect one.
54 tools is far past the useful ceiling for a single server; even granting the breadth (Roslyn analysis, quality gate, config, DI, XAML, telemetry, snapshots, docs), the surface is large enough that selection itself becomes the hard problem. A pool/profile mechanism (list_skills, list_mcp_profiles, out-of-pool tools) mitigates this by pruning the active set, but the registered surface as presented is heavy.
The lifecycle is closed: analyze/refresh, symbol and usage navigation, impact and coverage, snapshots plus compare_with_previous and verify_claim, config init/apply/status/drift, export and bounded views, plus server/session introspection and docs. Markup (bindings, resources), DI wire-up, external calls and side-effect profiles cover niche domains that a C#-only graph would miss, and the few absent tools (diff_public_contract, semantic_diff) are explicitly disclosed as existing out-of-pool rather than silently missing.
Maintenance
Related MCP Connectors
Deterministic context layer for your codebase: change impact, blast radius, answers with receipts.
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Search indexed code, trace dependencies, assess change impact, and recall repository memory.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceProvides efficient code navigation and graph-based analysis for AI agents, enabling symbol resolution, callers, implementations, and type schemas with minimal token usage.-
- AlicenseAqualityAmaintenanceEnables AI coding agents to query a semantic cross-repository code graph for symbols, references, callers, dependencies, and change impact across registered repositories.1222Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables AI coding agents and IDEs to query a local structural code graph and retrieve focused, token-bounded context on code entities, Git relationships, callers/callees, impact, paths, and recorded mistakes for more efficient sessions.6 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI coding agents to retrieve bounded, focused context from a local structural code graph, including source entities, Git relationships, and recorded project memory. It supports exploring structure, inspecting callers, callees, and impact, and carrying prior mistakes into later sessions without reading full files.6 npmMIT