@prmichaelsen/acp-visualizer 0.1.0 → 0.1.2

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 (159) hide show
  1. package/package.json +8 -10
  2. package/src/components/ExtraFieldsBadge.tsx +1 -1
  3. package/src/components/FilterBar.tsx +1 -1
  4. package/src/components/Header.tsx +1 -1
  5. package/src/components/MilestoneTable.tsx +1 -1
  6. package/src/components/MilestoneTree.tsx +2 -2
  7. package/src/components/StatusBadge.tsx +1 -1
  8. package/src/components/StatusDot.tsx +1 -1
  9. package/src/components/TaskList.tsx +1 -1
  10. package/src/routes/__root.tsx +5 -5
  11. package/src/routes/api/watch.ts +1 -1
  12. package/src/routes/index.tsx +2 -2
  13. package/src/routes/milestones.tsx +7 -7
  14. package/src/routes/search.tsx +4 -4
  15. package/src/routes/tasks.tsx +3 -3
  16. package/src/services/progress-database.service.ts +3 -3
  17. package/agent/commands/acp.clarification-address.md +0 -417
  18. package/agent/commands/acp.clarification-capture.md +0 -386
  19. package/agent/commands/acp.clarification-create.md +0 -437
  20. package/agent/commands/acp.clarifications-research.md +0 -326
  21. package/agent/commands/acp.command-create.md +0 -432
  22. package/agent/commands/acp.design-create.md +0 -286
  23. package/agent/commands/acp.design-reference.md +0 -355
  24. package/agent/commands/acp.handoff.md +0 -270
  25. package/agent/commands/acp.index.md +0 -423
  26. package/agent/commands/acp.init.md +0 -546
  27. package/agent/commands/acp.package-create.md +0 -895
  28. package/agent/commands/acp.package-info.md +0 -212
  29. package/agent/commands/acp.package-install.md +0 -539
  30. package/agent/commands/acp.package-list.md +0 -280
  31. package/agent/commands/acp.package-publish.md +0 -541
  32. package/agent/commands/acp.package-remove.md +0 -293
  33. package/agent/commands/acp.package-search.md +0 -307
  34. package/agent/commands/acp.package-update.md +0 -361
  35. package/agent/commands/acp.package-validate.md +0 -540
  36. package/agent/commands/acp.pattern-create.md +0 -386
  37. package/agent/commands/acp.plan.md +0 -587
  38. package/agent/commands/acp.proceed.md +0 -882
  39. package/agent/commands/acp.project-create.md +0 -675
  40. package/agent/commands/acp.project-info.md +0 -312
  41. package/agent/commands/acp.project-list.md +0 -226
  42. package/agent/commands/acp.project-remove.md +0 -379
  43. package/agent/commands/acp.project-set.md +0 -227
  44. package/agent/commands/acp.project-update.md +0 -307
  45. package/agent/commands/acp.projects-restore.md +0 -228
  46. package/agent/commands/acp.projects-sync.md +0 -347
  47. package/agent/commands/acp.report.md +0 -407
  48. package/agent/commands/acp.resume.md +0 -239
  49. package/agent/commands/acp.sessions.md +0 -301
  50. package/agent/commands/acp.status.md +0 -293
  51. package/agent/commands/acp.sync.md +0 -364
  52. package/agent/commands/acp.task-create.md +0 -500
  53. package/agent/commands/acp.update.md +0 -302
  54. package/agent/commands/acp.validate.md +0 -466
  55. package/agent/commands/acp.version-check-for-updates.md +0 -276
  56. package/agent/commands/acp.version-check.md +0 -191
  57. package/agent/commands/acp.version-update.md +0 -289
  58. package/agent/commands/command.template.md +0 -339
  59. package/agent/commands/git.commit.md +0 -526
  60. package/agent/commands/git.init.md +0 -514
  61. package/agent/commands/tanstack-cloudflare.deploy.md +0 -272
  62. package/agent/commands/tanstack-cloudflare.tail.md +0 -275
  63. package/agent/design/.gitkeep +0 -0
  64. package/agent/design/design.template.md +0 -154
  65. package/agent/design/local.dashboard-layout-routing.md +0 -288
  66. package/agent/design/local.data-model-yaml-parsing.md +0 -310
  67. package/agent/design/local.search-filtering.md +0 -331
  68. package/agent/design/local.server-api-auto-refresh.md +0 -235
  69. package/agent/design/local.table-tree-views.md +0 -299
  70. package/agent/design/local.visualizer-requirements.md +0 -349
  71. package/agent/design/requirements.template.md +0 -387
  72. package/agent/index/.gitkeep +0 -0
  73. package/agent/index/acp.core.yaml +0 -137
  74. package/agent/index/local.main.template.yaml +0 -37
  75. package/agent/manifest.template.yaml +0 -13
  76. package/agent/manifest.yaml +0 -302
  77. package/agent/milestones/.gitkeep +0 -0
  78. package/agent/milestones/milestone-1-project-scaffold-data-pipeline.md +0 -67
  79. package/agent/milestones/milestone-1-{title}.template.md +0 -206
  80. package/agent/milestones/milestone-2-dashboard-views-interaction.md +0 -79
  81. package/agent/package.template.yaml +0 -86
  82. package/agent/patterns/.gitkeep +0 -0
  83. package/agent/patterns/bootstrap.template.md +0 -1237
  84. package/agent/patterns/pattern.template.md +0 -382
  85. package/agent/patterns/tanstack-cloudflare.acl-permissions.md +0 -332
  86. package/agent/patterns/tanstack-cloudflare.action-bar-item.md +0 -416
  87. package/agent/patterns/tanstack-cloudflare.api-route-handlers.md +0 -401
  88. package/agent/patterns/tanstack-cloudflare.auth-session-management.md +0 -387
  89. package/agent/patterns/tanstack-cloudflare.card-and-list.md +0 -271
  90. package/agent/patterns/tanstack-cloudflare.chat-engine.md +0 -353
  91. package/agent/patterns/tanstack-cloudflare.confirmation-tokens.md +0 -346
  92. package/agent/patterns/tanstack-cloudflare.durable-objects-websocket.md +0 -516
  93. package/agent/patterns/tanstack-cloudflare.email-service.md +0 -431
  94. package/agent/patterns/tanstack-cloudflare.expander.md +0 -98
  95. package/agent/patterns/tanstack-cloudflare.fcm-push.md +0 -115
  96. package/agent/patterns/tanstack-cloudflare.firebase-anonymous-sessions.md +0 -441
  97. package/agent/patterns/tanstack-cloudflare.firebase-auth.md +0 -348
  98. package/agent/patterns/tanstack-cloudflare.firebase-firestore.md +0 -550
  99. package/agent/patterns/tanstack-cloudflare.firebase-storage.md +0 -369
  100. package/agent/patterns/tanstack-cloudflare.form-controls.md +0 -145
  101. package/agent/patterns/tanstack-cloudflare.global-search-context.md +0 -93
  102. package/agent/patterns/tanstack-cloudflare.image-carousel.md +0 -126
  103. package/agent/patterns/tanstack-cloudflare.library-services.md +0 -553
  104. package/agent/patterns/tanstack-cloudflare.lightbox.md +0 -169
  105. package/agent/patterns/tanstack-cloudflare.markdown-content.md +0 -115
  106. package/agent/patterns/tanstack-cloudflare.mention-suggestions.md +0 -98
  107. package/agent/patterns/tanstack-cloudflare.modal.md +0 -156
  108. package/agent/patterns/tanstack-cloudflare.nextjs-to-tanstack-routing.md +0 -461
  109. package/agent/patterns/tanstack-cloudflare.notifications-engine.md +0 -151
  110. package/agent/patterns/tanstack-cloudflare.oauth-token-refresh.md +0 -90
  111. package/agent/patterns/tanstack-cloudflare.og-metadata.md +0 -296
  112. package/agent/patterns/tanstack-cloudflare.pagination.md +0 -442
  113. package/agent/patterns/tanstack-cloudflare.pill-input.md +0 -220
  114. package/agent/patterns/tanstack-cloudflare.provider-adapter.md +0 -401
  115. package/agent/patterns/tanstack-cloudflare.rate-limiting.md +0 -323
  116. package/agent/patterns/tanstack-cloudflare.scheduled-tasks.md +0 -338
  117. package/agent/patterns/tanstack-cloudflare.searchable-settings.md +0 -375
  118. package/agent/patterns/tanstack-cloudflare.slide-over.md +0 -129
  119. package/agent/patterns/tanstack-cloudflare.ssr-preload.md +0 -571
  120. package/agent/patterns/tanstack-cloudflare.third-party-api-integration.md +0 -508
  121. package/agent/patterns/tanstack-cloudflare.toast-system.md +0 -142
  122. package/agent/patterns/tanstack-cloudflare.unified-header.md +0 -280
  123. package/agent/patterns/tanstack-cloudflare.user-scoped-collections.md +0 -628
  124. package/agent/patterns/tanstack-cloudflare.websocket-manager.md +0 -237
  125. package/agent/patterns/tanstack-cloudflare.wrangler-configuration.md +0 -358
  126. package/agent/patterns/tanstack-cloudflare.zod-schema-validation.md +0 -336
  127. package/agent/progress.template.yaml +0 -161
  128. package/agent/progress.yaml +0 -145
  129. package/agent/schemas/package.schema.yaml +0 -276
  130. package/agent/scripts/acp.common.sh +0 -1781
  131. package/agent/scripts/acp.install.sh +0 -333
  132. package/agent/scripts/acp.package-create.sh +0 -924
  133. package/agent/scripts/acp.package-info.sh +0 -288
  134. package/agent/scripts/acp.package-install.sh +0 -893
  135. package/agent/scripts/acp.package-list.sh +0 -311
  136. package/agent/scripts/acp.package-publish.sh +0 -420
  137. package/agent/scripts/acp.package-remove.sh +0 -348
  138. package/agent/scripts/acp.package-search.sh +0 -156
  139. package/agent/scripts/acp.package-update.sh +0 -517
  140. package/agent/scripts/acp.package-validate.sh +0 -1018
  141. package/agent/scripts/acp.uninstall.sh +0 -85
  142. package/agent/scripts/acp.version-check-for-updates.sh +0 -98
  143. package/agent/scripts/acp.version-check.sh +0 -47
  144. package/agent/scripts/acp.version-update.sh +0 -176
  145. package/agent/scripts/acp.yaml-parser.sh +0 -985
  146. package/agent/scripts/acp.yaml-validate.sh +0 -205
  147. package/agent/tasks/.gitkeep +0 -0
  148. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-1-initialize-tanstack-start-project.md +0 -210
  149. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-2-implement-data-model-yaml-parser.md +0 -294
  150. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-3-build-server-api-data-loading.md +0 -193
  151. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-4-add-auto-refresh-sse.md +0 -262
  152. package/agent/tasks/milestone-2-dashboard-views-interaction/task-10-polish-integration-testing.md +0 -156
  153. package/agent/tasks/milestone-2-dashboard-views-interaction/task-5-build-dashboard-layout-routing.md +0 -178
  154. package/agent/tasks/milestone-2-dashboard-views-interaction/task-6-build-overview-page.md +0 -141
  155. package/agent/tasks/milestone-2-dashboard-views-interaction/task-7-implement-milestone-table-view.md +0 -153
  156. package/agent/tasks/milestone-2-dashboard-views-interaction/task-8-implement-milestone-tree-view.md +0 -174
  157. package/agent/tasks/milestone-2-dashboard-views-interaction/task-9-implement-search-filtering.md +0 -233
  158. package/agent/tasks/task-1-{title}.template.md +0 -244
  159. package/vitest.config.ts +0 -27
@@ -1,1237 +0,0 @@
1
- # MCP Server Bootstrap Pattern
2
-
3
- ## Overview
4
-
5
- This document describes the organizational patterns for bootstrapping...
6
-
7
- ## Core Principles
8
-
9
- Core principles...
10
-
11
- ## Project Structure
12
-
13
- ```
14
- project-root/
15
- ├── src/
16
- │ ├── index.ts # CLI entry point (bundled)
17
- │ ├── server.ts # Server class (for standalone)
18
- │ ├── server-factory.ts # Factory function (for multi-tenant)
19
- │ ├── client.ts # External API client wrapper
20
- │ ├── types.ts # Shared type definitions
21
- │ │
22
- │ ├── tools/ # Tool definitions
23
- │ │ ├── index.ts # Tool exports
24
- │ │ ├── tool-one.ts # Individual tool (definition + handler)
25
- │ │ ├── tool-two.ts
26
- │ │ └── ...
27
- │ │
28
- │ ├── types/ # Type definitions (optional subdirectory)
29
- │ │ ├── mcp.ts # MCP-specific types
30
- │ │ ├── api.ts # External API types
31
- │ │ └── ...
32
- │ │
33
- │ └── utils/ # Utilities
34
- │ ├── logger.ts # Logging (stdio-safe for MCP)
35
- │ ├── error-serializer.ts # Error handling
36
- │ └── ...
37
-
38
- ├── agent/ # Documentation & planning
39
- │ ├── patterns/ # Architecture patterns
40
- │ ├── tasks/ # Task tracking
41
- │ └── ...
42
-
43
- ├── package.json # Package configuration
44
- ├── tsconfig.json # TypeScript configuration
45
- ├── esbuild.build.js # Build script
46
- ├── esbuild.watch.js # Watch mode script
47
- ├── .gitignore
48
- └── README.md
49
- ```
50
-
51
- ## Configuration Files
52
-
53
- ### package.json Structure
54
-
55
- For a simple MCP server:
56
-
57
- ```json
58
- {
59
- "name": "remember-mcp",
60
- "version": "0.1.0",
61
- "description": "Multi-tenant memory system MCP server with vector search and relationships",
62
- "main": "dist/server.js",
63
- "type": "module",
64
- "repository": {
65
- "type": "git",
66
- "url": "git+https://github.com/prmichaelsen/remember-mcp.git"
67
- },
68
- "bugs": {
69
- "url": "https://github.com/prmichaelsen/remember-mcp/issues"
70
- },
71
- "homepage": "https://github.com/prmichaelsen/remember-mcp#readme",
72
- "scripts": {
73
- "build": "node esbuild.build.js",
74
- "build:watch": "node esbuild.watch.js",
75
- "clean": "rm -rf dist",
76
- "dev": "tsx watch src/server.ts",
77
- "start": "node dist/server.js",
78
- "test": "jest",
79
- "test:watch": "jest --watch",
80
- "test:e2e": "jest --config jest.e2e.config.js",
81
- "test:e2e:watch": "jest --config jest.e2e.config.js --watch",
82
- "test:all": "npm test && npm run test:e2e",
83
- "lint": "eslint src/**/*.ts",
84
- "typecheck": "tsc --noEmit",
85
- "prepublishOnly": "npm run clean && npm run build"
86
- },
87
- "keywords": [
88
- "mcp",
89
- "memory",
90
- "vector-search",
91
- "weaviate",
92
- "firebase"
93
- ],
94
- "author": "Patrick Michaelsen",
95
- "license": "MIT"
96
- }
97
- ```
98
-
99
- For a library with multiple exports:
100
-
101
- ```json
102
- {
103
- "name": "@scope/package-name",
104
- "version": "1.0.0",
105
- "description": "MCP server for [purpose]",
106
- "type": "module",
107
- "main": "dist/index.js",
108
- "types": "dist/index.d.ts",
109
-
110
- "repository": {
111
- "type": "git",
112
- "url": "git+https://github.com/username/repo.git"
113
- },
114
- "bugs": {
115
- "url": "https://github.com/username/repo/issues"
116
- },
117
- "homepage": "https://github.com/username/repo#readme",
118
-
119
- "exports": {
120
- ".": {
121
- "types": "./dist/index.d.ts",
122
- "import": "./dist/index.js"
123
- },
124
- "./factory": {
125
- "types": "./dist/server-factory.d.ts",
126
- "import": "./dist/server-factory.js"
127
- },
128
- "./client": {
129
- "types": "./dist/client.d.ts",
130
- "import": "./dist/client.js"
131
- },
132
- "./tools": {
133
- "types": "./dist/tools/index.d.ts",
134
- "import": "./dist/tools/index.js"
135
- },
136
- "./types": {
137
- "types": "./dist/types.d.ts",
138
- "import": "./dist/types.js"
139
- }
140
- },
141
-
142
- "files": [
143
- "dist",
144
- "README.md",
145
- "LICENSE"
146
- ],
147
-
148
- "scripts": {
149
- "build": "npm run build:types && npm run build:bundle",
150
- "build:types": "tsc --emitDeclarationOnly",
151
- "build:bundle": "node esbuild.build.js",
152
- "build:watch": "node esbuild.watch.js",
153
- "start": "node dist/index.js",
154
- "clean": "rm -rf dist",
155
- "test": "jest",
156
- "test:watch": "jest --watch",
157
- "test:e2e": "jest --config jest.e2e.config.js",
158
- "test:e2e:watch": "jest --config jest.e2e.config.js --watch",
159
- "test:all": "npm test && npm run test:e2e",
160
- "prepublishOnly": "npm run clean && npm run build"
161
- },
162
-
163
- "keywords": [
164
- "mcp",
165
- "model-context-protocol",
166
- "[domain-specific-keywords]"
167
- ],
168
-
169
- "dependencies": {
170
- "@modelcontextprotocol/sdk": "^1.0.0"
171
- },
172
-
173
- "devDependencies": {
174
- "@types/jest": "^30.0.0",
175
- "@types/node": "^20.0.0",
176
- "esbuild": "^0.25.0",
177
- "jest": "^30.0.0",
178
- "ts-jest": "^29.0.0",
179
- "typescript": "^5.3.0"
180
- },
181
-
182
- "engines": {
183
- "node": ">=18.0.0"
184
- }
185
- }
186
- ```
187
-
188
- **Key Points:**
189
- - `"type": "module"` required for ESM
190
- - `repository`, `bugs`, `homepage` for GitHub integration
191
- - `main` points to the built entry file
192
- - `exports` field for libraries with multiple entry points
193
- - `files` array specifies what to publish to npm
194
- - `build:watch` script for development
195
- - `clean` script removes build artifacts
196
- - `prepublishOnly` ensures clean build before publishing
197
- - `test` scripts for jest (unit and e2e)
198
- - `author` field for attribution
199
- - `engines` specifies minimum Node.js version
200
-
201
- ### tsconfig.json Structure
202
-
203
- ```json
204
- {
205
- "compilerOptions": {
206
- "target": "ES2022",
207
- "module": "Node16",
208
- "moduleResolution": "Node16",
209
- "lib": ["ES2022"],
210
- "types": ["node"],
211
-
212
- "outDir": "./dist",
213
- "rootDir": "./src",
214
-
215
- "strict": true,
216
- "esModuleInterop": true,
217
- "skipLibCheck": true,
218
- "forceConsistentCasingInFileNames": true,
219
- "resolveJsonModule": true,
220
-
221
- "declaration": true,
222
- "declarationMap": true,
223
- "sourceMap": true,
224
-
225
- "baseUrl": ".",
226
- "paths": {
227
- "@/*": ["src/*"]
228
- }
229
- },
230
-
231
- "include": ["src/**/*"],
232
- "exclude": ["node_modules", "dist"]
233
- }
234
- ```
235
-
236
- **Key Points:**
237
- - `Node16` module resolution for proper ESM support
238
- - `declaration: true` for type definitions
239
- - `strict: true` for type safety
240
- - Source maps for debugging
241
- - `baseUrl` and `paths` for module name mapping (`@/` → `src/`)
242
-
243
- ### Jest Configuration
244
-
245
- For projects with colocated tests (`.spec.ts` and `.e2e.ts` files alongside source code):
246
-
247
- #### jest.config.js - Unit Tests
248
-
249
- ```javascript
250
- module.exports = {
251
- preset: 'ts-jest',
252
- testEnvironment: 'node',
253
- roots: ['<rootDir>/src'],
254
- testMatch: ['**/*.spec.ts'],
255
- moduleFileExtensions: ['ts', 'js'],
256
- collectCoverage: true,
257
- coverageDirectory: 'coverage',
258
- coverageReporters: ['text', 'lcov', 'html'],
259
- collectCoverageFrom: [
260
- 'src/**/*.ts',
261
- '!src/**/*.d.ts',
262
- '!src/**/*.spec.ts',
263
- '!src/**/*.e2e.ts',
264
- '!src/index.ts', // Barrel export only
265
- '!src/types/**/*.ts', // Type definitions only
266
- ],
267
- moduleNameMapper: {
268
- '^@/(.*)$': '<rootDir>/src/$1',
269
- },
270
- };
271
- ```
272
-
273
- #### jest.e2e.config.js - E2E Tests
274
-
275
- ```javascript
276
- module.exports = {
277
- preset: 'ts-jest',
278
- testEnvironment: 'node',
279
- testMatch: ['**/*.e2e.ts'],
280
- testTimeout: 30000, // 30 seconds for real API calls
281
- roots: ['<rootDir>/src'],
282
- collectCoverageFrom: [
283
- 'src/**/*.ts',
284
- '!src/**/*.spec.ts',
285
- '!src/**/*.e2e.ts',
286
- '!src/types/**/*.ts',
287
- '!src/index.ts',
288
- ],
289
- moduleNameMapper: {
290
- '^@/(.*)$': '<rootDir>/src/$1',
291
- },
292
- };
293
- ```
294
-
295
- **Key Points:**
296
- - Separate configs for unit tests (`.spec.ts`) and e2e tests (`.e2e.ts`)
297
- - E2E tests have longer timeout for real API calls
298
- - Coverage excludes test files and type definitions
299
- - `moduleNameMapper` matches TypeScript path aliases
300
- - Tests are colocated with source files in `src/`
301
-
302
- **Package.json Scripts:**
303
- ```json
304
- {
305
- "scripts": {
306
- "test": "jest --config jest.config.js",
307
- "test:e2e": "jest --config jest.e2e.config.js",
308
- "test:watch": "jest --config jest.config.js --watch",
309
- "test:coverage": "jest --config jest.config.js --coverage"
310
- },
311
- "devDependencies": {
312
- "@types/jest": "^29.0.0",
313
- "jest": "^29.0.0",
314
- "ts-jest": "^29.0.0"
315
- }
316
- }
317
- ```
318
-
319
- ### esbuild.build.js Structure
320
-
321
- For a simple MCP server (single entry point):
322
-
323
- ```javascript
324
- import * as esbuild from 'esbuild';
325
-
326
- await esbuild.build({
327
- entryPoints: ['src/server.ts'],
328
- bundle: true,
329
- platform: 'node',
330
- target: 'node20',
331
- format: 'esm',
332
- outfile: 'dist/server.js',
333
- sourcemap: true,
334
- external: [
335
- 'weaviate-client',
336
- 'firebase-admin',
337
- '@modelcontextprotocol/sdk'
338
- ],
339
- banner: {
340
- js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
341
- },
342
- alias: {
343
- '@': './src'
344
- }
345
- });
346
-
347
- console.log('✓ Build complete');
348
- ```
349
-
350
- For a library with multiple entry points:
351
-
352
- ```javascript
353
- import * as esbuild from 'esbuild';
354
- import { readdir } from 'fs/promises';
355
- import { join } from 'path';
356
-
357
- // Option 1: Find all entry points dynamically
358
- async function findEntryPoints(dir, base = 'src') {
359
- const entries = [];
360
- const files = await readdir(dir, { withFileTypes: true });
361
-
362
- for (const file of files) {
363
- const fullPath = join(dir, file.name);
364
- if (file.isDirectory()) {
365
- entries.push(...await findEntryPoints(fullPath, base));
366
- } else if (file.name.endsWith('.ts') && !file.name.endsWith('.d.ts')) {
367
- entries.push(fullPath);
368
- }
369
- }
370
-
371
- return entries;
372
- }
373
-
374
- // Option 2: Explicit entry points
375
- const explicitEntryPoints = [
376
- 'src/server-factory.ts',
377
- 'src/client.ts',
378
- 'src/types.ts',
379
- 'src/tools/tool-one.ts',
380
- 'src/tools/tool-two.ts'
381
- ];
382
-
383
- // Build CLI entry point (bundled)
384
- await esbuild.build({
385
- entryPoints: ['src/index.ts'],
386
- bundle: true,
387
- outfile: 'dist/index.js',
388
- platform: 'node',
389
- target: 'node18',
390
- format: 'esm',
391
- sourcemap: true,
392
- external: [
393
- '@modelcontextprotocol/sdk',
394
- // Add other peer dependencies
395
- ],
396
- banner: {
397
- js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
398
- },
399
- alias: {
400
- '@': './src'
401
- },
402
- minify: false,
403
- keepNames: true
404
- });
405
-
406
- // Build library exports (unbundled, preserves module structure)
407
- await esbuild.build({
408
- entryPoints: await findEntryPoints('src'), // or explicitEntryPoints
409
- bundle: false, // Key: don't bundle for library
410
- outdir: 'dist',
411
- outbase: 'src', // Preserve directory structure
412
- platform: 'node',
413
- target: 'node18',
414
- format: 'esm',
415
- sourcemap: true,
416
- alias: {
417
- '@': './src'
418
- }
419
- });
420
-
421
- console.log('Build complete!');
422
- ```
423
-
424
- **Key Points:**
425
- - **Simple servers**: Single bundled entry point
426
- - **Library exports**: Dual build strategy (bundle CLI, preserve modules)
427
- - `bundle: true` for standalone executable
428
- - `bundle: false` + `outbase: 'src'` for library exports
429
- - `external` array lists dependencies not to bundle (peer dependencies)
430
- - `banner` adds CommonJS compatibility for ESM bundles
431
- - `alias` enables path alias resolution (`@/` → `src/`)
432
- - `target` specifies Node.js version compatibility
433
- - Dynamic or explicit entry point discovery for libraries
434
-
435
- ### esbuild.watch.js Structure
436
-
437
- ```javascript
438
- import * as esbuild from 'esbuild';
439
-
440
- const ctx = await esbuild.context({
441
- entryPoints: ['src/server.ts'],
442
- bundle: true,
443
- platform: 'node',
444
- target: 'node20',
445
- format: 'esm',
446
- outfile: 'dist/server.js',
447
- sourcemap: true,
448
- external: [
449
- 'weaviate-client',
450
- 'firebase-admin',
451
- '@modelcontextprotocol/sdk'
452
- ],
453
- banner: {
454
- js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
455
- },
456
- alias: {
457
- '@': './src'
458
- }
459
- });
460
-
461
- await ctx.watch();
462
- console.log('👀 Watching for changes...');
463
- ```
464
-
465
- **Key Points:**
466
- - Uses `esbuild.context()` API for watch mode
467
- - Same configuration as `esbuild.build.js` for consistency
468
- - Automatically rebuilds on file changes
469
- - Includes all the same options: `external`, `banner`, `alias`, etc.
470
-
471
- ## Source Code Patterns
472
-
473
- ### Tool Definition Pattern
474
-
475
- Each tool file exports both definition and handler:
476
-
477
- ```typescript
478
- // src/tools/example-tool.ts
479
- import { ClientWrapper } from '../client.js';
480
-
481
- export const exampleTool = {
482
- name: 'prefix_tool_name',
483
- description: 'Clear description of what the tool does',
484
- inputSchema: {
485
- type: 'object',
486
- properties: {
487
- param1: {
488
- type: 'string',
489
- description: 'Parameter description'
490
- },
491
- param2: {
492
- type: 'number',
493
- description: 'Optional parameter',
494
- default: 10
495
- }
496
- },
497
- required: ['param1']
498
- }
499
- };
500
-
501
- export async function handleExampleTool(
502
- client: ClientWrapper,
503
- args: any
504
- ): Promise<string> {
505
- try {
506
- const result = await client.doSomething(args.param1, args.param2);
507
- return JSON.stringify(result, null, 2);
508
- } catch (error) {
509
- throw new Error(`Failed to execute: ${error instanceof Error ? error.message : String(error)}`);
510
- }
511
- }
512
- ```
513
-
514
- **Key Points:**
515
- - Tool definition is a plain object (MCP Tool schema)
516
- - Handler is a separate async function
517
- - Handler receives client instance and args
518
- - Returns JSON string for MCP response
519
- - Proper error handling
520
-
521
- ### Server Factory Pattern (Multi-Tenant)
522
-
523
- For use with `mcp-auth` or other multi-tenant wrappers:
524
-
525
- ```typescript
526
- // src/server-factory.ts
527
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
528
- import { ClientWrapper } from './client.js';
529
- import {
530
- CallToolRequestSchema,
531
- ListToolsRequestSchema,
532
- ErrorCode,
533
- McpError
534
- } from '@modelcontextprotocol/sdk/types.js';
535
-
536
- // Import all tools
537
- import { toolOne, handleToolOne } from './tools/tool-one.js';
538
- import { toolTwo, handleToolTwo } from './tools/tool-two.js';
539
-
540
- export interface ServerOptions {
541
- name?: string;
542
- version?: string;
543
- }
544
-
545
- /**
546
- * Create a server instance for a specific user/tenant
547
- *
548
- * @param accessToken - User's access token for external API
549
- * @param userId - User identifier
550
- * @param options - Optional server configuration
551
- * @returns Configured MCP Server instance
552
- */
553
- export function createServer(
554
- accessToken: string,
555
- userId: string,
556
- options: ServerOptions = {}
557
- ): Server {
558
- if (!accessToken) {
559
- throw new Error('accessToken is required');
560
- }
561
-
562
- if (!userId) {
563
- throw new Error('userId is required');
564
- }
565
-
566
- // Initialize client with user's credentials
567
- const client = new ClientWrapper(accessToken);
568
-
569
- // Create MCP server
570
- const server = new Server(
571
- {
572
- name: options.name || 'mcp-server',
573
- version: options.version || '1.0.0'
574
- },
575
- {
576
- capabilities: {
577
- tools: {}
578
- }
579
- }
580
- );
581
-
582
- // Register list_tools handler
583
- server.setRequestHandler(ListToolsRequestSchema, async () => {
584
- return {
585
- tools: [
586
- toolOne,
587
- toolTwo,
588
- // ... all tool definitions
589
- ]
590
- };
591
- });
592
-
593
- // Register call_tool handler
594
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
595
- const { name, arguments: args } = request.params;
596
-
597
- try {
598
- let result: string;
599
-
600
- switch (name) {
601
- case 'prefix_tool_one':
602
- result = await handleToolOne(client, args);
603
- break;
604
-
605
- case 'prefix_tool_two':
606
- result = await handleToolTwo(client, args);
607
- break;
608
-
609
- default:
610
- throw new McpError(
611
- ErrorCode.MethodNotFound,
612
- `Unknown tool: ${name}`
613
- );
614
- }
615
-
616
- return {
617
- content: [
618
- {
619
- type: 'text',
620
- text: result
621
- }
622
- ]
623
- };
624
- } catch (error) {
625
- if (error instanceof McpError) {
626
- throw error;
627
- }
628
-
629
- throw new McpError(
630
- ErrorCode.InternalError,
631
- `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`
632
- );
633
- }
634
- });
635
-
636
- return server;
637
- }
638
- ```
639
-
640
- **Key Points:**
641
- - Factory function creates isolated server instances
642
- - Each instance has its own client with user credentials
643
- - No shared state between instances
644
- - Compatible with `mcp-auth` wrapping pattern
645
-
646
- ### Standalone Server Pattern
647
-
648
- For direct stdio usage without multi-tenancy:
649
-
650
- ```typescript
651
- // src/server.ts
652
- #!/usr/bin/env node
653
-
654
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
655
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
656
- import {
657
- CallToolRequestSchema,
658
- ListToolsRequestSchema,
659
- } from '@modelcontextprotocol/sdk/types.js';
660
- import { config } from 'dotenv';
661
- import { ClientWrapper } from './client.js';
662
- import { logger } from './utils/logger.js';
663
-
664
- // Import tools
665
- import { ToolOne } from './tools/tool-one.js';
666
- import { ToolTwo } from './tools/tool-two.js';
667
-
668
- // Load environment variables
669
- config();
670
-
671
- class MCPServer {
672
- private server: Server;
673
- private client: ClientWrapper;
674
- private toolOne: ToolOne;
675
- private toolTwo: ToolTwo;
676
-
677
- constructor() {
678
- // Initialize server
679
- this.server = new Server(
680
- {
681
- name: 'mcp-server',
682
- version: '1.0.0',
683
- },
684
- {
685
- capabilities: {
686
- tools: {},
687
- },
688
- }
689
- );
690
-
691
- // Initialize client
692
- const apiKey = process.env.API_KEY;
693
- if (!apiKey) {
694
- throw new Error('API_KEY environment variable is required');
695
- }
696
-
697
- this.client = new ClientWrapper(apiKey);
698
-
699
- // Initialize tools
700
- this.toolOne = new ToolOne(this.client);
701
- this.toolTwo = new ToolTwo(this.client);
702
-
703
- this.setupHandlers();
704
- }
705
-
706
- private setupHandlers(): void {
707
- // List available tools
708
- this.server.setRequestHandler(ListToolsRequestSchema, async () => {
709
- return {
710
- tools: [
711
- this.toolOne.getToolDefinition(),
712
- this.toolTwo.getToolDefinition(),
713
- ],
714
- };
715
- });
716
-
717
- // Handle tool calls
718
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
719
- const { name, arguments: args } = request.params;
720
-
721
- try {
722
- let result: any;
723
-
724
- switch (name) {
725
- case 'prefix_tool_one':
726
- result = await this.toolOne.execute(args);
727
- break;
728
-
729
- case 'prefix_tool_two':
730
- result = await this.toolTwo.execute(args);
731
- break;
732
-
733
- default:
734
- throw new Error(`Unknown tool: ${name}`);
735
- }
736
-
737
- return {
738
- content: [
739
- {
740
- type: 'text',
741
- text: JSON.stringify(result, null, 2),
742
- },
743
- ],
744
- };
745
- } catch (error) {
746
- logger.error(`Tool execution failed for ${name}:`, error);
747
- return {
748
- content: [
749
- {
750
- type: 'text',
751
- text: JSON.stringify({
752
- error: error instanceof Error ? error.message : 'Unknown error',
753
- tool: name
754
- }, null, 2),
755
- },
756
- ],
757
- isError: true,
758
- };
759
- }
760
- });
761
- }
762
-
763
- async start(): Promise<void> {
764
- try {
765
- logger.info('Starting MCP Server...');
766
-
767
- // Connect to external service
768
- await this.client.connect();
769
-
770
- // Start MCP server with stdio transport
771
- const transport = new StdioServerTransport();
772
- await this.server.connect(transport);
773
-
774
- // Don't log to stdout/stderr when using stdio transport
775
- // It interferes with MCP JSON protocol
776
-
777
- } catch (error) {
778
- process.exit(1);
779
- }
780
- }
781
-
782
- async stop(): Promise<void> {
783
- await this.server.close();
784
- }
785
- }
786
-
787
- // Handle graceful shutdown
788
- const server = new MCPServer();
789
-
790
- process.on('SIGINT', async () => {
791
- await server.stop();
792
- process.exit(0);
793
- });
794
-
795
- process.on('SIGTERM', async () => {
796
- await server.stop();
797
- process.exit(0);
798
- });
799
-
800
- // Start the server
801
- server.start().catch((error) => {
802
- process.exit(1);
803
- });
804
- ```
805
-
806
- **Key Points:**
807
- - Class-based server for encapsulation
808
- - Environment variable configuration
809
- - Graceful shutdown handling
810
- - **Critical**: No stdout/stderr logging when using stdio transport
811
- - Tool instances as class properties
812
-
813
- ### Client Wrapper Pattern
814
-
815
- ```typescript
816
- // src/client.ts
817
- export interface ClientConfig {
818
- apiKey: string;
819
- baseUrl?: string;
820
- timeout?: number;
821
- }
822
-
823
- export class ClientWrapper {
824
- private config: ClientConfig;
825
- private isConnected = false;
826
-
827
- constructor(apiKey: string, options?: Partial<ClientConfig>) {
828
- this.config = {
829
- apiKey,
830
- baseUrl: options?.baseUrl || 'https://api.example.com',
831
- timeout: options?.timeout || 30000
832
- };
833
- }
834
-
835
- async connect(): Promise<void> {
836
- // Initialize connection, validate credentials, etc.
837
- this.isConnected = true;
838
- }
839
-
840
- async doSomething(param: string): Promise<any> {
841
- if (!this.isConnected) {
842
- throw new Error('Client not connected');
843
- }
844
-
845
- // Make API call
846
- const response = await fetch(`${this.config.baseUrl}/endpoint`, {
847
- method: 'POST',
848
- headers: {
849
- 'Authorization': `Bearer ${this.config.apiKey}`,
850
- 'Content-Type': 'application/json'
851
- },
852
- body: JSON.stringify({ param })
853
- });
854
-
855
- if (!response.ok) {
856
- throw new Error(`API error: ${response.statusText}`);
857
- }
858
-
859
- return response.json();
860
- }
861
-
862
- isClientConnected(): boolean {
863
- return this.isConnected;
864
- }
865
- }
866
- ```
867
-
868
- **Key Points:**
869
- - Encapsulates external API communication
870
- - Accepts credentials in constructor (for multi-tenant)
871
- - Connection state management
872
- - Error handling
873
-
874
- ### Logger Pattern (Stdio-Safe)
875
-
876
- ```typescript
877
- // src/utils/logger.ts
878
- export enum LogLevel {
879
- ERROR = 0,
880
- WARN = 1,
881
- INFO = 2,
882
- DEBUG = 3
883
- }
884
-
885
- class Logger {
886
- // No-op logger to avoid interfering with stdio MCP transport
887
- // All logging methods do nothing to prevent JSON corruption
888
-
889
- error(message: string, ...args: any[]): void {
890
- // No-op when using stdio
891
- // Could write to file or use process.stderr in non-stdio mode
892
- }
893
-
894
- warn(message: string, ...args: any[]): void {
895
- // No-op
896
- }
897
-
898
- info(message: string, ...args: any[]): void {
899
- // No-op
900
- }
901
-
902
- debug(message: string, ...args: any[]): void {
903
- // No-op
904
- }
905
- }
906
-
907
- export const logger = new Logger();
908
- ```
909
-
910
- **Key Points:**
911
- - **Critical**: No console output when using stdio transport
912
- - Stdio transport uses stdout/stdin for JSON-RPC
913
- - Any console output corrupts the protocol
914
- - Alternative: Write to file or use stderr carefully
915
-
916
- ### Error Serializer Pattern
917
-
918
- ```typescript
919
- // src/utils/error-serializer.ts
920
- export function serializeError(error: unknown): any {
921
- if (error instanceof Error) {
922
- return {
923
- name: error.name,
924
- message: error.message,
925
- stack: error.stack,
926
- ...(error as any) // Include any additional properties
927
- };
928
- }
929
-
930
- return {
931
- message: String(error)
932
- };
933
- }
934
- ```
935
-
936
- ## Integration with mcp-auth
937
-
938
- ### Using AuthenticatedMCPServer
939
-
940
- If building a new server with tool-level auth:
941
-
942
- ```typescript
943
- // src/index.ts
944
- import { AuthenticatedMCPServer } from '@prmichaelsen/mcp-auth/server';
945
- import { EnvAuthProvider } from '@prmichaelsen/mcp-auth/providers/env';
946
- import { SimpleTokenResolver } from '@prmichaelsen/mcp-auth';
947
- import { withAuth } from '@prmichaelsen/mcp-auth/server';
948
-
949
- const server = new AuthenticatedMCPServer({
950
- name: 'my-server',
951
- authProvider: new EnvAuthProvider(),
952
- tokenResolver: new SimpleTokenResolver({ tokenEnvVar: 'API_TOKEN' }),
953
- resourceType: 'myapi',
954
- transport: { type: 'stdio' }
955
- });
956
-
957
- server.registerTool('get_data', withAuth(async (args, accessToken, userId) => {
958
- const client = new ClientWrapper(accessToken);
959
- return client.getData(args);
960
- }));
961
-
962
- await server.start();
963
- ```
964
-
965
- ### Using Server Wrapping Pattern
966
-
967
- If wrapping an existing server factory:
968
-
969
- ```typescript
970
- // Wrapper server using mcp-auth
971
- import { wrapServer } from '@prmichaelsen/mcp-auth/wrapper';
972
- import { createServer } from './server-factory.js';
973
-
974
- const wrappedServer = wrapServer({
975
- serverFactory: createServer,
976
- authProvider: new JWTAuthProvider({ secret: process.env.JWT_SECRET }),
977
- tokenResolver: new APITokenResolver({ apiUrl: process.env.API_URL }),
978
- resourceType: 'myapi',
979
- transport: { type: 'sse', port: 3000 }
980
- });
981
-
982
- await wrappedServer.start();
983
- ```
984
-
985
- ## Directory Organization Best Practices
986
-
987
- ### Agent Directory
988
-
989
- The `agent/` directory contains documentation and planning:
990
-
991
- ```
992
- agent/
993
- ├── patterns/ # Architecture patterns
994
- │ ├── bootstrap.md # This document
995
- │ ├── library-services.md # Service layer patterns
996
- │ └── ...
997
-
998
- ├── tasks/ # Task tracking
999
- │ ├── task-001.md
1000
- │ └── ...
1001
-
1002
- ├── milestones/ # Milestone planning
1003
- │ ├── milestone-1.md
1004
- │ └── ...
1005
-
1006
- ├── progress.yaml # Progress tracking
1007
- └── requirements.md # Requirements document
1008
- ```
1009
-
1010
- ### Types Organization
1011
-
1012
- Types can be organized in two ways:
1013
-
1014
- **Option 1: Flat structure** (simple projects)
1015
- ```
1016
- src/
1017
- ├── types.ts # All types in one file
1018
- └── ...
1019
- ```
1020
-
1021
- **Option 2: Types directory** (complex projects)
1022
- ```
1023
- src/
1024
- ├── types/
1025
- │ ├── mcp.ts # MCP-specific types
1026
- │ ├── api.ts # External API types
1027
- │ ├── domain.ts # Domain types
1028
- │ └── index.ts # Re-exports
1029
- └── ...
1030
- ```
1031
-
1032
- ### Utils Organization
1033
-
1034
- ```
1035
- src/
1036
- ├── utils/
1037
- │ ├── logger.ts # Logging utility
1038
- │ ├── error-serializer.ts # Error handling
1039
- │ ├── validation.ts # Input validation
1040
- │ └── index.ts # Re-exports
1041
- └── ...
1042
- ```
1043
-
1044
- ## Build Output Structure
1045
-
1046
- After building, the output should mirror the source structure:
1047
-
1048
- ```
1049
- dist/
1050
- ├── index.js # Bundled CLI entry
1051
- ├── index.d.ts
1052
- ├── server-factory.js # Unbundled library exports
1053
- ├── server-factory.d.ts
1054
- ├── client.js
1055
- ├── client.d.ts
1056
- ├── types.js
1057
- ├── types.d.ts
1058
- ├── tools/
1059
- │ ├── tool-one.js
1060
- │ ├── tool-one.d.ts
1061
- │ ├── tool-two.js
1062
- │ ├── tool-two.d.ts
1063
- │ └── index.js
1064
- └── utils/
1065
- ├── logger.js
1066
- ├── logger.d.ts
1067
- └── ...
1068
- ```
1069
-
1070
- **Key Points:**
1071
- - `index.js` is bundled (single file)
1072
- - Other exports preserve module structure
1073
- - Type definitions (`.d.ts`) for all modules
1074
- - Source maps (`.js.map`) for debugging
1075
-
1076
- ## Import Patterns
1077
-
1078
- ### ESM Import Extensions
1079
-
1080
- Always include `.js` extension in imports (even for `.ts` files):
1081
-
1082
- ```typescript
1083
- // ✅ Correct
1084
- import { ClientWrapper } from './client.js';
1085
- import { toolOne } from './tools/tool-one.js';
1086
-
1087
- // ❌ Wrong
1088
- import { ClientWrapper } from './client';
1089
- import { toolOne } from './tools/tool-one';
1090
- ```
1091
-
1092
- ### Re-export Patterns
1093
-
1094
- ```typescript
1095
- // src/tools/index.ts
1096
- export * from './tool-one.js';
1097
- export * from './tool-two.js';
1098
-
1099
- // Usage
1100
- import { toolOne, toolTwo } from './tools/index.js';
1101
- ```
1102
-
1103
- ## Environment Configuration
1104
-
1105
- ### .env.example
1106
-
1107
- ```bash
1108
- # API Configuration
1109
- API_KEY=your_api_key_here
1110
- API_URL=https://api.example.com
1111
-
1112
- # Server Configuration
1113
- PORT=3000
1114
- NODE_ENV=development
1115
-
1116
- # Logging
1117
- LOG_LEVEL=info
1118
- ```
1119
-
1120
- ### Environment Loading
1121
-
1122
- ```typescript
1123
- import { config } from 'dotenv';
1124
-
1125
- // Load at server startup
1126
- config();
1127
-
1128
- // Access variables
1129
- const apiKey = process.env.API_KEY;
1130
- if (!apiKey) {
1131
- throw new Error('API_KEY is required');
1132
- }
1133
- ```
1134
-
1135
- ## Testing Considerations
1136
-
1137
- While not covered in detail, consider:
1138
-
1139
- ```
1140
- src/
1141
- ├── tools/
1142
- │ ├── tool-one.ts
1143
- │ ├── tool-one.test.ts # Co-located tests
1144
- │ └── ...
1145
- ```
1146
-
1147
- Or separate test directory:
1148
-
1149
- ```
1150
- tests/
1151
- ├── tools/
1152
- │ ├── tool-one.test.ts
1153
- │ └── ...
1154
- └── integration/
1155
- └── ...
1156
- ```
1157
-
1158
- ## Common Patterns Summary
1159
-
1160
- ### 1. Tool Organization
1161
- - One file per tool
1162
- - Export definition and handler separately
1163
- - Handler receives client and args
1164
- - Return JSON strings
1165
-
1166
- ### 2. Server Patterns
1167
- - **Factory**: For multi-tenant (returns Server instance)
1168
- - **Class**: For standalone (manages lifecycle)
1169
- - Both patterns supported
1170
-
1171
- ### 3. Build Strategy
1172
- - **Bundle**: CLI entry point (single file)
1173
- - **Preserve**: Library exports (module structure)
1174
- - TypeScript declarations always generated
1175
-
1176
- ### 4. Client Pattern
1177
- - Wrapper class for external API
1178
- - Accept credentials in constructor
1179
- - Stateful connection management
1180
-
1181
- ### 5. Logging Pattern
1182
- - No-op for stdio transport
1183
- - File or stderr for other transports
1184
- - Never use console.log with stdio
1185
-
1186
- ### 6. Type Safety
1187
- - Strong typing throughout
1188
- - Separate type files or directories
1189
- - Export types for library consumers
1190
-
1191
- ### 7. Error Handling
1192
- - Serialize errors for MCP responses
1193
- - Proper error types (McpError)
1194
- - Graceful degradation
1195
-
1196
- ## Compatibility Checklist
1197
-
1198
- When building a server compatible with `mcp-auth`:
1199
-
1200
- - ✅ Export a factory function that accepts `(accessToken, userId, options?)`
1201
- - ✅ Factory returns a configured `Server` instance
1202
- - ✅ No shared state between server instances
1203
- - ✅ Client wrapper accepts credentials in constructor
1204
- - ✅ Tools are stateless (receive client as parameter)
1205
- - ✅ Proper TypeScript types exported
1206
- - ✅ ESM with `.js` extensions in imports
1207
- - ✅ Dual build: bundled CLI + preserved modules
1208
-
1209
- ## Migration Path
1210
-
1211
- ### From Standalone to Multi-Tenant
1212
-
1213
- 1. Extract server creation into factory function
1214
- 2. Move credential loading from env to factory parameters
1215
- 3. Ensure no shared state between instances
1216
- 4. Add factory export to package.json
1217
- 5. Update build to preserve module structure
1218
-
1219
- ### From Multi-Tenant to mcp-auth Integration
1220
-
1221
- 1. Keep existing factory function
1222
- 2. Add mcp-auth wrapper in separate entry point
1223
- 3. Configure auth provider and token resolver
1224
- 4. Deploy wrapped server for remote access
1225
- 5. Keep factory for direct usage
1226
-
1227
- ## Conclusion
1228
-
1229
- This bootstrap pattern provides a foundation for building MCP servers that are:
1230
-
1231
- - **Modular**: Clear separation of concerns
1232
- - **Type-safe**: Strong TypeScript typing
1233
- - **Multi-tenant ready**: Isolated instances per user
1234
- - **Library-friendly**: Dual build strategy
1235
- - **mcp-auth compatible**: Works with authentication framework
1236
-
1237
- The pattern emphasizes **organization and structure** over specific implementations, allowing flexibility in choosing tools and technologies while maintaining consistency and compatibility.