@polymorphism-tech/morph-spec 8.38.0 → 8.40.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 (227) hide show
  1. package/CLAUDE.md +19 -8
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +60 -43
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +3 -2
  8. package/framework/MORPH.md +1 -1
  9. package/framework/agents.json +36 -25
  10. package/framework/docs/CLI.md +2 -2
  11. package/framework/evals/rubrics/code-quality.md +4 -4
  12. package/framework/evals/rubrics/condensed.md +2 -2
  13. package/framework/mcp/registry.json +33 -2
  14. package/framework/rules/infrastructure-standards.md +0 -1
  15. package/framework/rules/morph-workflow.md +9 -4
  16. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  17. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  18. package/framework/skills/core/morph-apply/SKILL.md +5 -1
  19. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  20. package/framework/skills/core/morph-eval/SKILL.md +1 -1
  21. package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
  22. package/framework/skills/core/morph-implement/SKILL.md +6 -1
  23. package/framework/skills/core/morph-media/SKILL.md +1 -1
  24. package/framework/skills/core/morph-plan/SKILL.md +4 -3
  25. package/framework/skills/core/morph-proposal/SKILL.md +1 -1
  26. package/framework/skills/core/morph-review/SKILL.md +1 -1
  27. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  28. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  29. package/framework/skills/core/morph-uiux/SKILL.md +6 -5
  30. package/framework/standards/STANDARDS.json +3 -3
  31. package/framework/standards/ai-agents/context-providers.md +16 -26
  32. package/framework/standards/ai-agents/durable-workflows-hitl.md +15 -21
  33. package/framework/standards/ai-agents/modalities-image-gen.md +21 -25
  34. package/framework/standards/ai-agents/modalities-speech-to-text.md +4 -15
  35. package/framework/standards/ai-agents/modalities-text-to-speech.md +2 -11
  36. package/framework/standards/ai-agents/modalities-vision.md +1 -18
  37. package/framework/standards/ai-agents/prompt-sources.md +0 -4
  38. package/framework/standards/architecture/code-comments.md +52 -16
  39. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +63 -50
  40. package/framework/standards/frontend/design-system/ai-image-generation.md +5 -5
  41. package/framework/standards/integration/mcp/mcp-tools.md +48 -117
  42. package/framework/templates/code/dotnet/abstractions/result.cs +0 -2
  43. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +26 -39
  44. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +28 -68
  45. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +99 -117
  46. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +2 -44
  47. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +40 -61
  48. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +54 -107
  49. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +53 -58
  50. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +192 -281
  51. package/framework/templates/code/dotnet/database/migration.cs +49 -83
  52. package/framework/templates/code/dotnet/database/vector-entity.cs +2 -46
  53. package/framework/templates/code/dotnet/extensions/result-extensions.cs +0 -2
  54. package/framework/templates/code/dotnet/feature/validator.cs.hbs +11 -15
  55. package/framework/templates/code/dotnet/jobs/agent.cs +3 -51
  56. package/framework/templates/code/dotnet/jobs/job.cs +2 -97
  57. package/framework/templates/code/dotnet/test.cs +2 -87
  58. package/framework/templates/code/typescript/contracts.ts +140 -167
  59. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +1 -48
  60. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +3 -79
  61. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +1 -70
  62. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +1 -47
  63. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +2 -99
  64. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +0 -6
  65. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +3 -88
  66. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +1 -41
  67. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +0 -21
  68. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +1 -25
  69. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +2 -63
  70. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +0 -30
  71. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +1 -52
  72. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +3 -78
  73. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +4 -109
  74. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +0 -22
  75. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +1 -36
  76. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +2 -57
  77. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +0 -75
  78. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +2 -59
  79. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +4 -111
  80. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +0 -34
  81. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +1 -57
  82. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +0 -19
  83. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +2 -74
  84. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +2 -33
  85. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +1 -43
  86. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +1 -96
  87. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +0 -13
  88. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +0 -27
  89. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +0 -33
  90. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +0 -31
  91. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +3 -75
  92. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +0 -42
  93. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +0 -39
  94. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +1 -55
  95. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +3 -59
  96. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +0 -46
  97. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +3 -28
  98. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +7 -61
  99. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +2 -37
  100. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +1 -23
  101. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +2 -82
  102. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +1 -68
  103. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +1 -62
  104. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +2 -62
  105. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +1 -25
  106. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +0 -124
  107. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +1 -73
  108. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +1 -66
  109. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +0 -41
  110. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +2 -112
  111. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +2 -43
  112. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +5 -110
  113. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +7 -103
  114. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +1 -42
  115. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +1 -30
  116. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +1 -19
  117. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +0 -48
  118. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +1 -29
  119. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +2 -38
  120. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +1 -14
  121. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +4 -69
  122. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +1 -10
  123. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +1 -57
  124. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +0 -26
  125. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +1 -19
  126. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +0 -32
  127. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +0 -14
  128. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +0 -24
  129. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +0 -32
  130. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +0 -37
  131. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +0 -24
  132. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +0 -78
  133. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +0 -53
  134. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +0 -44
  135. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +0 -44
  136. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +0 -19
  137. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +0 -24
  138. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +6 -48
  139. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +1 -13
  140. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +2 -71
  141. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +5 -100
  142. package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +39 -43
  143. package/framework/templates/frontend/nextjs/env.mjs.hbs +29 -32
  144. package/framework/templates/frontend/nextjs/page.tsx.hbs +21 -22
  145. package/framework/templates/frontend/nextjs/use-feature.ts.hbs +42 -54
  146. package/framework/templates/integrations/asaas-client.cs +332 -387
  147. package/framework/templates/integrations/asaas-webhook.cs +290 -351
  148. package/framework/templates/integrations/neon-auth-config.cs +9 -105
  149. package/framework/templates/project/validate.js +97 -120
  150. package/package.json +2 -2
  151. package/src/commands/dashboard/dashboard.js +80 -53
  152. package/src/commands/mcp/mcp-setup.js +37 -9
  153. package/src/commands/project/doctor.js +3 -5
  154. package/src/commands/project/init.js +6 -3
  155. package/src/commands/project/install-plugin-cmd.js +1 -1
  156. package/src/commands/project/update.js +5 -0
  157. package/src/dashboard/app/App.jsx +80 -16
  158. package/src/dashboard/app/components/ActivityFeed.jsx +172 -0
  159. package/src/dashboard/app/components/CommandPalette.jsx +155 -0
  160. package/src/dashboard/app/components/DetailPanel.jsx +47 -11
  161. package/src/dashboard/app/components/EntityLink.jsx +55 -0
  162. package/src/dashboard/app/components/ErrorBoundary.jsx +54 -0
  163. package/src/dashboard/app/components/FlowGraph.jsx +19 -17
  164. package/src/dashboard/app/components/KnowledgeMarkdown.jsx +53 -0
  165. package/src/dashboard/app/components/Markdown.jsx +47 -0
  166. package/src/dashboard/app/components/PhaseRail.jsx +111 -0
  167. package/src/dashboard/app/components/SearchFilter.jsx +40 -22
  168. package/src/dashboard/app/components/Sidebar.jsx +146 -37
  169. package/src/dashboard/app/hooks/useMorphQuery.js +54 -0
  170. package/src/dashboard/app/hooks/usePref.js +38 -0
  171. package/src/dashboard/app/lib/format.js +69 -0
  172. package/src/dashboard/app/lib/phases.js +56 -0
  173. package/src/dashboard/app/lib/project.js +50 -0
  174. package/src/dashboard/app/pages/Activity.jsx +24 -0
  175. package/src/dashboard/app/pages/AgentMap.jsx +371 -370
  176. package/src/dashboard/app/pages/FeatureDetail.jsx +604 -0
  177. package/src/dashboard/app/pages/Features.jsx +400 -0
  178. package/src/dashboard/app/pages/Guide.jsx +146 -0
  179. package/src/dashboard/app/pages/HookInspector.jsx +357 -322
  180. package/src/dashboard/app/pages/PhasePipeline.jsx +277 -408
  181. package/src/dashboard/app/pages/Portfolio.jsx +156 -0
  182. package/src/dashboard/app/pages/Rubrics.jsx +101 -0
  183. package/src/dashboard/app/pages/RulesMap.jsx +300 -273
  184. package/src/dashboard/app/pages/SkillsLibrary.jsx +483 -366
  185. package/src/dashboard/app/pages/Standards.jsx +407 -332
  186. package/src/dashboard/app/styles/index.css +187 -47
  187. package/src/dashboard/index.html +14 -12
  188. package/src/dashboard/package.json +32 -24
  189. package/src/dashboard/scanner/activity-scanner.js +351 -0
  190. package/src/dashboard/scanner/agents-scanner.js +59 -1
  191. package/src/dashboard/scanner/docs-scanner.js +59 -0
  192. package/src/dashboard/scanner/feature-status.js +10 -0
  193. package/src/dashboard/scanner/features-scanner.js +360 -0
  194. package/src/dashboard/scanner/index.js +14 -7
  195. package/src/dashboard/scanner/phases-scanner.js +14 -15
  196. package/src/dashboard/scanner/portfolio.js +153 -0
  197. package/src/dashboard/scanner/project-api.js +195 -0
  198. package/src/dashboard/scanner/rules-scanner.js +42 -37
  199. package/src/dashboard/scanner/skills-scanner.js +105 -43
  200. package/src/dashboard/scanner/standards-scanner.js +2 -0
  201. package/src/dashboard/vite-plugin-morph-data.js +134 -17
  202. package/src/lib/detectors/claude-config-detector.js +2 -7
  203. package/src/lib/detectors/index.js +5 -1
  204. package/src/lib/evaluator-report.js +22 -0
  205. package/src/lib/generators/settings-generator.js +208 -209
  206. package/src/lib/installers/mcp-installer.js +724 -719
  207. package/src/lib/installers/memory-installer.js +1 -2
  208. package/src/lib/projects/registry.js +154 -0
  209. package/src/lib/validators/code-budget/code-budget-validator.js +32 -4
  210. package/src/scripts/install-plugin.js +1 -1
  211. package/src/scripts/setup-infra.js +2 -4
  212. package/src/utils/agents-installer.js +57 -12
  213. package/src/utils/banner.js +1 -1
  214. package/src/commands/index.js +0 -13
  215. package/src/commands/project/checkpoint.js +0 -209
  216. package/src/core/state/phase-state-machine.js +0 -197
  217. package/src/dashboard/app/hooks/useDetailPanel.js +0 -15
  218. package/src/dashboard/app/pages/LiveState.jsx +0 -206
  219. package/src/dashboard/scanner/squads-scanner.js +0 -13
  220. package/src/dashboard/scanner/state-scanner.js +0 -85
  221. package/src/lib/generators/index.js +0 -10
  222. package/src/lib/hooks/hook-executor.js +0 -167
  223. package/src/lib/validators/checkpoint-persistence.js +0 -39
  224. package/src/lib/validators/shared/emit-validator-dispatch.js +0 -14
  225. package/src/lib/validators/shared/index.js +0 -12
  226. package/src/lib/validators/shared/issue-counter.js +0 -14
  227. package/src/lib/validators/shared/result-formatter.js +0 -124
@@ -125,16 +125,19 @@ real sign-in attempt, not after debugging a mysterious "session never sticks" bu
125
125
 
126
126
  ### SDK Initialization
127
127
 
128
+ `lib/auth/client.ts` — `createAuthClient` takes the public auth URL as a positional argument, and the
129
+ React hooks are re-exported from the client instance for ergonomic imports:
130
+
128
131
  ```typescript
129
- // lib/auth/client.ts
130
132
  'use client';
131
133
  import { createAuthClient } from '@neondatabase/auth/next';
132
- // createAuthClient takes the public auth URL as a positional argument
133
134
  export const authClient = createAuthClient(process.env.NEXT_PUBLIC_AUTH_URL!);
134
- // Re-export the React hooks from the client instance for ergonomic imports
135
135
  export const { useSession } = authClient;
136
+ ```
137
+
138
+ `lib/auth/server.ts`:
136
139
 
137
- // lib/auth/server.ts
140
+ ```typescript
138
141
  import { createNeonAuth } from '@neondatabase/auth/next/server';
139
142
  export const auth = createNeonAuth({
140
143
  baseUrl: process.env.NEON_AUTH_BASE_URL!,
@@ -152,8 +155,9 @@ Import the Tailwind styles for the UI components in `globals.css`:
152
155
  @import '@neondatabase/auth-ui/tailwind';
153
156
  ```
154
157
 
158
+ `app/providers.tsx`:
159
+
155
160
  ```tsx
156
- // app/providers.tsx
157
161
  'use client';
158
162
  import { NeonAuthUIProvider } from '@neondatabase/auth-ui';
159
163
  import { authClient } from '@/lib/auth/client';
@@ -169,8 +173,9 @@ export function Providers({ children }: { children: React.ReactNode }) {
169
173
 
170
174
  ### Auth API Route
171
175
 
176
+ `app/api/auth/[...path]/route.ts`:
177
+
172
178
  ```typescript
173
- // app/api/auth/[...path]/route.ts
174
179
  import { auth } from '@/lib/auth/server';
175
180
 
176
181
  export const { GET, POST } = auth.handler();
@@ -182,8 +187,9 @@ export const { GET, POST } = auth.handler();
182
187
 
183
188
  ### Sign In / Sign Up Pages
184
189
 
190
+ `app/auth/sign-in/page.tsx`:
191
+
185
192
  ```tsx
186
- // app/auth/sign-in/page.tsx
187
193
  import { AuthView } from '@neondatabase/auth-ui';
188
194
 
189
195
  export default function SignInPage() {
@@ -193,8 +199,11 @@ export default function SignInPage() {
193
199
  </div>
194
200
  );
195
201
  }
202
+ ```
203
+
204
+ `app/auth/sign-up/page.tsx`:
196
205
 
197
- // app/auth/sign-up/page.tsx
206
+ ```tsx
198
207
  import { AuthView } from '@neondatabase/auth-ui';
199
208
 
200
209
  export default function SignUpPage() {
@@ -208,8 +217,9 @@ export default function SignUpPage() {
208
217
 
209
218
  ### Server-Side Auth Check
210
219
 
220
+ `app/dashboard/page.tsx`:
221
+
211
222
  ```typescript
212
- // app/dashboard/page.tsx
213
223
  import { auth } from '@/lib/auth/server';
214
224
  import { redirect } from 'next/navigation';
215
225
 
@@ -228,8 +238,9 @@ export default async function DashboardPage() {
228
238
 
229
239
  ### Client Component with User Data
230
240
 
241
+ `components/UserProfile.tsx`:
242
+
231
243
  ```tsx
232
- // components/UserProfile.tsx
233
244
  'use client';
234
245
  import { useSession } from '@/lib/auth/client';
235
246
 
@@ -249,14 +260,15 @@ export function UserProfile() {
249
260
 
250
261
  ### Route Protection (Middleware)
251
262
 
263
+ `middleware.ts`. The `runtime = 'nodejs'` line is **mandatory** for any `middleware.ts` that touches
264
+ Neon Auth: Next.js middleware runs on the Edge runtime by default, and the network call the Neon Auth
265
+ SDK makes to mint the session-data cookie times out inside the Edge sandbox on `next dev` — the request
266
+ silently bounces back to sign-in even with a fully valid session, with no error surfaced.
267
+
252
268
  ```typescript
253
- // middleware.ts
254
269
  import { auth } from '@/lib/auth/server';
255
270
 
256
- // MANDATORY for any middleware.ts that touches Neon Auth. Next.js middleware runs on the Edge
257
- // runtime by default, and the network call the Neon Auth SDK makes to mint the session-data cookie
258
- // times out inside the Edge sandbox on `next dev` — the request silently bounces back to sign-in
259
- // even with a fully valid session, with no error surfaced. Force the Node.js runtime instead.
271
+ // Mandatory: on the Edge runtime the SDK's session-cookie call times out and silently bounces to sign-in.
260
272
  export const runtime = 'nodejs';
261
273
 
262
274
  export default auth.middleware({
@@ -294,7 +306,6 @@ export default function ProtectedPage() {
294
306
  ## OAuth (Social Login)
295
307
 
296
308
  ```typescript
297
- // Trigger OAuth sign-in
298
309
  await authClient.signIn.social({
299
310
  provider: 'google',
300
311
  callbackURL: 'http://localhost:3000/auth/callback',
@@ -307,8 +318,9 @@ Configure OAuth providers in the Neon Console under Auth > Configuration.
307
318
 
308
319
  ## API Route Protection
309
320
 
321
+ `app/api/protected/route.ts`:
322
+
310
323
  ```typescript
311
- // app/api/protected/route.ts
312
324
  import { auth } from '@/lib/auth/server';
313
325
 
314
326
  export const dynamic = 'force-dynamic';
@@ -348,34 +360,38 @@ backend's real prefix and the proxy's public prefix don't happen to match charac
348
360
  because this is a runtime routing mismatch (404, or the proxy calling itself), it **never shows up at
349
361
  build time**, only when a human clicks the page.
350
362
 
363
+ `lib/api/prefixes.ts` — `BACKEND_API_PREFIX` is used ONLY by Server Components / Route Handlers
364
+ calling the .NET backend directly (e.g. `https://api.example.com`; the backend's own routes have NO
365
+ `/api` prefix); `PROXY_API_PREFIX` is used ONLY by Client Components calling the same-origin Next.js
366
+ proxy, and matches `app/api/proxy/[...path]/route.ts`:
367
+
351
368
  ```typescript
352
- // lib/api/prefixes.ts
353
- // BACKEND_API_PREFIX: used ONLY by Server Components / Route Handlers calling the .NET backend directly.
354
- export const BACKEND_API_PREFIX = process.env.API_URL; // e.g. https://api.example.com — backend's own routes have NO /api prefix
369
+ export const BACKEND_API_PREFIX = process.env.API_URL;
355
370
 
356
- // PROXY_API_PREFIX: used ONLY by Client Components calling the same-origin Next.js proxy.
357
- export const PROXY_API_PREFIX = '/api/proxy'; // matches app/api/proxy/[...path]/route.ts
371
+ export const PROXY_API_PREFIX = '/api/proxy';
358
372
  ```
359
373
 
374
+ The two call sites below — `app/(dashboard)/catalog/page.tsx`, a Server Component calling the backend
375
+ directly, and `features/catalog/hooks/use-items.ts`, a Client Component going through the same-origin
376
+ proxy — MUST resolve to the same backend route:
377
+
360
378
  ```typescript
361
- // app/(dashboard)/catalog/page.tsx — Server Component, direct backend call
362
379
  import { BACKEND_API_PREFIX } from '@/lib/api/prefixes';
363
380
 
364
381
  async function getItems() {
365
- // cross-reference: PROXY_API_PREFIX below MUST resolve to the same backend route
366
382
  const res = await fetch(`${BACKEND_API_PREFIX}/catalog/items`, { next: { revalidate: 60 } });
367
383
  return res.json();
368
384
  }
369
385
  ```
370
386
 
387
+ `features/catalog/hooks/use-items.ts`:
388
+
371
389
  ```typescript
372
- // features/catalog/hooks/use-items.ts — Client Component, via same-origin proxy
373
390
  import { PROXY_API_PREFIX } from '@/lib/api/prefixes';
374
391
 
375
392
  export function useItems() {
376
393
  return useQuery({
377
394
  queryKey: ['catalog', 'items'],
378
- // cross-reference: BACKEND_API_PREFIX above MUST resolve to the same backend route
379
395
  queryFn: async () => (await fetch(`${PROXY_API_PREFIX}/catalog/items`)).json(),
380
396
  });
381
397
  }
@@ -435,31 +451,30 @@ Before marking any task that adds or touches an endpoint as done:
435
451
 
436
452
  ### JWT Bearer Configuration
437
453
 
454
+ `Infrastructure/Auth/NeonAuthOptions.cs` — `BaseUrl` is the Neon Auth Base URL, e.g.
455
+ `https://ep-xxx.neonauth.us-east-2.aws.neon.build/neondb/auth`:
456
+
438
457
  ```csharp
439
- // Infrastructure/Auth/NeonAuthOptions.cs
440
458
  namespace {ProjectName}.Infrastructure.Auth;
441
459
 
442
460
  public sealed class NeonAuthOptions
443
461
  {
444
462
  public const string SectionName = "NeonAuth";
445
463
 
446
- /// <summary>Neon Auth Base URL, e.g. https://ep-xxx.neonauth.us-east-2.aws.neon.build/neondb/auth</summary>
447
464
  public string BaseUrl { get; set; } = string.Empty;
448
465
  }
449
466
  ```
450
467
 
468
+ `Infrastructure/Auth/NeonAuthJwksProvider.cs` fetches and caches Neon Auth's raw JWKS
469
+ (`/.well-known/jwks.json` — there is no OIDC discovery document) for 15 minutes; an unknown `kid`
470
+ forces one refresh, to survive key rotation without waiting out the TTL:
471
+
451
472
  ```csharp
452
- // Infrastructure/Auth/NeonAuthJwksProvider.cs
453
473
  namespace {ProjectName}.Infrastructure.Auth;
454
474
 
455
475
  using Microsoft.Extensions.Options;
456
476
  using Microsoft.IdentityModel.Tokens;
457
477
 
458
- /// <summary>
459
- /// Fetches and caches Neon Auth's raw JWKS (/.well-known/jwks.json — there is no OIDC discovery
460
- /// document). Cached for 15 minutes; a forced refresh happens once when an unknown `kid` is seen,
461
- /// to survive key rotation without waiting out the TTL.
462
- /// </summary>
463
478
  public sealed class NeonAuthJwksProvider(HttpClient httpClient, IOptions<NeonAuthOptions> options)
464
479
  {
465
480
  private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(15);
@@ -473,7 +488,7 @@ public sealed class NeonAuthJwksProvider(HttpClient httpClient, IOptions<NeonAut
473
488
  var key = keySet.Keys.FirstOrDefault(k => k.Kid == kid);
474
489
  if (key is not null) return key;
475
490
 
476
- // Unknown kid — could be key rotation. Force a single refresh before giving up.
491
+ // Unknown kid may be key rotation: refresh once before giving up.
477
492
  keySet = await GetKeySetAsync(forceRefresh: true, cancellationToken);
478
493
  return keySet.Keys.FirstOrDefault(k => k.Kid == kid);
479
494
  }
@@ -503,8 +518,9 @@ public sealed class NeonAuthJwksProvider(HttpClient httpClient, IOptions<NeonAut
503
518
  }
504
519
  ```
505
520
 
521
+ `Infrastructure/Auth/NeonAuthServiceExtensions.cs`:
522
+
506
523
  ```csharp
507
- // Infrastructure/Auth/NeonAuthServiceExtensions.cs
508
524
  namespace {ProjectName}.Infrastructure.Auth;
509
525
 
510
526
  using System.Text;
@@ -527,9 +543,7 @@ public static class NeonAuthServiceExtensions
527
543
  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
528
544
  .AddJwtBearer(options =>
529
545
  {
530
- // Do NOT set options.Authority — Neon Auth serves no /.well-known/openid-configuration,
531
- // so Authority-driven metadata refresh has nothing valid to fetch. ValidIssuer is set
532
- // explicitly below instead.
546
+ // No options.Authority: Neon Auth serves no OIDC discovery document, so ValidIssuer is explicit.
533
547
  options.TokenValidationParameters = new TokenValidationParameters
534
548
  {
535
549
  ValidateIssuer = true,
@@ -537,14 +551,12 @@ public static class NeonAuthServiceExtensions
537
551
  ValidateAudience = false,
538
552
  ValidateLifetime = true,
539
553
  NameClaimType = "sub",
540
- // Trust in the signing key is established entirely inside SignatureValidator
541
- // below (fetched from our own cached JWKS) — this flag doesn't gate that path.
554
+ // Key trust is established inside SignatureValidator below; this flag doesn't gate that path.
542
555
  ValidateIssuerSigningKey = false,
543
556
  };
544
557
  });
545
558
 
546
- // A second Configure<TDep> pass with DI available — AddJwtBearer's own setup has already run,
547
- // so this only *adds* the SignatureValidator to the TokenValidationParameters built above.
559
+ // Runs after AddJwtBearer's own setup, with DI available: it only adds the SignatureValidator.
548
560
  services.AddOptions<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
549
561
  .Configure<NeonAuthJwksProvider>((options, jwks) =>
550
562
  {
@@ -561,9 +573,7 @@ public static class NeonAuthServiceExtensions
561
573
  if (string.IsNullOrEmpty(kid))
562
574
  throw new SecurityTokenInvalidSignatureException("Token is missing 'kid'.");
563
575
 
564
- // Blocking call: JWKS is cached in-memory (see NeonAuthJwksProvider), so this is
565
- // I/O-free on the hot path. SignatureValidator has no async overload in this
566
- // library version — only a cold-start / key-rotation miss ever awaits real I/O here.
576
+ // Blocking is safe: SignatureValidator has no async overload and the JWKS is cached in memory.
567
577
  var jwk = jwks.GetKeyAsync(kid, CancellationToken.None).GetAwaiter().GetResult()
568
578
  ?? throw new SecurityTokenInvalidSignatureException($"No JWKS key found for kid '{kid}'.");
569
579
 
@@ -585,10 +595,7 @@ public static class NeonAuthServiceExtensions
585
595
  if (!verifier.VerifySignature(signature))
586
596
  throw new SecurityTokenInvalidSignatureException("Ed25519 signature verification failed.");
587
597
 
588
- // MUST return Microsoft.IdentityModel.JsonWebTokens.JsonWebToken — ASP.NET Core 8+
589
- // uses JsonWebTokenHandler internally. Returning a
590
- // System.IdentityModel.Tokens.Jwt.JwtSecurityToken here fails with IDX10506
591
- // ("SignatureValidator returned a token of an unexpected type").
598
+ // Must be JsonWebToken: ASP.NET Core 8+ rejects a JwtSecurityToken here with IDX10506.
592
599
  return jwt;
593
600
  };
594
601
  });
@@ -600,6 +607,12 @@ public static class NeonAuthServiceExtensions
600
607
  }
601
608
  ```
602
609
 
610
+ Two details of the validator above: it returns `Microsoft.IdentityModel.JsonWebTokens.JsonWebToken`
611
+ because ASP.NET Core 8+ uses `JsonWebTokenHandler` internally — returning a
612
+ `System.IdentityModel.Tokens.Jwt.JwtSecurityToken` fails with IDX10506 ("SignatureValidator returned a
613
+ token of an unexpected type"); and the blocking `GetResult()` is I/O-free on the hot path, since only a
614
+ cold-start or key-rotation miss ever awaits real I/O.
615
+
603
616
  ### Protected Endpoints
604
617
 
605
618
  ```csharp
@@ -43,7 +43,7 @@ Skipping this chain is the most common cause of a page whose images do not feel
43
43
 
44
44
  ```javascript
45
45
  // Generate a new image
46
- mcp__gemini_image_mcp__generate_image({
46
+ mcp__gemini-image-mcp__generate_image({
47
47
  prompt: string, // Text description (max 5000 chars, narrative style)
48
48
  aspectRatio?: "1:1" | "2:3" | "3:2" | "3:4" | "4:3" | "9:16" | "16:9",
49
49
  outputPath?: string, // File path to save (e.g., "public/images/feature/hero.png")
@@ -51,25 +51,25 @@ mcp__gemini_image_mcp__generate_image({
51
51
  })
52
52
 
53
53
  // Edit an existing image
54
- mcp__gemini_image_mcp__edit_image({
54
+ mcp__gemini-image-mcp__edit_image({
55
55
  imageSource: string, // Path to image or image ID
56
56
  prompt: string, // Short, targeted edit instructions (1-2 sentences)
57
57
  outputPath?: string,
58
58
  })
59
59
 
60
60
  // Continue editing last image
61
- mcp__gemini_image_mcp__continue_editing({
61
+ mcp__gemini-image-mcp__continue_editing({
62
62
  prompt: string, // One adjustment at a time
63
63
  })
64
64
 
65
65
  // List generated images
66
- mcp__gemini_image_mcp__list_images({
66
+ mcp__gemini-image-mcp__list_images({
67
67
  type?: "generated" | "edited" | "all",
68
68
  limit?: number,
69
69
  })
70
70
 
71
71
  // Get image details
72
- mcp__gemini_image_mcp__get_image_info({
72
+ mcp__gemini-image-mcp__get_image_info({
73
73
  imageId?: string, // Defaults to last image
74
74
  })
75
75
  ```
@@ -5,32 +5,26 @@
5
5
  > **Keywords:** mcp, model-context-protocol, mcp-tools, context7, playwright, mcp-client
6
6
  > **Load When:** an MCP tool is used in any morph-spec phase
7
7
 
8
- **Verified against:** Claude Code MCP tooling — context7, Playwright; GitHub via `gh` CLI; Neon via `neonctl`. Last-verified: 2026-07-08.
8
+ **Verified against:** Claude Code 2.1.282 MCP tooling — context7, Playwright (as plugin and as a project MCP server); GitHub via `gh` CLI; Neon via its MCP or `neonctl`. Last-verified: 2026-09-24.
9
9
 
10
10
  ---
11
11
 
12
12
  Reference for using Model Context Protocol (MCP) tools across morph-spec phases. Each phase benefits from different MCPs depending on what data is needed.
13
13
 
14
- ## MCP Availability Detection
14
+ ## Tool Names Depend on Where the Server Is Configured
15
15
 
16
- Before using any MCP tool, check if it's available in the current session:
16
+ The names below use the `.mcp.json` form, `mcp__<server>__<tool>`. The same server installed as a **plugin** is named `mcp__plugin_<plugin>_<server>__<tool>`: context7 from the plugin is `mcp__plugin_context7_context7__query-docs`, not `mcp__context7__query-docs`. Call the name that exists in your session. The tool part (`query-docs`, `browser_navigate`) is the same under both prefixes.
17
17
 
18
- ```javascript
19
- // Pattern: Attempt the call — if the tool doesn't exist, Claude Code will report it
20
- // There is no "list MCPs" command; just try the most common operation
18
+ In a morph persona the grant follows the same rule: the installer emits one `mcp__<name>` per spelling in the registry's `serverNames`, and a grant matches only its own spelling. If a tool you expect is missing, it may be deferred: load it with `ToolSearch` before calling it.
19
+
20
+ ## MCP Availability Detection
21
21
 
22
- // GitHub — o morph-spec NÃO usa MCP do GitHub: use o `gh` CLI via Bash
23
- // gh repo view --json name,defaultBranchRef,languages
22
+ Before using any MCP tool, check if it's available in the current session. There is no "list MCPs" command: attempt the most common operation, and Claude Code reports a tool that doesn't exist. GitHub and Neon are not checked this way — o morph-spec NÃO usa MCP do GitHub nem do Neon: use o `gh` CLI (`gh repo view --json name,defaultBranchRef,languages`) e o `neonctl` + `psql` (`neonctl connection-string` dá a URL do banco) via Bash.
24
23
 
25
- // Context7 (library docs)
26
- await mcp__context7__resolve_library_id({ libraryName: "react" });
24
+ ```javascript
25
+ await mcp__context7__resolve-library-id({ libraryName: "react" });
27
26
 
28
- // Playwright (browser automation)
29
27
  await mcp__playwright__browser_navigate({ url: "https://example.com" });
30
-
31
- // Neon — use `neonctl` CLI + `psql`
32
- // neonctl connection-string → get DB URL
33
- // psql <DB_URL> -c "SELECT ..."
34
28
  ```
35
29
 
36
30
  **Fallback rule:** If an MCP is not available, every phase has a manual alternative using Claude Code native tools (Read, Grep, Glob, Bash).
@@ -61,36 +55,31 @@ gh issue list --limit 10 --json title,labels
61
55
  | MCP | Use Case | Example |
62
56
  |-----|----------|---------|
63
57
  | **Playwright** | Navigate, screenshot, inspect live pages | `mcp__playwright__browser_navigate({ url })` |
64
- | **Context7** | Component library documentation | `mcp__context7__query_docs({ libraryId, query })` |
58
+ | **Context7** | Component library documentation | `mcp__context7__query-docs({ libraryId, query })` |
59
+
60
+ The screenshot is the visual reference; the snapshot is the accessibility tree (headings, buttons, inputs); the resize tests the mobile layout; Context7 brings the component docs for the UI spec.
65
61
 
66
62
  ```javascript
67
- // Screenshot existing app for design reference
68
63
  await mcp__playwright__browser_navigate({ url: "https://app.example.com/dashboard" });
69
64
  const screenshot = await mcp__playwright__browser_take_screenshot();
70
- // → Visual reference for UI/UX design
71
65
 
72
- // Inspect page structure via accessibility tree
73
66
  const snapshot = await mcp__playwright__browser_snapshot();
74
- // → Structured element tree (headings, buttons, inputs, etc.)
75
67
 
76
- // Test responsive layout
77
68
  await mcp__playwright__browser_resize({ width: 375, height: 812 });
78
69
  const mobileScreenshot = await mcp__playwright__browser_take_screenshot();
79
70
 
80
- // Get MudBlazor component docs for UI specs
81
- const libId = await mcp__context7__resolve_library_id({
71
+ const libId = await mcp__context7__resolve-library-id({
82
72
  libraryName: "mudblazor",
83
73
  query: "data grid with sorting and filtering"
84
74
  });
85
- const docs = await mcp__context7__query_docs({
75
+ const docs = await mcp__context7__query-docs({
86
76
  libraryId: libId,
87
77
  query: "DataGrid component props and events"
88
78
  });
89
-
90
- // Fallback: WebSearch for component documentation
91
- // WebFetch for specific component API pages
92
79
  ```
93
80
 
81
+ Fallback: WebSearch for component documentation, WebFetch for specific component API pages.
82
+
94
83
  ### Gemini Image MCP — AI Image Generation
95
84
 
96
85
  > Available in: **UI/UX** (preview generation), **Implement** (production assets)
@@ -103,29 +92,27 @@ const docs = await mcp__context7__query_docs({
103
92
  | `list_images` | Browse image generation history | `mcp__gemini-image-mcp__list_images({ type: "all" })` |
104
93
  | `get_image_info` | Get metadata about a specific image | `mcp__gemini-image-mcp__get_image_info({ imageId })` |
105
94
 
95
+ Read `design-system.md` first to get the project colors and aesthetic direction. Keep edits short and targeted, and iterate with `continue_editing` one change at a time.
96
+
106
97
  ```javascript
107
- // Generate a hero image using design system tokens
108
- // Read design-system.md first to get project colors and aesthetic direction
109
- const image = await mcp__gemini_image_mcp__generate_image({
98
+ const image = await mcp__gemini-image-mcp__generate_image({
110
99
  prompt: "A floating tablet showing a modern dashboard interface on a dark charcoal background with copper and gold accent lighting. Premium luxury aesthetic, photorealistic, cinematic lighting with warm rim light.",
111
100
  aspectRatio: "16:9",
112
101
  outputPath: "public/images/my-feature/hero-mockup.png"
113
102
  });
114
103
 
115
- // Edit an existing image (keep edits short and targeted)
116
- await mcp__gemini_image_mcp__edit_image({
104
+ await mcp__gemini-image-mcp__edit_image({
117
105
  imageSource: "public/images/my-feature/hero-mockup.png",
118
106
  prompt: "Make the lighting warmer and add a subtle copper glow around the tablet edges."
119
107
  });
120
108
 
121
- // Iterate with continue_editing (one change at a time)
122
- await mcp__gemini_image_mcp__continue_editing({
109
+ await mcp__gemini-image-mcp__continue_editing({
123
110
  prompt: "More contrast in the shadows."
124
111
  });
125
-
126
- // Fallback: Manual image creation, stock photos, or placeholder divs
127
112
  ```
128
113
 
114
+ Fallback: manual image creation, stock photos, or placeholder divs.
115
+
129
116
  **Use cases by phase:**
130
117
 
131
118
  | Phase | Use Case | Tool |
@@ -143,7 +130,7 @@ await mcp__gemini_image_mcp__continue_editing({
143
130
  | Tool | Use Case | Example |
144
131
  |------|----------|---------|
145
132
  | **Neon CLI (`neonctl`) / psql** | Database schema, tables, relationships, RLS | `psql <DB_URL> -c "SELECT ..."` |
146
- | **Context7** | Library docs for architecture decisions | `mcp__context7__query_docs()` |
133
+ | **Context7** | Library docs for architecture decisions | `mcp__context7__query-docs()` |
147
134
  | **GitHub CLI (`gh`)** | Check existing code patterns, PRs | `gh search code` (Bash) |
148
135
 
149
136
  ```bash
@@ -183,26 +170,26 @@ psql $(neonctl connection-string) -c "SELECT tablename, policyname, cmd, qual FR
183
170
 
184
171
  | MCP | Use Case | Example |
185
172
  |-----|----------|---------|
186
- | **Context7** | Verify library capabilities, API limits | `mcp__context7__query_docs()` |
173
+ | **Context7** | Verify library capabilities, API limits | `mcp__context7__query-docs()` |
187
174
  | **GitHub CLI (`gh`)** | Check issue discussions, known limitations | `gh search issues` (Bash) |
188
175
 
176
+ The answer confirms a capability or identifies a limitation for the spec update:
177
+
189
178
  ```javascript
190
- // Verify if library supports a required feature
191
- const docs = await mcp__context7__query_docs({
179
+ const docs = await mcp__context7__query-docs({
192
180
  libraryId: "/mudblazor/mudblazor",
193
181
  query: "DataGrid server-side pagination with virtual scrolling"
194
182
  });
195
- // → Confirms capability or identifies limitation for spec update
196
-
197
- // Fallback: WebSearch for library capabilities
198
183
  ```
199
184
 
185
+ Fallback: WebSearch for library capabilities.
186
+
200
187
  ### Phase 6 (Tasks) — Planning & Organization
201
188
 
202
189
  | Tool | Use Case | Example |
203
190
  |------|----------|---------|
204
191
  | **GitHub CLI (`gh`)** | Create issues from tasks, link to milestone | `gh issue create` (Bash) |
205
- | **Context7** | Estimate complexity based on library docs | `mcp__context7__query_docs()` |
192
+ | **Context7** | Estimate complexity based on library docs | `mcp__context7__query-docs()` |
206
193
 
207
194
  ```bash
208
195
  # Create GitHub issues from tasks.json (if team uses GitHub Projects)
@@ -218,7 +205,7 @@ gh issue create --title "T001: Create Entity Lead" \
218
205
  |------|----------|---------|
219
206
  | **Neon CLI (`neonctl`) / psql** | Run migrations, create RLS policies | `dotnet ef database update` |
220
207
  | **GitHub CLI (`gh`)** | Create PR, push branches | `gh pr create` (Bash) |
221
- | **Context7** | Look up API usage during coding | `mcp__context7__query_docs()` |
208
+ | **Context7** | Look up API usage during coding | `mcp__context7__query-docs()` |
222
209
  | **Playwright** | Smoke test deployed features, verify UI | `mcp__playwright__browser_navigate()` |
223
210
  | **Vercel** | Deploy, check logs, manage env vars | `mcp__vercel__list_projects()` |
224
211
  | **Azure CLI** | Resource management, deployments | `az` commands |
@@ -240,35 +227,23 @@ psql $(neonctl connection-string) -c "SELECT column_name, data_type FROM informa
240
227
  psql $(neonctl connection-string) -c "SELECT policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
241
228
  ```
242
229
 
230
+ Look up the API while coding, then smoke test the deployed feature: the snapshot shows whether the page renders, the console messages catch JavaScript errors and failed API calls, and the screenshot goes to `recap.md`. Vercel covers deployment status, logs and environment variables.
231
+
243
232
  ```javascript
244
- // Lookup API during implementation
245
- const docs = await mcp__context7__query_docs({
233
+ const docs = await mcp__context7__query-docs({
246
234
  libraryId: "/dotnet/efcore",
247
235
  query: "owned entity types configuration"
248
236
  });
249
237
 
250
- // Smoke test deployed feature via browser
251
238
  await mcp__playwright__browser_navigate({ url: "https://localhost:5001/leads" });
252
239
  const snapshot = await mcp__playwright__browser_snapshot();
253
- // → Verify page renders correctly, check for errors
254
-
255
- // Check for console errors after deploy
256
240
  const logs = await mcp__playwright__browser_console_messages();
257
- // → Catch JavaScript errors, failed API calls
258
-
259
- // Screenshot for recap.md documentation
260
241
  const screenshot = await mcp__playwright__browser_take_screenshot();
261
242
 
262
- // === VERCEL (Deployment & Environment) ===
263
-
264
- // List projects
265
243
  const projects = await mcp__vercel__list_projects();
266
-
267
- // Check deployment status and logs
268
244
  const deployments = await mcp__vercel__get_deployments({ projectId: 'my-project' });
269
- const logs = await mcp__vercel__get_deployment_logs({ deploymentId: deployments[0].uid });
245
+ const deploymentLogs = await mcp__vercel__get_deployment_logs({ deploymentId: deployments[0].uid });
270
246
 
271
- // Manage environment variables
272
247
  await mcp__vercel__manage_env_vars({
273
248
  projectId: 'my-project',
274
249
  action: 'set',
@@ -276,10 +251,10 @@ await mcp__vercel__manage_env_vars({
276
251
  value: process.env.DATABASE_URL,
277
252
  target: ['production', 'preview']
278
253
  });
279
-
280
- // PRs/issues: sempre `gh` CLI (Bash). Deployments fallback: vercel CLI
281
254
  ```
282
255
 
256
+ PRs/issues: sempre `gh` CLI (Bash). Deployments fallback: `vercel` CLI.
257
+
283
258
  ---
284
259
 
285
260
  ## MCP vs Native Tools Decision
@@ -306,76 +281,33 @@ await mcp__vercel__manage_env_vars({
306
281
 
307
282
  ### Browser (Playwright): Page Automation & Analysis
308
283
 
309
- ```javascript
310
- // === SETUP ===
311
- // Playwright MCP: npx @playwright/mcp@latest
312
- // Config in .claude/settings.json or claude_desktop_config.json:
313
- // { "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }
284
+ Setup: `npx @playwright/mcp@latest`, configured in `.claude/settings.json` or `claude_desktop_config.json` as `{ "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }`.
314
285
 
315
- // === NAVIGATION & SNAPSHOT ===
286
+ Prefer the accessibility snapshot to the screenshot: it is structured, LLM-friendly, and returns the element `ref`s that the interaction calls take. `browser_fill_form` replaces the field's existing value; `browser_handle_dialog` answers alert, confirm and prompt.
316
287
 
317
- // 1. Navigate to a page
288
+ ```javascript
318
289
  await mcp__playwright__browser_navigate({ url: "https://app.example.com/dashboard" });
319
-
320
- // 2. Take accessibility snapshot (preferred — structured, LLM-friendly)
321
290
  const snapshot = await mcp__playwright__browser_snapshot();
322
- // → Returns accessibility tree with element refs for interaction
323
-
324
- // 3. Take visual screenshot (requires --caps vision)
325
- const screenshot = await mcp__playwright__browser_take_screenshot();
326
- // → Returns PNG image of current page
327
-
328
- // === INTERACTION ===
291
+ const screenshot = await mcp__playwright__browser_take_screenshot(); // requires --caps vision
329
292
 
330
- // 4. Click an element (use ref from snapshot)
331
293
  await mcp__playwright__browser_click({ element: "Submit button", ref: "s1e15" });
332
-
333
- // 5. Type into an input field
334
294
  await mcp__playwright__browser_type({ element: "Search input", ref: "s1e8", text: "query" });
335
-
336
- // 6. Fill a form field (replaces existing value)
337
295
  await mcp__playwright__browser_fill_form({ ref: "s1e8", value: "new value" });
338
-
339
- // 7. Select dropdown option
340
296
  await mcp__playwright__browser_select_option({ element: "Status", ref: "s1e12", values: ["active"] });
341
-
342
- // 8. Press keyboard key
343
297
  await mcp__playwright__browser_press_key({ key: "Enter" });
344
298
 
345
- // === TABS & NAVIGATION ===
346
-
347
- // 9. List open tabs
348
299
  const tabs = await mcp__playwright__browser_tabs();
349
-
350
- // 10. Navigate back
351
300
  await mcp__playwright__browser_navigate_back();
352
-
353
- // 11. Close current tab
354
301
  await mcp__playwright__browser_close();
355
302
 
356
- // === ADVANCED ===
357
-
358
- // 12. Evaluate JavaScript in page context
359
303
  const result = await mcp__playwright__browser_evaluate({
360
304
  expression: "document.querySelectorAll('.error').length"
361
305
  });
362
-
363
- // 13. Get console messages (debug)
364
306
  const logs = await mcp__playwright__browser_console_messages();
365
-
366
- // 14. Get network requests
367
307
  const requests = await mcp__playwright__browser_network_requests();
368
-
369
- // 15. Handle dialog (alert, confirm, prompt)
370
308
  await mcp__playwright__browser_handle_dialog({ accept: true });
371
-
372
- // 16. Resize viewport
373
- await mcp__playwright__browser_resize({ width: 375, height: 812 }); // iPhone viewport
374
-
375
- // 17. Save page as PDF (requires --caps pdf)
376
- await mcp__playwright__browser_pdf_save();
377
-
378
- // 18. Upload file
309
+ await mcp__playwright__browser_resize({ width: 375, height: 812 });
310
+ await mcp__playwright__browser_pdf_save(); // requires --caps pdf
379
311
  await mcp__playwright__browser_file_upload({ ref: "s1e20", paths: ["/path/to/file.png"] });
380
312
  ```
381
313
 
@@ -424,16 +356,15 @@ psql $(neonctl connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu
424
356
 
425
357
  ### Context7: Library Research
426
358
 
359
+ For any phase needing library documentation: resolve the library ID first, then query the specific documentation with it.
360
+
427
361
  ```javascript
428
- // Workflow for any phase needing library documentation
429
- // Step 1: Resolve library ID
430
- const lib = await mcp__context7__resolve_library_id({
362
+ const lib = await mcp__context7__resolve-library-id({
431
363
  libraryName: "fluent-ui-blazor",
432
364
  query: "dialog component with form validation"
433
365
  });
434
366
 
435
- // Step 2: Query specific documentation
436
- const docs = await mcp__context7__query_docs({
367
+ const docs = await mcp__context7__query-docs({
437
368
  libraryId: lib.id,
438
369
  query: "FluentDialog component usage with EditForm validation"
439
370
  });