AI agents
BootUI can expose its advisor findings and runtime diagnostics to a local AI coding agent, so the agent can consult your running application before proposing a fix and verify the fix afterwards. It works with GitHub Copilot, Claude Code, and any other client that speaks the Model Context Protocol (MCP).
This page covers installing the agent skill, the Cursor plugin, or the Claude Code plugin, connecting an agent to the MCP server, choosing between that and the CLI, a worked example that fixes Hibernate findings, and how BootUI pairs with Coffilot.
Why use BootUI from an agent
An agent reading your source code can only guess at runtime behavior. BootUI gives it machine-readable context from the running application instead:
- Advisor scans — architecture, REST API, Spring, Hibernate, JVM memory, Spring Security, pentesting, GraalVM and CRaC readiness. The agent gets the same prioritized, severity-ranked findings the panels show, with remediation hints.
- Runtime diagnostics — a correlated live activity feed (recent HTTP requests, SQL statements, exceptions, and security events grouped by request/trace), full exception detail (stack trace, causes, occurrences) by id, security audit events, SQL traces, distributed traces, log tail, and HTTP exchanges, so the agent can correlate a failure with what the app actually did.
- Core context — application overview, health, effective configuration (secrets masked), beans, and request mappings.
Every tool reuses the same controllers and immutable DTOs as the browser UI, so the agent sees the same masked, bounded shape a human would, never raw internals.
Dismissed Pentesting findings
pentest_scan, get_pentest_report, their CLI equivalents, and the REST API retain accepted findings with dismissed: true, while finding totals and severity counts include only active findings. Dismissals use the exact PT-* check ID from the shared local store and do not carry over from Security rule IDs. Reading the cached report reflects a dismissal or restoration without rescanning, and scan evidence and coverage limits are unchanged.
MCP server or CLI?
Both surfaces give the agent identical data: the same registry, the same panel policy, the same masked, bounded DTOs. The CLI can neither offer a diagnostic the MCP server lacks nor miss one it has, because its command table is generated from the tool registry at build time.
Use the MCP server when your agent or IDE speaks MCP natively. The agent discovers tools, schemas, and descriptions automatically and calls them as native tool calls, with no shell commands and no JSON parsing glue. This is the path the rest of this page follows, and what the agent skill, the Claude Code plugin, and Coffilot wire up for you.
Use the CLI when the agent's host can only run shell commands: a sandboxed or cloud agent with no MCP wiring, a CI job, or a human running one-off checks. The agent skill falls back to bootui commands whenever its host does not already expose BootUI's MCP tools.
Install the BootUI agent skill
BootUI ships an agent skill that teaches GitHub Copilot how to install and configure BootUI, inspect a running application from the command line or the MCP server, turn advisor findings into focused fixes, and verify those fixes.
Install the canonical skill in any Agent Skills-compatible coding agent:
npx skills add https://github.com/jdubois/boot-ui/tree/main/skills/bootui
The interactive installer detects supported agents and lets you select where to install the skill. Like any third-party skill, review its instructions before installation.
With GitHub CLI 2.90 or later, GitHub Copilot users can inspect the skill before installing it:
gh skill preview jdubois/boot-ui skills/bootui
Then install it for the current project:
gh skill install jdubois/boot-ui skills/bootui
The skill works with Copilot cloud agent, Copilot CLI, the GitHub Copilot app, Copilot code review, and agent mode in supported IDEs. You can also copy skills/bootui into a project's .github/skills directory manually.
Cursor and Claude Code users should prefer their plugin, which installs this skill and wires up the MCP server in one step.
Repository-wide skill searches may show both skills/bootui and plugins/bootui/skills/bootui. Install skills/bootui: it is the canonical consumer skill. The second result is an identical copy kept inside the portable plugin because plugin clients install a self-contained directory and cannot follow a reference to the canonical file outside it. A build test prevents the two copies from drifting.
Install the BootUI Cursor plugin
BootUI ships an Agent Plugins payload that Cursor loads as a plugin. It bundles the same agent skill and registers the local MCP endpoint, so it is the preferred Cursor setup once the plugin is available in the Cursor Marketplace:
- Open Customize in Cursor.
- Find BootUI, select Install, and choose user or project scope.
- Confirm that the
bootuiskill and MCP server appear.
BootUI must already be running in your application, and its MCP server must be enabled with bootui.mcp.enabled=ON or from /bootui/#/mcp-server. The bundled connection points at http://127.0.0.1:8080/bootui/api/mcp.
If the application uses another port or a custom bootui.api-path, disable the bundled BootUI MCP server in Customize and use the manual ~/.cursor/mcp.json entry below with the correct URL. Do the same for an application reached from a container or another host, adding its Authorization bearer token to your local configuration. Agent Plugins does not expand environment variables in remote URLs, and the portable plugin deliberately ships no credentials.
Agent Plugins names BootUI's transport streamable-http; Claude Code and VS Code call the same transport http, while Cursor's personal MCP configuration omits the type. This is only client vocabulary: BootUI has always accepted JSON-RPC over Streamable HTTP at POST /bootui/api/mcp.
Install the BootUI Claude Code plugin
For Claude Code, BootUI ships a plugin that bundles the same agent skill and the MCP server connection, so there is no separate claude mcp add step. Add the marketplace and install it:
/plugin marketplace add jdubois/boot-ui
/plugin install bootui@bootui
The plugin registers the bootui skill and an HTTP MCP server pointing at http://127.0.0.1:8080/bootui/api/mcp.
Two things to know before your first call:
The MCP server is off by default. The plugin cannot turn it on for you — it lives in your application. Set
bootui.mcp.enabled=ON, or flip the toggle in the MCP Server panel (/bootui/#/mcp-server), as described in Connect an agent to the BootUI MCP server. Until then every tool call answers that the server is disabled.If your application does not listen on port 8080, set
BOOTUI_MCP_URLbefore starting Claude Code. The plugin reads it and falls back to the address above when it is unset, so this also covers a custombootui.api-pathor an application reached from a container:export BOOTUI_MCP_URL=http://127.0.0.1:8081/bootui/api/mcp
An agent reaching BootUI from anywhere other than loopback must also present the bearer token; the plugin's configuration carries no header, so register that server yourself with the claude mcp add form below instead.
Because BootUI is loopback-only by default, the plugin asks for no credentials and stores nothing. It is published from this repository, so /plugin marketplace update bootui picks up every change to the skill. The plugin changes no policy of its own: the safety model below — panel availability, read-only flags, and confirmation for mutating actions — applies exactly as it does to any other MCP client.
Connect an agent to the BootUI MCP server
The BootUI MCP server is a local, opt-in JSON-RPC 2.0 endpoint at POST /bootui/api/mcp. It is disabled by default (fail-closed) and, like the rest of BootUI, only reachable over the loopback interface unless non-loopback access is explicitly enabled, which requires authentication.
Run your app locally with BootUI active (the
dev/localprofiles, orspring-boot-devtoolson the classpath). See Setup.Enable the server. Set
bootui.mcp.enabled=ON, or flip the toggle at the top of the MCP Server panel (/bootui/#/mcp-server). The panel toggle overrides the property at runtime for the life of the process, so you can turn the server on only while you are pairing with an agent.Point your agent at the endpoint. The MCP Server panel shows a ready-to-copy client configuration, with one tab per client because they do not agree on a shape. Replace
8080with your application's port.VS Code (
.vscode/mcp.json) uses aserversblock:{ "servers": { "bootui": { "type": "http", "url": "http://127.0.0.1:8080/bootui/api/mcp" } } }Claude Code registers the server from a terminal in your project — though the plugin does this for you:
claude mcp add --transport http bootui http://127.0.0.1:8080/bootui/api/mcpCursor users should prefer the plugin. For a manual setup or an endpoint that differs from the plugin default,
~/.cursor/mcp.jsonkeys a remote server onurland takes notype:{ "mcpServers": { "bootui": { "url": "http://127.0.0.1:8080/bootui/api/mcp" } } }Most other clients — including the
.mcp.jsonClaude Code writes — accept themcpServersshape with an explicit type:{ "mcpServers": { "bootui": { "type": "http", "url": "http://127.0.0.1:8080/bootui/api/mcp" } } }No credentials are needed on loopback — the endpoint is exempt from BootUI's browser-only CSRF token so a local non-browser MCP client connects with a plain HTTP config, while the loopback,
Hostallow-list, and cross-site write defenses still apply.If the agent is not on loopback, send the bearer token. An agent that reaches the app from anywhere other than loopback — the common case being an app in a container reached through a published port — is a remote API caller like any other, and every MCP call answers
401until it presents BootUI's token in the standardAuthorizationheader. Tick Agent connects from another host or container in the panel and the snippets gain the header. For Claude Code that is:claude mcp add --transport http bootui http://localhost:8080/bootui/api/mcp \ --header "Authorization: Bearer <BootUI authentication token>"and for a JSON client, a
headersentry besideurl:{ "mcpServers": { "bootui": { "type": "http", "url": "http://localhost:8080/bootui/api/mcp", "headers": { "Authorization": "Bearer <BootUI authentication token>" } } } }The token is the value of
bootui.authentication.token. When that property is blank, BootUI generates a new token at every start and logs it once — set the property to a stable value if you do not want to re-edit the client configuration after each restart. The browser console does not need this because it authenticates once and keeps an HTTP-only session cookie; a non-browser MCP client has no such fallback.
A GET /bootui/api/mcp-server status request returns the advertised tool list, which is handy for inspecting what an agent will see before you wire it up.
Tools the agent can call
Tools whose backing panel/controller is absent (for example Hibernate or Spring Security when those libraries are not on the classpath) are simply not advertised.
- Advisor scans (actions):
architecture_scan,spring_scan,hibernate_scan,database_advisor_scan,memory_scan,security_scan,pentest_scan,rest_api_scan,graalvm_scan,crac_scan, andvulnerabilities_scan. Each runs the same scan as the panel's action button and returns the report DTO;vulnerabilities_scanadditionally sends package names/versions to OSV.dev and, when EPSS is enabled, CVE ids to FIRST. Run it only with approval. Inspectscan.status,scan.message,coverage, andscan.packagesSkipped; partial or unknown evidence is not a clean result.coverage.archivesFirstParty/firstPartyArchivesname the application's own module JARs, which are not a coverage gap. Fix candidates need compatibility checks, and EPSS is the highest available per-CVE probability, not a combined probability or severity. See Vulnerabilities checks. - Cached advisor reports:
get_architecture_report,get_spring_report,get_hibernate_report,get_database_advisor_report,get_memory_report,get_security_report,get_pentest_report,get_rest_api_report,get_graalvm_report,get_crac_report, andget_vulnerabilities_reportreturn the last completed report without starting another scan. - Cached per-rule violations (reads):
get_architecture_rule_violations,get_hibernate_rule_violations,get_spring_rule_violations,get_rest_api_rule_violations,get_memory_rule_violations,get_security_rule_violations, andget_database_advisor_rule_violationspage the retained details from that advisor's latest completed scan. Each takes requiredid(rule ID) andscanId, with optionaloffsetandlimit. They have the same stack/capability availability as their report, and remain usable in read-only mode. - Diagnostics reads:
get_live_activity,get_request_profile,get_exceptions,get_exception_detail,get_security_logs,get_sql_traces,get_transactions(Spring MVC/WebFlux only),get_traces,get_log_tail,get_http_exchanges,get_http_routes, andget_rest_client_traces.get_http_routesreturns the HTTP Exchanges route rankings: per method and route template, request and status-class counts, p50/p95/p99 and maximum duration, share of request time, and the evidence window they cover; its optionallimitis the number of routes each ranking criterion contributes.get_live_activityreturns the correlated feed the Live Activity panel shows (HTTP requests, SQL statements, exceptions, and security events grouped by request/trace);get_request_profiletakes the requiredidof aREQUESTentry whoseprofileableflag is true and returns the same masked profile asGET /bootui/api/activity/request/{id}and the panel's profile drawer — see Investigate one request;get_exception_detailtakes a requiredid(fromget_exceptions,get_live_activity, or a profile exception'sexceptionGroupId) and returns that exception group's full stack trace, causes, and individual occurrences.get_http_exchanges,get_sql_traces, andget_rest_client_tracesread bounded buffers that keep recent failed and slow records longer than routine ones; each includes aretentionobject with the capacity and the retained, reserved, and evicted counts, so an agent can tell a partial window from "it never happened". See Failure-preserving retention. - Core context and integration reads:
get_overview,get_health,get_config(masked),get_beans,get_mappings,get_loggers,get_conditions,get_http_sessions,get_scheduled_tasks,get_fault_tolerance,get_cache_stats,get_database_connection_pools,get_postgresql_report,get_mysql_report,get_metrics,get_live_memory,get_jvm_tuning,get_heap_dump_report,get_threads,get_startup_timeline,get_profile_diff,get_spring_data_repositories,get_flyway_migrations,get_liquibase_changesets,get_spring_security,get_ai_overview,get_emails,get_kafka_activity,get_rabbitmq_activity,get_jms_activity,get_devtools_status,get_dev_services,get_github_dashboard,get_copilot_sessions, andget_claude_code_sessions. Stack-specific or unavailable capabilities are omitted. - Bounded controls (actions):
clear_exceptions,clear_sql_traces,pause_sql_trace_recording,resume_sql_trace_recording,clear_transactions,pause_transaction_recording,resume_transaction_recording,clear_traces,clear_rest_client_traces,pause_rest_client_recording,resume_rest_client_recording,postgresql_read,mysql_read,analyze_heap_dump, andtrigger_devtools_livereload. They never capture or download a heap dump, execute an HTTP probe, mutate a database, clear a cache, write GitHub state, restart a dev service, or run an agent command.
Investigate one request
get_live_activity says which request was slow or failed; get_request_profile says why. The workflow is the same through MCP and the CLI:
- List activity. Call
get_live_activity(bootui activity --limit 50 --json) and pick theREQUESTentry in question. Only entries withprofileable: truehave a profile, andsqlNPlusOneSuspectedor anERRORorSLOWseverity marks the ones worth opening. - Fetch its profile. Call
get_request_profilewith that entry'sid(bootui request-profile <id> --json). The profile carries the request, its correlated SQL as normalized statement groups with N+1 flags and the application call sites that issued them, exceptions, security events, REST client calls, cache accesses, a timing breakdown, per-section correlation tiers and truncation counts, and notes. It is the same DTO the REST endpoint returns, masked the same way, including the embedded trace's status messages, exception events, and attribute values (Trace value exposure). An unknown or evicted id returnsavailable: falsewith anunavailableReason; that is an answer, not a failure to retry. - Follow each exception. Every profile exception carries an
exceptionGroupId; pass it toget_exception_detail(bootui exceptions show <id> --json) for the stack trace, cause chain, and recent occurrences.
The tool belongs to the Live Activity panel, so it is unavailable when that panel is disabled. In the browser, Copy for AI in the profile drawer and in an Exceptions detail renders the same evidence as one Markdown document, previewed with what it omits before anything reaches the clipboard. It sends nothing to any AI provider.
MySQL operational evidence
MySQL exposes two argument-free tools on MVC, WebFlux with JDBC, and Quarkus with JDBC:
| Tool | Behavior |
|---|---|
get_mysql_report | Read the latest sanitized in-memory report without opening a connection or executing SQL. |
mysql_read | Explicitly collect bounded operational evidence through the application's existing JDBC datasources. |
Oracle MySQL 8.4 LTS and 9.7 LTS are the tested server lines, with live coverage on 8.4.6 and 9.7.2. MariaDB reached through MySQL Connector/J is read but unsupported (serverFlavor is MARIADB, with an INFO diagnostic naming the gaps); reactive-client-only or R2DBC-only applications are outside this scope. Check the running catalog for the application's actual capability.
Read the cache first. Ask for approval before mysql_read, naming the database collection even though it is read-only: it performs external work and is blocked by global/panel read-only policy. Do not automatically repeat a busy, failed, partial, or stale read. A change in exposure policy invalidates the cache without SQL; an explained NOT_READ is not authorization to collect again.
These are observations, not advisor findings or scores. Inspect report status, per-section reasons, capabilities, timestamps, and limitations. PARTIAL can mean retained top-N rows, disabled/unknown instrumentation, denied permissions, or a timeout; truncated identifies row omissions only. Failed replication evidence is not "no replication." Server-wide counters and default-schema-associated sessions/digests are not this JVM's workload. Unknown values are null; large/unsigned counters, byte sizes, and numeric IDs are exact decimal strings and must retain precision. Do not request raw session/sample SQL or lock values, infer recommendations from absent metrics, grant privileges, or enable Performance Schema automatically. See MySQL for the eight areas and capability-specific permissions, and CLI equivalents.
Reading retained advisor violations
The seven rule-based advisors keep compact sampleViolations previews: at most ten per result, or twenty for the Quarkus application and Security advisors. violationCount is the actual counted total, not the preview size. First read the cached report, then use its violationDetails.scanId with the matching detail tool:
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_architecture_report","arguments":{}}}
For example, if the report identifies scan scan-opaque-1 and rule ARCH-SPRING-004:
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_architecture_rule_violations","arguments":{"id":"ARCH-SPRING-004","scanId":"scan-opaque-1","offset":0,"limit":100}}}
Each page contains scanId, ruleId, violationCount, retainedCount, truncated, violations, page, and locations. Advance offset by page.returned until page.hasMore is false, keeping the same rule and scan ID. Both page.total and page.matched count retained entries for that rule, not violationCount. An offset at or past the retained end returns an empty terminal page.
The default offset is zero and page size is 100, capped at min(1000, bootui.mcp.max-results) (or bootui.cli.max-results on the CLI facade). id and scanId must be nonblank strings; offsets must be nonnegative integers and limits positive integers. Nulls, fractional/overflowing numbers, and undeclared arguments are refused, not silently normalized.
Report-level violationDetails carries scanId, total, retained, retentionLimit, truncated, and locationNotes. Only the latest scan is retained, by default up to 10,000 sanitized details across that advisor's rules, configurable with bootui.advisors.max-retained-violations. A truncated report or rule is not a complete retained list, even when page.hasMore becomes false; a rule can have a positive count and zero retained details. Increasing the retention limit cannot recover discarded details without an explicitly authorized new scan. This retrieval completeness is separate from the report's evidence coverage. Dismissal does not change the scan ID or remove retained details. Some upstream observations supply a count but not every affected identity; their diagnostics and truncation remain visible rather than inventing missing detail strings. Raising the retention limit cannot repair that observation gap. Existing observation bounds also remain: for example, Memory rules that inspect only their top-five inputs do not inspect more inputs when details are paged. The count is the rule's existing counted sequence, not proof of full coverage. Always verify each finding against source and effective configuration before editing.
These reads never rerun checks, import classes, query the database, or start a scan. A missing or replaced snapshot returns a known client failure (REST 409): reread the cached report, not the scan tool, then restart paging that report's scan ID. An unknown/non-finding rule returns REST 404. MCP exposes these as in-band isError: true failures with actionable messages, not internal errors. The CLI facade retains its existing tool-error mapping: unknown rules are HTTP 400 (HTTP 404 is reserved for an unadvertised tool), and stale snapshots remain HTTP 409.
MCP still refuses an oversized rendered response with JSON-RPC -32003. Retry the same scan ID and offset with a smaller limit; a byte-budget refusal is neither an empty page nor proof of completion. Do not advance the offset on any error. Keep pages bounded and stop rather than looping if even one detail exceeds the byte budget.
Going straight to the code
Architecture, REST API, and Hibernate findings that name exactly one code element carry a structured location, so an agent can open the file instead of parsing the violation text. In get_architecture_report, get_rest_api_report, and get_hibernate_report, each result's sampleLocations is aligned index-for-index with sampleViolations; in the matching get_*_rule_violations page, locations is aligned with violations. A null entry means that violation has no location, and an empty list means none of them has one. Each location has className, memberName, kind (CLASS, METHOD, CONSTRUCTOR, or FIELD), sourceFile, line, sourcePath, and precision (LINE, MEMBER, or CLASS):
{"className":"com.example.OrderService","memberName":"place","kind":"METHOD","sourceFile":"OrderService.java",
"line":42,"sourcePath":"/work/shop/src/main/java/com/example/OrderService.java","precision":"LINE"}
Open sourcePath at line when both are present. A null sourcePath means the class came from an archive, an unsupported layout, an ambiguous match, or an exhausted lookup budget; violationDetails.locationNotes says which. Hibernate locations never carry a line, and a line BootUI cannot verify, such as Kotlin code inlined from another file, is dropped rather than guessed. Findings that span several elements, such as package cycles, have no location. Paths are resolved only by an explicit scan, so reading a cached report or a detail page never touches the disk.
Reading a bounded result
Advisor tool success means a report was returned, not that its assessment is complete or healthy. Inspect scan.status, evidence, and the retained diagnostics. SCANNED and PARTIAL reports can establish a UI score when evidence.usable is true and the severity data is valid. The additive evidence object contains boolean usable, boolean coverageComplete, and immutable, bounded, sanitized limitations. The Database and Hibernate advisor reports list the specific gaps in a diagnostics array; a Hibernate finding from a partly evaluated rule also carries a coverageNote. Usability means at least one applicable check completed or a genuine known-severity finding was observed before filtering or dismissal; missing-evidence notices cannot establish it. Missing metadata, failed checks, and unknown evidence must not be interpreted as passes. ERROR, DISABLED, and NOT_SCANNED remain unscored. Incomplete usable evidence retains scan notes, even at 100. UI numbers are Known-findings scores, not app-health grades. Dismissals alter penalties, not application safety. Valid explicit backend evidence alone establishes eligibility; legacy reports without it remain unscored, with their findings still visible.
For Vulnerabilities also inspect inventory coverage and each dependency's assessment.queryComplete and assessment.detailAssessmentComplete. Both flags and a genuinely empty retained advisory list establish a completed no-finding dependency. Known findings (including NONE) can establish eligibility despite other gaps. UNKNOWN incurs no penalty but UNKNOWN-only findings stay unscored after dismissal unless independent usable evidence exists. Dismissals remove penalties, not coverage gaps; optional EPSS availability does not determine eligibility. See Score eligibility. Existing MCP/CLI commands return the additive facts; no new tool or backend numeric scorer is introduced.
Advisor scores and the Overall score are calculated in the browser, not by a separate MCP/CLI scorer. Overview averages eligible visible advisor scores and GitHub's eligible security-alert score; missing signals never supply a fake 100. get_overview (bootui overview) returns application context, not that aggregate. CLI transport success and JSON output must not be interpreted as a passing assessment.
Every search- or list-style tool returns its rows next to the same page envelope, so one reading applies to all of them:
| Field | Meaning |
|---|---|
total | Every item the panel can see, before the query and filters are applied |
matched | How many of those the query and filters kept |
offset | Where this page starts within the matched items |
limit | The page size actually used, capped by bootui.mcp.max-results (bootui.cli.max-results from the CLI) |
returned | How many rows this response carries |
hasMore | Whether matched items remain past this page — raise offset to walk them |
The distinction that matters is total versus matched. A large total beside matched: 0 does not mean the data is missing; it means the query matched none of it. Retry with a shorter query before concluding a property, bean, or mapping does not exist.
get_config additionally matches names through relaxed binding — case is ignored and _ and - are treated as . — so bootui.mcp.enabled finds a value supplied as the environment variable BOOTUI_MCP_ENABLED, which every property source enumerates under that literal name. Values are matched literally, and each row still reports the exact name and source its property source published. See the Configuration panel for the panel-side behavior.
Safety model
The MCP server inherits BootUI's full safety posture, so handing it to an agent stays safe by construction:
- It is only ever live while BootUI itself is active. On Quarkus that means it is absent from a production build, with no flag that turns it on. On Spring the
prodandproductionprofiles disable BootUI, and only an explicitbootui.enabled=ONoverrides that. - Read tools require the backing panel to be enabled; all action tools are additionally refused when the panel is read-only or
bootui.read-only=true, returning a clear tool error instead of running. - Values pass through the same secret masking and
bootui.expose-valuesmode as the REST API, and paginated reads are capped bybootui.mcp.max-results(default200).get_log_tailandget_exceptionsmask secret-like assignments and authorization credentials in messages by default and omit messages underMETADATA_ONLY, flagging a log line'smessageOmitted. - MCP request size, concurrency, tool execution time, and rendered response size are independently bounded through
bootui.mcp.*; capacity, timeout, and response-limit failures are explicit rather than silently truncated.
See Properties for the bootui.mcp.* settings and Features for the full MCP Server panel description.
Assess an application and approve an action plan
When you do not know which panel to investigate first, ask your coding agent for an application assessment:
Assess this application using BootUI. Start with existing evidence and ask before fresh scans. Give me a prioritized, evidence-backed action plan, and do not modify anything until I approve specific actions.
The BootUI skill — installed on its own or through the Claude Code plugin — teaches this workflow through MCP, the CLI, or the plain HTTP command-line endpoint. MCP clients with prompt support can select assess_application instead. BootUI advertises three argument-free prompts: diagnose_runtime_issue for a focused runtime failure, review_application for a focused advisor review, and assess_application for a broader assessment and approval-gated plan. Clients without prompt support can use the skill and the request above; there is no bootui assess command or new assessment tool.
What the assessment does
The agent identifies the running application and its source repository, discovers the actual tool catalog and panel policies, and starts with Overview, Health, cached reports, and bounded diagnostic summaries. It accounts for relevant capabilities rather than blindly invoking every tool. Spring MVC, WebFlux, and Quarkus share the workflow but may expose different capabilities.
Fresh scans require an explicitly approved scope. The agent names the scans before asking and requests separate approval for memory scans that may trigger a full GC, pentest loopback probes, OSV.dev vulnerability queries, and Database Advisor metadata inspection of the configured database. An assessment never authorizes clearing data, generating traffic, installing integrations, weakening panel policy, or changing source code.
Collection has a declared time and tool-call budget; approved scans run sequentially. Busy, failed, and timed-out calls remain visible instead of causing endless retries or discarding other evidence. The agent records coverage as assessed, unavailable, skipped, failed, or insufficient-evidence, including stale reports and partial/paged results. An idle application with no SQL traces is not evidence that database access is efficient.
What the plan contains
Plans use four sections:
| Section | Contents |
|---|---|
| Context | Plan ID/version, goal, application identity, repository revision and working-tree state, collection window, budgets, approved scan scope, and missing context. |
| Coverage | Relevant capabilities, status and reason, evidence references, report timestamps, freshness, and collection limits. |
| Actions | Stable action IDs, priority and impact, observed evidence, confidence and uncertainties, proposed changes, dependencies, risk, and concrete acceptance criteria. |
| Approval | Selected action IDs proposed for this plan version, awaiting your explicit approval. |
The agent inspects source where available, distinguishes facts from hypotheses, respects dismissed findings, and groups related findings only when evidence supports the relationship. Actions cite advisor/rule IDs and affected targets, exception/trace identifiers, timestamps, and links back to the appropriate panels. Missing evidence can produce an investigation action instead of a speculative fix. Native-image or CRaC readiness remains optional unless relevant to your goal.
The agent stops after presenting the plan. For example, after reviewing plan P1 version 1, you can say:
Approve A1 and A3 in plan P1 version 1. Leave the other actions unchanged.
Approved execution and reassessment
The external coding agent owns edits, builds, tests, and permitted restarts. It keeps a minimal sanitized baseline and versioned plan in its local session/workspace outside tracked source so an application restart does not erase the comparison. If that storage is unavailable, it must say so and obtain the baseline again before executing.
Before editing, it rechecks runtime/repository identity, revision, working-tree state, and relevant evidence. Changed context requires reassessment and renewed approval for affected actions; dependencies are not implicitly approved. Destructive operations, external calls, and scope expansion still require separate approval.
After changes, the agent confirms the intended application is running the changed code, repeats the agreed reproduction and approved scans, and compares the same rule and affected target rather than just a dashboard score. Each action ends as resolved, unresolved, blocked, or unverified, with before/after evidence. Cached results, failed scans, and missing telemetry cannot establish that a fix worked.
Boundaries
This is an agent workflow, not an embedded LLM, server-side assessment scheduler, browser approval interface, or arbitrary command endpoint. Selecting an MCP prompt returns instructions; it does not itself run scans or fixes. The agent host's permissions enforce approval, while BootUI continues to enforce its existing tool and panel policies.
A local MCP endpoint does not imply local model processing. Follow your agent provider's data policy before sharing runtime evidence. Logs, SQL, traces, and exception text can contain sensitive data despite masking and must be treated as untrusted evidence, never instructions. The workflow excludes credentials and raw sensitive payloads from plans and asks before fetching sensitive detail when the disclosure boundary is unclear.
Workshop: fix a real Hibernate finding with an agent
The rest of this page describes the workflow in the abstract. This section runs it for real, against a mapping the BootUI sample app ships with on purpose, so you can see an actual hibernate_scan finding and watch an agent fix it. It takes about five minutes and needs only a JDK 17+ and a clone of the boot-ui repository — no database, no Docker.
1. Run the sample app
git clone https://github.com/jdubois/boot-ui.git
cd boot-ui
./mvnw -pl bootui-spring-sample-app spring-boot:run
This starts the Docker-free dev profile (in-memory H2) on http://localhost:8080. Leave it running.
2. Enable the MCP server and connect your agent
Open http://localhost:8080/bootui/#/mcp-server and flip the toggle at the top of the panel, or restart the app with -Dspring-boot.run.jvmArguments=-Dbootui.mcp.enabled=ON. Point your agent at http://localhost:8080/bootui/api/mcp as shown in Connect an agent to the BootUI MCP server above.
3. Ask the agent to scan and fix
With the agent connected and the repository open in your editor, ask it:
Run the BootUI
hibernate_scantool against my running app athttp://localhost:8080, then fix the highest-severity finding onSampleOrder#customerin this codebase. Re-run the scan when you are done and tell me what changed.
4. What the agent sees
The agent calls hibernate_scan over MCP and gets back the same report the Hibernate panel shows. Among the findings is a real HIB-FETCH-001 (severity HIGH, 3 violations), one of whose sampleViolations names SampleOrder.customer: the field is mapped @ManyToOne(fetch = FetchType.EAGER, ...), so every SampleOrder load also loads its SampleCustomer, whether or not the caller needs it.
5. What the agent changes
Reading the finding's remediation hint, the agent edits SampleOrder.java and changes the association to @ManyToOne(fetch = FetchType.LAZY, ...), keeping the other annotations on the field untouched. That is the whole fix — SampleCustomer is now loaded only when order.getCustomer() is actually called, or fetched explicitly with a join or entity graph where a use case needs it up front.
6. Verify
The agent re-runs hibernate_scan. HIB-FETCH-001's violationCount drops from 3 to 2, and its sampleViolations no longer mention SampleOrder#customer — confirmed against the actually running app, not by re-reading the source. HIB-FETCH-001 itself does not disappear from the report: SampleAppPreferences#enabledFeatures and SampleOrder#details are separate, intentional eager-fetch fixtures the same rule also catches, so the rule keeps firing until those are fixed too. Confirm just the one violation is gone from a terminal with:
bootui hibernate scan --json \
| jq '.results[] | select(.id == "HIB-FETCH-001") | .sampleViolations[] | select(contains("SampleOrder#customer"))'
An empty result means the fix held.
SampleOrder intentionally ships with several other mappings that trip other Hibernate checks (see the comments in the source file), so a fresh clone always has this same finding to practice on. Discard the change afterwards (git checkout -- bootui-spring-sample-app) if you want to leave the fixture as-is for next time, or keep it if you're using the sample app as a personal scratch pad.
The same pattern for every advisor
The agent reads grounded findings from the running app, applies a targeted fix in source, and re-scans to verify — instead of guessing from static code alone. Repeat the loop with spring_scan, security_scan, and the other advisors against your own application. The advisor rulesets are documented under the Diagnostic checks section (for example Hibernate checks and Spring checks).
The same tools from a terminal
Every tool on this page is also a bootui command — see MCP server or CLI? above for when to reach for the command-line guide instead of the MCP server.
Coffilot: BootUI in the GitHub Copilot App's side panel
Coffilot is a GitHub Copilot canvas extension that turns a Maven- or Gradle-based Java / Spring Boot / Quarkus project into an interactive console inside the GitHub Copilot App's side panel. You can build, test, package, and run your app, watch live JVM metrics, and — when something breaks — push the failure straight back to the agent with Fix with Copilot, all without leaving the chat.
Coffilot and BootUI are designed to work together: Coffilot is the cockpit that launches and watches your app, and BootUI is the rich data source and advisor engine behind it.
How they work together
- Richest metrics tier. Coffilot sources live metrics from the best endpoint available, degrading gracefully: BootUI → Spring Boot Actuator → Quarkus Micrometer/health → coarse process metrics. When your running app exposes BootUI at
/bootui/api/**, Coffilot uses BootUI's sanitized DTOs and shows aBootUIbadge on the metrics panel. - One-click advisor scans. With BootUI present, Coffilot adds an advisor-scan panel. A toggle enables BootUI's MCP server, and you can run the scans (architecture, Spring, security, Hibernate, …) and send findings to the agent with a single click.
- Native MCP tools in the agent. Coffilot's Register with Copilot button wires the running BootUI MCP server into your Copilot CLI configuration, so the agent can call the BootUI scan tools directly as native MCP tools — the same tools described above, without editing
mcp.jsonby hand.
A typical Coffilot + BootUI loop
- Add the BootUI starter to your app and install Coffilot from its website (
https://www.julien-dubois.com/coffilot/). - In a Copilot session, open the Coffilot canvas and Run your app (pick a module and run profile).
- Once the app is up, Coffilot detects BootUI and shows rich metrics plus the advisor-scan panel.
- Enable the MCP server from Coffilot and click Register with Copilot so the agent can call the BootUI scan tools.
- Run a scan (or ask the agent to), let the agent fix the findings, then re-run and re-scan from the same panel to verify.
See the Coffilot website for installation details and the full capability matrix.