Skip to content

refactor(mcp): extract registerTypedAppTool + typedAppSpec helper (KLA-419)#40

Open
jklaassenjc wants to merge 1 commit into
mainfrom
juergen/kla-419-typed-app-helper
Open

refactor(mcp): extract registerTypedAppTool + typedAppSpec helper (KLA-419)#40
jklaassenjc wants to merge 1 commit into
mainfrom
juergen/kla-419-typed-app-helper

Conversation

@jklaassenjc
Copy link
Copy Markdown
Collaborator

@jklaassenjc jklaassenjc commented May 27, 2026

Summary

KLA-419 — surfaced during the 1.17.0 code-quality review.

After KLA-404 / KLA-405 / KLA-406 landed, the typed-input MCP App registration path was triplicated across apps_user.go, apps_device.go, apps_insights.go. Each was ~40 lines of identical mcp.Meta + wrap-fetch / errorResult / jsonResult + AddResource boilerplate. Every future typed MCP App would pay the same tax until extracted.

What changes

  • typedAppSpec[In any] — mirrors appSpec for typed-input apps. Can't live in a []typedAppSpec slice (each In differs), but standardizes the per-app literal callers construct.
  • registerTypedAppTool[In](s, spec) — wires the tool half with _meta.ui.resourceUri + the wrap-fetch / errorResult(spec.Name + ": ...") / jsonResult shape, plus the ui:// resource via the also-extracted registerUIResource helper. Future refactors of any of those subroutines now happen in one place.
  • registerUIResource — factored out of registerAppResource so the typed path reuses the same 18 lines.

Migrations

registerUserView, registerDeviceView, registerInsightsView all collapse to a single typedAppSpec literal + helper call. Each register function dropped from ~40 lines to ~15.

One incidental wording change

insights_view used to emit "fetching insights: <err>" on handler failure; it now emits "insights_view: <err>" matching user_view / device_view. Same information; standardized for AI clients that correlate errors back to the calling tool. Pinned by TestRegisterTypedAppTool_ErrorMessagePrefixedWithToolName.

Test plan

  • go test ./... full suite green (existing TestUserView_*, TestDeviceView_*, TestInsightsView_* cover the happy path through the helper end-to-end)
  • go vet ./... clean
  • New TestRegisterTypedAppTool_ErrorMessagePrefixedWithToolName locks the error-prefix contract
  • Manually verified MCP tool count + _meta.ui unchanged for all four migrated/affected tools

Net diff

5 files changed, +140 / -127. The helper itself adds ~50 lines but each new typed app costs ~15 lines instead of ~40 going forward.

🤖 Generated with Claude Code


Note

Low Risk
Mechanical refactor of MCP registration with one minor user-visible error string change for insights_view; behavior and metadata are intended to stay the same.

Overview
Introduces typedAppSpec[In] and registerTypedAppTool so typed MCP Apps (user_view, device_view, insights_view) register tools and ui:// resources from one spec literal instead of repeating meta, handler wrapping, and AddResource boilerplate in each file.

registerUIResource is factored out of registerAppResource so both no-args and typed apps share the same HTML + common.js injection path.

insights_view handler errors now use the insights_view: prefix (aligned with the other typed apps); previously they used fetching insights:. A new test locks that error-prefix contract.

Reviewed by Cursor Bugbot for commit 6cfaee0. Bugbot is set up for automated code reviews on this repo. Configure here.

…A-419)

After 1.17.0, the typed-input MCP App registration path was
triplicated across apps_user.go, apps_device.go, apps_insights.go
— each ~40 lines of identical mcp.Meta + wrap-fetch-errorResult /
jsonResult + AddResource boilerplate. Every future typed MCP App
would pay the same tax until extracted.

This change adds:

- typedAppSpec[In any]: mirrors appSpec for typed-input apps. Can't
  live in a []typedAppSpec slice (each In differs), but standardizes
  the per-app literal callers construct.

- registerTypedAppTool[In](s, spec): wires the tool half with
  _meta.ui.resourceUri + the wrap-fetch / errorResult(name + ": ...")
  / jsonResult shape, plus the ui:// resource via the also-extracted
  registerUIResource helper. Refactors of any of those subroutines
  now happen in one place instead of three.

- registerUIResource: factored out of registerAppResource so the
  typed path reuses the same 18 lines.

Migrations: registerUserView, registerDeviceView, registerInsightsView
all collapse to a single typedAppSpec literal + helper call.

One incidental wording change: insights_view used to emit
"fetching insights: <err>" on handler failure; it now emits
"insights_view: <err>" matching user_view / device_view. Same
information; standardized for AI clients that correlate errors
back to the calling tool. The new test
TestRegisterTypedAppTool_ErrorMessagePrefixedWithToolName pins the
contract.

Existing integration tests (TestUserView_*, TestDeviceView_*,
TestInsightsView_*) cover the happy path through the helper
end-to-end and pass unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

2 participants