@mrfentmen/technology-runbook-gap-sim-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
+ # Runbook Gap Simulator
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
+ Simulate runbook gap 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-runbook-gap-sim-mcp
9
+ ```
10
+
11
+ ## Use with an MCP client
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "technology-runbook-gap-sim-mcp": {
17
+ "command": "npx",
18
+ "args": ["-y", "@mrfentmen/technology-runbook-gap-sim-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": "runbook_gap_sim-high-error-rate-alert",
33
+ "name": "High error rate alert",
34
+ "category": "detection",
35
+ "tags": [
36
+ "alert",
37
+ "errors"
38
+ ],
39
+ "cost": 1,
40
+ "quantity": 0,
41
+ "acquired": "2026-08-01",
42
+ "lastUsed": "2026-11-10",
43
+ "condition": "new"
44
+ },
45
+ {
46
+ "id": "runbook_gap_sim-queue-backlog-alert",
47
+ "name": "Queue backlog alert",
48
+ "category": "detection",
49
+ "tags": [
50
+ "alert",
51
+ "queue"
52
+ ],
53
+ "cost": 1,
54
+ "quantity": 1,
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_runbook_gap_sim` | Count items by category and show spend, quantity, freshness and the primary metric. |
68
+ | `score_runbook_gap_sim_readiness` | Score readiness from 0 to 100 with coverage, condition, data and metric components. |
69
+ | `audit_runbook_gap_sim_coverage` | Show category coverage ratios and unknown categories. |
70
+ | `flag_runbook_gap_sim_gaps` | List missing categories, expired items, expiring items and dependency gaps. |
71
+ | `rank_runbook_gap_sim_risks` | Rank coverage, expiry, budget, duplicate, condition and data risks. |
72
+ | `check_runbook_gap_sim_constraints` | Check item cap, budget, coverage, expiry and metric targets. |
73
+ | `compare_runbook_gap_sim_baseline` | Compare category counts with the configured baseline. |
74
+ | `estimate_runbook_gap_sim_gap_count` | Calculate the primary metric for every item with mean and pass count. |
75
+ | `find_runbook_gap_sim_quick_wins` | Find low-effort fixes from small gaps, missing data, expiry and duplicates. |
76
+ | `map_runbook_gap_sim_dependencies` | Map dependency groups and show which ones are missing. |
77
+ | `test_runbook_gap_sim_edge_cases` | Test empty, single-item, duplicate-id, zero-cost, expiry and unknown-category cases. |
78
+ | `summarize_runbook_gap_sim_findings` | Summarize counts, top gaps, top risks and data issues. |
79
+ | `prioritize_runbook_gap_sim_fixes` | Rank fixes by impact divided by effort. |
80
+ | `validate_runbook_gap_sim_inputs` | Validate arbitrary JSON and report schema errors and warnings. |
81
+ | `detect_runbook_gap_sim_duplicates` | Group items with the same category and normalized name. |
82
+ | `measure_runbook_gap_sim_variance` | Measure metric spread, category variance and tag diversity. |
83
+ | `benchmark_runbook_gap_sim_options` | Benchmark lean, balanced and full sizes against readiness and data targets. |
84
+ | `explain_runbook_gap_sim_tradeoffs` | Explain size, cost, freshness and data-quality tradeoffs. |
85
+ | `draft_runbook_gap_sim_checklist` | Draft a checklist from gaps, high risks, missing data and budget. |
86
+ | `export_runbook_gap_sim_audit` | Export the full audit with metrics, gaps, risks, constraints and next steps. |
87
+ | `track_runbook_gap_sim_changes` | Compare two snapshots by item id and list added, removed and changed items. |
88
+ | `review_runbook_gap_sim_history` | Review dated snapshots and show readiness, cost and metric trends. |
89
+ | `score_runbook_gap_sim_confidence` | Score trust from data completeness, item count and field coverage. |
90
+ | `recommend_runbook_gap_sim_next_steps` | Recommend the next five actions with quick wins. |
91
+ | `open_runbook_gap_sim_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,224 @@
1
+ export const config = {
2
+ "name": "technology-runbook-gap-sim-mcp",
3
+ "title": "Runbook Gap Simulator",
4
+ "description": "Simulate runbook gap by category, cost, coverage and dependency gaps. Real local JSON analysis, 25 MCP tools, no paywall.",
5
+ "prefix": "runbook_gap_sim",
6
+ "entity": "runbook step simulation",
7
+ "categories": [
8
+ {
9
+ "id": "detection",
10
+ "label": "Detection",
11
+ "baseline": 2
12
+ },
13
+ {
14
+ "id": "diagnosis",
15
+ "label": "Diagnosis",
16
+ "baseline": 2
17
+ },
18
+ {
19
+ "id": "remediation",
20
+ "label": "Remediation",
21
+ "baseline": 3
22
+ },
23
+ {
24
+ "id": "rollback",
25
+ "label": "Rollback",
26
+ "baseline": 2
27
+ },
28
+ {
29
+ "id": "verification",
30
+ "label": "Verification",
31
+ "baseline": 1
32
+ }
33
+ ],
34
+ "metric": {
35
+ "id": "gap_count",
36
+ "label": "Gap count",
37
+ "unit": "gaps",
38
+ "target": 0,
39
+ "direction": "lower"
40
+ },
41
+ "target": {
42
+ "maxItems": 30,
43
+ "budget": 500,
44
+ "coverage": 0.75,
45
+ "expiryDays": 0
46
+ },
47
+ "dependencies": [
48
+ {
49
+ "id": "detection",
50
+ "label": "Detection",
51
+ "categories": [
52
+ "detection"
53
+ ]
54
+ },
55
+ {
56
+ "id": "diagnosis",
57
+ "label": "Diagnosis",
58
+ "categories": [
59
+ "diagnosis"
60
+ ]
61
+ },
62
+ {
63
+ "id": "remediation",
64
+ "label": "Remediation",
65
+ "categories": [
66
+ "remediation"
67
+ ]
68
+ },
69
+ {
70
+ "id": "rollback",
71
+ "label": "Rollback",
72
+ "categories": [
73
+ "rollback"
74
+ ]
75
+ },
76
+ {
77
+ "id": "verification",
78
+ "label": "Verification",
79
+ "categories": [
80
+ "verification"
81
+ ]
82
+ }
83
+ ],
84
+ "sample": [
85
+ {
86
+ "id": "runbook_gap_sim-high-error-rate-alert",
87
+ "name": "High error rate alert",
88
+ "category": "detection",
89
+ "tags": [
90
+ "alert",
91
+ "errors"
92
+ ],
93
+ "cost": 1,
94
+ "quantity": 0,
95
+ "acquired": "2026-08-01",
96
+ "lastUsed": "2026-11-10",
97
+ "condition": "new"
98
+ },
99
+ {
100
+ "id": "runbook_gap_sim-queue-backlog-alert",
101
+ "name": "Queue backlog alert",
102
+ "category": "detection",
103
+ "tags": [
104
+ "alert",
105
+ "queue"
106
+ ],
107
+ "cost": 1,
108
+ "quantity": 1,
109
+ "acquired": "2026-08-01",
110
+ "lastUsed": "2026-11-10",
111
+ "condition": "fair"
112
+ },
113
+ {
114
+ "id": "runbook_gap_sim-trace-lookup",
115
+ "name": "Trace lookup",
116
+ "category": "diagnosis",
117
+ "tags": [
118
+ "trace",
119
+ "diagnosis"
120
+ ],
121
+ "cost": 2,
122
+ "quantity": 0,
123
+ "acquired": "2026-08-01",
124
+ "lastUsed": "2026-11-10",
125
+ "condition": "good"
126
+ },
127
+ {
128
+ "id": "runbook_gap_sim-dependency-health-check",
129
+ "name": "Dependency health check",
130
+ "category": "diagnosis",
131
+ "tags": [
132
+ "dependency"
133
+ ],
134
+ "cost": 1,
135
+ "quantity": 1,
136
+ "acquired": "2026-08-01",
137
+ "lastUsed": "2026-11-10",
138
+ "condition": "fair"
139
+ },
140
+ {
141
+ "id": "runbook_gap_sim-restart-worker",
142
+ "name": "Restart worker",
143
+ "category": "remediation",
144
+ "tags": [
145
+ "restart",
146
+ "worker"
147
+ ],
148
+ "cost": 3,
149
+ "quantity": 0,
150
+ "acquired": "2026-08-01",
151
+ "lastUsed": "2026-11-10",
152
+ "condition": "good"
153
+ },
154
+ {
155
+ "id": "runbook_gap_sim-scale-queue-consumers",
156
+ "name": "Scale queue consumers",
157
+ "category": "remediation",
158
+ "tags": [
159
+ "scale",
160
+ "queue"
161
+ ],
162
+ "cost": 2,
163
+ "quantity": 2,
164
+ "acquired": "2026-08-01",
165
+ "lastUsed": "2026-11-10",
166
+ "condition": "worn"
167
+ },
168
+ {
169
+ "id": "runbook_gap_sim-purge-poison-message",
170
+ "name": "Purge poison message",
171
+ "category": "remediation",
172
+ "tags": [
173
+ "queue",
174
+ "poison"
175
+ ],
176
+ "cost": 1,
177
+ "quantity": 1,
178
+ "acquired": "2026-08-01",
179
+ "lastUsed": "2026-11-10",
180
+ "condition": "fair"
181
+ },
182
+ {
183
+ "id": "runbook_gap_sim-rollback-deployment",
184
+ "name": "Rollback deployment",
185
+ "category": "rollback",
186
+ "tags": [
187
+ "deploy",
188
+ "rollback"
189
+ ],
190
+ "cost": 2,
191
+ "quantity": 0,
192
+ "acquired": "2026-08-01",
193
+ "lastUsed": "2026-11-10",
194
+ "condition": "good"
195
+ },
196
+ {
197
+ "id": "runbook_gap_sim-restore-previous-config",
198
+ "name": "Restore previous config",
199
+ "category": "rollback",
200
+ "tags": [
201
+ "config",
202
+ "rollback"
203
+ ],
204
+ "cost": 1,
205
+ "quantity": 1,
206
+ "acquired": "2026-08-01",
207
+ "lastUsed": "2026-11-10",
208
+ "condition": "fair"
209
+ },
210
+ {
211
+ "id": "runbook_gap_sim-verify-error-budget",
212
+ "name": "Verify error budget",
213
+ "category": "verification",
214
+ "tags": [
215
+ "slo"
216
+ ],
217
+ "cost": 1,
218
+ "quantity": 0,
219
+ "acquired": "2026-08-01",
220
+ "lastUsed": "2026-11-10",
221
+ "condition": "good"
222
+ }
223
+ ]
224
+ };
@@ -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
+ };