@morphism-systems/mcp-server 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.
- package/README.md +40 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +356 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# @morphism-systems/mcp-server
|
|
2
|
+
|
|
3
|
+
Governance MCP server for AI agents. Validate governance policies, compute maturity scores, track convergence and drift metrics.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @morphism-systems/mcp-server
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## MCP Config
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"morphism-governance": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": ["@morphism-systems/mcp-server"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Tools
|
|
25
|
+
|
|
26
|
+
| Tool | Description |
|
|
27
|
+
|------|-------------|
|
|
28
|
+
| `governance_validate` | Run full governance validation pipeline |
|
|
29
|
+
| `governance_score` | Compute maturity score (0-105) |
|
|
30
|
+
| `compute_kappa` | Convergence metric (kappa < 1 = converging) |
|
|
31
|
+
| `compute_delta` | Drift metric between governance states |
|
|
32
|
+
| `ssot_verify` | Verify SSOT integrity |
|
|
33
|
+
|
|
34
|
+
## Why Morphism
|
|
35
|
+
|
|
36
|
+
Governance-as-code with mathematical guarantees. [Learn more](https://morphism.systems).
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
|
|
6
|
+
// src/server.ts
|
|
7
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
|
|
9
|
+
// src/tools/validate.ts
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { execSync } from "child_process";
|
|
12
|
+
var ValidateInput = z.object({
|
|
13
|
+
project_path: z.string().describe("Path to the project root to validate"),
|
|
14
|
+
mode: z.enum(["categorical", "pipeline", "full"]).optional().default("full").describe(
|
|
15
|
+
"categorical: naturality + sheaf + kappa only; pipeline: legacy file checks; full: both"
|
|
16
|
+
)
|
|
17
|
+
});
|
|
18
|
+
function runPython(cmd, cwd) {
|
|
19
|
+
try {
|
|
20
|
+
const stdout = execSync(cmd, { cwd, encoding: "utf-8", timeout: 6e4 });
|
|
21
|
+
return { stdout, stderr: "", ok: true };
|
|
22
|
+
} catch (err) {
|
|
23
|
+
return { stdout: err.stdout || "", stderr: err.stderr || "", ok: false };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function governanceValidate(input) {
|
|
27
|
+
const { project_path, mode } = input;
|
|
28
|
+
const catScript = `
|
|
29
|
+
import json, sys
|
|
30
|
+
sys.path.insert(0, '${project_path}/src')
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from morphism.governance_category import full_categorical_validation
|
|
33
|
+
result = full_categorical_validation(Path('${project_path}'))
|
|
34
|
+
print(json.dumps(result))
|
|
35
|
+
`;
|
|
36
|
+
const catResult = runPython(
|
|
37
|
+
`python3 -c "${catScript.replace(/\n/g, "; ").replace(/"/g, '\\"')}"`,
|
|
38
|
+
project_path
|
|
39
|
+
);
|
|
40
|
+
let categorical = null;
|
|
41
|
+
if (catResult.ok && catResult.stdout.trim()) {
|
|
42
|
+
try {
|
|
43
|
+
categorical = JSON.parse(catResult.stdout.trim());
|
|
44
|
+
} catch (_) {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
let pipelineOutput = "";
|
|
48
|
+
let pipelineOk = true;
|
|
49
|
+
if (mode === "pipeline" || mode === "full") {
|
|
50
|
+
const pipe = runPython("python3 scripts/verify_pipeline.py", project_path);
|
|
51
|
+
pipelineOutput = pipe.stdout + pipe.stderr;
|
|
52
|
+
pipelineOk = pipe.ok;
|
|
53
|
+
}
|
|
54
|
+
if (categorical) {
|
|
55
|
+
const proofScript = `
|
|
56
|
+
import json, sys
|
|
57
|
+
sys.path.insert(0, '${project_path}/src')
|
|
58
|
+
from pathlib import Path
|
|
59
|
+
from morphism.governance_category import full_categorical_validation, compute_runtime_evidence
|
|
60
|
+
from morphism.proof.artifact import generate_proof_artifact, write_proof_artifact
|
|
61
|
+
root = Path('${project_path}')
|
|
62
|
+
cat = full_categorical_validation(root)
|
|
63
|
+
gov_vec = cat['governance_vector']
|
|
64
|
+
kappa = cat['kappa']
|
|
65
|
+
proof = generate_proof_artifact(
|
|
66
|
+
root=root,
|
|
67
|
+
naturality_result=cat['naturality'],
|
|
68
|
+
chain_morphisms=[v['morphism'] for v in cat['naturality'].get('verdicts', [])],
|
|
69
|
+
chain_source='Policy',
|
|
70
|
+
chain_target='Runbook',
|
|
71
|
+
convergence_data={'kappa': kappa, 'governance_vector': gov_vec, 'vector_labels': cat['vector_labels'], 'l_inf_distance': kappa},
|
|
72
|
+
sheaf_radius=cat['sheaf']['consistency_radius'],
|
|
73
|
+
drift_types=cat['sheaf']['drift_types'],
|
|
74
|
+
governance_score=sum(gov_vec) / len(gov_vec) if gov_vec else 0.0,
|
|
75
|
+
)
|
|
76
|
+
p = write_proof_artifact(proof, root)
|
|
77
|
+
print(str(p))
|
|
78
|
+
`;
|
|
79
|
+
const proofResult = runPython(
|
|
80
|
+
`python3 -c "${proofScript.replace(/\n/g, "; ").replace(/"/g, '\\"')}"`,
|
|
81
|
+
project_path
|
|
82
|
+
);
|
|
83
|
+
const proofPath = proofResult.ok ? proofResult.stdout.trim() : void 0;
|
|
84
|
+
const nat = categorical.naturality || {};
|
|
85
|
+
return {
|
|
86
|
+
valid: categorical.all_valid && pipelineOk,
|
|
87
|
+
kappa: categorical.kappa,
|
|
88
|
+
governance_vector: categorical.governance_vector,
|
|
89
|
+
vector_labels: categorical.vector_labels,
|
|
90
|
+
naturality: {
|
|
91
|
+
all_natural: nat.all_natural ?? false,
|
|
92
|
+
summary: nat.summary ?? "",
|
|
93
|
+
total: nat.total ?? 0
|
|
94
|
+
},
|
|
95
|
+
sheaf: {
|
|
96
|
+
consistency_radius: categorical.sheaf?.consistency_radius ?? 0,
|
|
97
|
+
severity: categorical.sheaf?.severity ?? "unknown",
|
|
98
|
+
drift_types: categorical.sheaf?.drift_types ?? []
|
|
99
|
+
},
|
|
100
|
+
categorical_errors: categorical.categorical_errors ?? [],
|
|
101
|
+
proof_artifact_path: proofPath,
|
|
102
|
+
output: pipelineOutput || void 0
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const legacy = runPython("python3 scripts/verify_pipeline.py", project_path);
|
|
106
|
+
return {
|
|
107
|
+
valid: legacy.ok,
|
|
108
|
+
output: legacy.stdout,
|
|
109
|
+
error: legacy.stderr || catResult.stderr || void 0
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/tools/score.ts
|
|
114
|
+
import { z as z2 } from "zod";
|
|
115
|
+
var ScoreInput = z2.object({
|
|
116
|
+
project_path: z2.string().describe("Path to the project root")
|
|
117
|
+
});
|
|
118
|
+
async function governanceScore(input) {
|
|
119
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
120
|
+
try {
|
|
121
|
+
const result = execSync3(
|
|
122
|
+
`python3 scripts/maturity_score.py --ci --threshold 0`,
|
|
123
|
+
{ cwd: input.project_path, encoding: "utf-8", timeout: 3e4 }
|
|
124
|
+
);
|
|
125
|
+
const match = result.match(/(\d+)\s*\/\s*(\d+)/);
|
|
126
|
+
if (match) {
|
|
127
|
+
return { score: parseInt(match[1]), total: parseInt(match[2]), output: result };
|
|
128
|
+
}
|
|
129
|
+
return { output: result };
|
|
130
|
+
} catch (err) {
|
|
131
|
+
const error = err;
|
|
132
|
+
return { error: error.stderr || error.stdout || "Unknown error" };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/tools/kappa.ts
|
|
137
|
+
import { z as z3 } from "zod";
|
|
138
|
+
import { execSync as execSync2 } from "child_process";
|
|
139
|
+
var KappaInput = z3.object({
|
|
140
|
+
scores: z3.array(z3.number()).optional().describe("Legacy scalar score sequence (backward compat)"),
|
|
141
|
+
governance_vector: z3.array(z3.number()).optional().describe(
|
|
142
|
+
"7-dimensional governance state vector [Policy, GitHook, CIWorkflow, SSOTAtom, Document, SecurityGate, Runbook]"
|
|
143
|
+
),
|
|
144
|
+
kappa_history: z3.array(z3.number()).optional().describe(
|
|
145
|
+
"Historical kappa values for convergence trajectory check"
|
|
146
|
+
),
|
|
147
|
+
project_path: z3.string().optional().describe(
|
|
148
|
+
"If provided, compute vector from live project state (ignores governance_vector)"
|
|
149
|
+
),
|
|
150
|
+
tolerance: z3.number().optional().default(1e-6)
|
|
151
|
+
});
|
|
152
|
+
var GOVERNANCE_OBJECTS = [
|
|
153
|
+
"Policy",
|
|
154
|
+
"GitHook",
|
|
155
|
+
"CIWorkflow",
|
|
156
|
+
"SSOTAtom",
|
|
157
|
+
"Document",
|
|
158
|
+
"SecurityGate",
|
|
159
|
+
"Runbook"
|
|
160
|
+
];
|
|
161
|
+
var WEIGHTS = {
|
|
162
|
+
Policy: 1.5,
|
|
163
|
+
GitHook: 1.2,
|
|
164
|
+
CIWorkflow: 1.2,
|
|
165
|
+
SSOTAtom: 1,
|
|
166
|
+
Document: 0.8,
|
|
167
|
+
SecurityGate: 1.5,
|
|
168
|
+
Runbook: 0.9
|
|
169
|
+
};
|
|
170
|
+
function vectorKappa(v, ideal = []) {
|
|
171
|
+
const n = GOVERNANCE_OBJECTS.length;
|
|
172
|
+
if (v.length !== n) return NaN;
|
|
173
|
+
const target = ideal.length === n ? ideal : new Array(n).fill(1);
|
|
174
|
+
return Math.max(...GOVERNANCE_OBJECTS.map(
|
|
175
|
+
(obj, i) => (WEIGHTS[obj] ?? 1) * Math.abs(target[i] - v[i])
|
|
176
|
+
));
|
|
177
|
+
}
|
|
178
|
+
function legacyKappa(scores, tolerance) {
|
|
179
|
+
if (scores.length < 3) return 0;
|
|
180
|
+
const deltas = scores.slice(1).map((s, i) => Math.abs(s - scores[i]));
|
|
181
|
+
if (deltas[deltas.length - 1] <= tolerance) return 0;
|
|
182
|
+
const ratios = [];
|
|
183
|
+
for (let i = 1; i < deltas.length; i++) {
|
|
184
|
+
if (deltas[i - 1] > tolerance) ratios.push(deltas[i] / deltas[i - 1]);
|
|
185
|
+
}
|
|
186
|
+
return ratios.length > 0 ? ratios.reduce((a, b) => a + b, 0) / ratios.length : 0;
|
|
187
|
+
}
|
|
188
|
+
function isConverging(history, tolerance = 1e-4) {
|
|
189
|
+
for (let i = 0; i < history.length - 1; i++) {
|
|
190
|
+
if (history[i + 1] > history[i] + tolerance) return false;
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
function computeKappa(input) {
|
|
195
|
+
const tolerance = input.tolerance ?? 1e-6;
|
|
196
|
+
if (input.project_path) {
|
|
197
|
+
try {
|
|
198
|
+
const out = execSync2(
|
|
199
|
+
`python3 -c "
|
|
200
|
+
import json, sys
|
|
201
|
+
sys.path.insert(0, '${input.project_path}/src')
|
|
202
|
+
from pathlib import Path
|
|
203
|
+
from morphism.governance_category import compute_runtime_evidence, compute_governance_vector, compute_vector_kappa
|
|
204
|
+
ev, _ = compute_runtime_evidence(Path('${input.project_path}'))
|
|
205
|
+
vec = compute_governance_vector(ev)
|
|
206
|
+
k = compute_vector_kappa(vec)
|
|
207
|
+
print(json.dumps({'vector': vec, 'kappa': k}))
|
|
208
|
+
"`,
|
|
209
|
+
{ cwd: input.project_path, encoding: "utf-8", timeout: 3e4 }
|
|
210
|
+
);
|
|
211
|
+
const parsed = JSON.parse(out.trim());
|
|
212
|
+
const kappa = parsed.kappa;
|
|
213
|
+
const history = input.kappa_history ? [...input.kappa_history, kappa] : [kappa];
|
|
214
|
+
return {
|
|
215
|
+
kappa,
|
|
216
|
+
governance_vector: parsed.vector,
|
|
217
|
+
vector_labels: GOVERNANCE_OBJECTS,
|
|
218
|
+
converging: isConverging(history),
|
|
219
|
+
kappa_history: history,
|
|
220
|
+
method: "vector_linf_formal",
|
|
221
|
+
interpretation: interpretKappa(kappa)
|
|
222
|
+
};
|
|
223
|
+
} catch (_) {
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (input.governance_vector && input.governance_vector.length === GOVERNANCE_OBJECTS.length) {
|
|
227
|
+
const kappa = vectorKappa(input.governance_vector);
|
|
228
|
+
const history = input.kappa_history ? [...input.kappa_history, kappa] : [kappa];
|
|
229
|
+
return {
|
|
230
|
+
kappa,
|
|
231
|
+
governance_vector: input.governance_vector,
|
|
232
|
+
vector_labels: GOVERNANCE_OBJECTS,
|
|
233
|
+
converging: isConverging(history),
|
|
234
|
+
kappa_history: history,
|
|
235
|
+
method: "vector_linf_formal",
|
|
236
|
+
interpretation: interpretKappa(kappa)
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (input.scores && input.scores.length >= 2) {
|
|
240
|
+
const kappa = legacyKappa(input.scores, tolerance);
|
|
241
|
+
return {
|
|
242
|
+
kappa,
|
|
243
|
+
converges: kappa < 1,
|
|
244
|
+
method: "legacy_scalar_ratio",
|
|
245
|
+
interpretation: kappa === 0 ? "Converged or insufficient data" : kappa < 1 ? `Converging (\u03BA=${kappa.toFixed(4)}) \u2014 NOTE: scalar heuristic, use governance_vector for formal \u03BA` : `Diverging (\u03BA=${kappa.toFixed(4)})`
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
return { error: "Provide governance_vector (preferred), scores, or project_path" };
|
|
249
|
+
}
|
|
250
|
+
function interpretKappa(k) {
|
|
251
|
+
if (k === 0) return "Fixed point: governance is fully compliant";
|
|
252
|
+
if (k < 0.1) return `\u03BA=${k.toFixed(3)}: Excellent \u2014 near fixed point`;
|
|
253
|
+
if (k < 0.3) return `\u03BA=${k.toFixed(3)}: Good \u2014 governance converging`;
|
|
254
|
+
if (k < 0.6) return `\u03BA=${k.toFixed(3)}: WARNING \u2014 significant compliance gaps`;
|
|
255
|
+
return `\u03BA=${k.toFixed(3)}: CRITICAL \u2014 governance far from fixed point`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/tools/delta.ts
|
|
259
|
+
import { z as z4 } from "zod";
|
|
260
|
+
var DeltaInput = z4.object({
|
|
261
|
+
baseline: z4.union([z4.number(), z4.array(z4.number())]).describe("Baseline state"),
|
|
262
|
+
current: z4.union([z4.number(), z4.array(z4.number())]).describe("Current state")
|
|
263
|
+
});
|
|
264
|
+
function robustnessDelta(baseline, current) {
|
|
265
|
+
if (typeof baseline === "number" && typeof current === "number") {
|
|
266
|
+
return Math.abs(current - baseline);
|
|
267
|
+
}
|
|
268
|
+
if (Array.isArray(baseline) && Array.isArray(current)) {
|
|
269
|
+
if (baseline.length !== current.length) return Infinity;
|
|
270
|
+
if (baseline.length === 0) return 0;
|
|
271
|
+
const sum = baseline.reduce((acc, b, i) => acc + Math.abs(current[i] - b), 0);
|
|
272
|
+
return sum / baseline.length;
|
|
273
|
+
}
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
function computeDelta(input) {
|
|
277
|
+
const delta = robustnessDelta(input.baseline, input.current);
|
|
278
|
+
return {
|
|
279
|
+
delta,
|
|
280
|
+
drifted: delta > 0,
|
|
281
|
+
severity: delta === 0 ? "none" : delta < 5 ? "low" : delta < 15 ? "medium" : "high"
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// src/tools/ssot.ts
|
|
286
|
+
import { z as z5 } from "zod";
|
|
287
|
+
var SsotInput = z5.object({
|
|
288
|
+
project_path: z5.string().describe("Path to the project root")
|
|
289
|
+
});
|
|
290
|
+
async function ssotVerify(input) {
|
|
291
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
292
|
+
try {
|
|
293
|
+
const result = execSync3(
|
|
294
|
+
`python3 scripts/ssot_verify.py`,
|
|
295
|
+
{ cwd: input.project_path, encoding: "utf-8", timeout: 3e4 }
|
|
296
|
+
);
|
|
297
|
+
return { valid: true, output: result };
|
|
298
|
+
} catch (err) {
|
|
299
|
+
const error = err;
|
|
300
|
+
return { valid: false, output: error.stdout || "", error: error.stderr || "" };
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/server.ts
|
|
305
|
+
function createServer() {
|
|
306
|
+
const server2 = new McpServer({
|
|
307
|
+
name: "morphism-governance",
|
|
308
|
+
version: "0.1.0"
|
|
309
|
+
});
|
|
310
|
+
server2.tool(
|
|
311
|
+
"governance_validate",
|
|
312
|
+
"Run the full governance validation pipeline on a project.",
|
|
313
|
+
ValidateInput.shape,
|
|
314
|
+
async (input) => ({
|
|
315
|
+
content: [{ type: "text", text: JSON.stringify(await governanceValidate(input), null, 2) }]
|
|
316
|
+
})
|
|
317
|
+
);
|
|
318
|
+
server2.tool(
|
|
319
|
+
"governance_score",
|
|
320
|
+
"Compute the governance maturity score (0-105) for a project.",
|
|
321
|
+
ScoreInput.shape,
|
|
322
|
+
async (input) => ({
|
|
323
|
+
content: [{ type: "text", text: JSON.stringify(await governanceScore(input), null, 2) }]
|
|
324
|
+
})
|
|
325
|
+
);
|
|
326
|
+
server2.tool(
|
|
327
|
+
"compute_kappa",
|
|
328
|
+
"Compute convergence metric \u03BA from governance scores. \u03BA < 1 means converging.",
|
|
329
|
+
KappaInput.shape,
|
|
330
|
+
async (input) => ({
|
|
331
|
+
content: [{ type: "text", text: JSON.stringify(computeKappa(input), null, 2) }]
|
|
332
|
+
})
|
|
333
|
+
);
|
|
334
|
+
server2.tool(
|
|
335
|
+
"compute_delta",
|
|
336
|
+
"Compute drift metric \u03B4 between baseline and current governance state.",
|
|
337
|
+
DeltaInput.shape,
|
|
338
|
+
async (input) => ({
|
|
339
|
+
content: [{ type: "text", text: JSON.stringify(computeDelta(input), null, 2) }]
|
|
340
|
+
})
|
|
341
|
+
);
|
|
342
|
+
server2.tool(
|
|
343
|
+
"ssot_verify",
|
|
344
|
+
"Verify SSOT integrity \u2014 check for drift between source of truth atoms.",
|
|
345
|
+
SsotInput.shape,
|
|
346
|
+
async (input) => ({
|
|
347
|
+
content: [{ type: "text", text: JSON.stringify(await ssotVerify(input), null, 2) }]
|
|
348
|
+
})
|
|
349
|
+
);
|
|
350
|
+
return server2;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/index.ts
|
|
354
|
+
var server = createServer();
|
|
355
|
+
var transport = new StdioServerTransport();
|
|
356
|
+
await server.connect(transport);
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@morphism-systems/mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Governance MCP server — validation, maturity scoring, convergence and drift metrics",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"morphism-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"lint": "echo 'no lint configured'"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mcp",
|
|
18
|
+
"model-context-protocol",
|
|
19
|
+
"ai-governance",
|
|
20
|
+
"morphism",
|
|
21
|
+
"governance-as-code"
|
|
22
|
+
],
|
|
23
|
+
"license": "BUSL-1.1",
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
29
|
+
"zod": "^3.24.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"tsup": "^8.4.0",
|
|
33
|
+
"typescript": "^5.8.3",
|
|
34
|
+
"vitest": "^3.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|