@markdy/mcp-server 1.2.0 → 1.3.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/dist/index.js +68 -8
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -668,7 +668,8 @@ var EDGE_OPERATORS = {
|
|
|
668
668
|
"->": "request",
|
|
669
669
|
"<-": "response",
|
|
670
670
|
"~>": "event",
|
|
671
|
-
"--": "dependency"
|
|
671
|
+
"--": "dependency",
|
|
672
|
+
"..>": "dependency"
|
|
672
673
|
};
|
|
673
674
|
var RESERVED_SELECTORS = /* @__PURE__ */ new Set(["$title", "$nodes", "$edges"]);
|
|
674
675
|
var CUE_ALIASES = {
|
|
@@ -916,7 +917,7 @@ var THEMES = {
|
|
|
916
917
|
dependency: "#818cf8"
|
|
917
918
|
},
|
|
918
919
|
fonts: {
|
|
919
|
-
title: "
|
|
920
|
+
title: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Inter, sans-serif",
|
|
920
921
|
nodeName: "ui-sans-serif, system-ui, sans-serif",
|
|
921
922
|
mono: "ui-monospace, SFMono-Regular, Menlo, monospace"
|
|
922
923
|
},
|
|
@@ -1137,7 +1138,7 @@ var ParseError = class extends Error {
|
|
|
1137
1138
|
this.column = column;
|
|
1138
1139
|
}
|
|
1139
1140
|
};
|
|
1140
|
-
var FLOW_OP_RE = /(
|
|
1141
|
+
var FLOW_OP_RE = /(->|<-|~>|--|\.\.>|<->)/;
|
|
1141
1142
|
function stripComment(line) {
|
|
1142
1143
|
let inString = false;
|
|
1143
1144
|
let escaped = false;
|
|
@@ -1189,7 +1190,7 @@ function parseProps(raw) {
|
|
|
1189
1190
|
i = raw.length - parsed.rest.length;
|
|
1190
1191
|
continue;
|
|
1191
1192
|
}
|
|
1192
|
-
const keyMatch = raw.slice(i).match(/^(
|
|
1193
|
+
const keyMatch = raw.slice(i).match(/^(@?[\w.-]+)=/);
|
|
1193
1194
|
if (!keyMatch) {
|
|
1194
1195
|
i++;
|
|
1195
1196
|
continue;
|
|
@@ -1307,6 +1308,14 @@ function tokenizeFlowChain(line) {
|
|
|
1307
1308
|
current += ch;
|
|
1308
1309
|
continue;
|
|
1309
1310
|
}
|
|
1311
|
+
const op3 = line.slice(i, i + 3);
|
|
1312
|
+
if (op3 === "..>" || op3 === "<->") {
|
|
1313
|
+
if (current.trim()) parts.push(current.trim());
|
|
1314
|
+
parts.push(op3);
|
|
1315
|
+
current = "";
|
|
1316
|
+
i += 2;
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1310
1319
|
const op = line.slice(i, i + 2);
|
|
1311
1320
|
if (op === "->" || op === "<-" || op === "~>" || op === "--") {
|
|
1312
1321
|
if (current.trim()) parts.push(current.trim());
|
|
@@ -1330,11 +1339,27 @@ function parseFlowChain(line, lineNo) {
|
|
|
1330
1339
|
let from = splitTargetLabel(parts[i++], lineNo).node;
|
|
1331
1340
|
while (i < parts.length) {
|
|
1332
1341
|
const opToken = parts[i++];
|
|
1333
|
-
const op = EDGE_OPERATORS[opToken];
|
|
1334
|
-
if (!op) throw new ParseError(`unknown flow operator '${opToken}'`, lineNo);
|
|
1335
1342
|
if (i >= parts.length) throw new ParseError(`expected target after '${opToken}'`, lineNo);
|
|
1336
1343
|
const { node: to, label } = splitTargetLabel(parts[i++], lineNo);
|
|
1337
1344
|
if (!to) throw new ParseError(`expected target node after '${opToken}'`, lineNo);
|
|
1345
|
+
if (opToken === "<->") {
|
|
1346
|
+
segments.push({
|
|
1347
|
+
from,
|
|
1348
|
+
op: "request",
|
|
1349
|
+
to,
|
|
1350
|
+
label
|
|
1351
|
+
});
|
|
1352
|
+
segments.push({
|
|
1353
|
+
from: to,
|
|
1354
|
+
op: "response",
|
|
1355
|
+
to: from,
|
|
1356
|
+
label
|
|
1357
|
+
});
|
|
1358
|
+
from = to;
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
const op = EDGE_OPERATORS[opToken];
|
|
1362
|
+
if (!op) throw new ParseError(`unknown flow operator '${opToken}'`, lineNo);
|
|
1338
1363
|
segments.push({
|
|
1339
1364
|
from: op === "response" ? to : from,
|
|
1340
1365
|
op,
|
|
@@ -2131,7 +2156,13 @@ function matchNode(node, selector) {
|
|
|
2131
2156
|
if (selector.kindEquals && node.kind.toLowerCase() !== selector.kindEquals.toLowerCase()) return false;
|
|
2132
2157
|
if (selector.roleEquals) {
|
|
2133
2158
|
const role = nodeRole(node.kind);
|
|
2134
|
-
|
|
2159
|
+
const targetRole = selector.roleEquals.toLowerCase();
|
|
2160
|
+
if (targetRole === "gateway") {
|
|
2161
|
+
const isGateway = role === "network" || ["gateway", "api_gateway", "reverse_proxy", "proxy", "router"].includes(node.kind.toLowerCase());
|
|
2162
|
+
if (!isGateway) return false;
|
|
2163
|
+
} else if (role.toLowerCase() !== targetRole) {
|
|
2164
|
+
return false;
|
|
2165
|
+
}
|
|
2135
2166
|
}
|
|
2136
2167
|
if (selector.labelContains) {
|
|
2137
2168
|
const target = (node.label || node.id).toLowerCase();
|
|
@@ -2292,6 +2323,30 @@ var ARCH_RULE_PRESETS = {
|
|
|
2292
2323
|
from: { roleEquals: "security" }
|
|
2293
2324
|
}
|
|
2294
2325
|
]
|
|
2326
|
+
},
|
|
2327
|
+
deploymentOwnership: {
|
|
2328
|
+
id: "deployment-ownership",
|
|
2329
|
+
name: "Deployment Ownership & Regional Governance",
|
|
2330
|
+
description: "Ensure production stateful stores and services are guarded in explicit group perimeters",
|
|
2331
|
+
rules: [
|
|
2332
|
+
{
|
|
2333
|
+
id: "no-unprotected-public-database",
|
|
2334
|
+
name: "No Public Database Exposure",
|
|
2335
|
+
description: "Databases and stateful stores must not be directly accessed from public browser/mobile clients.",
|
|
2336
|
+
severity: "error",
|
|
2337
|
+
type: "cannot-connect",
|
|
2338
|
+
from: { roleEquals: "client" },
|
|
2339
|
+
to: { roleEquals: "data" }
|
|
2340
|
+
},
|
|
2341
|
+
{
|
|
2342
|
+
id: "no-cross-region-sync-bypasses",
|
|
2343
|
+
name: "Synchronous Request Cycle Prevention",
|
|
2344
|
+
description: "Synchronous requests must not form cycles across microservices.",
|
|
2345
|
+
severity: "error",
|
|
2346
|
+
type: "forbidden-cycle",
|
|
2347
|
+
edge: { kind: "request" }
|
|
2348
|
+
}
|
|
2349
|
+
]
|
|
2295
2350
|
}
|
|
2296
2351
|
};
|
|
2297
2352
|
function validateArchitecture(ast, rules = [
|
|
@@ -2299,7 +2354,7 @@ function validateArchitecture(ast, rules = [
|
|
|
2299
2354
|
...ARCH_RULE_PRESETS.microservicesGovernance.rules
|
|
2300
2355
|
]) {
|
|
2301
2356
|
const violations = [];
|
|
2302
|
-
const nodes = Object.values(ast
|
|
2357
|
+
const nodes = Object.values(ast?.nodes || {});
|
|
2303
2358
|
const nodeMap = new Map(nodes.map((n) => [n.id, n]));
|
|
2304
2359
|
const edges = extractAllEdges(ast);
|
|
2305
2360
|
for (const rule of rules) {
|
|
@@ -2346,6 +2401,11 @@ function validateArchitecture(ast, rules = [
|
|
|
2346
2401
|
break;
|
|
2347
2402
|
}
|
|
2348
2403
|
case "forbidden-cycle": {
|
|
2404
|
+
const dtype = ast.meta?.type || ast.config?.type || "architecture";
|
|
2405
|
+
const nonServiceArchetypes = ["state", "sequence", "layers", "flywheel", "loop", "venn"];
|
|
2406
|
+
if (nonServiceArchetypes.includes(dtype)) {
|
|
2407
|
+
break;
|
|
2408
|
+
}
|
|
2349
2409
|
const cycleInfo = detectCycleInGraph(nodes, edges, rule.edge);
|
|
2350
2410
|
if (cycleInfo) {
|
|
2351
2411
|
violations.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markdy/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Model Context Protocol server for Markdy diagram validation, transpilation, and generation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
42
|
-
"@markdy/compat": "1.
|
|
43
|
-
"@markdy/core": "1.
|
|
42
|
+
"@markdy/compat": "1.3.0",
|
|
43
|
+
"@markdy/core": "1.3.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^25.9.5",
|