feat(mcp-tools): OpenBuiltToolProvider — AI companion MCP tools#14
Conversation
Quality Report — ConductionNL/openbuilt @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 428/428 | |||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/71 statements)
Quality workflow — 2026-05-12 05:04 UTC
Download the full PDF report from the workflow artifacts.
…skeleton) Implements OCA\OpenRegister\Mcp\IMcpToolProvider (hydra ADR-034 AI Chat Companion + ADR-035 MCP tool surface) with two read-only MVP tools: - openbuilt.listApps — list the virtual apps in the caller's org - openbuilt.getAppManifest — fetch one published virtual app's manifest by slug Per-object auth (requireAuthenticatedUser) runs after argument validation and before business logic; org scoping is enforced by OpenRegister's ObjectService multitenancy filter. invokeTool never throws — all failure paths return a structured error envelope. Adds: - lib/Mcp/OpenBuiltToolProvider.php - tests/Stubs/Mcp/IMcpToolProvider.php (stub until openregister PR #1466) - tests/Unit/Mcp/OpenBuiltToolProviderTest.php - DI registration in lib/AppInfo/Application.php - composer autoload-dev PSR-4 for the stub - bump @conduction/nextcloud-vue to ^1.0.0-beta.31 (CnAppRoot auto-mounts CnAiCompanion) Refs #13
49311fe to
0e39294
Compare
|
Rebased onto |
|
CI follow-up: all quality gates green (PHP quality x6, PHPUnit matrix PHP 8.3/8.4 x NC 31/32/33, Vue eslint/stylelint, Security composer/npm, License). The only red check — |
Quality Report — ConductionNL/openbuilt @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 432/432 | |||
| PHPUnit | ✅ | ||||
| Newman | ❌ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/19 statements)
Quality workflow — 2026-05-12 12:35 UTC
Download the full PDF report from the workflow artifacts.
Summary
Adds the per-app MCP tool provider for OpenBuilt so the AI Chat Companion (hydra ADR-034) can surface OpenBuilt's virtual-app catalogue to an LLM. Implements
OCA\OpenRegister\Mcp\IMcpToolProviderper hydra ADR-035 (MCP tool surface). The interface ships in openregister PR #1466 (not yet merged); until then OpenBuilt implements the test stub attests/Stubs/Mcp/IMcpToolProvider.php(loaded via composerautoload-devPSR-4).This is an MVP skeleton — two read-only tools backed by code that exists today (
ApplicationsControlleralready does the slug → manifest lookup; OpenBuilt storesapplication+built-app-routeobjects in OpenRegister'sopenbuiltregister).Tools (2, read-only)
openbuilt.listAppslimit(int 1–50, default 20),statusFilter(any/draft/published/archived).openbuilt.getAppManifestslug(required). Resolves slug → BuiltAppRoute → Application → manifest.Auth design (OWASP A01 / ADR-005):
requireAuthenticatedUser()runs after argument validation and before business logic; it returnsstring|null(no unconditional pass, nocatch(\Throwable)swallow). Object-level scoping to the caller's organisation is enforced by OpenRegister'sObjectServicemultitenancy filter.invokeTool()never throws — every failure path returns['isError'=>true,'error'=>…,'message'=>…]. List results are capped at 20 items.Files
lib/Mcp/OpenBuiltToolProvider.php— the provider (SPDX in docblock,@category Mcp,@package OCA\OpenBuilt\Mcp)tests/Stubs/Mcp/IMcpToolProvider.php— interface stub (used in CI before openregister PR #1466)tests/Unit/Mcp/OpenBuiltToolProviderTest.php— 9 tests (getAppId, catalogue shape, unknown-tool error array, arg validation, unauthenticated-forbidden gate, auth-passed-then-internal-error)lib/AppInfo/Application.php—registerServiceAlias('OCA\OpenRegister\Mcp\IMcpToolProvider::openbuilt', OpenBuiltToolProvider::class)composer.json—autoload-devPSR-4OCA\OpenRegister\→tests/Stubs/package.json/package-lock.json— bump@conduction/nextcloud-vue^1.0.0-beta.30→^1.0.0-beta.31Quality
composer check(lint, phpcs, psalm, test:unit) passes.phpmdclean.psalm/phpstanclean.npm run lintclean. New unit tests (9) pass.Pre-existing (unrelated):
tests/unit/Controller/ApplicationsControllerTest.phphas 5 errors when run outside the NC container (createMock(Register::class)->method('getId')against thetests/stubs/openregister-stubs.phpstubs, which don't declare theRegister/Schemaentities) — passes in CI where openregister is installed. Not touched here.Done vs. deferred
Done: the two tools above, DI registration, stub interface, unit tests, nc-vue bump.
Widget mount: the nc-vue bump is the mount —
CnAppRootinbeta.31auto-mounts<CnAiCompanion />. OpenBuilt'sBuilderHost.vuealready usesCnAppRoot, so the companion renders inside virtual apps. WiringCnAppRootinto the OpenBuilt shell itself (App.vuecurrently usesNcContent) is a separate frontend task — deferred.Deferred (remaining #13 work): write tools (create app, publish/archive, edit manifest), template-marketplace tools, schema-editor tools, RBAC-aware scoping once the RBAC spec lands. Tracked under #13.
Refs #13 · hydra ADR-034 · hydra ADR-035
MCP coverage
openbuilt.listApps— list the organisation's OpenBuilt virtual apps (slug/name/status/version), capped at 20, auth-gated, org-scoped via OpenRegister multitenancyopenbuilt.getAppManifest— fetch a published virtual app's runtime manifest by slug (slug → BuiltAppRoute → Application → manifest), auth-gated