@withpica/mcp-server 2.47.0 → 2.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/apps/generated/shared-bundle.d.ts +1 -1
  3. package/dist/apps/generated/shared-bundle.d.ts.map +1 -1
  4. package/dist/apps/generated/shared-bundle.js +1 -1
  5. package/dist/apps/generated/shared-bundle.js.map +1 -1
  6. package/dist/prompts/creator-question-atlas.d.ts +48 -0
  7. package/dist/prompts/creator-question-atlas.d.ts.map +1 -0
  8. package/dist/prompts/creator-question-atlas.js +586 -0
  9. package/dist/prompts/creator-question-atlas.js.map +1 -0
  10. package/dist/prompts/index.d.ts +32 -0
  11. package/dist/prompts/index.d.ts.map +1 -1
  12. package/dist/prompts/index.js +235 -0
  13. package/dist/prompts/index.js.map +1 -1
  14. package/dist/server.d.ts +26 -0
  15. package/dist/server.d.ts.map +1 -1
  16. package/dist/server.js +108 -10
  17. package/dist/server.js.map +1 -1
  18. package/dist/tools/agent-identity.d.ts.map +1 -1
  19. package/dist/tools/agent-identity.js +15 -0
  20. package/dist/tools/agent-identity.js.map +1 -1
  21. package/dist/tools/agreement-types.d.ts.map +1 -1
  22. package/dist/tools/agreement-types.js +25 -1
  23. package/dist/tools/agreement-types.js.map +1 -1
  24. package/dist/tools/agreements.d.ts.map +1 -1
  25. package/dist/tools/agreements.js +22 -4
  26. package/dist/tools/agreements.js.map +1 -1
  27. package/dist/tools/analytics.d.ts.map +1 -1
  28. package/dist/tools/analytics.js +19 -1
  29. package/dist/tools/analytics.js.map +1 -1
  30. package/dist/tools/app-tools.d.ts.map +1 -1
  31. package/dist/tools/app-tools.js +13 -4
  32. package/dist/tools/app-tools.js.map +1 -1
  33. package/dist/tools/assets.d.ts.map +1 -1
  34. package/dist/tools/assets.js +73 -14
  35. package/dist/tools/assets.js.map +1 -1
  36. package/dist/tools/audio-files.d.ts +5 -0
  37. package/dist/tools/audio-files.d.ts.map +1 -1
  38. package/dist/tools/audio-files.js +94 -3
  39. package/dist/tools/audio-files.js.map +1 -1
  40. package/dist/tools/audit.d.ts.map +1 -1
  41. package/dist/tools/audit.js +11 -2
  42. package/dist/tools/audit.js.map +1 -1
  43. package/dist/tools/auth.d.ts.map +1 -1
  44. package/dist/tools/auth.js +6 -0
  45. package/dist/tools/auth.js.map +1 -1
  46. package/dist/tools/bulk.d.ts.map +1 -1
  47. package/dist/tools/bulk.js +8 -2
  48. package/dist/tools/bulk.js.map +1 -1
  49. package/dist/tools/calendar.d.ts.map +1 -1
  50. package/dist/tools/calendar.js +3 -0
  51. package/dist/tools/calendar.js.map +1 -1
  52. package/dist/tools/collaborators.d.ts.map +1 -1
  53. package/dist/tools/collaborators.js +29 -8
  54. package/dist/tools/collaborators.js.map +1 -1
  55. package/dist/tools/comparisons.d.ts.map +1 -1
  56. package/dist/tools/comparisons.js +6 -0
  57. package/dist/tools/comparisons.js.map +1 -1
  58. package/dist/tools/credits.d.ts +18 -0
  59. package/dist/tools/credits.d.ts.map +1 -1
  60. package/dist/tools/credits.js +347 -7
  61. package/dist/tools/credits.js.map +1 -1
  62. package/dist/tools/custody.d.ts.map +1 -1
  63. package/dist/tools/custody.js +23 -2
  64. package/dist/tools/custody.js.map +1 -1
  65. package/dist/tools/dashboard.d.ts.map +1 -1
  66. package/dist/tools/dashboard.js +43 -7
  67. package/dist/tools/dashboard.js.map +1 -1
  68. package/dist/tools/directory.d.ts.map +1 -1
  69. package/dist/tools/directory.js +3 -0
  70. package/dist/tools/directory.js.map +1 -1
  71. package/dist/tools/discovery.d.ts.map +1 -1
  72. package/dist/tools/discovery.js +81 -2
  73. package/dist/tools/discovery.js.map +1 -1
  74. package/dist/tools/disputes.d.ts.map +1 -1
  75. package/dist/tools/disputes.js +4 -1
  76. package/dist/tools/disputes.js.map +1 -1
  77. package/dist/tools/documents.d.ts.map +1 -1
  78. package/dist/tools/documents.js +3 -0
  79. package/dist/tools/documents.js.map +1 -1
  80. package/dist/tools/duplicates.d.ts.map +1 -1
  81. package/dist/tools/duplicates.js +6 -0
  82. package/dist/tools/duplicates.js.map +1 -1
  83. package/dist/tools/enrichment.d.ts.map +1 -1
  84. package/dist/tools/enrichment.js +46 -13
  85. package/dist/tools/enrichment.js.map +1 -1
  86. package/dist/tools/explainability.d.ts +24 -0
  87. package/dist/tools/explainability.d.ts.map +1 -0
  88. package/dist/tools/explainability.js +137 -0
  89. package/dist/tools/explainability.js.map +1 -0
  90. package/dist/tools/exports.d.ts.map +1 -1
  91. package/dist/tools/exports.js +18 -3
  92. package/dist/tools/exports.js.map +1 -1
  93. package/dist/tools/feedback.d.ts.map +1 -1
  94. package/dist/tools/feedback.js +4 -1
  95. package/dist/tools/feedback.js.map +1 -1
  96. package/dist/tools/forbidden-keywords.d.ts +62 -0
  97. package/dist/tools/forbidden-keywords.d.ts.map +1 -0
  98. package/dist/tools/forbidden-keywords.js +99 -0
  99. package/dist/tools/forbidden-keywords.js.map +1 -0
  100. package/dist/tools/groups.d.ts.map +1 -1
  101. package/dist/tools/groups.js +12 -0
  102. package/dist/tools/groups.js.map +1 -1
  103. package/dist/tools/import-documents.d.ts.map +1 -1
  104. package/dist/tools/import-documents.js +10 -1
  105. package/dist/tools/import-documents.js.map +1 -1
  106. package/dist/tools/import.d.ts.map +1 -1
  107. package/dist/tools/import.js +36 -3
  108. package/dist/tools/import.js.map +1 -1
  109. package/dist/tools/index.d.ts +99 -4
  110. package/dist/tools/index.d.ts.map +1 -1
  111. package/dist/tools/index.js +171 -99
  112. package/dist/tools/index.js.map +1 -1
  113. package/dist/tools/integrations.d.ts.map +1 -1
  114. package/dist/tools/integrations.js +28 -8
  115. package/dist/tools/integrations.js.map +1 -1
  116. package/dist/tools/labels.d.ts.map +1 -1
  117. package/dist/tools/labels.js +3 -0
  118. package/dist/tools/labels.js.map +1 -1
  119. package/dist/tools/licensing.d.ts.map +1 -1
  120. package/dist/tools/licensing.js +15 -0
  121. package/dist/tools/licensing.js.map +1 -1
  122. package/dist/tools/memory.d.ts.map +1 -1
  123. package/dist/tools/memory.js +15 -3
  124. package/dist/tools/memory.js.map +1 -1
  125. package/dist/tools/metadata.d.ts.map +1 -1
  126. package/dist/tools/metadata.js +75 -25
  127. package/dist/tools/metadata.js.map +1 -1
  128. package/dist/tools/multimedia.d.ts.map +1 -1
  129. package/dist/tools/multimedia.js +15 -0
  130. package/dist/tools/multimedia.js.map +1 -1
  131. package/dist/tools/my-recent-questions.d.ts +25 -0
  132. package/dist/tools/my-recent-questions.d.ts.map +1 -0
  133. package/dist/tools/my-recent-questions.js +186 -0
  134. package/dist/tools/my-recent-questions.js.map +1 -0
  135. package/dist/tools/my-reported-issues.d.ts.map +1 -1
  136. package/dist/tools/my-reported-issues.js +3 -0
  137. package/dist/tools/my-reported-issues.js.map +1 -1
  138. package/dist/tools/notes.d.ts.map +1 -1
  139. package/dist/tools/notes.js +12 -0
  140. package/dist/tools/notes.js.map +1 -1
  141. package/dist/tools/notifications.d.ts.map +1 -1
  142. package/dist/tools/notifications.js +28 -4
  143. package/dist/tools/notifications.js.map +1 -1
  144. package/dist/tools/onboarding.d.ts.map +1 -1
  145. package/dist/tools/onboarding.js +3 -0
  146. package/dist/tools/onboarding.js.map +1 -1
  147. package/dist/tools/people.d.ts.map +1 -1
  148. package/dist/tools/people.js +21 -1
  149. package/dist/tools/people.js.map +1 -1
  150. package/dist/tools/projects.d.ts.map +1 -1
  151. package/dist/tools/projects.js +24 -7
  152. package/dist/tools/projects.js.map +1 -1
  153. package/dist/tools/public-filter.d.ts.map +1 -1
  154. package/dist/tools/public-filter.js +8 -36
  155. package/dist/tools/public-filter.js.map +1 -1
  156. package/dist/tools/publishers.d.ts.map +1 -1
  157. package/dist/tools/publishers.js +6 -0
  158. package/dist/tools/publishers.js.map +1 -1
  159. package/dist/tools/purchases.d.ts +11 -10
  160. package/dist/tools/purchases.d.ts.map +1 -1
  161. package/dist/tools/purchases.js.map +1 -1
  162. package/dist/tools/recordings.d.ts.map +1 -1
  163. package/dist/tools/recordings.js +90 -27
  164. package/dist/tools/recordings.js.map +1 -1
  165. package/dist/tools/recovery-hints.d.ts +26 -0
  166. package/dist/tools/recovery-hints.d.ts.map +1 -1
  167. package/dist/tools/recovery-hints.js +591 -0
  168. package/dist/tools/recovery-hints.js.map +1 -1
  169. package/dist/tools/release-rich.d.ts.map +1 -1
  170. package/dist/tools/release-rich.js +14 -8
  171. package/dist/tools/release-rich.js.map +1 -1
  172. package/dist/tools/releases.d.ts.map +1 -1
  173. package/dist/tools/releases.js +42 -0
  174. package/dist/tools/releases.js.map +1 -1
  175. package/dist/tools/report-issue.d.ts.map +1 -1
  176. package/dist/tools/report-issue.js +3 -0
  177. package/dist/tools/report-issue.js.map +1 -1
  178. package/dist/tools/royalties.d.ts.map +1 -1
  179. package/dist/tools/royalties.js +18 -3
  180. package/dist/tools/royalties.js.map +1 -1
  181. package/dist/tools/search.d.ts.map +1 -1
  182. package/dist/tools/search.js +10 -1
  183. package/dist/tools/search.js.map +1 -1
  184. package/dist/tools/send.d.ts.map +1 -1
  185. package/dist/tools/send.js +9 -0
  186. package/dist/tools/send.js.map +1 -1
  187. package/dist/tools/sessions.d.ts.map +1 -1
  188. package/dist/tools/sessions.js +12 -0
  189. package/dist/tools/sessions.js.map +1 -1
  190. package/dist/tools/settings.d.ts.map +1 -1
  191. package/dist/tools/settings.js +44 -18
  192. package/dist/tools/settings.js.map +1 -1
  193. package/dist/tools/share-links.d.ts.map +1 -1
  194. package/dist/tools/share-links.js +15 -0
  195. package/dist/tools/share-links.js.map +1 -1
  196. package/dist/tools/sharing.d.ts +29 -0
  197. package/dist/tools/sharing.d.ts.map +1 -0
  198. package/dist/tools/sharing.js +131 -0
  199. package/dist/tools/sharing.js.map +1 -0
  200. package/dist/tools/signup.d.ts.map +1 -1
  201. package/dist/tools/signup.js +4 -1
  202. package/dist/tools/signup.js.map +1 -1
  203. package/dist/tools/split-sheets.d.ts.map +1 -1
  204. package/dist/tools/split-sheets.js +23 -2
  205. package/dist/tools/split-sheets.js.map +1 -1
  206. package/dist/tools/storage-config.d.ts.map +1 -1
  207. package/dist/tools/storage-config.js +8 -2
  208. package/dist/tools/storage-config.js.map +1 -1
  209. package/dist/tools/subscription.d.ts.map +1 -1
  210. package/dist/tools/subscription.js +13 -16
  211. package/dist/tools/subscription.js.map +1 -1
  212. package/dist/tools/sync-placements.d.ts.map +1 -1
  213. package/dist/tools/sync-placements.js +22 -4
  214. package/dist/tools/sync-placements.js.map +1 -1
  215. package/dist/tools/team.d.ts.map +1 -1
  216. package/dist/tools/team.js +15 -0
  217. package/dist/tools/team.js.map +1 -1
  218. package/dist/tools/telegram.d.ts.map +1 -1
  219. package/dist/tools/telegram.js +9 -0
  220. package/dist/tools/telegram.js.map +1 -1
  221. package/dist/tools/uploads.d.ts.map +1 -1
  222. package/dist/tools/uploads.js +6 -0
  223. package/dist/tools/uploads.js.map +1 -1
  224. package/dist/tools/works.d.ts.map +1 -1
  225. package/dist/tools/works.js +74 -25
  226. package/dist/tools/works.js.map +1 -1
  227. package/package.json +4 -4
  228. package/server.json +2 -2
  229. package/.claude/settings.local.json +0 -5
@@ -40,8 +40,74 @@ export interface NextStepHint {
40
40
  * lands so every tool is forced to declare its workflow at compile time.
41
41
  */
42
42
  export type WorkflowTag = "work-required" | "recording-required" | "work-credits-required" | "recording-credits-required" | "person-required" | "audio-upload-required" | "enrichment-resolve-required" | "agreement-required" | "multimedia-required" | "export-required" | "claim-required" | "session-required" | "split-sheet-required" | "recording-splits-required" | "sync-placement-required" | "infrastructure";
43
+ /**
44
+ * ADR-226 Decision 2 — vernacular intent posture for every tool.
45
+ *
46
+ * - `creator-entry` — Atlas covers it; `Use when the user asks: '...'` block
47
+ * in the description is required (Phase 7 lint enforces).
48
+ * - `internal` — programmatic handoff between tools (e.g. presigned-PUT
49
+ * finalize step). Requires a one-line `vernacular_reason`.
50
+ * - `specialist` — mutating / destructive / not-yet-covered context;
51
+ * invoked by exact name. Requires a one-line `vernacular_reason`.
52
+ *
53
+ * Universal coverage: every tool declares its kind. Phase 7 lint promotes
54
+ * the field to a required-with-blocking check; Phase 3 (this commit)
55
+ * leaves it optional during the bulk-classification ramp and flips it to
56
+ * required in the same commit once all 244 tools have been populated by
57
+ * `scripts/bulk-classify-vernacular-kind.ts`.
58
+ */
59
+ export type VernacularKind = "creator-entry" | "internal" | "specialist";
60
+ /**
61
+ * ADR-230 — authority tier declared on every tool definition.
62
+ *
63
+ * - `read` — pure query, no state mutation. Maps to readOnlyHint:true,
64
+ * risk_level:"safe", required scope `read:*` (or `write:*`
65
+ * via the read-implies-write rule in `hasScope`).
66
+ * - `draft` — produces a proposal/preview/hint without persisting
67
+ * state. Same hints as `write` (readOnlyHint:false,
68
+ * risk_level:"mutating"). No confirmation token.
69
+ * - `write` — persistent state change. May opt into per-tool
70
+ * confirmation via `previewMode: "two_step_token"`.
71
+ * - `destructive` — irreversible state change (delete / merge / send
72
+ * broadcast / disconnect). destructiveHint:true,
73
+ * risk_level:"destructive", confirmation token required,
74
+ * requires elevated `destructive:*` scope (admin satisfies).
75
+ *
76
+ * The 4-value `tier` is PICA's authority surface. The 3-value `risk_level`
77
+ * on `mcp_audit_log` is derived from `tier` (read→safe, draft|write→mutating,
78
+ * destructive→destructive) — sister of the MCP-standard `readOnlyHint` /
79
+ * `destructiveHint` fields, kept for ADR-199 client compatibility.
80
+ */
81
+ export type Tier = "read" | "draft" | "write" | "destructive";
82
+ /**
83
+ * ADR-230 — derive the MCP-standard 3-value risk classification from the
84
+ * declared tier. Sourced once at registration and at audit-write time so
85
+ * the contract that hints, audit row, and confirmation requirement all
86
+ * agree is mechanical.
87
+ */
88
+ export declare function tierToRiskLevel(tier: Tier): "safe" | "mutating" | "destructive";
89
+ /**
90
+ * ADR-230 — derive the required API-key scope from the declared tier.
91
+ *
92
+ * - `read` → `read:<resource>` (write:* satisfies via `hasScope`).
93
+ * - `draft|write` → `write:<resource>`.
94
+ * - `destructive` → `destructive:*` (admin satisfies via `hasScope`); the
95
+ * write:<resource> scope is also required for the
96
+ * underlying write surface.
97
+ *
98
+ * Returns the *additional* scope tier beyond per-resource. Resource scope
99
+ * is composed at call-site by `lib/services/mcp-scopes.ts`.
100
+ */
101
+ export declare function tierToScopeKind(tier: Tier): "read" | "write" | "destructive";
43
102
  export interface ToolDefinition {
44
103
  name: string;
104
+ /**
105
+ * ADR-230 — authority tier. Required for every customer-facing tool.
106
+ * Sourced from per-tool declaration; drives MCP hints, audit-log
107
+ * `risk_level`, confirmation-token requirement, and required scope.
108
+ * See {@link Tier} above for semantics.
109
+ */
110
+ tier: Tier;
45
111
  description: string;
46
112
  /**
47
113
  * ADR-214 — workflow(s) this tool belongs to. See `WorkflowTag` above.
@@ -50,6 +116,21 @@ export interface ToolDefinition {
50
116
  * part of any user-facing workflow.
51
117
  */
52
118
  workflows: WorkflowTag | WorkflowTag[];
119
+ /**
120
+ * ADR-226 Decision 2 — vernacular intent posture. See `VernacularKind`
121
+ * above. Optional during Phase 3 ramp; Phase 7 lint flips it to a
122
+ * required-with-blocking check once every tool is populated.
123
+ */
124
+ vernacular_kind?: VernacularKind;
125
+ /**
126
+ * ADR-226 Decision 2 — required when `vernacular_kind` is `'internal'`
127
+ * or `'specialist'`. One-line documentation of why the tool is not a
128
+ * creator-vernacular entry point (e.g. "Invoked after presigned PUT
129
+ * completes" or "Specialist context; not yet covered by the Creator
130
+ * Question Atlas"). Phase 7 lint enforces presence on non-`creator-entry`
131
+ * kinds.
132
+ */
133
+ vernacular_reason?: string;
53
134
  inputSchema: {
54
135
  type: string;
55
136
  properties: Record<string, any>;
@@ -118,6 +199,16 @@ export interface ToolDefinition {
118
199
  export type ToolCategory = "catalog" | "enrichment" | "business" | "discovery" | "media" | "comms" | "settings";
119
200
  export interface ToolMetadata {
120
201
  category: ToolCategory;
202
+ /**
203
+ * @deprecated ADR-230 — use the declared `tier` on the tool
204
+ * definition (`ToolDefinition.tier` — required by lint Rule 13) as
205
+ * the source of truth. `risk` is retained as a quiet fallback for
206
+ * the unlikely case of a tool that bypasses lint (legacy tolerance
207
+ * inside `ToolRegistry.listTools`) and to drive the
208
+ * `injectMetadataIntoDescription` annotations + `retry_safe` hints
209
+ * exposed via `getToolMetadata`. Do NOT add new consumers; route
210
+ * tier-aware logic through the tool definition's declared `tier`.
211
+ */
121
212
  risk: "safe" | "mutating" | "destructive";
122
213
  retry_safe: boolean;
123
214
  display_name: string;
@@ -196,10 +287,14 @@ export declare class ToolRegistry {
196
287
  * Register all available tools
197
288
  */
198
289
  private registerAllTools;
199
- private static readonly DESTRUCTIVE_PATTERNS;
200
- private static readonly MUTATING_PATTERNS;
201
- private static readonly SAFE_OVERRIDES;
202
- private classifyTool;
290
+ /**
291
+ * ADR-230 declared tier lookup by tool name. Used by the HTTP MCP
292
+ * dispatcher (`app/api/mcp/route.ts`) to enforce the elevated
293
+ * `destructive:*` scope on top of the resource-level scope from
294
+ * `lib/services/mcp-scopes`. Returns undefined for unknown tools or
295
+ * tools that haven't declared tier yet (legacy tolerance).
296
+ */
297
+ getToolTier(name: string): Tier | undefined;
203
298
  /**
204
299
  * List all available tools with write-safety prefixes injected.
205
300
  * When discoveryMode is enabled, only the 5 handshake-visible tools are returned.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -43,9 +43,12 @@ import { SubscriptionTools } from "./subscription.js";
43
43
  import { OnboardingTools } from "./onboarding.js";
44
44
  import { ReportIssueTools } from "./report-issue.js";
45
45
  import { MyReportedIssuesTools } from "./my-reported-issues.js";
46
+ import { MyRecentQuestionsTools } from "./my-recent-questions.js";
46
47
  import { AgentIdentityTools } from "./agent-identity.js";
47
48
  import { RoyaltiesTools } from "./royalties.js";
48
49
  import { ShareLinksTools } from "./share-links.js";
50
+ import { SharingTools } from "./sharing.js";
51
+ import { ExplainabilityTools } from "./explainability.js";
49
52
  import { DisputesTools } from "./disputes.js";
50
53
  import { CustodyTools } from "./custody.js";
51
54
  import { PurchasesTools } from "./purchases.js";
@@ -65,6 +68,46 @@ import { getToolMetadata } from "./metadata.js";
65
68
  import { getRecoveryHint } from "./recovery-hints.js";
66
69
  import { generateConfirmationToken, validateAndConsumeToken, } from "@withpica/mcp-utils";
67
70
  import { buildSessionState, incrementSessionMutations, resetSinceLastBriefing, } from "@withpica/mcp-utils";
71
+ /**
72
+ * ADR-230 — derive the MCP-standard 3-value risk classification from the
73
+ * declared tier. Sourced once at registration and at audit-write time so
74
+ * the contract that hints, audit row, and confirmation requirement all
75
+ * agree is mechanical.
76
+ */
77
+ export function tierToRiskLevel(tier) {
78
+ switch (tier) {
79
+ case "read":
80
+ return "safe";
81
+ case "draft":
82
+ case "write":
83
+ return "mutating";
84
+ case "destructive":
85
+ return "destructive";
86
+ }
87
+ }
88
+ /**
89
+ * ADR-230 — derive the required API-key scope from the declared tier.
90
+ *
91
+ * - `read` → `read:<resource>` (write:* satisfies via `hasScope`).
92
+ * - `draft|write` → `write:<resource>`.
93
+ * - `destructive` → `destructive:*` (admin satisfies via `hasScope`); the
94
+ * write:<resource> scope is also required for the
95
+ * underlying write surface.
96
+ *
97
+ * Returns the *additional* scope tier beyond per-resource. Resource scope
98
+ * is composed at call-site by `lib/services/mcp-scopes.ts`.
99
+ */
100
+ export function tierToScopeKind(tier) {
101
+ switch (tier) {
102
+ case "read":
103
+ return "read";
104
+ case "draft":
105
+ case "write":
106
+ return "write";
107
+ case "destructive":
108
+ return "destructive";
109
+ }
110
+ }
68
111
  /**
69
112
  * Build a tool description with metadata injected.
70
113
  * Format: "[category] original description"
@@ -370,6 +413,21 @@ export class ToolRegistry {
370
413
  myReportedIssuesTools.getTools().forEach((tool) => {
371
414
  this.tools.set(tool.definition.name, tool);
372
415
  });
416
+ // My-recent-questions tool (ADR-226 Phase 5 — pica_my_recent_questions)
417
+ // — user-scoped read of the Phase 4 substrate (assistant_interactions
418
+ // joined with mcp_sessions for client identity). Atlas-resolved entry
419
+ // for "what did I ask the AI?".
420
+ //
421
+ // ADR-230 post-ship cleanup — the tier resolver is the registry's
422
+ // own `getToolTier` shape (declared `tier` on each tool definition).
423
+ // Lint Rule 13 makes tier required for every customer MCP tool, so
424
+ // this resolver returns a populated value for all known tools and
425
+ // `undefined` only for unknown / meta tools — `dominantTier` falls
426
+ // back to "read" in that case.
427
+ const myRecentQuestionsTools = new MyRecentQuestionsTools(pica, (name) => this.tools.get(name)?.definition.tier);
428
+ myRecentQuestionsTools.getTools().forEach((tool) => {
429
+ this.tools.set(tool.definition.name, tool);
430
+ });
373
431
  // Agent identity tools (ADR-185 Part 1 — session-auth-only MCP surface).
374
432
  // The three tools refuse grant-auth callers at the HTTP API layer;
375
433
  // the stdio path carries an API key so behaviour is identical either
@@ -388,6 +446,16 @@ export class ToolRegistry {
388
446
  shareLinksTools.getTools().forEach((tool) => {
389
447
  this.tools.set(tool.definition.name, tool);
390
448
  });
449
+ // Sharing trace tool (ADR-232 § Decision 2)
450
+ const sharingTools = new SharingTools(pica);
451
+ sharingTools.getTools().forEach((tool) => {
452
+ this.tools.set(tool.definition.name, tool);
453
+ });
454
+ // Explainability tools (ADR-232 § Decision 3)
455
+ const explainabilityTools = new ExplainabilityTools(pica);
456
+ explainabilityTools.getTools().forEach((tool) => {
457
+ this.tools.set(tool.definition.name, tool);
458
+ });
391
459
  // Disputes tools (ADR-139 Step 3)
392
460
  const disputesTools = new DisputesTools(pica);
393
461
  disputesTools.getTools().forEach((tool) => {
@@ -449,72 +517,15 @@ export class ToolRegistry {
449
517
  });
450
518
  }
451
519
  }
452
- // ── Write-safety classification ──
453
- // Destructive tools require confirmation before AND summary after.
454
- // Mutating tools should present what they'll do and confirm after.
455
- // Safe (read-only) tools need no confirmation.
456
- static DESTRUCTIVE_PATTERNS = [
457
- "_delete",
458
- "_bulk_delete",
459
- "_merge",
460
- "_remove",
461
- "_disconnect",
462
- ];
463
- static MUTATING_PATTERNS = [
464
- "_create",
465
- "_update",
466
- "_bulk_update",
467
- "_invite",
468
- "_link",
469
- "_send_",
470
- "_import_",
471
- "_execute",
472
- "_ingest",
473
- "_enrich",
474
- "_verify",
475
- "_mark_",
476
- "_review",
477
- "_purchase",
478
- "_submit",
479
- "_generate",
480
- "_set_default",
481
- "_duplicate",
482
- "_toggle",
483
- "_save",
484
- "_upload",
485
- "_complete",
486
- "_analyze",
487
- "_analyse",
488
- "_identify",
489
- "_resend",
490
- "_notify",
491
- ];
492
- // Read-only tools that match mutating patterns by name but are actually safe
493
- static SAFE_OVERRIDES = new Set([
494
- "pica_collaborators_invites_list",
495
- "pica_enrichment_candidates",
496
- "pica_enrichment_compare",
497
- "pica_find_duplicates",
498
- "pica_import_analyze",
499
- "pica_import_validate",
500
- "pica_import_fields",
501
- "pica_import_template",
502
- "pica_import_documents_query",
503
- "pica_import_documents_inspect",
504
- "pica_send_query",
505
- "pica_share_links_list",
506
- ]);
507
- classifyTool(name) {
508
- if (ToolRegistry.SAFE_OVERRIDES.has(name)) {
509
- return "safe";
510
- }
511
- if (ToolRegistry.DESTRUCTIVE_PATTERNS.some((p) => name.includes(p))) {
512
- return "destructive";
513
- }
514
- if (ToolRegistry.MUTATING_PATTERNS.some((p) => name.includes(p))) {
515
- return "mutating";
516
- }
517
- return "safe";
520
+ /**
521
+ * ADR-230 declared tier lookup by tool name. Used by the HTTP MCP
522
+ * dispatcher (`app/api/mcp/route.ts`) to enforce the elevated
523
+ * `destructive:*` scope on top of the resource-level scope from
524
+ * `lib/services/mcp-scopes`. Returns undefined for unknown tools or
525
+ * tools that haven't declared tier yet (legacy tolerance).
526
+ */
527
+ getToolTier(name) {
528
+ return this.tools.get(name)?.definition.tier;
518
529
  }
519
530
  /**
520
531
  * List all available tools with write-safety prefixes injected.
@@ -536,9 +547,14 @@ export class ToolRegistry {
536
547
  return toolsToList.map((tool) => {
537
548
  let definition = tool.definition;
538
549
  const metadata = getToolMetadata(definition.name);
539
- // Inject confirmation_token into destructive tool schemas
540
- const isDestructive = metadata?.risk === "destructive" ||
541
- (!metadata && this.classifyTool(definition.name) === "destructive");
550
+ // ADR-230 declared tier is the source of truth for hints + risk.
551
+ // Lint Rule 13 enforces tier presence on every customer MCP tool;
552
+ // metadata.risk is a quiet fallback for the unlikely case of a tool
553
+ // that bypasses lint.
554
+ const declaredTier = definition.tier;
555
+ const isDestructive = declaredTier
556
+ ? declaredTier === "destructive"
557
+ : metadata?.risk === "destructive";
542
558
  if (isDestructive) {
543
559
  definition = {
544
560
  ...definition,
@@ -566,6 +582,26 @@ export class ToolRegistry {
566
582
  },
567
583
  };
568
584
  }
585
+ // ADR-230 — derive hints from declared tier when present (every
586
+ // tool registered in mcp-server/src/tools/*.ts has tier as of
587
+ // PR-1; the metadata branch stays as a defensive code path).
588
+ if (declaredTier && metadata) {
589
+ return {
590
+ ...definition,
591
+ description: injectMetadataIntoDescription(tool.definition.description, metadata),
592
+ annotations: {
593
+ title: metadata.display_name,
594
+ readOnlyHint: declaredTier === "read",
595
+ destructiveHint: declaredTier === "destructive",
596
+ idempotentHint: declaredTier !== "destructive" && metadata.retry_safe,
597
+ openWorldHint: false,
598
+ // ADR-199 extended annotation classes — read by ChatGPT/Claude.ai
599
+ // connectors directly. Derived from declared tier so the four
600
+ // surfaces (hint, riskLevel, audit row, scope) all agree.
601
+ ...this.deriveExtendedAnnotations(definition, metadata, undefined, declaredTier),
602
+ },
603
+ };
604
+ }
569
605
  if (metadata) {
570
606
  return {
571
607
  ...definition,
@@ -574,27 +610,27 @@ export class ToolRegistry {
574
610
  title: metadata.display_name,
575
611
  readOnlyHint: metadata.risk === "safe",
576
612
  destructiveHint: metadata.risk === "destructive",
577
- idempotentHint: metadata.risk === "safe" && metadata.retry_safe,
613
+ idempotentHint: metadata.risk !== "destructive" && metadata.retry_safe,
578
614
  openWorldHint: false,
579
- // ADR-199 extended annotation classes — read by ChatGPT/Claude.ai
580
- // connectors directly. Derived from existing metadata so existing
581
- // tools get this for free without per-tool edits.
582
615
  ...this.deriveExtendedAnnotations(definition, metadata),
583
616
  },
584
617
  };
585
618
  }
586
- // Fallback to old pattern-matching for any tool without explicit metadata
587
- const classification = this.classifyTool(definition.name);
619
+ // ADR-230 tools without a TOOL_METADATA entry (the 5 lobby
620
+ // meta-tools sign_in/out/discover/tool_details/execute) still
621
+ // declare tier. Source hints from declared tier; default to read
622
+ // when tier is somehow missing (lint blocks; defensive only).
623
+ const tierForHints = declaredTier ?? "read";
588
624
  const annotations = {
589
625
  title: definition.name,
590
- readOnlyHint: classification === "safe",
591
- destructiveHint: classification === "destructive",
626
+ readOnlyHint: tierForHints === "read",
627
+ destructiveHint: tierForHints === "destructive",
592
628
  idempotentHint: false,
593
629
  openWorldHint: false,
594
- // ADR-199: derive the extended classes even without explicit
595
- // metadata so the fallback tools also surface category/risk to
596
- // ChatGPT/Claude.ai connectors.
597
- ...this.deriveExtendedAnnotations(definition, null, classification),
630
+ // ADR-199: derive the extended classes from declared tier so the
631
+ // category/risk surface stays aligned with the rest of the
632
+ // hint/audit/scope chain.
633
+ ...this.deriveExtendedAnnotations(definition, null, undefined, tierForHints),
598
634
  };
599
635
  // No risk prefix needed — annotations handle this structurally
600
636
  return { ...definition, annotations };
@@ -609,9 +645,16 @@ export class ToolRegistry {
609
645
  * edits required for the retrofit. Future tool authors can override by
610
646
  * setting fields directly on definition.annotations.
611
647
  */
612
- deriveExtendedAnnotations(definition, metadata, classification) {
648
+ deriveExtendedAnnotations(definition, metadata, _classification, declaredTier) {
613
649
  const name = definition.name;
614
- const risk = metadata?.risk ?? classification ?? "safe";
650
+ // ADR-230 declared tier is the source of truth. metadata.risk
651
+ // remains a quiet fallback for any tool that bypasses lint Rule 13.
652
+ // (The `_classification` parameter is retained as an unused
653
+ // positional slot so legacy call signatures continue to compile;
654
+ // its value is now ignored — classifyTool was removed in PR-3.)
655
+ const risk = declaredTier
656
+ ? tierToRiskLevel(declaredTier)
657
+ : (metadata?.risk ?? "safe");
615
658
  // Side-effecting external systems: telegram, send-hub, comms, broadcasts.
616
659
  // Pattern-derived so new tools inherit without edits.
617
660
  const externalSideEffectPatterns = [
@@ -631,10 +674,16 @@ export class ToolRegistry {
631
674
  // the agent wants to confirm — the gap report flagged this as a useful
632
675
  // class for ChatGPT to surface in the UI.
633
676
  const requiresFollowUpInspection = risk === "mutating" || risk === "destructive";
677
+ // ADR-230 — destructive tier always requires confirmation. Other tiers
678
+ // never do via this annotation (per-tool opt-in for `write` tier is
679
+ // expressed through `previewMode: "two_step_token"`, not here).
680
+ const requiresConfirmation = declaredTier
681
+ ? declaredTier === "destructive"
682
+ : risk === "destructive";
634
683
  return {
635
684
  riskLevel: risk,
636
685
  category: metadata?.category,
637
- requiresConfirmation: risk === "destructive",
686
+ requiresConfirmation,
638
687
  createsExternalSideEffects,
639
688
  returnsPaginated,
640
689
  requiresFollowUpInspection,
@@ -1011,10 +1060,22 @@ export class ToolRegistry {
1011
1060
  throw new ToolExecutionError(`Tool not found: ${name}`);
1012
1061
  }
1013
1062
  const metadata = getToolMetadata(name);
1063
+ // ADR-230 — declared tier is the source of truth for the freshness +
1064
+ // confirmation gates and the audit-log surfaces. Fall back to
1065
+ // metadata.risk only if the tool somehow lacks tier (lint blocks
1066
+ // missing tier on creator + team + directory MCPs as of PR-2).
1067
+ const declaredTier = tool.definition.tier;
1068
+ const fallbackRisk = metadata?.risk ?? "safe";
1069
+ const auditTier = declaredTier ??
1070
+ (fallbackRisk === "safe"
1071
+ ? "read"
1072
+ : fallbackRisk === "destructive"
1073
+ ? "destructive"
1074
+ : "write");
1075
+ const auditRiskLevel = tierToRiskLevel(auditTier);
1076
+ const isDestructive = auditTier === "destructive";
1014
1077
  // ── Session freshness gate (ADR-151) ──
1015
- if (metadata?.risk === "destructive" &&
1016
- this.config &&
1017
- !this.config.lobbyMode) {
1078
+ if (isDestructive && this.config && !this.config.lobbyMode) {
1018
1079
  const creds = readCredentials(this.config.credentialsPath);
1019
1080
  if (creds?.authenticated_at) {
1020
1081
  const authAge = Date.now() - new Date(creds.authenticated_at).getTime();
@@ -1032,12 +1093,15 @@ export class ToolRegistry {
1032
1093
  }
1033
1094
  }
1034
1095
  }
1035
- // ── Destructive confirmation gate ──
1036
- if (metadata?.risk === "destructive") {
1096
+ // ── Destructive confirmation gate (ADR-230 — keyed on declared tier) ──
1097
+ if (isDestructive) {
1037
1098
  const confirmationToken = args.confirmation_token;
1038
1099
  if (!confirmationToken) {
1039
- // First call — generate preview and return confirmation challenge
1040
- const token = generateConfirmationToken(name, args);
1100
+ // First call — generate preview and return confirmation challenge.
1101
+ // ADR-230 PR-4 — token state lives in Postgres for HTTP MCP under
1102
+ // Fluid Compute (or in-memory for stdio); both paths via the
1103
+ // active ConfirmationStore singleton, so callers stay unchanged.
1104
+ const token = await generateConfirmationToken(name, args);
1041
1105
  const preview = await this.buildDestructivePreview(name, args);
1042
1106
  const response = {
1043
1107
  content: [
@@ -1063,6 +1127,7 @@ export class ToolRegistry {
1063
1127
  ?.logToolExecution({
1064
1128
  tool_name: name,
1065
1129
  tool_category: metadata?.category || "unknown",
1130
+ tier: "destructive",
1066
1131
  risk_level: "destructive",
1067
1132
  parameters: this.sanitizeParams(args),
1068
1133
  result_status: "confirmation_required",
@@ -1074,8 +1139,9 @@ export class ToolRegistry {
1074
1139
  .catch(() => { }); // Never block on audit
1075
1140
  return response;
1076
1141
  }
1077
- // Second call — validate token
1078
- const validation = validateAndConsumeToken(confirmationToken, name, args);
1142
+ // Second call — validate token (Postgres-backed under Fluid Compute
1143
+ // since ADR-230 PR-4; the active store handles cross-instance state).
1144
+ const validation = await validateAndConsumeToken(confirmationToken, name, args);
1079
1145
  if (!validation.valid) {
1080
1146
  return {
1081
1147
  content: [
@@ -1108,10 +1174,10 @@ export class ToolRegistry {
1108
1174
  }
1109
1175
  }
1110
1176
  // ADR-208 Primitive B — ambient session-state on write-tool results.
1111
- // Read tools (`risk: safe` ⇒ `readOnlyHint: true`) skip this entirely so
1112
- // the high-volume read path stays cheap. `result.isError === true` also
1113
- // skips because a failed mutation didn't change catalog state.
1114
- const isWriteTool = (metadata?.risk ?? this.classifyTool(name)) !== "safe";
1177
+ // Read tools (`tier: "read"`) skip this entirely so the high-volume
1178
+ // read path stays cheap. `result.isError === true` also skips because
1179
+ // a failed mutation didn't change catalog state.
1180
+ const isWriteTool = auditRiskLevel !== "safe";
1115
1181
  if (isWriteTool && result && !result.isError) {
1116
1182
  await this.attachSessionState(result, name);
1117
1183
  }
@@ -1137,7 +1203,8 @@ export class ToolRegistry {
1137
1203
  ?.logToolExecution({
1138
1204
  tool_name: name,
1139
1205
  tool_category: metadata?.category || "unknown",
1140
- risk_level: metadata?.risk || this.classifyTool(name),
1206
+ tier: auditTier,
1207
+ risk_level: auditRiskLevel,
1141
1208
  parameters: this.sanitizeParams(args),
1142
1209
  result_status: "success",
1143
1210
  execution_time_ms: Date.now() - startTime,
@@ -1163,10 +1230,15 @@ export class ToolRegistry {
1163
1230
  ?.logToolExecution({
1164
1231
  tool_name: name,
1165
1232
  tool_category: metadata?.category || "unknown",
1166
- risk_level: metadata?.risk || this.classifyTool(name),
1233
+ tier: auditTier,
1234
+ risk_level: auditRiskLevel,
1167
1235
  parameters: this.sanitizeParams(args),
1168
1236
  result_status: "error",
1169
1237
  error_code: parsed.error,
1238
+ // Stage A — forward the parsed body's message so mcp_audit_log
1239
+ // captures the underlying cause. Without this every error row had
1240
+ // error_message=null, leaving UNKNOWN_ERROR rows opaque.
1241
+ error_message: typeof parsed.message === "string" ? parsed.message : undefined,
1170
1242
  execution_time_ms: Date.now() - startTime,
1171
1243
  caller_identity: this.callerContext.callerIdentity,
1172
1244
  transport: this.callerContext.transport,