@mrfentmen/technology-architecture-decision-plan-mcp 0.0.0-stage → 1.0.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.
package/README.md CHANGED
@@ -1,3 +1,98 @@
1
- # Temporary Holding Version
1
+ # Architecture Decision Planning Audit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Plan architecture decision by category, cost, coverage and dependency gaps. Real local JSON analysis, 25 MCP tools, no paywall.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @mrfentmen/technology-architecture-decision-plan-mcp
9
+ ```
10
+
11
+ ## Use with an MCP client
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "technology-architecture-decision-plan-mcp": {
17
+ "command": "npx",
18
+ "args": ["-y", "@mrfentmen/technology-architecture-decision-plan-mcp"]
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## Input
25
+
26
+ Pass an array, an object with an `items` array, or a JSON file path. Every item needs a name and category. Cost, quantity, dates, condition, tags and notes are optional.
27
+
28
+ ```json
29
+ {
30
+ "items": [
31
+ {
32
+ "id": "architecture_decision_plan-payments-service-boundary",
33
+ "name": "Payments service boundary",
34
+ "category": "context",
35
+ "tags": [
36
+ "context",
37
+ "payments"
38
+ ],
39
+ "cost": 4,
40
+ "quantity": 0,
41
+ "acquired": "2026-08-01",
42
+ "lastUsed": "2026-11-10",
43
+ "condition": "good"
44
+ },
45
+ {
46
+ "id": "architecture_decision_plan-event-bus-ownership",
47
+ "name": "Event bus ownership",
48
+ "category": "context",
49
+ "tags": [
50
+ "context",
51
+ "events"
52
+ ],
53
+ "cost": 3,
54
+ "quantity": 2,
55
+ "acquired": "2026-08-01",
56
+ "lastUsed": "2026-11-10",
57
+ "condition": "fair"
58
+ }
59
+ ]
60
+ }
61
+ ```
62
+
63
+ ## Tools (25)
64
+
65
+ | Tool | What it does |
66
+ | --- | --- |
67
+ | `inventory_architecture_decision_plan` | Count items by category and show spend, quantity, freshness and the primary metric. |
68
+ | `score_architecture_decision_plan_readiness` | Score readiness from 0 to 100 with coverage, condition, data and metric components. |
69
+ | `audit_architecture_decision_plan_coverage` | Show category coverage ratios and unknown categories. |
70
+ | `flag_architecture_decision_plan_gaps` | List missing categories, expired items, expiring items and dependency gaps. |
71
+ | `rank_architecture_decision_plan_risks` | Rank coverage, expiry, budget, duplicate, condition and data risks. |
72
+ | `check_architecture_decision_plan_constraints` | Check item cap, budget, coverage, expiry and metric targets. |
73
+ | `compare_architecture_decision_plan_baseline` | Compare category counts with the configured baseline. |
74
+ | `estimate_architecture_decision_plan_open_questions` | Calculate the primary metric for every item with mean and pass count. |
75
+ | `find_architecture_decision_plan_quick_wins` | Find low-effort fixes from small gaps, missing data, expiry and duplicates. |
76
+ | `map_architecture_decision_plan_dependencies` | Map dependency groups and show which ones are missing. |
77
+ | `test_architecture_decision_plan_edge_cases` | Test empty, single-item, duplicate-id, zero-cost, expiry and unknown-category cases. |
78
+ | `summarize_architecture_decision_plan_findings` | Summarize counts, top gaps, top risks and data issues. |
79
+ | `prioritize_architecture_decision_plan_fixes` | Rank fixes by impact divided by effort. |
80
+ | `validate_architecture_decision_plan_inputs` | Validate arbitrary JSON and report schema errors and warnings. |
81
+ | `detect_architecture_decision_plan_duplicates` | Group items with the same category and normalized name. |
82
+ | `measure_architecture_decision_plan_variance` | Measure metric spread, category variance and tag diversity. |
83
+ | `benchmark_architecture_decision_plan_options` | Benchmark lean, balanced and full sizes against readiness and data targets. |
84
+ | `explain_architecture_decision_plan_tradeoffs` | Explain size, cost, freshness and data-quality tradeoffs. |
85
+ | `draft_architecture_decision_plan_checklist` | Draft a checklist from gaps, high risks, missing data and budget. |
86
+ | `export_architecture_decision_plan_audit` | Export the full audit with metrics, gaps, risks, constraints and next steps. |
87
+ | `track_architecture_decision_plan_changes` | Compare two snapshots by item id and list added, removed and changed items. |
88
+ | `review_architecture_decision_plan_history` | Review dated snapshots and show readiness, cost and metric trends. |
89
+ | `score_architecture_decision_plan_confidence` | Score trust from data completeness, item count and field coverage. |
90
+ | `recommend_architecture_decision_plan_next_steps` | Recommend the next five actions with quick wins. |
91
+ | `open_architecture_decision_plan_questions` | List open questions that block a better audit. |
92
+
93
+ ## Rules
94
+
95
+ - Local computation only. No network calls, no telemetry, no paywall.
96
+ - Missing dates, costs and quantities are reported, not invented.
97
+ - Dates use `YYYY-MM-DD`.
98
+ - MIT licence.
@@ -0,0 +1,2 @@
1
+ import type { ServerConfig } from "./engine.js";
2
+ export declare const config: ServerConfig;
package/dist/config.js ADDED
@@ -0,0 +1,211 @@
1
+ export const config = {
2
+ "name": "technology-architecture-decision-plan-mcp",
3
+ "title": "Architecture Decision Planning Audit",
4
+ "description": "Plan architecture decision by category, cost, coverage and dependency gaps. Real local JSON analysis, 25 MCP tools, no paywall.",
5
+ "prefix": "architecture_decision_plan",
6
+ "entity": "architecture decision plan",
7
+ "categories": [
8
+ {
9
+ "id": "context",
10
+ "label": "Context",
11
+ "baseline": 2
12
+ },
13
+ {
14
+ "id": "decision",
15
+ "label": "Decision",
16
+ "baseline": 2
17
+ },
18
+ {
19
+ "id": "consequences",
20
+ "label": "Consequences",
21
+ "baseline": 2
22
+ },
23
+ {
24
+ "id": "alternatives",
25
+ "label": "Alternatives",
26
+ "baseline": 2
27
+ },
28
+ {
29
+ "id": "status",
30
+ "label": "Status",
31
+ "baseline": 1
32
+ }
33
+ ],
34
+ "metric": {
35
+ "id": "open_questions",
36
+ "label": "Open questions",
37
+ "unit": "questions",
38
+ "target": 0,
39
+ "direction": "lower"
40
+ },
41
+ "target": {
42
+ "maxItems": 30,
43
+ "budget": 800,
44
+ "coverage": 0.75,
45
+ "expiryDays": 0
46
+ },
47
+ "dependencies": [
48
+ {
49
+ "id": "context",
50
+ "label": "Context",
51
+ "categories": [
52
+ "context"
53
+ ]
54
+ },
55
+ {
56
+ "id": "decision",
57
+ "label": "Decision",
58
+ "categories": [
59
+ "decision"
60
+ ]
61
+ },
62
+ {
63
+ "id": "consequences",
64
+ "label": "Consequences",
65
+ "categories": [
66
+ "consequences"
67
+ ]
68
+ },
69
+ {
70
+ "id": "alternatives",
71
+ "label": "Alternatives",
72
+ "categories": [
73
+ "alternatives"
74
+ ]
75
+ },
76
+ {
77
+ "id": "status",
78
+ "label": "Status",
79
+ "categories": [
80
+ "status"
81
+ ]
82
+ }
83
+ ],
84
+ "sample": [
85
+ {
86
+ "id": "architecture_decision_plan-payments-service-boundary",
87
+ "name": "Payments service boundary",
88
+ "category": "context",
89
+ "tags": [
90
+ "context",
91
+ "payments"
92
+ ],
93
+ "cost": 4,
94
+ "quantity": 0,
95
+ "acquired": "2026-08-01",
96
+ "lastUsed": "2026-11-10",
97
+ "condition": "good"
98
+ },
99
+ {
100
+ "id": "architecture_decision_plan-event-bus-ownership",
101
+ "name": "Event bus ownership",
102
+ "category": "context",
103
+ "tags": [
104
+ "context",
105
+ "events"
106
+ ],
107
+ "cost": 3,
108
+ "quantity": 2,
109
+ "acquired": "2026-08-01",
110
+ "lastUsed": "2026-11-10",
111
+ "condition": "fair"
112
+ },
113
+ {
114
+ "id": "architecture_decision_plan-adopt-postgresql",
115
+ "name": "Adopt PostgreSQL",
116
+ "category": "decision",
117
+ "tags": [
118
+ "decision",
119
+ "database"
120
+ ],
121
+ "cost": 0,
122
+ "quantity": 0,
123
+ "acquired": "2026-08-01",
124
+ "lastUsed": "2026-11-10",
125
+ "condition": "good"
126
+ },
127
+ {
128
+ "id": "architecture_decision_plan-use-async-jobs",
129
+ "name": "Use async jobs",
130
+ "category": "decision",
131
+ "tags": [
132
+ "decision",
133
+ "jobs"
134
+ ],
135
+ "cost": 2,
136
+ "quantity": 1,
137
+ "acquired": "2026-08-01",
138
+ "lastUsed": "2026-11-10",
139
+ "condition": "fair"
140
+ },
141
+ {
142
+ "id": "architecture_decision_plan-postgresql-operating-cost",
143
+ "name": "PostgreSQL operating cost",
144
+ "category": "consequences",
145
+ "tags": [
146
+ "consequence",
147
+ "database"
148
+ ],
149
+ "cost": 2,
150
+ "quantity": 0,
151
+ "acquired": "2026-08-01",
152
+ "lastUsed": "2026-11-10",
153
+ "condition": "good"
154
+ },
155
+ {
156
+ "id": "architecture_decision_plan-async-retry-complexity",
157
+ "name": "Async retry complexity",
158
+ "category": "consequences",
159
+ "tags": [
160
+ "consequence",
161
+ "jobs"
162
+ ],
163
+ "cost": 3,
164
+ "quantity": 2,
165
+ "acquired": "2026-08-01",
166
+ "lastUsed": "2026-11-10",
167
+ "condition": "fair"
168
+ },
169
+ {
170
+ "id": "architecture_decision_plan-managed-queue-alternative",
171
+ "name": "Managed queue alternative",
172
+ "category": "alternatives",
173
+ "tags": [
174
+ "alternative",
175
+ "queue"
176
+ ],
177
+ "cost": 2,
178
+ "quantity": 1,
179
+ "acquired": "2026-08-01",
180
+ "lastUsed": "2026-11-10",
181
+ "condition": "good"
182
+ },
183
+ {
184
+ "id": "architecture_decision_plan-single-database-alternative",
185
+ "name": "Single database alternative",
186
+ "category": "alternatives",
187
+ "tags": [
188
+ "alternative",
189
+ "database"
190
+ ],
191
+ "cost": 1,
192
+ "quantity": 0,
193
+ "acquired": "2026-08-01",
194
+ "lastUsed": "2026-11-10",
195
+ "condition": "good"
196
+ },
197
+ {
198
+ "id": "architecture_decision_plan-adr-001-status",
199
+ "name": "ADR-001 status",
200
+ "category": "status",
201
+ "tags": [
202
+ "accepted"
203
+ ],
204
+ "cost": 0,
205
+ "quantity": 0,
206
+ "acquired": "2026-08-01",
207
+ "lastUsed": "2026-11-10",
208
+ "condition": "new"
209
+ }
210
+ ]
211
+ };
@@ -0,0 +1,270 @@
1
+ import { z } from "zod";
2
+ export declare const CONDITIONS: readonly ["new", "good", "fair", "worn"];
3
+ export type Condition = (typeof CONDITIONS)[number];
4
+ export interface CategoryConfig {
5
+ id: string;
6
+ label: string;
7
+ baseline: number;
8
+ }
9
+ export interface MetricConfig {
10
+ id: string;
11
+ label: string;
12
+ unit: string;
13
+ target: number;
14
+ direction: "lower" | "higher";
15
+ }
16
+ export interface DependencyGroup {
17
+ id: string;
18
+ label: string;
19
+ categories: string[];
20
+ }
21
+ export interface ServerConfig {
22
+ name: string;
23
+ title: string;
24
+ description: string;
25
+ prefix: string;
26
+ entity: string;
27
+ categories: CategoryConfig[];
28
+ metric: MetricConfig;
29
+ target: {
30
+ maxItems: number;
31
+ budget: number | null;
32
+ coverage: number;
33
+ expiryDays: number;
34
+ };
35
+ dependencies: DependencyGroup[];
36
+ sample: RawItem[];
37
+ }
38
+ export declare const itemSchema: z.ZodObject<{
39
+ id: z.ZodOptional<z.ZodString>;
40
+ name: z.ZodString;
41
+ category: z.ZodString;
42
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
43
+ cost: z.ZodOptional<z.ZodNumber>;
44
+ quantity: z.ZodOptional<z.ZodNumber>;
45
+ acquired: z.ZodOptional<z.ZodString>;
46
+ expires: z.ZodOptional<z.ZodString>;
47
+ lastUsed: z.ZodOptional<z.ZodString>;
48
+ condition: z.ZodOptional<z.ZodEnum<["new", "good", "fair", "worn"]>>;
49
+ notes: z.ZodOptional<z.ZodString>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ name: string;
52
+ category: string;
53
+ id?: string | undefined;
54
+ tags?: string[] | undefined;
55
+ cost?: number | undefined;
56
+ quantity?: number | undefined;
57
+ acquired?: string | undefined;
58
+ expires?: string | undefined;
59
+ lastUsed?: string | undefined;
60
+ condition?: "new" | "good" | "fair" | "worn" | undefined;
61
+ notes?: string | undefined;
62
+ }, {
63
+ name: string;
64
+ category: string;
65
+ id?: string | undefined;
66
+ tags?: string[] | undefined;
67
+ cost?: number | undefined;
68
+ quantity?: number | undefined;
69
+ acquired?: string | undefined;
70
+ expires?: string | undefined;
71
+ lastUsed?: string | undefined;
72
+ condition?: "new" | "good" | "fair" | "worn" | undefined;
73
+ notes?: string | undefined;
74
+ }>;
75
+ export type RawItem = z.infer<typeof itemSchema>;
76
+ export declare const targetSchema: z.ZodObject<{
77
+ maxItems: z.ZodOptional<z.ZodNumber>;
78
+ budget: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
79
+ coverage: z.ZodOptional<z.ZodNumber>;
80
+ expiryDays: z.ZodOptional<z.ZodNumber>;
81
+ }, "strip", z.ZodTypeAny, {
82
+ maxItems?: number | undefined;
83
+ budget?: number | null | undefined;
84
+ coverage?: number | undefined;
85
+ expiryDays?: number | undefined;
86
+ }, {
87
+ maxItems?: number | undefined;
88
+ budget?: number | null | undefined;
89
+ coverage?: number | undefined;
90
+ expiryDays?: number | undefined;
91
+ }>;
92
+ export type TargetInput = z.infer<typeof targetSchema>;
93
+ export interface TargetProfile {
94
+ maxItems: number;
95
+ budget: number | null;
96
+ coverage: number;
97
+ expiryDays: number;
98
+ }
99
+ export interface DataIssue {
100
+ code: string;
101
+ severity: "error" | "warning";
102
+ message: string;
103
+ itemId?: string;
104
+ }
105
+ export interface CollectionItem {
106
+ id: string;
107
+ name: string;
108
+ category: string;
109
+ tags: string[];
110
+ cost: number | null;
111
+ quantity: number | null;
112
+ acquired: string | null;
113
+ expires: string | null;
114
+ lastUsed: string | null;
115
+ condition: Condition;
116
+ notes: string | null;
117
+ dataFields: number;
118
+ }
119
+ export interface LoadedCollection {
120
+ items: CollectionItem[];
121
+ issues: DataIssue[];
122
+ source: string;
123
+ rawCount: number;
124
+ }
125
+ export interface Gap {
126
+ type: "category" | "expiry" | "dependency";
127
+ key: string;
128
+ missing: number;
129
+ severity: "high" | "medium" | "low";
130
+ message: string;
131
+ }
132
+ export interface Risk {
133
+ code: string;
134
+ severity: "critical" | "high" | "medium" | "low";
135
+ message: string;
136
+ impact: number;
137
+ }
138
+ export interface Constraint {
139
+ key: string;
140
+ label: string;
141
+ pass: boolean;
142
+ actual: unknown;
143
+ target: unknown;
144
+ message: string;
145
+ }
146
+ export interface DuplicateGroup {
147
+ key: string;
148
+ count: number;
149
+ ids: string[];
150
+ names: string[];
151
+ }
152
+ export interface Fix {
153
+ action: string;
154
+ impact: number;
155
+ effort: number;
156
+ score: number;
157
+ source: string;
158
+ }
159
+ export interface Analysis {
160
+ target: TargetProfile;
161
+ itemCount: number;
162
+ items: CollectionItem[];
163
+ categoryCounts: Record<string, number>;
164
+ unknownCategories: string[];
165
+ totalCost: number;
166
+ knownCostCount: number;
167
+ totalQuantity: number;
168
+ knownQuantityCount: number;
169
+ expired: CollectionItem[];
170
+ expiring: CollectionItem[];
171
+ metricRows: Array<{
172
+ id: string;
173
+ name: string;
174
+ value: number | null;
175
+ }>;
176
+ metricMean: number;
177
+ metricPassCount: number;
178
+ metricKnownCount: number;
179
+ categoryCoverage: Record<string, number>;
180
+ coverageScore: number;
181
+ conditionScore: number;
182
+ dataCompleteness: number;
183
+ readiness: number;
184
+ confidence: number;
185
+ gaps: Gap[];
186
+ risks: Risk[];
187
+ constraints: Constraint[];
188
+ duplicates: DuplicateGroup[];
189
+ variance: {
190
+ metric: {
191
+ count: number;
192
+ mean: number;
193
+ variance: number;
194
+ stddev: number;
195
+ min: number;
196
+ max: number;
197
+ };
198
+ categories: {
199
+ mean: number;
200
+ variance: number;
201
+ };
202
+ tagDiversity: number;
203
+ };
204
+ benchmark: {
205
+ rows: Array<{
206
+ metric: string;
207
+ value: number;
208
+ target: string;
209
+ pass: boolean;
210
+ }>;
211
+ passed: number;
212
+ total: number;
213
+ verdict: "strong" | "mixed" | "thin";
214
+ };
215
+ options: Array<{
216
+ name: string;
217
+ maxItems: number;
218
+ expected: Record<string, number>;
219
+ fit: number;
220
+ }>;
221
+ tradeoffs: Array<{
222
+ title: string;
223
+ current: string;
224
+ note: string;
225
+ }>;
226
+ checklist: Array<{
227
+ item: string;
228
+ done: boolean;
229
+ }>;
230
+ quickWins: Fix[];
231
+ fixes: Fix[];
232
+ nextSteps: Fix[];
233
+ questions: string[];
234
+ edgeCases: string[];
235
+ dataIssues: DataIssue[];
236
+ summary: {
237
+ items: number;
238
+ readiness: number;
239
+ confidence: number;
240
+ totalCost: number;
241
+ metricMean: number;
242
+ gaps: number;
243
+ risks: number;
244
+ duplicates: number;
245
+ dataIssues: number;
246
+ };
247
+ }
248
+ export declare function loadCollection(input: {
249
+ items?: unknown[];
250
+ content?: string;
251
+ path?: string;
252
+ cwd?: string;
253
+ }): Promise<LoadedCollection>;
254
+ export declare function normalizeTarget(input?: TargetInput): TargetProfile;
255
+ export declare function analyze(loaded: LoadedCollection, targetInput?: TargetProfile): Analysis;
256
+ export declare function changeSet(before: LoadedCollection, after: LoadedCollection): {
257
+ counts: {
258
+ before: number;
259
+ after: number;
260
+ added: number;
261
+ removed: number;
262
+ changed: number;
263
+ };
264
+ added: CollectionItem[];
265
+ removed: CollectionItem[];
266
+ changed: {
267
+ before: CollectionItem | undefined;
268
+ after: CollectionItem;
269
+ }[];
270
+ };