Skip to content

feat(mcp): native business-action execution (list_actions / run_action)#2307

Merged
os-zhuang merged 2 commits into
mainfrom
feat/mcp-action-tools
Jun 24, 2026
Merged

feat(mcp): native business-action execution (list_actions / run_action)#2307
os-zhuang merged 2 commits into
mainfrom
feat/mcp-action-tools

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

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's toolRegistry, which MCP only ever optionally duck-typed (it must not hard-depend on service-ai). Now that the in-UI ask agent 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 (registerObjectToolsregisterActionTools), bound to the caller's principal:

Tool Description
list_actions Enumerate the invokable business actions the caller may run — permission- + visibility-filtered.
run_action Invoke an action by name with { recordId, params }.

@objectstack/mcp (mcp-http-tools.ts)

  • New registerActionTools() + McpActionBridge seam (McpActionSummary, RegisterActionToolsOptions). Owns the tool shape; delegates execution + security to the runtime bridge — the same split as registerObjectTools.
  • Wired into handleHttpRequest by capability: only registered when the runtime bridge can resolve the action mechanism (graceful degradation, mirroring how record resources need a dataEngine). package.json unchanged — no @objectstack/service-ai.
  • run_action marked destructiveHint (clients confirm); sys_*-object actions rejected fail-closed at the tool layer.

@objectstack/runtime (http-dispatcher.ts)

  • buildMcpBridge now implements listActions + runAction, resolving + dispatching through the framework's own mechanism — IDataEngine.executeAction (script/body) / automation flow runner (flow) — bound to the request's ExecutionContext: the same permission + RLS path the REST /actions/... route uses.
  • list_actions enumerates headless-invokable actions (script/flow; UI-only url/modal/form excluded), filtered to what the caller may run; sys_*-object actions held back fail-closed.
  • The ADR-0066 D4 requiredPermissions capability gate is now single-sourced (actionPermissionError) and enforced for both the REST action route and run_action (no drift).

Referenced the now-moved service-ai/src/tools/action-tools.ts for the resolution + invocation contract (resolve by name → dispatch via the action's targetexecuteAction), and reproduced it directly in the runtime bridge without importing service-ai.

Permissions / safety

  • Actions run AS the caller (same RLS posture as the CRUD tools): row-context records load under RLS; an unseen record reads as not-found.
  • requiredPermissions enforced before dispatch; list_actions hides 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-closed sys_* guard, tool-error surfacing (mirrors the object-tools http test).
  • packages/runtime/src/http-dispatcher.test.ts — real buildMcpBridge: list_actions filtering, run_action dispatching via the action's target handler key, ADR-0066 D4 gate deny/allow, modal/unknown rejection.
  • examples/app-todo/test/mcp-actions.test.tsCE end-to-end: boots the real ObjectQL engine + app-todo handlers (NO service-ai) and drives the real MCPServerRuntime over JSON-RPC. run_action complete_task flows through engine.executeAction → the registered handler → the driver; verifies the record becomes completed, plus the fail-closed sys_* guard and the requiredPermissions gate (deny → allow) end-to-end. (pnpm --filter @objectstack/example-todo test:mcp)
✅ MCP action E2E PASSED — CE runtime lists + executes business actions, permission-enforced

Full suites green: @objectstack/mcp 53/53, @objectstack/runtime 441/441. Both packages typecheck clean.

Acceptance

  • CE runtime (open framework + @objectstack/mcp, no cloud studio) lists and executes the app's business actions, permission-enforced.
  • @objectstack/mcp has no @objectstack/service-ai dependency; existing object tools unchanged.
  • Unit + integration tests added under packages/mcp/src/ and packages/runtime/src/.
  • Verified end-to-end via an MCP client over JSON-RPC against a seeded local env.

🤖 Generated with Claude Code

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>
@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Canceled Canceled Jun 24, 2026 5:03pm

Request Review

@github-actions github-actions Bot added size/xl documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling and removed size/xl labels Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR is very large. Consider breaking it into smaller PRs for easier review.

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/mcp, @objectstack/runtime.

17 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/cloud-artifact-api.mdx (via packages/runtime)
  • content/docs/concepts/implementation-status.mdx (via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx (via packages/runtime)
  • content/docs/concepts/packages.mdx (via @objectstack/mcp, @objectstack/runtime)
  • content/docs/guides/api-reference.mdx (via @objectstack/runtime)
  • content/docs/guides/authentication.mdx (via @objectstack/runtime)
  • content/docs/guides/cloud-deployment.mdx (via @objectstack/runtime)
  • content/docs/guides/deployment-vercel.mdx (via @objectstack/runtime)
  • content/docs/guides/driver-configuration.mdx (via @objectstack/runtime)
  • content/docs/guides/hook-bodies.mdx (via @objectstack/runtime)
  • content/docs/guides/packages.mdx (via @objectstack/mcp, @objectstack/runtime)
  • content/docs/guides/plugin-chatbot-integration.mdx (via @objectstack/runtime)
  • content/docs/guides/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/guides/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/runtime)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@os-zhuang os-zhuang merged commit 7d7fee7 into main Jun 24, 2026
17 checks passed
@os-zhuang os-zhuang deleted the feat/mcp-action-tools branch June 24, 2026 17:07
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant