feat(mcp): native business-action execution (list_actions / run_action)#2307
Merged
Conversation
Make the open-source MCP server (`@objectstack/mcp`) natively expose business
action execution, so a self-host / Community-Edition runtime (open framework +
@objectstack/mcp, no cloud studio) can *operate* an app over MCP — run its
business actions/flows — not just CRUD records.
Action execution previously rode on `@objectstack/service-ai`'s tool registry,
which the MCP server only ever optionally duck-typed. With the in-UI `ask`
agent moved out to the closed cloud package, that registry is empty in a
headless CE runtime, so BYO-AI via MCP could read/write rows but never trigger
business logic. Action execution is an open *mechanism*, so it now lives in the
open framework.
@objectstack/mcp:
- `registerActionTools()` registers two native tools alongside the object-CRUD
tools, via a `McpActionBridge` seam (mirrors `registerObjectTools` exactly):
- `list_actions` — enumerate invokable business actions the caller may run.
- `run_action` — invoke an action by name with { recordId, params }.
- Wired into `handleHttpRequest` by capability (only when the runtime bridge can
resolve the action mechanism — graceful degradation, like record resources
needing a dataEngine). No dependency on `@objectstack/service-ai`.
@objectstack/runtime:
- `buildMcpBridge` now resolves + dispatches actions through the framework's own
mechanism — `IDataEngine.executeAction` (script/body) / automation flow runner
(flow) — bound to the caller's ExecutionContext: the same permission + RLS
path the REST `/actions/...` route uses. `list_actions` is permission- and
visibility-filtered; `sys_*`-object actions are held back fail-closed.
- The ADR-0066 D4 `requiredPermissions` capability gate is single-sourced
(`actionPermissionError`) and enforced for both the REST route and run_action.
Tests:
- mcp: `mcp-action-tools.test.ts` — tool shapes, delegation, capability gating,
fail-closed sys_* guard, tool-error surfacing.
- runtime: `http-dispatcher.test.ts` — real `buildMcpBridge` listActions filtering,
run_action executeAction dispatch (via the action's target), ADR-0066 D4 gate.
- examples/app-todo: `mcp-actions.test.ts` — CE E2E booting the real engine (no
service-ai) and driving the MCP runtime over JSON-RPC: list + execute a real
action end-to-end, permission-enforced.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
This PR is very large. Consider breaking it into smaller PRs for easier review. |
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 17 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 6, 2026
fix(app-shell): give freshly-created records a back link to their origin (#2307) objectui@5eea2017aa42103a0f84b493aa5b3cb716361b1a
os-zhuang
added a commit
that referenced
this pull request
Jul 9, 2026
…2714 Phase 0) (#2715) The skill's tool list covered 7 of the 9 native tools — the business-action pair from #2307 was missing, so skill-installed agents never learned they can run app-registered actions directly. Adds the two tools with their real signatures, weaves actions into the intro / when-to-use / discover / workflow sections, and teaches action preference over hand-editing records. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Why
The open-source MCP server (
@objectstack/mcp, Apache-2.0) let a BYO-AI client (Claude Code, Cursor, …) read/write records but could not operate the app — run its business actions/flows. Action execution rode on@objectstack/service-ai'stoolRegistry, which MCP only ever optionally duck-typed (it must not hard-depend on service-ai). Now that the in-UIaskagent moved out to the closed cloud@objectstack/service-ai-studio, the framework AI runtime is headless and that bridged registry is empty in a CE runtime → MCP could CRUD rows but never trigger business logic.An action is an open mechanism, not closed "intelligence", so this moves action execution into the open framework — bridged directly from the framework's action mechanism, with no dependency on
@objectstack/service-ai.What
Two native MCP tools, registered exactly like the existing object-CRUD tools (
registerObjectTools→registerActionTools), bound to the caller's principal:list_actionsrun_action{ recordId, params }.@objectstack/mcp(mcp-http-tools.ts)registerActionTools()+McpActionBridgeseam (McpActionSummary,RegisterActionToolsOptions). Owns the tool shape; delegates execution + security to the runtime bridge — the same split asregisterObjectTools.handleHttpRequestby capability: only registered when the runtime bridge can resolve the action mechanism (graceful degradation, mirroring how record resources need adataEngine).package.jsonunchanged — no@objectstack/service-ai.run_actionmarkeddestructiveHint(clients confirm);sys_*-object actions rejected fail-closed at the tool layer.@objectstack/runtime(http-dispatcher.ts)buildMcpBridgenow implementslistActions+runAction, resolving + dispatching through the framework's own mechanism —IDataEngine.executeAction(script/body) / automation flow runner (flow) — bound to the request'sExecutionContext: the same permission + RLS path the REST/actions/...route uses.list_actionsenumerates headless-invokable actions (script/flow; UI-onlyurl/modal/formexcluded), filtered to what the caller may run;sys_*-object actions held back fail-closed.requiredPermissionscapability gate is now single-sourced (actionPermissionError) and enforced for both the REST action route andrun_action(no drift).Referenced the now-moved
service-ai/src/tools/action-tools.tsfor the resolution + invocation contract (resolve by name → dispatch via the action'starget→executeAction), and reproduced it directly in the runtime bridge without importing service-ai.Permissions / safety
requiredPermissionsenforced before dispatch;list_actionshides what the caller can't run.sys_*-object actions excluded by default (fail-closed) at both the tool layer and the bridge.Tests
packages/mcp/src/mcp-action-tools.test.ts— tool shapes, capability-gated registration, delegation, fail-closedsys_*guard, tool-error surfacing (mirrors the object-tools http test).packages/runtime/src/http-dispatcher.test.ts— realbuildMcpBridge:list_actionsfiltering,run_actiondispatching via the action'stargethandler key, ADR-0066 D4 gate deny/allow, modal/unknown rejection.examples/app-todo/test/mcp-actions.test.ts— CE end-to-end: boots the real ObjectQL engine + app-todo handlers (NO service-ai) and drives the realMCPServerRuntimeover JSON-RPC.run_action complete_taskflows throughengine.executeAction→ the registered handler → the driver; verifies the record becomescompleted, plus the fail-closedsys_*guard and the requiredPermissions gate (deny → allow) end-to-end. (pnpm --filter @objectstack/example-todo test:mcp)Full suites green:
@objectstack/mcp53/53,@objectstack/runtime441/441. Both packages typecheck clean.Acceptance
@objectstack/mcp, no cloud studio) lists and executes the app's business actions, permission-enforced.@objectstack/mcphas no@objectstack/service-aidependency; existing object tools unchanged.packages/mcp/src/andpackages/runtime/src/.🤖 Generated with Claude Code