@prmichaelsen/acp-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.env.example +5 -0
  2. package/AGENT.md +1279 -0
  3. package/README.md +78 -0
  4. package/agent/commands/acp.command-create.md +372 -0
  5. package/agent/commands/acp.design-create.md +224 -0
  6. package/agent/commands/acp.init.md +410 -0
  7. package/agent/commands/acp.package-create.md +894 -0
  8. package/agent/commands/acp.package-info.md +211 -0
  9. package/agent/commands/acp.package-install.md +461 -0
  10. package/agent/commands/acp.package-list.md +279 -0
  11. package/agent/commands/acp.package-publish.md +540 -0
  12. package/agent/commands/acp.package-remove.md +292 -0
  13. package/agent/commands/acp.package-search.md +306 -0
  14. package/agent/commands/acp.package-update.md +310 -0
  15. package/agent/commands/acp.package-validate.md +535 -0
  16. package/agent/commands/acp.pattern-create.md +326 -0
  17. package/agent/commands/acp.plan.md +552 -0
  18. package/agent/commands/acp.proceed.md +336 -0
  19. package/agent/commands/acp.project-create.md +672 -0
  20. package/agent/commands/acp.report.md +394 -0
  21. package/agent/commands/acp.resume.md +237 -0
  22. package/agent/commands/acp.status.md +280 -0
  23. package/agent/commands/acp.sync.md +363 -0
  24. package/agent/commands/acp.task-create.md +390 -0
  25. package/agent/commands/acp.update.md +301 -0
  26. package/agent/commands/acp.validate.md +436 -0
  27. package/agent/commands/acp.version-check-for-updates.md +275 -0
  28. package/agent/commands/acp.version-check.md +190 -0
  29. package/agent/commands/acp.version-update.md +288 -0
  30. package/agent/commands/command.template.md +316 -0
  31. package/agent/commands/git.commit.md +513 -0
  32. package/agent/commands/git.init.md +513 -0
  33. package/agent/commands/mcp-server-starter.add-tool.md +677 -0
  34. package/agent/commands/mcp-server-starter.init.md +894 -0
  35. package/agent/design/.gitkeep +0 -0
  36. package/agent/design/design.template.md +136 -0
  37. package/agent/design/remember-mcp-analysis.md +987 -0
  38. package/agent/design/requirements.template.md +387 -0
  39. package/agent/manifest.template.yaml +13 -0
  40. package/agent/manifest.yaml +109 -0
  41. package/agent/milestones/.gitkeep +0 -0
  42. package/agent/milestones/milestone-1-{title}.template.md +206 -0
  43. package/agent/package.template.yaml +36 -0
  44. package/agent/patterns/.gitkeep +0 -0
  45. package/agent/patterns/bootstrap.template.md +1237 -0
  46. package/agent/patterns/mcp-server-starter.bootstrap.md +597 -0
  47. package/agent/patterns/mcp-server-starter.build-config.md +554 -0
  48. package/agent/patterns/mcp-server-starter.config-management.md +525 -0
  49. package/agent/patterns/mcp-server-starter.server-factory.md +616 -0
  50. package/agent/patterns/mcp-server-starter.server-standalone.md +642 -0
  51. package/agent/patterns/mcp-server-starter.test-config.md +558 -0
  52. package/agent/patterns/mcp-server-starter.tool-creation.md +653 -0
  53. package/agent/patterns/pattern.template.md +364 -0
  54. package/agent/progress.template.yaml +161 -0
  55. package/agent/progress.yaml +33 -0
  56. package/agent/schemas/package.schema.yaml +161 -0
  57. package/agent/scripts/acp.common.sh +1362 -0
  58. package/agent/scripts/acp.install.sh +213 -0
  59. package/agent/scripts/acp.package-create.sh +925 -0
  60. package/agent/scripts/acp.package-info.sh +270 -0
  61. package/agent/scripts/acp.package-install.sh +550 -0
  62. package/agent/scripts/acp.package-list.sh +263 -0
  63. package/agent/scripts/acp.package-publish.sh +420 -0
  64. package/agent/scripts/acp.package-remove.sh +272 -0
  65. package/agent/scripts/acp.package-search.sh +156 -0
  66. package/agent/scripts/acp.package-update.sh +356 -0
  67. package/agent/scripts/acp.package-validate.sh +766 -0
  68. package/agent/scripts/acp.uninstall.sh +85 -0
  69. package/agent/scripts/acp.version-check-for-updates.sh +98 -0
  70. package/agent/scripts/acp.version-check.sh +47 -0
  71. package/agent/scripts/acp.version-update.sh +158 -0
  72. package/agent/scripts/acp.yaml-parser.sh +736 -0
  73. package/agent/scripts/acp.yaml-validate.sh +205 -0
  74. package/agent/tasks/.gitkeep +0 -0
  75. package/agent/tasks/task-1-{title}.template.md +225 -0
  76. package/dist/config.d.ts +4 -0
  77. package/dist/server-factory.d.ts +9 -0
  78. package/dist/server-factory.js +99 -0
  79. package/dist/server-factory.js.map +7 -0
  80. package/dist/server.d.ts +2 -0
  81. package/dist/server.js +106 -0
  82. package/dist/server.js.map +7 -0
  83. package/dist/tools/acp-remote-list-files.d.ts +15 -0
  84. package/dist/types/ssh-config.d.ts +16 -0
  85. package/esbuild.build.js +34 -0
  86. package/esbuild.watch.js +31 -0
  87. package/jest.config.js +31 -0
  88. package/package.json +54 -0
  89. package/src/config.ts +16 -0
  90. package/src/server-factory.ts +43 -0
  91. package/src/server.ts +46 -0
  92. package/src/tools/acp-remote-list-files.ts +89 -0
  93. package/src/types/ssh-config.ts +17 -0
  94. package/tsconfig.json +22 -0
@@ -0,0 +1,525 @@
1
+ # Config Management Pattern
2
+
3
+ **Pattern**: Environment Variable and Configuration Management
4
+ **Category**: Configuration
5
+ **Complexity**: Beginner
6
+ **Last Updated**: 2026-02-22
7
+
8
+ ---
9
+
10
+ ## Overview
11
+
12
+ The Config Management Pattern provides type-safe, validated configuration management for MCP servers using environment variables, with proper defaults and error handling.
13
+
14
+ **When to use this pattern**:
15
+ - Managing environment-specific configuration
16
+ - Handling API keys and secrets
17
+ - Configuring database connections
18
+ - Setting server options
19
+ - Multi-environment deployments
20
+
21
+ ---
22
+
23
+ ## Core Principles
24
+
25
+ ### 1. Type Safety
26
+ Use TypeScript for compile-time configuration validation.
27
+
28
+ ### 2. Validation
29
+ Validate required configuration at startup.
30
+
31
+ ### 3. Defaults
32
+ Provide sensible defaults for optional configuration.
33
+
34
+ ### 4. Immutability
35
+ Configuration should be read-only (`as const`).
36
+
37
+ ### 5. Documentation
38
+ Document all configuration in `.env.example`.
39
+
40
+ ---
41
+
42
+ ## Complete Configuration
43
+
44
+ **src/config.ts**:
45
+
46
+ ```typescript
47
+ import dotenv from 'dotenv';
48
+ import { logger } from './utils/logger.js';
49
+
50
+ // Load environment variables
51
+ dotenv.config();
52
+
53
+ /**
54
+ * Application configuration
55
+ *
56
+ * All configuration is loaded from environment variables.
57
+ * See .env.example for required variables.
58
+ */
59
+ export const config = {
60
+ // Service configuration
61
+ service: {
62
+ url: process.env.SERVICE_URL || 'http://localhost:8080',
63
+ apiKey: process.env.SERVICE_API_KEY || '',
64
+ },
65
+
66
+ // Server configuration
67
+ server: {
68
+ port: parseInt(process.env.PORT || '3000', 10),
69
+ nodeEnv: process.env.NODE_ENV || 'development',
70
+ logLevel: process.env.LOG_LEVEL || 'info',
71
+ },
72
+
73
+ // MCP configuration
74
+ mcp: {
75
+ transport: process.env.MCP_TRANSPORT || 'stdio',
76
+ },
77
+ } as const;
78
+
79
+ /**
80
+ * Validate required configuration
81
+ *
82
+ * Call this at server startup to ensure all required
83
+ * configuration is present.
84
+ *
85
+ * @throws Error if required configuration is missing
86
+ */
87
+ export function validateConfig(): void {
88
+ const required = [
89
+ { key: 'SERVICE_URL', value: config.service.url },
90
+ { key: 'SERVICE_API_KEY', value: config.service.apiKey },
91
+ ];
92
+
93
+ const missing = required.filter((r) => !r.value || r.value === 'http://localhost:8080');
94
+
95
+ if (missing.length > 0) {
96
+ throw new Error(
97
+ `Missing required environment variables: ${missing.map((m) => m.key).join(', ')}`
98
+ );
99
+ }
100
+
101
+ logger.info('Configuration validated', {
102
+ nodeEnv: config.server.nodeEnv,
103
+ logLevel: config.server.logLevel,
104
+ });
105
+ }
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Environment Variables
111
+
112
+ **.env.example**:
113
+
114
+ ```bash
115
+ # Service Configuration
116
+ SERVICE_URL=http://localhost:8080
117
+ SERVICE_API_KEY=
118
+
119
+ # Server Configuration
120
+ PORT=3000
121
+ NODE_ENV=development
122
+ LOG_LEVEL=info
123
+
124
+ # MCP Configuration
125
+ MCP_TRANSPORT=stdio
126
+ ```
127
+
128
+ **.env** (not committed):
129
+
130
+ ```bash
131
+ # Service Configuration
132
+ SERVICE_URL=https://api.example.com
133
+ SERVICE_API_KEY=sk-1234567890abcdef
134
+
135
+ # Server Configuration
136
+ PORT=3000
137
+ NODE_ENV=production
138
+ LOG_LEVEL=info
139
+
140
+ # MCP Configuration
141
+ MCP_TRANSPORT=sse
142
+ ```
143
+
144
+ **.gitignore**:
145
+
146
+ ```gitignore
147
+ .env
148
+ .env.local
149
+ .env.*.local
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Usage
155
+
156
+ ### In Server
157
+
158
+ ```typescript
159
+ import { config, validateConfig } from './config.js';
160
+
161
+ async function initServer() {
162
+ // Validate configuration first
163
+ validateConfig();
164
+
165
+ // Use configuration
166
+ const client = new ServiceClient({
167
+ url: config.service.url,
168
+ apiKey: config.service.apiKey,
169
+ });
170
+
171
+ // ...
172
+ }
173
+ ```
174
+
175
+ ### In Tools
176
+
177
+ ```typescript
178
+ import { config } from '../config.js';
179
+
180
+ export async function handleTool(args, userId) {
181
+ // Access configuration
182
+ const response = await fetch(config.service.url, {
183
+ headers: {
184
+ 'Authorization': `Bearer ${config.service.apiKey}`,
185
+ },
186
+ });
187
+
188
+ // ...
189
+ }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Advanced Patterns
195
+
196
+ ### Nested Configuration
197
+
198
+ ```typescript
199
+ export const config = {
200
+ database: {
201
+ host: process.env.DB_HOST || 'localhost',
202
+ port: parseInt(process.env.DB_PORT || '5432', 10),
203
+ name: process.env.DB_NAME || 'mydb',
204
+ user: process.env.DB_USER || 'user',
205
+ password: process.env.DB_PASSWORD || '',
206
+ ssl: process.env.DB_SSL === 'true',
207
+ pool: {
208
+ min: parseInt(process.env.DB_POOL_MIN || '2', 10),
209
+ max: parseInt(process.env.DB_POOL_MAX || '10', 10),
210
+ },
211
+ },
212
+ } as const;
213
+ ```
214
+
215
+ ### Environment-Specific Config
216
+
217
+ ```typescript
218
+ const isDevelopment = process.env.NODE_ENV === 'development';
219
+ const isProduction = process.env.NODE_ENV === 'production';
220
+
221
+ export const config = {
222
+ server: {
223
+ port: parseInt(process.env.PORT || (isDevelopment ? '3000' : '8080'), 10),
224
+ cors: isDevelopment,
225
+ debug: isDevelopment,
226
+ },
227
+ logging: {
228
+ level: process.env.LOG_LEVEL || (isDevelopment ? 'debug' : 'info'),
229
+ pretty: isDevelopment,
230
+ },
231
+ } as const;
232
+ ```
233
+
234
+ ### Type-Safe Enums
235
+
236
+ ```typescript
237
+ const LOG_LEVELS = ['debug', 'info', 'warn', 'error'] as const;
238
+ type LogLevel = typeof LOG_LEVELS[number];
239
+
240
+ function parseLogLevel(value: string | undefined): LogLevel {
241
+ const level = value?.toLowerCase();
242
+ if (level && LOG_LEVELS.includes(level as LogLevel)) {
243
+ return level as LogLevel;
244
+ }
245
+ return 'info';
246
+ }
247
+
248
+ export const config = {
249
+ logging: {
250
+ level: parseLogLevel(process.env.LOG_LEVEL),
251
+ },
252
+ } as const;
253
+ ```
254
+
255
+ ### Validation with Zod
256
+
257
+ ```typescript
258
+ import { z } from 'zod';
259
+
260
+ const configSchema = z.object({
261
+ service: z.object({
262
+ url: z.string().url(),
263
+ apiKey: z.string().min(1),
264
+ }),
265
+ server: z.object({
266
+ port: z.number().int().min(1).max(65535),
267
+ nodeEnv: z.enum(['development', 'production', 'test']),
268
+ }),
269
+ });
270
+
271
+ export const config = configSchema.parse({
272
+ service: {
273
+ url: process.env.SERVICE_URL,
274
+ apiKey: process.env.SERVICE_API_KEY,
275
+ },
276
+ server: {
277
+ port: parseInt(process.env.PORT || '3000', 10),
278
+ nodeEnv: process.env.NODE_ENV || 'development',
279
+ },
280
+ });
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Benefits
286
+
287
+ ### 1. Type Safety
288
+ - Compile-time checking
289
+ - IDE autocomplete
290
+ - Refactoring support
291
+
292
+ ### 2. Validation
293
+ - Catch configuration errors early
294
+ - Clear error messages
295
+ - Startup-time validation
296
+
297
+ ### 3. Documentation
298
+ - `.env.example` documents all variables
299
+ - Self-documenting code
300
+ - Easy onboarding
301
+
302
+ ### 4. Security
303
+ - Secrets not in code
304
+ - Environment-specific values
305
+ - `.env` not committed
306
+
307
+ ---
308
+
309
+ ## Anti-Patterns
310
+
311
+ ### ❌ Don't: Hardcode Configuration
312
+
313
+ ```typescript
314
+ // ❌ Wrong
315
+ const apiKey = 'sk-1234567890';
316
+ const dbUrl = 'mongodb://localhost:27017';
317
+ ```
318
+
319
+ ```typescript
320
+ // ✅ Correct
321
+ const apiKey = process.env.API_KEY;
322
+ const dbUrl = process.env.DATABASE_URL;
323
+ ```
324
+
325
+ **Why**: Hardcoded values can't change per environment and expose secrets.
326
+
327
+ ### ❌ Don't: Skip Validation
328
+
329
+ ```typescript
330
+ // ❌ Wrong
331
+ export const config = {
332
+ apiKey: process.env.API_KEY, // Might be undefined!
333
+ };
334
+ ```
335
+
336
+ ```typescript
337
+ // ✅ Correct
338
+ export const config = {
339
+ apiKey: process.env.API_KEY || '',
340
+ };
341
+
342
+ export function validateConfig() {
343
+ if (!config.apiKey) {
344
+ throw new Error('API_KEY is required');
345
+ }
346
+ }
347
+ ```
348
+
349
+ **Why**: Missing configuration causes runtime errors.
350
+
351
+ ### ❌ Don't: Use Mutable Configuration
352
+
353
+ ```typescript
354
+ // ❌ Wrong
355
+ export let config = {
356
+ port: 3000,
357
+ };
358
+
359
+ config.port = 8080; // Mutable!
360
+ ```
361
+
362
+ ```typescript
363
+ // ✅ Correct
364
+ export const config = {
365
+ port: 3000,
366
+ } as const; // Immutable
367
+ ```
368
+
369
+ **Why**: Mutable configuration leads to bugs.
370
+
371
+ ### ❌ Don't: Commit .env Files
372
+
373
+ ```gitignore
374
+ # ❌ Wrong - .env not ignored
375
+ # (no .env entry)
376
+ ```
377
+
378
+ ```gitignore
379
+ # ✅ Correct
380
+ .env
381
+ .env.local
382
+ .env.*.local
383
+ ```
384
+
385
+ **Why**: `.env` contains secrets and should never be committed.
386
+
387
+ ### ❌ Don't: Use process.env Directly
388
+
389
+ ```typescript
390
+ // ❌ Wrong - Scattered throughout code
391
+ const url = process.env.SERVICE_URL;
392
+ const key = process.env.API_KEY;
393
+ ```
394
+
395
+ ```typescript
396
+ // ✅ Correct - Centralized in config
397
+ import { config } from './config.js';
398
+ const url = config.service.url;
399
+ const key = config.service.apiKey;
400
+ ```
401
+
402
+ **Why**: Centralized configuration is easier to manage and test.
403
+
404
+ ---
405
+
406
+ ## Testing
407
+
408
+ ### Mock Configuration
409
+
410
+ ```typescript
411
+ import { describe, it, expect, jest } from '@jest/globals';
412
+
413
+ // Mock config module
414
+ jest.mock('./config.js', () => ({
415
+ config: {
416
+ service: {
417
+ url: 'http://test.example.com',
418
+ apiKey: 'test-key',
419
+ },
420
+ },
421
+ }));
422
+
423
+ import { config } from './config.js';
424
+ import { handleTool } from './tool.js';
425
+
426
+ describe('tool with mocked config', () => {
427
+ it('should use test configuration', async () => {
428
+ expect(config.service.url).toBe('http://test.example.com');
429
+ // Test tool with mocked config
430
+ });
431
+ });
432
+ ```
433
+
434
+ ### Test Validation
435
+
436
+ ```typescript
437
+ describe('validateConfig', () => {
438
+ const originalEnv = process.env;
439
+
440
+ beforeEach(() => {
441
+ process.env = { ...originalEnv };
442
+ });
443
+
444
+ afterEach(() => {
445
+ process.env = originalEnv;
446
+ });
447
+
448
+ it('should pass with valid config', () => {
449
+ process.env.SERVICE_URL = 'https://api.example.com';
450
+ process.env.SERVICE_API_KEY = 'sk-123';
451
+
452
+ expect(() => validateConfig()).not.toThrow();
453
+ });
454
+
455
+ it('should fail with missing API key', () => {
456
+ process.env.SERVICE_URL = 'https://api.example.com';
457
+ delete process.env.SERVICE_API_KEY;
458
+
459
+ expect(() => validateConfig()).toThrow('SERVICE_API_KEY');
460
+ });
461
+ });
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Related Patterns
467
+
468
+ - [Bootstrap Pattern](mcp-server-starter.bootstrap.md) - Initial setup
469
+ - [Server Standalone Pattern](mcp-server-starter.server-standalone.md) - Using config
470
+ - [Server Factory Pattern](mcp-server-starter.server-factory.md) - Multi-tenant config
471
+ - [Tool Creation Pattern](mcp-server-starter.tool-creation.md) - Config in tools
472
+
473
+ ---
474
+
475
+ ## Troubleshooting
476
+
477
+ **Problem**: Environment variables not loaded
478
+
479
+ **Solution**: Ensure `dotenv.config()` is called early:
480
+ ```typescript
481
+ import dotenv from 'dotenv';
482
+ dotenv.config(); // Call first!
483
+
484
+ import { config } from './config.js';
485
+ ```
486
+
487
+ **Problem**: Type errors with `as const`
488
+
489
+ **Solution**: Use type assertions for dynamic values:
490
+ ```typescript
491
+ export const config = {
492
+ port: parseInt(process.env.PORT || '3000', 10) as number,
493
+ } as const;
494
+ ```
495
+
496
+ **Problem**: Validation fails in tests
497
+
498
+ **Solution**: Mock environment variables in tests:
499
+ ```typescript
500
+ beforeEach(() => {
501
+ process.env.API_KEY = 'test-key';
502
+ });
503
+ ```
504
+
505
+ ---
506
+
507
+ ## Checklist
508
+
509
+ - [ ] Created `src/config.ts`
510
+ - [ ] Loaded environment variables with dotenv
511
+ - [ ] Defined configuration object with types
512
+ - [ ] Made configuration immutable (`as const`)
513
+ - [ ] Created validation function
514
+ - [ ] Provided sensible defaults
515
+ - [ ] Created `.env.example` template
516
+ - [ ] Added `.env` to `.gitignore`
517
+ - [ ] Called `validateConfig()` at startup
518
+ - [ ] Documented all environment variables
519
+ - [ ] Tested configuration validation
520
+
521
+ ---
522
+
523
+ **Pattern**: Config Management
524
+ **Status**: Production Ready
525
+ **Last Updated**: 2026-02-22