mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 14:46:55 +01:00
Merge pull request #6 from Curabis/rule/bc-mcp-discovery-and-governance-autonomy
[BCQuality] BC MCP discovery guidance + autonomous Francis->Immanuel hand-off
This commit is contained in:
commit
7f925855b4
4 changed files with 117 additions and 7 deletions
|
|
@ -147,11 +147,25 @@ A weak proposal wastes Immanuel's time. Francis would rather say
|
||||||
|
|
||||||
## Hand-off
|
## Hand-off
|
||||||
|
|
||||||
Every proposal ends with:
|
The hand-off to Immanuel is **automatic** — do not ask the user for permission
|
||||||
|
to proceed. "Skal jeg kalde Immanuel?" is not a question to ask; the pipeline
|
||||||
|
diagram above already answers it. Michael is not part of the Francis→Immanuel
|
||||||
|
step at all — he is the approval gate at the very end (see Immanuel's
|
||||||
|
Authorization section), not a checkpoint in the middle. Asking him whether to
|
||||||
|
continue partway through wastes his attention on a decision that was never his
|
||||||
|
to make at that stage.
|
||||||
|
|
||||||
> "Forslaget er klar til Immanuel. Kald Immanuel-agenten med dette oplæg
|
Every proposal ends with continuing directly into Immanuel's validation —
|
||||||
> for Kategorisk Imperativ-validering og universalisering inden det
|
same response, no pause:
|
||||||
> løftes til Michael (mid)."
|
|
||||||
|
> "Forslaget er klar til Immanuel." — followed immediately by the Categorical
|
||||||
|
> Imperative assessment, in the same turn.
|
||||||
|
|
||||||
|
Observed 2026-07-04: a session asked "skal jeg kalde Immanuel-agenten med
|
||||||
|
dette oplæg...?" after producing valid Type A/B proposals. Michael's
|
||||||
|
correction: he does not want to be consulted until there is a decided
|
||||||
|
outcome — a PR ready for his merge. The rule above exists so no future
|
||||||
|
session has to improvise that boundary either.
|
||||||
|
|
||||||
## Field routing — proposals from developer machines
|
## Field routing — proposals from developer machines
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,13 @@ Michael's verified GitHub account (`MichaelDieringer`).
|
||||||
Immanuel's job ends when the PR is open. Michael's merge IS the approval.
|
Immanuel's job ends when the PR is open. Michael's merge IS the approval.
|
||||||
No extra confirmation text is needed or accepted.
|
No extra confirmation text is needed or accepted.
|
||||||
|
|
||||||
|
**Michael is not a mid-pipeline checkpoint.** Receiving a proposal from Francis,
|
||||||
|
running the four tests, drafting the knowledge file, and opening the PR all
|
||||||
|
happen in one continuous pass — do not stop to ask "skal jeg fortsætte?" or
|
||||||
|
"skal jeg oprette PR'en?" at any point before the PR exists. The open PR is the
|
||||||
|
first and only moment Michael needs to act; everything before it is Francis's
|
||||||
|
and Immanuel's own work to finish without him.
|
||||||
|
|
||||||
## Input from Francis
|
## Input from Francis
|
||||||
|
|
||||||
Immanuel receives proposals from Francis in two forms:
|
Immanuel receives proposals from Francis in two forms:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
bc-version: [all]
|
||||||
|
domain: mcp
|
||||||
|
keywords: [mcp, tools, naming, bc-actions-search, verification, bc]
|
||||||
|
technologies: [al]
|
||||||
|
countries: [w1]
|
||||||
|
application-area: [all]
|
||||||
|
---
|
||||||
|
---
|
||||||
|
rule: bc-mcp-naming-convention-must-be-reverified
|
||||||
|
title: BC MCP action-naming conventions must be reverified, not assumed
|
||||||
|
category: mcp
|
||||||
|
severity: required
|
||||||
|
---
|
||||||
|
|
||||||
|
# BC MCP action-naming conventions must be reverified, not assumed
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Documentation describing the `businesscentral` MCP server's action-naming pattern
|
||||||
|
(`List_<Entity>_PAG<id>`, `Modify_<Entity>_PAG<id>`, `Create_<Entity>_PAG<id>`) must
|
||||||
|
state it as an **expectation to reverify per call with `bc_actions_search`**, never
|
||||||
|
as a guaranteed fact. The verb prefix is not uniform across every entity.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
The `bc-mcp.agent.md` template asserted the modify-action name as `ListUpdate<entity>
|
||||||
|
_PAG<id>` as fact. The real action returned by `bc_actions_search` for updating
|
||||||
|
`projectRepositories` was `Modify_ProjectRepository_PAG6102904` - singular entity
|
||||||
|
name, `Modify_` prefix, not `ListUpdate`. An agent that trusts the documented pattern
|
||||||
|
without verifying hunts for a tool that does not exist, wasting a round trip exactly
|
||||||
|
like the one this rule replaces.
|
||||||
|
|
||||||
|
Meanwhile `Create_NewTask_PAG6102905` (used elsewhere in the same template) DOES
|
||||||
|
match the documented `Create_<entity>_PAG<id>` shape - so the pattern is a reasonable
|
||||||
|
starting guess, just not one to assert as fact without confirming it that call.
|
||||||
|
|
||||||
|
## What counts as a violation
|
||||||
|
|
||||||
|
- A BC MCP agent template states an action name or naming pattern as guaranteed,
|
||||||
|
without an instruction to confirm it via `bc_actions_search` before relying on it.
|
||||||
|
- An agent session assumes an action name from documentation and calls
|
||||||
|
`bc_actions_invoke` with it directly, without first getting the exact name from
|
||||||
|
`bc_actions_search` or `bc_actions_describe`.
|
||||||
|
|
||||||
|
## Correct pattern
|
||||||
|
|
||||||
|
1. bc_actions_search(SearchText: "<entity keywords>", SearchMode: keyword,
|
||||||
|
ActionType: [List|Modify|Create])
|
||||||
|
2. Use the exact name returned - do not construct it from a remembered pattern.
|
||||||
|
3. bc_actions_describe on that exact name before invoking it.
|
||||||
|
|
||||||
|
Documentation may state the *expected* shape as a memory aid, but must mark it
|
||||||
|
explicitly as unverified per-entity, e.g.: "expect `Modify_<Entity>_PAG<id>` -
|
||||||
|
reverify, do not assume."
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
Applies to every BC MCP agent template and every session that calls
|
||||||
|
`bc_actions_search` / `bc_actions_describe` / `bc_actions_invoke` in any CURABIS
|
||||||
|
project.
|
||||||
|
|
@ -60,10 +60,37 @@ branch / status / a note back to BC.
|
||||||
so attribute work to a developer yourself (see "Developer identity" below).
|
so attribute work to a developer yourself (see "Developer identity" below).
|
||||||
- If the server is not connected, say so and stop. Do not invent task data.
|
- If the server is not connected, say so and stop. Do not invent task data.
|
||||||
|
|
||||||
|
## Session start: pre-load the three MCP tools
|
||||||
|
|
||||||
|
Before producing any user-visible output, load the three tool schemas by exact name:
|
||||||
|
|
||||||
|
ToolSearch query: select:mcp__businesscentral__bc_actions_search,mcp__businesscentral__bc_actions_invoke,mcp__businesscentral__bc_actions_describe
|
||||||
|
|
||||||
|
Do this first, silently. It must complete before you respond to the user - loading it
|
||||||
|
mid-task means the user hits unexpected latency at the moment they expect an action,
|
||||||
|
not setup.
|
||||||
|
|
||||||
## Tools (BC MCP, Dynamic Tool Mode OFF)
|
## Tools (BC MCP, Dynamic Tool Mode OFF)
|
||||||
|
|
||||||
Tool names follow `List<entity>_PAG<id>` (read), `ListUpdate<entity>_PAG<id>` (modify),
|
The `businesscentral` MCP server exposes exactly **three** callable tools:
|
||||||
`Create<entity>_PAG<id>` (create). Confirm exact names from the server's tool list.
|
`bc_actions_search`, `bc_actions_describe`, `bc_actions_invoke`. There is no static
|
||||||
|
tool list to browse - BC entity/action names (`List_Projects_PAG6102901` and so on)
|
||||||
|
are not separate MCP tools; they only exist as results of `bc_actions_search`.
|
||||||
|
|
||||||
|
**Do not use the general-purpose `ToolSearch` to look for BC entity/action names.**
|
||||||
|
`ToolSearch` only resolves this session's own deferred client-side tools (the three
|
||||||
|
above) - it does not search Business Central's action catalog and will return
|
||||||
|
irrelevant matches from unrelated servers. To find an action:
|
||||||
|
|
||||||
|
1. `bc_actions_search` with `SearchMode: keyword` and a few field/entity keywords
|
||||||
|
(e.g. `"project, repository, gitHubRepository"`), filtered by `ActionType` if known.
|
||||||
|
2. `bc_actions_describe` on the exact name it returns, to get the callable schema.
|
||||||
|
3. `bc_actions_invoke` with matching `RequestParameters`.
|
||||||
|
|
||||||
|
Expected naming convention - **reverify per call with `bc_actions_search`, do not
|
||||||
|
assume it holds**: `List_<Entity>_PAG<id>` (read), `Modify_<Entity>_PAG<id>` (update,
|
||||||
|
**singular** entity name - e.g. `Modify_ProjectRepository_PAG6102904`, not
|
||||||
|
`ModifyProjectRepositories` or `ListUpdate...`), `Create_<Entity>_PAG<id>` (create).
|
||||||
|
|
||||||
| Entity (page) | Read | Write you MAY do | Never |
|
| Entity (page) | Read | Write you MAY do | Never |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
|
|
@ -85,7 +112,8 @@ Moving to `Accepted` requires `Starting date`, `Estimated time` and `Expected De
|
||||||
1. **Find the work.** Read `activeTasks` (filter by `projectNo` or `gitHubRepository`). Use
|
1. **Find the work.** Read `activeTasks` (filter by `projectNo` or `gitHubRepository`). Use
|
||||||
`gitHubRepository` on the project to confirm you are in the right repo.
|
`gitHubRepository` on the project to confirm you are in the right repo.
|
||||||
2. **Claim it.** When you start, set `gitHubBranch` to the working branch and
|
2. **Claim it.** When you start, set `gitHubBranch` to the working branch and
|
||||||
`gitHubDevStatus = In Progress` on the task (`ListUpdate activeTasks`).
|
`gitHubDevStatus = In Progress` on the task (search `bc_actions_search` for the
|
||||||
|
modify action on `activeTasks` - expect `Modify_ActiveTask_PAG6102900`, reverify).
|
||||||
3. **Record progress.** Post a status note with `Create taskComments`
|
3. **Record progress.** Post a status note with `Create taskComments`
|
||||||
(`projectNo` + `subTaskNo` scope it to one task). Keep notes short and factual.
|
(`projectNo` + `subTaskNo` scope it to one task). Keep notes short and factual.
|
||||||
4. **Finish.** Set `gitHubDevStatus = Done` automatically when branch is merged to main.
|
4. **Finish.** Set `gitHubDevStatus = Done` automatically when branch is merged to main.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue