Skip to content

Commit a078d4f

Browse files
feat(tools): add idempotentHint + openWorldHint annotations to all 12 tools (R3 F39) (#42)
R3 § 4 Bundle 2 finding F39: tool annotations were missing `idempotentHint`, `openWorldHint`, and `title`. Non-Claude MCP clients (GPT-4, Gemini, Kimi, DeepSeek via Cursor/ChatGPT/Codex/etc.) reason about side-effect classes using these annotations before invoking; without them, those models fall back to conservative defaults (refuse, ask, escalate) — degrading UX. This PR adds `idempotentHint` and `openWorldHint` to all 12 tools. `title` was already present at the top level of every tool definition, so no `title` changes were needed. Per CLAUDE.md verb-pattern table + MCP 2025-06-18 spec semantics: | Verb | readOnly | destructive | idempotent | openWorld | |------------|----------|-------------|------------|-----------| | list*, get*| true | false | true | false | | reserve* | false | false | false | false | | upload* | false | false | false | false | | confirm* | false | false | true | false | | terminate* | false | true | false | false | `openWorldHint: false` is uniform across all 12 tools — the Kobiton MCP server is a bounded API surface (`api.kobiton.com/mcp`), not an "open world" like web search or arbitrary HTTP fetch. `idempotentHint` values derive from MCP/HTTP idempotency semantics ("no additional effect after first request"). `confirmAppUpload` is idempotent because the second call after a successful first call sees the existing app record rather than creating a new one (consistent with R2 finding F5/F25 observations); but `uploadAppToStore` is NOT idempotent because it allocates a fresh S3 pre-signed URL per call. Tools touched (all 12): - tools/devices.yaml: listDevices, getDeviceStatus, reserveDevice, terminateReservation - tools/sessions.yaml: listSessions, getSession, getSessionArtifacts, terminateSession - tools/apps.yaml: listApps, uploadAppToStore, confirmAppUpload, getApp `outputSchema` per tool is NOT included in this PR — adding outputSchema without evidence of the actual server response shape would be speculative. Defer to a follow-up PR backed by empirical response captures (test-runs/ has the raw JSON dumps from the R2 experiment campaign that can ground outputSchemas accurately). Cross-references: - R3 § 4 Bundle 2 fork issue #26 - MCP spec primitives: modelcontextprotocol.io/specification/2025-06-18/server/tools Validation: - `pnpm run validate` passes - `pnpm test` passes (22 tests) - `validate-skills-schema.py --enterprise` — 0 ERRORs (all pre-existing WARNs unchanged); Skills: 1, Agents: 3; 91/100 average Signed-off-by: jeremylongshore <jeremylongshore@users.noreply.github.com> Co-authored-by: jeremylongshore <jeremylongshore@users.noreply.github.com>
1 parent a112fd9 commit a078d4f

3 files changed

Lines changed: 24 additions & 0 deletions

File tree

tools/apps.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ tools:
88
annotations:
99
readOnlyHint: true
1010
destructiveHint: false
11+
idempotentHint: true
12+
openWorldHint: false
1113
inputSchema:
1214
type: object
1315
properties:
@@ -46,6 +48,8 @@ tools:
4648
annotations:
4749
readOnlyHint: false
4850
destructiveHint: false
51+
idempotentHint: false
52+
openWorldHint: false
4953
inputSchema:
5054
type: object
5155
properties:
@@ -79,6 +83,8 @@ tools:
7983
annotations:
8084
readOnlyHint: false
8185
destructiveHint: false
86+
idempotentHint: true
87+
openWorldHint: false
8288
inputSchema:
8389
type: object
8490
properties:
@@ -106,6 +112,8 @@ tools:
106112
annotations:
107113
readOnlyHint: true
108114
destructiveHint: false
115+
idempotentHint: true
116+
openWorldHint: false
109117
inputSchema:
110118
type: object
111119
properties:

tools/devices.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ tools:
99
annotations:
1010
readOnlyHint: true
1111
destructiveHint: false
12+
idempotentHint: true
13+
openWorldHint: false
1214
inputSchema:
1315
type: object
1416
properties:
@@ -59,6 +61,8 @@ tools:
5961
annotations:
6062
readOnlyHint: true
6163
destructiveHint: false
64+
idempotentHint: true
65+
openWorldHint: false
6266
inputSchema:
6367
type: object
6468
properties:
@@ -84,6 +88,8 @@ tools:
8488
annotations:
8589
readOnlyHint: false
8690
destructiveHint: false
91+
idempotentHint: false
92+
openWorldHint: false
8793
inputSchema:
8894
type: object
8995
properties:
@@ -112,6 +118,8 @@ tools:
112118
annotations:
113119
readOnlyHint: false
114120
destructiveHint: true
121+
idempotentHint: false
122+
openWorldHint: false
115123
inputSchema:
116124
type: object
117125
properties:

tools/sessions.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ tools:
88
annotations:
99
readOnlyHint: true
1010
destructiveHint: false
11+
idempotentHint: true
12+
openWorldHint: false
1113
inputSchema:
1214
type: object
1315
properties:
@@ -68,6 +70,8 @@ tools:
6870
annotations:
6971
readOnlyHint: true
7072
destructiveHint: false
73+
idempotentHint: true
74+
openWorldHint: false
7175
inputSchema:
7276
type: object
7377
properties:
@@ -91,6 +95,8 @@ tools:
9195
annotations:
9296
readOnlyHint: true
9397
destructiveHint: false
98+
idempotentHint: true
99+
openWorldHint: false
94100
inputSchema:
95101
type: object
96102
properties:
@@ -114,6 +120,8 @@ tools:
114120
annotations:
115121
readOnlyHint: false
116122
destructiveHint: true
123+
idempotentHint: false
124+
openWorldHint: false
117125
inputSchema:
118126
type: object
119127
properties:

0 commit comments

Comments
 (0)