Skip to content

Commit 9b4440b

Browse files
os-zhuangclaude
andcommitted
fix(mcp): document list_actions/run_action in the generated SKILL.md (#2714 Phase 0)
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>
1 parent 57b89b4 commit 9b4440b

3 files changed

Lines changed: 54 additions & 9 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
'@objectstack/mcp': patch
3+
---
4+
5+
fix(mcp): the generated SKILL.md now documents the business-action tools
6+
7+
`renderSkillMarkdown()` listed only the 7 object-CRUD tools; the MCP surface
8+
exposes 9 — `list_actions` / `run_action` (business actions) were missing, so
9+
agents installing the skill never learned they can run approvals, conversions,
10+
or flow triggers directly. The skill now covers the full native tool surface
11+
and teaches action preference: when `list_actions` offers a matching action,
12+
call it instead of hand-editing the records it would have touched (actions
13+
carry the app's validation and side effects), confirming destructive or
14+
confirmation-flagged actions with the user first.
15+
16+
Prerequisite for the distribution shells (#2714 Phase 0): every shell repo
17+
copies this rendered content, so the gap had to close before fan-out.

packages/mcp/src/skill.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('renderSkillMarkdown', () => {
5151
expect(md).toContain('Authorization: ApiKey');
5252
});
5353

54-
it('lists the object-CRUD tools and a discover-first instruction', () => {
54+
it('lists the full native tool surface (CRUD + business actions) and a discover-first instruction', () => {
5555
const md = renderSkillMarkdown();
5656
for (const tool of [
5757
'list_objects',
@@ -61,12 +61,20 @@ describe('renderSkillMarkdown', () => {
6161
'create_record',
6262
'update_record',
6363
'delete_record',
64+
'list_actions',
65+
'run_action',
6466
]) {
6567
expect(md).toContain(tool);
6668
}
6769
expect(md.toLowerCase()).toContain('discover');
6870
});
6971

72+
it('teaches action preference — run a matching business action instead of hand-editing records', () => {
73+
const md = renderSkillMarkdown();
74+
expect(md).toContain('Prefer actions over hand-edits');
75+
expect(md).toContain('run_action({ actionName, objectName?, recordId?, params? })');
76+
});
77+
7078
it('is generic — it does not enumerate any concrete schema', () => {
7179
// The skill must not bake in tenant object/field names; it points to live
7280
// discovery instead. Sanity: no stray "objectName: <something concrete>".

packages/mcp/src/skill.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,21 @@ description: ${OBJECTSTACK_SKILL_DESCRIPTION}
5858
5959
# ObjectStack
6060
61-
${intro} An ObjectStack environment exposes its data **objects** (tables) as
62-
tools over the Model Context Protocol (MCP). Every operation runs **as you** —
61+
${intro} An ObjectStack environment exposes its data **objects** (tables) and
62+
its business **actions** (registered app logic: approvals, conversions, flow
63+
triggers) as tools over the Model Context Protocol (MCP). Every operation runs **as you** —
6364
under your account's permissions and row-level security — so you may see a
6465
subset of rows, or get a permission error on a write. That is expected
6566
governance, not a failure.
6667
6768
## When to use
6869
6970
Use these tools whenever the user wants to **inspect or change data** in their
70-
ObjectStack app: look up records, filter/report, create or update entries, or
71-
clean up data. Prefer these tools over guessing — the environment is the source
72-
of truth.
71+
ObjectStack app — look up records, filter/report, create or update entries,
72+
clean up data — or **run a business action** the app defines (approve a
73+
request, convert a lead, kick off a flow). Prefer these tools over guessing —
74+
the environment is the source of truth, and an action is always better than
75+
hand-editing the records it would have touched.
7376
7477
## Connect
7578
@@ -112,6 +115,8 @@ always current even as the app evolves:
112115
1. \`list_objects\` — see what objects exist.
113116
2. \`describe_object({ objectName })\` — get an object's fields (name, type,
114117
required) before querying or writing it.
118+
3. \`list_actions\` — see what business actions you may run (each entry
119+
includes its parameters and whether it needs a \`recordId\`).
115120
116121
Always discover the relevant object's shape before constructing a filter or a
117122
create/update payload.
@@ -128,6 +133,14 @@ create/update payload.
128133
- **update_record({ objectName, recordId, data })** — change fields on a record.
129134
- **delete_record({ objectName, recordId })** — delete a record (destructive —
130135
confirm with the user first).
136+
- **list_actions()** — list the business actions you are permitted to run, with
137+
each action's declared parameters, whether it operates on a record, and
138+
whether it is flagged destructive.
139+
- **run_action({ actionName, objectName?, recordId?, params? })** — invoke a
140+
business action by name. This executes the app's registered logic (can
141+
mutate data or trigger flows) under your permissions and RLS. Pass
142+
\`recordId\` for record-scoped actions and \`params\` for declared inputs;
143+
\`objectName\` only disambiguates a name shared by multiple objects.
131144
132145
## Conventions & gotchas
133146
@@ -139,13 +152,20 @@ create/update payload.
139152
- **Writes are real and immediate.** There is no implicit dry-run. Confirm
140153
destructive actions (\`delete_record\`, bulk updates) with the user.
141154
- **Page large reads.** Use \`limit\`/\`offset\` rather than asking for everything.
155+
- **Prefer actions over hand-edits.** When \`list_actions\` offers an action for
156+
the task (approve, convert, close, …), call it instead of updating the
157+
records yourself — actions carry the app's validation and side effects.
158+
Confirm first when an action is record-destructive or flagged for
159+
confirmation.
142160
143161
## Recommended workflow
144162
145-
1. \`list_objects\` to orient.
163+
1. \`list_objects\` (and \`list_actions\` when the task sounds like a business
164+
operation) to orient.
146165
2. \`describe_object\` on the target object.
147166
3. \`query_records\` to read / verify current state.
148-
4. \`create_record\` / \`update_record\` / \`delete_record\` to make changes,
149-
confirming destructive steps with the user.
167+
4. \`run_action\` when a matching business action exists; otherwise
168+
\`create_record\` / \`update_record\` / \`delete_record\` — confirming
169+
destructive steps with the user.
150170
`;
151171
}

0 commit comments

Comments
 (0)