This repository was archived by the owner on May 29, 2026. It is now read-only.
feat(mcp-tools): ProcestToolProvider — AI companion MCP tools#418
Merged
Conversation
…eleton)
Adds the per-app IMcpToolProvider (hydra ADR-034 / ADR-035) for the AI
Chat Companion, exposing 2 read-only tools:
- procest.listProcesses — list running process instances (cases),
optional limit (1-50, default 20) and status filter
- procest.getProcessDetails — one case by id/uuid with its current step
(status) and chronological transition history
invokeTool() validates arguments, then runs per-object authorisation
(admin via IGroupManager / assignee / role record on the case) BEFORE
business logic, delegates to SettingsService + ObjectService, caps lists
at 20, and returns a structured {error: {code, message}} envelope on any
failure — it never throws.
Registered in Application::register() under the DI alias
'OCA\OpenRegister\Mcp\IMcpToolProvider::procest'. The real interface
ships in openregister PR #1466; until it merges procest implements the
stub at tests/Stubs/Mcp/IMcpToolProvider.php (loaded by tests/bootstrap.php
and via the OCA\OpenRegister -> tests/Stubs autoload-dev mapping).
Also fixes pre-existing quality issues touched along the way:
- psalm: suppress UndefinedClass for the dynamically-loaded OR Object*ing
events already referenced in Application.php
- phpmd: extract bezwaar listeners + widgets/providers helpers so
Application::register() is back under the method-length threshold
Contributor
Quality Report — ConductionNL/procest @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ❌ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 419/419 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ |
Spec coverage: 5% (21 tests / 456 specs)
Quality workflow — 2026-05-12 05:13 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the per-app
OCA\OpenRegister\Mcp\IMcpToolProviderfor Procest (hydra ADR-034 AI Chat Companion + ADR-035 per-app MCP coverage), so the in-app AI companion can surface Procest's process/workflow management to an LLM. This is the MVP skeleton — the remaining tools from #416 (startProcess,advanceStep,listMyTasks,getTaskDetails) are intentionally out of scope here.Refs #416(this PR ships 2 of the 6 tools in the issue's full MVP).Tools added
procest.listProcesseslimit(integer 1-50, default 20) + optionalstatusfilter.procest.getProcessDetailsidoruuid(required), including its current step (status) and chronological transition history.invokeTool()validates arguments first, then runs per-object authorisation before business logic (OWASP A01:2021 / ADR-005): admin viaIGroupManager(theprocest-admingroup OR the NC system admin group), otherwise the caller must be the caseassigneeor hold arolerecord linking them to the case. The auth helper actually runs — no unconditionalreturn true, not wrapped incatch(\Throwable). It delegates to the existingSettingsService+ OpenRegisterObjectService(samefindObject/findObjectspattern asStatusTransitionService/WorkflowDefinitionService), caps any returned list at 20 items, and returns a structured{error: {code, message}}envelope for every failure (unknown tool, bad args, not found, forbidden, storage unavailable, not configured) — it never throws.Files
lib/Mcp/ProcestToolProvider.php— the provider (getAppId()→'procest',getTools()→ 2 descriptors,invokeTool()).lib/AppInfo/Application.php— registers the provider under the DI aliasOCA\OpenRegister\Mcp\IMcpToolProvider::procest(the format OR'sMcpToolsServiceenumerates). Also extractedregisterBezwaarListeners()+registerWidgetsAndProviders()helpers soregister()stays under the PHPMD method-length threshold.tests/Stubs/Mcp/IMcpToolProvider.php— stub interface (copied from decidesk's exemplar, namespace/package adjusted) used until openregister PR #1466 (ai-chat-companion-orchestrator) ships the real interface; no-ops when the real interface is present.tests/bootstrap.php— loads the stub when the real interface is absent.tests/Unit/Mcp/ProcestToolProviderTest.php— assertsgetAppId(), the 2 descriptors (ids namespaced, non-empty descriptions, validinputSchemaobjects), and thatinvokeTool()returns structured errors (unknown tool, missing args, no storage) without throwing.composer.json—autoload-devPSR-4OCA\OpenRegister\→tests/Stubs/so PHPStan/PHPUnit discover the stub (mirrors decidesk).psalm.xml/phpstan.neon/phpmd.baseline.xml— analysis config for the dynamically-loadedIMcpToolProvider+ a single PHPMD baseline entry for the single-class provider design (mirrors decidesk's exemplar). The psalm change also fixes a pre-existingUndefinedClassgap for the ORObject*ingevents already referenced inApplication.php.Done vs deferred
IMcpToolProviderimplementation (2 read-only tools), DI registration, stub, unit test,### MCP coverageline below.@conduction/nextcloud-vueviaCnAppRoot(src/App.vue), butCnAiCompanionis not yet in any published@conduction/nextcloud-vuerelease (it currently lives onfeature/ai-chat-companion-widget/fix/ai-companion-*branches; latest published is1.0.0-beta.30). No package bump made; will follow once a release ships the component.procest.startProcess,procest.advanceStep,procest.listMyTasks,procest.getTaskDetails) — follow-up.Quality
composer lint/phpcs/phpmd(baselined) /psalm/phpstan/phpunit(140 tests, all green) pass for the new/changed code. Two pre-existing failures remain ondevelopment, unrelated to this change and not chased here:lib/Validator/ParaferingAuditAppendOnlyValidator.phptriggersInvalidTemplateParam(psalm) / 3×registerEventListenertype mismatch (phpstan) because it implementsIEventListenerover the ORObject*ingevents.MCP coverage
Adds tool: procest.listProcesses
Adds tool: procest.getProcessDetails
ADR-034: hydra
openspec/architecture/adr-034-ai-chat-companion.mdADR-035: hydra
openspec/architecture/adr-035-mcp-per-app-coverage.md