pilichoumao opened a new pull request, #4769:
URL: https://github.com/apache/rocketmq-dashboard/pull/4769
### Which Issue(s) This PR Fixes
No tracking issue. Closes a tool-coverage gap named by the AI-01/CLIENT-01
design: `rmq.client.list` / `rmqctl client list` for LLM-driven diagnosis of
"who is connected to this cluster". The Studio client page already queries
these connections (`ClientService.listConnections`), but the tool catalog —
topics, groups, brokers, proxies, messages, ACL, metrics, audit — had no client
tool, so MCP/CLI operators could not reach the same data.
### Brief Description
Add one L1 read-only tool, `rmq.client.list` (`rmqctl client list`),
wrapping the existing instance-scoped `ClientService` path. No new endpoint,
service, dependency or configuration.
- **Filters:** optional physical `clusterId`, optional `type`
(`Producer`/`Consumer`), and a case-insensitive substring `search` over
clientId, group/topic, producer group and address — the same search semantics
`rmq.alert.rule.list` uses.
- **Honest metadata:** `ClientItem` maps `ClientConnectionVO` without
inventing fields — `protocol`, `language`, `version`, `connectedAt` and
`clusterName` stay absent when the connection query cannot report them
(`@JsonInclude(NON_NULL)`, optional in the output schema), and rows kept from
an incomplete lookup keep `partial=true`. Nothing in this PR fabricates
protocol or SDK facts.
- **Capability gate:** `requiredCapabilities: [REMOTING]` — DIRECT and Proxy
instance types resolve it; CLOUD instances (no client provider, stub throws
501) are rejected by the existing capability filter instead of failing deep in
the provider.
- **Forward compatibility:** the tool consumes
`ClientService.listConnections(instanceId, ...)`, whose provider side is
exactly what #4550 extends. When #4550 merges, proxy-connected consumers appear
in this tool's output with no further change; this PR does not depend on it and
does not modify any shared code path.
- `rmqctl` support comes from the regenerated catalog (`make
catalog-generate` / `catalog-verify`); `client describe` deliberately stays out
of scope until a server-side detail API exists.
### How Did You Test This Change?
- **Unit:** `ClientListToolHandlerTest` — instance/cluster/type pass-through
to `ClientService`; VO→item mapping with full and sparse rows (absent optional
fields, `partial` preserved, enum names, ISO connect time); search filtering
case-insensitively across all four identity fields; blank search returns
everything.
- **Contract:** sample added to `ToolOutputSchemaContractTest` (it enforces
every catalog tool has a schema-valid output sample); catalog YAML validates
against `rmq-tools.schema.json` on load in every catalog test.
- **Build:** Java 21, `mvn -B -ntp -Dspring.profiles.active=dev package` —
**3,149 tests passed**, 0 failures, **0 Checkstyle violations**, packaged
successfully (clean local repository). `cd rmqctl && make catalog-verify && go
test ./... && gofmt -l . && go vet ./...` — all clean.
- **End-to-end against a real local Apache RocketMQ 5.5.0
NameServer/Broker:** built this branch's jar, ran a real Remoting 5.5.0 push
consumer (`ClientSmokeGroup`) and producer (`ClientSmokeProducerGroup`) against
it, then called `POST /api/ai/tools/rmq.client.list/execute`:
- unfiltered list returned 4 real rows — the producer group, the consumer
group, and both clients' `CLIENT_INNER_PRODUCER` entries — with
`protocol=Remoting`, `language=Java`, `version=V5_5_0`, real addresses and
`partial=false`;
- `type=Consumer` returned only consumer rows; `search=clientsmoke`
matched both clients case-insensitively;
`type=Producer&search=ClientSmokeGroup` correctly returned an empty list;
- an unknown instanceId returned `404 NOT_FOUND` through the existing
instance resolution;
- audit recorded `LIST_CLIENT on rmq.client.list -> SUCCESS`.
- One environment note: clients are only visible once their
subscribed/published topic exists (no route → no broker heartbeat); the smoke
creates the topic first. This is broker-side client registration behavior, not
tool behavior. All temporary JVMs were shut down afterwards.
Not exercised: CLOUD instances (rejected by the capability gate before
reaching any provider), ACL/TLS clusters, multi-NameServer deployments, and
proxy-connected clients (visible once #4550 merges; this PR neither requires
nor changes that path).
### CI Status
The repository's Actions policy still rejects action versions referenced by
the existing workflow (`docker/setup-buildx-action@v3`,
`docker/build-push-action@v6`), so GitHub-hosted runs end in `startup_failure`
before any job starts (same as #4550/#4665). This PR does not change the
workflow; all results above are local.
### Checklist
- [x] One coherent change; no unrelated modifications
- [x] Conventional commit subject; regression tests use `...Test`
- [x] Tool schema validates; output contract sample included
- [x] No invented metadata; unreportable fields stay absent, partial results
stay marked
- [x] Architecture and formatting checks pass (0 Checkstyle violations;
gofmt/vet clean)
- [x] rmqctl catalog regenerated and verified; no new dependency, port or
configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]