ag-cortex 0.1.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 (162) hide show
  1. package/.agent/commands/test-browser.md +339 -0
  2. package/.agent/rules/00-constitution.md +46 -0
  3. package/.agent/rules/project-rules.md +49 -0
  4. package/.agent/skills/agent-browser/SKILL.md +223 -0
  5. package/.agent/skills/agent-native-architecture/SKILL.md +435 -0
  6. package/.agent/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
  7. package/.agent/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
  8. package/.agent/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
  9. package/.agent/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
  10. package/.agent/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
  11. package/.agent/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
  12. package/.agent/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
  13. package/.agent/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
  14. package/.agent/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
  15. package/.agent/skills/agent-native-architecture/references/product-implications.md +443 -0
  16. package/.agent/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
  17. package/.agent/skills/agent-native-architecture/references/self-modification.md +269 -0
  18. package/.agent/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
  19. package/.agent/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
  20. package/.agent/skills/agent-native-reviewer/SKILL.md +246 -0
  21. package/.agent/skills/andrew-kane-gem-writer/SKILL.md +184 -0
  22. package/.agent/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  23. package/.agent/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  24. package/.agent/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  25. package/.agent/skills/andrew-kane-gem-writer/references/resources.md +119 -0
  26. package/.agent/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  27. package/.agent/skills/ankane-readme-writer/SKILL.md +50 -0
  28. package/.agent/skills/architecture-strategist/SKILL.md +52 -0
  29. package/.agent/skills/best-practices-researcher/SKILL.md +100 -0
  30. package/.agent/skills/bug-reproduction-validator/SKILL.md +67 -0
  31. package/.agent/skills/code-simplicity-reviewer/SKILL.md +85 -0
  32. package/.agent/skills/coding-tutor/.claude-plugin/plugin.json +9 -0
  33. package/.agent/skills/coding-tutor/README.md +37 -0
  34. package/.agent/skills/coding-tutor/commands/quiz-me.md +1 -0
  35. package/.agent/skills/coding-tutor/commands/sync-tutorials.md +25 -0
  36. package/.agent/skills/coding-tutor/commands/teach-me.md +1 -0
  37. package/.agent/skills/coding-tutor/skills/coding-tutor/SKILL.md +214 -0
  38. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/create_tutorial.py +202 -0
  39. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/index_tutorials.py +203 -0
  40. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/quiz_priority.py +190 -0
  41. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/setup_tutorials.py +132 -0
  42. package/.agent/skills/compound-docs/SKILL.md +510 -0
  43. package/.agent/skills/compound-docs/assets/critical-pattern-template.md +34 -0
  44. package/.agent/skills/compound-docs/assets/resolution-template.md +93 -0
  45. package/.agent/skills/compound-docs/references/yaml-schema.md +65 -0
  46. package/.agent/skills/compound-docs/schema.yaml +176 -0
  47. package/.agent/skills/create-agent-skills/SKILL.md +299 -0
  48. package/.agent/skills/create-agent-skills/references/api-security.md +226 -0
  49. package/.agent/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
  50. package/.agent/skills/create-agent-skills/references/best-practices.md +404 -0
  51. package/.agent/skills/create-agent-skills/references/common-patterns.md +595 -0
  52. package/.agent/skills/create-agent-skills/references/core-principles.md +437 -0
  53. package/.agent/skills/create-agent-skills/references/executable-code.md +175 -0
  54. package/.agent/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
  55. package/.agent/skills/create-agent-skills/references/official-spec.md +185 -0
  56. package/.agent/skills/create-agent-skills/references/recommended-structure.md +168 -0
  57. package/.agent/skills/create-agent-skills/references/skill-structure.md +372 -0
  58. package/.agent/skills/create-agent-skills/references/using-scripts.md +113 -0
  59. package/.agent/skills/create-agent-skills/references/using-templates.md +112 -0
  60. package/.agent/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
  61. package/.agent/skills/create-agent-skills/templates/router-skill.md +73 -0
  62. package/.agent/skills/create-agent-skills/templates/simple-skill.md +33 -0
  63. package/.agent/skills/create-agent-skills/workflows/add-reference.md +96 -0
  64. package/.agent/skills/create-agent-skills/workflows/add-script.md +93 -0
  65. package/.agent/skills/create-agent-skills/workflows/add-template.md +74 -0
  66. package/.agent/skills/create-agent-skills/workflows/add-workflow.md +120 -0
  67. package/.agent/skills/create-agent-skills/workflows/audit-skill.md +138 -0
  68. package/.agent/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
  69. package/.agent/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
  70. package/.agent/skills/create-agent-skills/workflows/get-guidance.md +121 -0
  71. package/.agent/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
  72. package/.agent/skills/create-agent-skills/workflows/verify-skill.md +204 -0
  73. package/.agent/skills/data-integrity-guardian/SKILL.md +70 -0
  74. package/.agent/skills/data-migration-expert/SKILL.md +97 -0
  75. package/.agent/skills/deployment-verification-agent/SKILL.md +159 -0
  76. package/.agent/skills/design-implementation-reviewer/SKILL.md +85 -0
  77. package/.agent/skills/design-iterator/SKILL.md +197 -0
  78. package/.agent/skills/dhh-rails-reviewer/SKILL.md +45 -0
  79. package/.agent/skills/dhh-rails-style/SKILL.md +184 -0
  80. package/.agent/skills/dhh-rails-style/references/architecture.md +653 -0
  81. package/.agent/skills/dhh-rails-style/references/controllers.md +303 -0
  82. package/.agent/skills/dhh-rails-style/references/frontend.md +510 -0
  83. package/.agent/skills/dhh-rails-style/references/gems.md +266 -0
  84. package/.agent/skills/dhh-rails-style/references/models.md +359 -0
  85. package/.agent/skills/dhh-rails-style/references/testing.md +338 -0
  86. package/.agent/skills/dspy-ruby/SKILL.md +594 -0
  87. package/.agent/skills/dspy-ruby/assets/config-template.rb +359 -0
  88. package/.agent/skills/dspy-ruby/assets/module-template.rb +326 -0
  89. package/.agent/skills/dspy-ruby/assets/signature-template.rb +143 -0
  90. package/.agent/skills/dspy-ruby/references/core-concepts.md +265 -0
  91. package/.agent/skills/dspy-ruby/references/optimization.md +623 -0
  92. package/.agent/skills/dspy-ruby/references/providers.md +305 -0
  93. package/.agent/skills/every-style-editor/SKILL.md +134 -0
  94. package/.agent/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  95. package/.agent/skills/figma-design-sync/SKILL.md +166 -0
  96. package/.agent/skills/file-todos/SKILL.md +251 -0
  97. package/.agent/skills/file-todos/assets/todo-template.md +155 -0
  98. package/.agent/skills/framework-docs-researcher/SKILL.md +83 -0
  99. package/.agent/skills/frontend-design/SKILL.md +42 -0
  100. package/.agent/skills/gemini-imagegen/SKILL.md +237 -0
  101. package/.agent/skills/gemini-imagegen/requirements.txt +2 -0
  102. package/.agent/skills/gemini-imagegen/scripts/compose_images.py +168 -0
  103. package/.agent/skills/gemini-imagegen/scripts/edit_image.py +157 -0
  104. package/.agent/skills/gemini-imagegen/scripts/gemini_images.py +265 -0
  105. package/.agent/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  106. package/.agent/skills/gemini-imagegen/scripts/multi_turn_chat.py +215 -0
  107. package/.agent/skills/git-history-analyzer/SKILL.md +42 -0
  108. package/.agent/skills/git-worktree/SKILL.md +302 -0
  109. package/.agent/skills/git-worktree/scripts/worktree-manager.sh +345 -0
  110. package/.agent/skills/julik-frontend-races-reviewer/SKILL.md +222 -0
  111. package/.agent/skills/kieran-python-reviewer/SKILL.md +104 -0
  112. package/.agent/skills/kieran-rails-reviewer/SKILL.md +86 -0
  113. package/.agent/skills/kieran-typescript-reviewer/SKILL.md +95 -0
  114. package/.agent/skills/lint/SKILL.md +16 -0
  115. package/.agent/skills/pattern-recognition-specialist/SKILL.md +57 -0
  116. package/.agent/skills/performance-oracle/SKILL.md +110 -0
  117. package/.agent/skills/pr-comment-resolver/SKILL.md +69 -0
  118. package/.agent/skills/rclone/SKILL.md +150 -0
  119. package/.agent/skills/rclone/scripts/check_setup.sh +60 -0
  120. package/.agent/skills/repo-research-analyst/SKILL.md +113 -0
  121. package/.agent/skills/security-sentinel/SKILL.md +93 -0
  122. package/.agent/skills/skill-creator/SKILL.md +209 -0
  123. package/.agent/skills/skill-creator/scripts/init_skill.py +304 -0
  124. package/.agent/skills/skill-creator/scripts/package_skill.py +112 -0
  125. package/.agent/skills/skill-creator/scripts/quick_validate.py +72 -0
  126. package/.agent/skills/spec-flow-analyzer/SKILL.md +113 -0
  127. package/.agent/skills/test-agent/SKILL.md +4 -0
  128. package/.agent/workflows/agent-native-audit.md +277 -0
  129. package/.agent/workflows/ask-user-question.md +21 -0
  130. package/.agent/workflows/changelog.md +137 -0
  131. package/.agent/workflows/compound.md +202 -0
  132. package/.agent/workflows/create-agent-skill.md +8 -0
  133. package/.agent/workflows/deepen-plan-research.md +334 -0
  134. package/.agent/workflows/deepen-plan-synthesis.md +182 -0
  135. package/.agent/workflows/deepen-plan.md +79 -0
  136. package/.agent/workflows/feature-video.md +342 -0
  137. package/.agent/workflows/generate-command.md +162 -0
  138. package/.agent/workflows/heal-skill.md +142 -0
  139. package/.agent/workflows/lfg.md +20 -0
  140. package/.agent/workflows/plan-analysis.md +67 -0
  141. package/.agent/workflows/plan-next-steps.md +63 -0
  142. package/.agent/workflows/plan-review.md +33 -0
  143. package/.agent/workflows/plan-synthesis.md +106 -0
  144. package/.agent/workflows/plan.md +49 -0
  145. package/.agent/workflows/report-bug.md +150 -0
  146. package/.agent/workflows/reproduce-bug.md +99 -0
  147. package/.agent/workflows/resolve-parallel.md +34 -0
  148. package/.agent/workflows/resolve-pr-parallel.md +49 -0
  149. package/.agent/workflows/resolve-todo-parallel.md +35 -0
  150. package/.agent/workflows/review-analysis.md +145 -0
  151. package/.agent/workflows/review-synthesis.md +262 -0
  152. package/.agent/workflows/review.md +64 -0
  153. package/.agent/workflows/ship.md +90 -0
  154. package/.agent/workflows/test-command.md +3 -0
  155. package/.agent/workflows/triage.md +310 -0
  156. package/.agent/workflows/work.md +157 -0
  157. package/.agent/workflows/xcode-test.md +332 -0
  158. package/LICENSE +22 -0
  159. package/README.md +49 -0
  160. package/bin/ag-cortex.js +54 -0
  161. package/lib/core.js +165 -0
  162. package/package.json +31 -0
@@ -0,0 +1,506 @@
1
+ <overview>
2
+ How to design MCP tools following prompt-native principles. Tools should be primitives that enable capability, not workflows that encode decisions.
3
+
4
+ **Core principle:** Whatever a user can do, the agent should be able to do. Don't artificially limit the agent—give it the same primitives a power user would have.
5
+ </overview>
6
+
7
+ <principle name="primitives-not-workflows">
8
+ ## Tools Are Primitives, Not Workflows
9
+
10
+ **Wrong approach:** Tools that encode business logic
11
+ ```typescript
12
+ tool("process_feedback", {
13
+ feedback: z.string(),
14
+ category: z.enum(["bug", "feature", "question"]),
15
+ priority: z.enum(["low", "medium", "high"]),
16
+ }, async ({ feedback, category, priority }) => {
17
+ // Tool decides how to process
18
+ const processed = categorize(feedback);
19
+ const stored = await saveToDatabase(processed);
20
+ const notification = await notify(priority);
21
+ return { processed, stored, notification };
22
+ });
23
+ ```
24
+
25
+ **Right approach:** Primitives that enable any workflow
26
+ ```typescript
27
+ tool("store_item", {
28
+ key: z.string(),
29
+ value: z.any(),
30
+ }, async ({ key, value }) => {
31
+ await db.set(key, value);
32
+ return { text: `Stored ${key}` };
33
+ });
34
+
35
+ tool("send_message", {
36
+ channel: z.string(),
37
+ content: z.string(),
38
+ }, async ({ channel, content }) => {
39
+ await messenger.send(channel, content);
40
+ return { text: "Sent" };
41
+ });
42
+ ```
43
+
44
+ The agent decides categorization, priority, and when to notify based on the system prompt.
45
+ </principle>
46
+
47
+ <principle name="descriptive-names">
48
+ ## Tools Should Have Descriptive, Primitive Names
49
+
50
+ Names should describe the capability, not the use case:
51
+
52
+ | Wrong | Right |
53
+ |-------|-------|
54
+ | `process_user_feedback` | `store_item` |
55
+ | `create_feedback_summary` | `write_file` |
56
+ | `send_notification` | `send_message` |
57
+ | `deploy_to_production` | `git_push` |
58
+
59
+ The prompt tells the agent *when* to use primitives. The tool just provides *capability*.
60
+ </principle>
61
+
62
+ <principle name="simple-inputs">
63
+ ## Inputs Should Be Simple
64
+
65
+ Tools accept data. They don't accept decisions.
66
+
67
+ **Wrong:** Tool accepts decisions
68
+ ```typescript
69
+ tool("format_content", {
70
+ content: z.string(),
71
+ format: z.enum(["markdown", "html", "json"]),
72
+ style: z.enum(["formal", "casual", "technical"]),
73
+ }, ...)
74
+ ```
75
+
76
+ **Right:** Tool accepts data, agent decides format
77
+ ```typescript
78
+ tool("write_file", {
79
+ path: z.string(),
80
+ content: z.string(),
81
+ }, ...)
82
+ // Agent decides to write index.html with HTML content, or data.json with JSON
83
+ ```
84
+ </principle>
85
+
86
+ <principle name="rich-outputs">
87
+ ## Outputs Should Be Rich
88
+
89
+ Return enough information for the agent to verify and iterate.
90
+
91
+ **Wrong:** Minimal output
92
+ ```typescript
93
+ async ({ key }) => {
94
+ await db.delete(key);
95
+ return { text: "Deleted" };
96
+ }
97
+ ```
98
+
99
+ **Right:** Rich output
100
+ ```typescript
101
+ async ({ key }) => {
102
+ const existed = await db.has(key);
103
+ if (!existed) {
104
+ return { text: `Key ${key} did not exist` };
105
+ }
106
+ await db.delete(key);
107
+ return { text: `Deleted ${key}. ${await db.count()} items remaining.` };
108
+ }
109
+ ```
110
+ </principle>
111
+
112
+ <design_template>
113
+ ## Tool Design Template
114
+
115
+ ```typescript
116
+ import { createSdkMcpServer, tool } from "@antigravity/agent-sdk";
117
+ import { z } from "zod";
118
+
119
+ export const serverName = createSdkMcpServer({
120
+ name: "server-name",
121
+ version: "1.0.0",
122
+ tools: [
123
+ // READ operations
124
+ tool(
125
+ "read_item",
126
+ "Read an item by key",
127
+ { key: z.string().describe("Item key") },
128
+ async ({ key }) => {
129
+ const item = await storage.get(key);
130
+ return {
131
+ content: [{
132
+ type: "text",
133
+ text: item ? JSON.stringify(item, null, 2) : `Not found: ${key}`,
134
+ }],
135
+ isError: !item,
136
+ };
137
+ }
138
+ ),
139
+
140
+ tool(
141
+ "list_items",
142
+ "List all items, optionally filtered",
143
+ {
144
+ prefix: z.string().optional().describe("Filter by key prefix"),
145
+ limit: z.number().default(100).describe("Max items"),
146
+ },
147
+ async ({ prefix, limit }) => {
148
+ const items = await storage.list({ prefix, limit });
149
+ return {
150
+ content: [{
151
+ type: "text",
152
+ text: `Found ${items.length} items:\n${items.map(i => i.key).join("\n")}`,
153
+ }],
154
+ };
155
+ }
156
+ ),
157
+
158
+ // WRITE operations
159
+ tool(
160
+ "store_item",
161
+ "Store an item",
162
+ {
163
+ key: z.string().describe("Item key"),
164
+ value: z.any().describe("Item data"),
165
+ },
166
+ async ({ key, value }) => {
167
+ await storage.set(key, value);
168
+ return {
169
+ content: [{ type: "text", text: `Stored ${key}` }],
170
+ };
171
+ }
172
+ ),
173
+
174
+ tool(
175
+ "delete_item",
176
+ "Delete an item",
177
+ { key: z.string().describe("Item key") },
178
+ async ({ key }) => {
179
+ const existed = await storage.delete(key);
180
+ return {
181
+ content: [{
182
+ type: "text",
183
+ text: existed ? `Deleted ${key}` : `${key} did not exist`,
184
+ }],
185
+ };
186
+ }
187
+ ),
188
+
189
+ // EXTERNAL operations
190
+ tool(
191
+ "call_api",
192
+ "Make an HTTP request",
193
+ {
194
+ url: z.string().url(),
195
+ method: z.enum(["GET", "POST", "PUT", "DELETE"]).default("GET"),
196
+ body: z.any().optional(),
197
+ },
198
+ async ({ url, method, body }) => {
199
+ const response = await fetch(url, { method, body: JSON.stringify(body) });
200
+ const text = await response.text();
201
+ return {
202
+ content: [{
203
+ type: "text",
204
+ text: `${response.status} ${response.statusText}\n\n${text}`,
205
+ }],
206
+ isError: !response.ok,
207
+ };
208
+ }
209
+ ),
210
+ ],
211
+ });
212
+ ```
213
+ </design_template>
214
+
215
+ <example name="feedback-server">
216
+ ## Example: Feedback Storage Server
217
+
218
+ This server provides primitives for storing feedback. It does NOT decide how to categorize or organize feedback—that's the agent's job via the prompt.
219
+
220
+ ```typescript
221
+ export const feedbackMcpServer = createSdkMcpServer({
222
+ name: "feedback",
223
+ version: "1.0.0",
224
+ tools: [
225
+ tool(
226
+ "store_feedback",
227
+ "Store a feedback item",
228
+ {
229
+ item: z.object({
230
+ id: z.string(),
231
+ author: z.string(),
232
+ content: z.string(),
233
+ importance: z.number().min(1).max(5),
234
+ timestamp: z.string(),
235
+ status: z.string().optional(),
236
+ urls: z.array(z.string()).optional(),
237
+ metadata: z.any().optional(),
238
+ }).describe("Feedback item"),
239
+ },
240
+ async ({ item }) => {
241
+ await db.feedback.insert(item);
242
+ return {
243
+ content: [{
244
+ type: "text",
245
+ text: `Stored feedback ${item.id} from ${item.author}`,
246
+ }],
247
+ };
248
+ }
249
+ ),
250
+
251
+ tool(
252
+ "list_feedback",
253
+ "List feedback items",
254
+ {
255
+ limit: z.number().default(50),
256
+ status: z.string().optional(),
257
+ },
258
+ async ({ limit, status }) => {
259
+ const items = await db.feedback.list({ limit, status });
260
+ return {
261
+ content: [{
262
+ type: "text",
263
+ text: JSON.stringify(items, null, 2),
264
+ }],
265
+ };
266
+ }
267
+ ),
268
+
269
+ tool(
270
+ "update_feedback",
271
+ "Update a feedback item",
272
+ {
273
+ id: z.string(),
274
+ updates: z.object({
275
+ status: z.string().optional(),
276
+ importance: z.number().optional(),
277
+ metadata: z.any().optional(),
278
+ }),
279
+ },
280
+ async ({ id, updates }) => {
281
+ await db.feedback.update(id, updates);
282
+ return {
283
+ content: [{ type: "text", text: `Updated ${id}` }],
284
+ };
285
+ }
286
+ ),
287
+ ],
288
+ });
289
+ ```
290
+
291
+ The system prompt then tells the agent *how* to use these primitives:
292
+
293
+ ```markdown
294
+ ## Feedback Processing
295
+
296
+ When someone shares feedback:
297
+ 1. Extract author, content, and any URLs
298
+ 2. Rate importance 1-5 based on actionability
299
+ 3. Store using feedback.store_feedback
300
+ 4. If high importance (4-5), notify the channel
301
+
302
+ Use your judgment about importance ratings.
303
+ ```
304
+ </example>
305
+
306
+ <principle name="dynamic-capability-discovery">
307
+ ## Dynamic Capability Discovery vs Static Tool Mapping
308
+
309
+ **This pattern is specifically for agent-native apps** where you want the agent to have full access to an external API—the same access a user would have. It follows the core agent-native principle: "Whatever the user can do, the agent can do."
310
+
311
+ If you're building a constrained agent with limited capabilities, static tool mapping may be intentional. But for agent-native apps integrating with HealthKit, HomeKit, GraphQL, or similar APIs:
312
+
313
+ **Static Tool Mapping (Anti-pattern for Agent-Native):**
314
+ Build individual tools for each API capability. Always out of date, limits agent to only what you anticipated.
315
+
316
+ ```typescript
317
+ // ❌ Static: Every API type needs a hardcoded tool
318
+ tool("read_steps", async ({ startDate, endDate }) => {
319
+ return healthKit.query(HKQuantityType.stepCount, startDate, endDate);
320
+ });
321
+
322
+ tool("read_heart_rate", async ({ startDate, endDate }) => {
323
+ return healthKit.query(HKQuantityType.heartRate, startDate, endDate);
324
+ });
325
+
326
+ tool("read_sleep", async ({ startDate, endDate }) => {
327
+ return healthKit.query(HKCategoryType.sleepAnalysis, startDate, endDate);
328
+ });
329
+
330
+ // When HealthKit adds glucose tracking... you need a code change
331
+ ```
332
+
333
+ **Dynamic Capability Discovery (Preferred):**
334
+ Build a meta-tool that discovers what's available, and a generic tool that can access anything.
335
+
336
+ ```typescript
337
+ // ✅ Dynamic: Agent discovers and uses any capability
338
+
339
+ // Discovery tool - returns what's available at runtime
340
+ tool("list_available_capabilities", async () => {
341
+ const quantityTypes = await healthKit.availableQuantityTypes();
342
+ const categoryTypes = await healthKit.availableCategoryTypes();
343
+
344
+ return {
345
+ text: `Available health metrics:\n` +
346
+ `Quantity types: ${quantityTypes.join(", ")}\n` +
347
+ `Category types: ${categoryTypes.join(", ")}\n` +
348
+ `\nUse read_health_data with any of these types.`
349
+ };
350
+ });
351
+
352
+ // Generic access tool - type is a string, API validates
353
+ tool("read_health_data", {
354
+ dataType: z.string(), // NOT z.enum - let HealthKit validate
355
+ startDate: z.string(),
356
+ endDate: z.string(),
357
+ aggregation: z.enum(["sum", "average", "samples"]).optional()
358
+ }, async ({ dataType, startDate, endDate, aggregation }) => {
359
+ // HealthKit validates the type, returns helpful error if invalid
360
+ const result = await healthKit.query(dataType, startDate, endDate, aggregation);
361
+ return { text: JSON.stringify(result, null, 2) };
362
+ });
363
+ ```
364
+
365
+ **When to Use Each Approach:**
366
+
367
+ | Dynamic (Agent-Native) | Static (Constrained Agent) |
368
+ |------------------------|---------------------------|
369
+ | Agent should access anything user can | Agent has intentionally limited scope |
370
+ | External API with many endpoints (HealthKit, HomeKit, GraphQL) | Internal domain with fixed operations |
371
+ | API evolves independently of your code | Tightly coupled domain logic |
372
+ | You want full action parity | You want strict guardrails |
373
+
374
+ **The agent-native default is Dynamic.** Only use Static when you're intentionally limiting the agent's capabilities.
375
+
376
+ **Complete Dynamic Pattern:**
377
+
378
+ ```swift
379
+ // 1. Discovery tool: What can I access?
380
+ tool("list_health_types", "Get available health data types") { _ in
381
+ let store = HKHealthStore()
382
+
383
+ let quantityTypes = HKQuantityTypeIdentifier.allCases.map { $0.rawValue }
384
+ let categoryTypes = HKCategoryTypeIdentifier.allCases.map { $0.rawValue }
385
+ let characteristicTypes = HKCharacteristicTypeIdentifier.allCases.map { $0.rawValue }
386
+
387
+ return ToolResult(text: """
388
+ Available HealthKit types:
389
+
390
+ ## Quantity Types (numeric values)
391
+ \(quantityTypes.joined(separator: ", "))
392
+
393
+ ## Category Types (categorical data)
394
+ \(categoryTypes.joined(separator: ", "))
395
+
396
+ ## Characteristic Types (user info)
397
+ \(characteristicTypes.joined(separator: ", "))
398
+
399
+ Use read_health_data or write_health_data with any of these.
400
+ """)
401
+ }
402
+
403
+ // 2. Generic read: Access any type by name
404
+ tool("read_health_data", "Read any health metric", {
405
+ dataType: z.string().describe("Type name from list_health_types"),
406
+ startDate: z.string(),
407
+ endDate: z.string()
408
+ }) { request in
409
+ // Let HealthKit validate the type name
410
+ guard let type = HKQuantityTypeIdentifier(rawValue: request.dataType)
411
+ ?? HKCategoryTypeIdentifier(rawValue: request.dataType) else {
412
+ return ToolResult(
413
+ text: "Unknown type: \(request.dataType). Use list_health_types to see available types.",
414
+ isError: true
415
+ )
416
+ }
417
+
418
+ let samples = try await healthStore.querySamples(type: type, start: startDate, end: endDate)
419
+ return ToolResult(text: samples.formatted())
420
+ }
421
+
422
+ // 3. Context injection: Tell agent what's available in system prompt
423
+ func buildSystemPrompt() -> String {
424
+ let availableTypes = healthService.getAuthorizedTypes()
425
+
426
+ return """
427
+ ## Available Health Data
428
+
429
+ You have access to these health metrics:
430
+ \(availableTypes.map { "- \($0)" }.joined(separator: "\n"))
431
+
432
+ Use read_health_data with any type above. For new types not listed,
433
+ use list_health_types to discover what's available.
434
+ """
435
+ }
436
+ ```
437
+
438
+ **Benefits:**
439
+ - Agent can use any API capability, including ones added after your code shipped
440
+ - API is the validator, not your enum definition
441
+ - Smaller tool surface (2-3 tools vs N tools)
442
+ - Agent naturally discovers capabilities by asking
443
+ - Works with any API that has introspection (HealthKit, GraphQL, OpenAPI)
444
+ </principle>
445
+
446
+ <principle name="crud-completeness">
447
+ ## CRUD Completeness
448
+
449
+ Every data type the agent can create, it should be able to read, update, and delete. Incomplete CRUD = broken action parity.
450
+
451
+ **Anti-pattern: Create-only tools**
452
+ ```typescript
453
+ // ❌ Can create but not modify or delete
454
+ tool("create_experiment", { hypothesis, variable, metric })
455
+ tool("write_journal_entry", { content, author, tags })
456
+ // User: "Delete that experiment" → Agent: "I can't do that"
457
+ ```
458
+
459
+ **Correct: Full CRUD for each entity**
460
+ ```typescript
461
+ // ✅ Complete CRUD
462
+ tool("create_experiment", { hypothesis, variable, metric })
463
+ tool("read_experiment", { id })
464
+ tool("update_experiment", { id, updates: { hypothesis?, status?, endDate? } })
465
+ tool("delete_experiment", { id })
466
+
467
+ tool("create_journal_entry", { content, author, tags })
468
+ tool("read_journal", { query?, dateRange?, author? })
469
+ tool("update_journal_entry", { id, content, tags? })
470
+ tool("delete_journal_entry", { id })
471
+ ```
472
+
473
+ **The CRUD Audit:**
474
+ For each entity type in your app, verify:
475
+ - [ ] Create: Agent can create new instances
476
+ - [ ] Read: Agent can query/search/list instances
477
+ - [ ] Update: Agent can modify existing instances
478
+ - [ ] Delete: Agent can remove instances
479
+
480
+ If any operation is missing, users will eventually ask for it and the agent will fail.
481
+ </principle>
482
+
483
+ <checklist>
484
+ ## MCP Tool Design Checklist
485
+
486
+ **Fundamentals:**
487
+ - [ ] Tool names describe capability, not use case
488
+ - [ ] Inputs are data, not decisions
489
+ - [ ] Outputs are rich (enough for agent to verify)
490
+ - [ ] CRUD operations are separate tools (not one mega-tool)
491
+ - [ ] No business logic in tool implementations
492
+ - [ ] Error states clearly communicated via `isError`
493
+ - [ ] Descriptions explain what the tool does, not when to use it
494
+
495
+ **Dynamic Capability Discovery (for agent-native apps):**
496
+ - [ ] For external APIs where agent should have full access, use dynamic discovery
497
+ - [ ] Include a `list_*` or `discover_*` tool for each API surface
498
+ - [ ] Use string inputs (not enums) when the API validates
499
+ - [ ] Inject available capabilities into system prompt at runtime
500
+ - [ ] Only use static tool mapping if intentionally limiting agent scope
501
+
502
+ **CRUD Completeness:**
503
+ - [ ] Every entity has create, read, update, delete operations
504
+ - [ ] Every UI action has a corresponding agent tool
505
+ - [ ] Test: "Can the agent undo what it just did?"
506
+ </checklist>