mcpgraph 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/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/config/loader.d.ts +6 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +8 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/parser.d.ts +6 -0
- package/dist/config/parser.d.ts.map +1 -0
- package/dist/config/parser.js +24 -0
- package/dist/config/parser.js.map +1 -0
- package/dist/config/schema.d.ts +366 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +75 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/count-files.test.d.ts +5 -0
- package/dist/count-files.test.d.ts.map +1 -0
- package/dist/count-files.test.js +46 -0
- package/dist/count-files.test.js.map +1 -0
- package/dist/execution/context.d.ts +18 -0
- package/dist/execution/context.d.ts.map +1 -0
- package/dist/execution/context.js +33 -0
- package/dist/execution/context.js.map +1 -0
- package/dist/execution/executor.d.ts +13 -0
- package/dist/execution/executor.d.ts.map +1 -0
- package/dist/execution/executor.js +72 -0
- package/dist/execution/executor.js.map +1 -0
- package/dist/execution/nodes/entry-executor.d.ts +10 -0
- package/dist/execution/nodes/entry-executor.d.ts.map +1 -0
- package/dist/execution/nodes/entry-executor.js +17 -0
- package/dist/execution/nodes/entry-executor.js.map +1 -0
- package/dist/execution/nodes/exit-executor.d.ts +9 -0
- package/dist/execution/nodes/exit-executor.d.ts.map +1 -0
- package/dist/execution/nodes/exit-executor.js +16 -0
- package/dist/execution/nodes/exit-executor.js.map +1 -0
- package/dist/execution/nodes/mcp-tool-executor.d.ts +11 -0
- package/dist/execution/nodes/mcp-tool-executor.d.ts.map +1 -0
- package/dist/execution/nodes/mcp-tool-executor.js +74 -0
- package/dist/execution/nodes/mcp-tool-executor.js.map +1 -0
- package/dist/execution/nodes/switch-executor.d.ts +10 -0
- package/dist/execution/nodes/switch-executor.d.ts.map +1 -0
- package/dist/execution/nodes/switch-executor.js +32 -0
- package/dist/execution/nodes/switch-executor.js.map +1 -0
- package/dist/execution/nodes/transform-executor.d.ts +10 -0
- package/dist/execution/nodes/transform-executor.d.ts.map +1 -0
- package/dist/execution/nodes/transform-executor.js +20 -0
- package/dist/execution/nodes/transform-executor.js.map +1 -0
- package/dist/expressions/context.d.ts +9 -0
- package/dist/expressions/context.d.ts.map +1 -0
- package/dist/expressions/context.js +10 -0
- package/dist/expressions/context.js.map +1 -0
- package/dist/expressions/json-logic.d.ts +11 -0
- package/dist/expressions/json-logic.d.ts.map +1 -0
- package/dist/expressions/json-logic.js +27 -0
- package/dist/expressions/json-logic.js.map +1 -0
- package/dist/expressions/jsonata.d.ts +5 -0
- package/dist/expressions/jsonata.d.ts.map +1 -0
- package/dist/expressions/jsonata.js +27 -0
- package/dist/expressions/jsonata.js.map +1 -0
- package/dist/graph/graph.d.ts +14 -0
- package/dist/graph/graph.d.ts.map +1 -0
- package/dist/graph/graph.js +38 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/validator.d.ts +11 -0
- package/dist/graph/validator.d.ts.map +1 -0
- package/dist/graph/validator.js +90 -0
- package/dist/graph/validator.js.map +1 -0
- package/dist/logger.d.ts +23 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +37 -0
- package/dist/logger.js.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +93 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp/client-manager.d.ts +11 -0
- package/dist/mcp/client-manager.d.ts.map +1 -0
- package/dist/mcp/client-manager.js +39 -0
- package/dist/mcp/client-manager.js.map +1 -0
- package/dist/types/config.d.ts +69 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +5 -0
- package/dist/types/config.js.map +1 -0
- package/examples/count_files.yaml +57 -0
- package/package.json +54 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Logic expression evaluation
|
|
3
|
+
*/
|
|
4
|
+
// @ts-ignore - json-logic-js doesn't have type definitions
|
|
5
|
+
import jsonLogic from "json-logic-js";
|
|
6
|
+
import { logger } from "../logger.js";
|
|
7
|
+
/**
|
|
8
|
+
* Evaluate a JSON Logic rule with the given context data
|
|
9
|
+
* @param rule - JSON Logic rule (can be any valid JSON Logic structure)
|
|
10
|
+
* @param context - Context data object to evaluate the rule against
|
|
11
|
+
* @returns Boolean result of the rule evaluation
|
|
12
|
+
*/
|
|
13
|
+
export function evaluateJsonLogic(rule, context) {
|
|
14
|
+
try {
|
|
15
|
+
logger.debug(`Evaluating JSON Logic rule: ${JSON.stringify(rule)}`);
|
|
16
|
+
logger.debug(`Context keys: ${Object.keys(context).join(", ")}`);
|
|
17
|
+
const result = jsonLogic.apply(rule, context);
|
|
18
|
+
logger.debug(`JSON Logic result: ${result}`);
|
|
19
|
+
// JSON Logic returns a boolean, but we'll ensure it's a boolean
|
|
20
|
+
return Boolean(result);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
logger.error(`JSON Logic evaluation error: ${error instanceof Error ? error.message : String(error)}`);
|
|
24
|
+
throw new Error(`Failed to evaluate JSON Logic rule: ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=json-logic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-logic.js","sourceRoot":"","sources":["../../src/expressions/json-logic.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2DAA2D;AAC3D,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAa,EACb,OAAgC;IAEhC,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE9C,MAAM,CAAC,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC;QAE7C,gEAAgE;QAChE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvG,MAAM,IAAI,KAAK,CACb,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAChG,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonata.d.ts","sourceRoot":"","sources":["../../src/expressions/jsonata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAqBlB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSONata expression evaluation
|
|
3
|
+
*/
|
|
4
|
+
import jsonata from "jsonata";
|
|
5
|
+
import { logger } from "../logger.js";
|
|
6
|
+
export async function evaluateJsonata(expression, context) {
|
|
7
|
+
try {
|
|
8
|
+
const expr = jsonata(expression);
|
|
9
|
+
const result = await expr.evaluate(context);
|
|
10
|
+
// Log for debugging
|
|
11
|
+
logger.debug(`JSONata expression: ${expression}`);
|
|
12
|
+
logger.debug(`JSONata context keys: ${Object.keys(context).join(", ")}`);
|
|
13
|
+
if (typeof context.list_directory_node === "string") {
|
|
14
|
+
logger.debug(`list_directory_node value (first 100 chars): ${context.list_directory_node.substring(0, 100)}`);
|
|
15
|
+
logger.debug(`list_directory_node has actual newlines: ${context.list_directory_node.includes("\n")}`);
|
|
16
|
+
}
|
|
17
|
+
logger.debug(`JSONata result: ${JSON.stringify(result)}`);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
logger.error(`JSONata evaluation error: ${error instanceof Error ? error.message : String(error)}`);
|
|
22
|
+
logger.error(`Expression: ${expression}`);
|
|
23
|
+
logger.error(`Context: ${JSON.stringify(context, null, 2)}`);
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=jsonata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonata.js","sourceRoot":"","sources":["../../src/expressions/jsonata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,OAAgC;IAEhC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAE5C,oBAAoB;QACpB,MAAM,CAAC,KAAK,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,yBAAyB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,IAAI,OAAO,OAAO,CAAC,mBAAmB,KAAK,QAAQ,EAAE,CAAC;YACpD,MAAM,CAAC,KAAK,CAAC,gDAAiD,OAAO,CAAC,mBAA8B,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1H,MAAM,CAAC,KAAK,CAAC,4CAA6C,OAAO,CAAC,mBAA8B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrH,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAE1D,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,KAAK,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph data structure and utilities
|
|
3
|
+
*/
|
|
4
|
+
import type { NodeDefinition } from "../types/config.js";
|
|
5
|
+
export declare class Graph {
|
|
6
|
+
private nodes;
|
|
7
|
+
private edges;
|
|
8
|
+
constructor(nodes: NodeDefinition[]);
|
|
9
|
+
getNode(nodeId: string): NodeDefinition | undefined;
|
|
10
|
+
getNextNodes(nodeId: string): string[];
|
|
11
|
+
getAllNodes(): NodeDefinition[];
|
|
12
|
+
hasNode(nodeId: string): boolean;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/graph/graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,KAAK,CAAwB;gBAEzB,KAAK,EAAE,cAAc,EAAE;IAsBnC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAInD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAItC,WAAW,IAAI,cAAc,EAAE;IAI/B,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAGjC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph data structure and utilities
|
|
3
|
+
*/
|
|
4
|
+
export class Graph {
|
|
5
|
+
nodes;
|
|
6
|
+
edges; // nodeId -> array of next node IDs
|
|
7
|
+
constructor(nodes) {
|
|
8
|
+
this.nodes = new Map();
|
|
9
|
+
this.edges = new Map();
|
|
10
|
+
for (const node of nodes) {
|
|
11
|
+
this.nodes.set(node.id, node);
|
|
12
|
+
// Build edges
|
|
13
|
+
if ("next" in node && node.next) {
|
|
14
|
+
const current = this.edges.get(node.id) || [];
|
|
15
|
+
current.push(node.next);
|
|
16
|
+
this.edges.set(node.id, current);
|
|
17
|
+
}
|
|
18
|
+
// Handle switch nodes with multiple targets
|
|
19
|
+
if (node.type === "switch") {
|
|
20
|
+
const targets = node.conditions.map((c) => c.target);
|
|
21
|
+
this.edges.set(node.id, targets);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
getNode(nodeId) {
|
|
26
|
+
return this.nodes.get(nodeId);
|
|
27
|
+
}
|
|
28
|
+
getNextNodes(nodeId) {
|
|
29
|
+
return this.edges.get(nodeId) || [];
|
|
30
|
+
}
|
|
31
|
+
getAllNodes() {
|
|
32
|
+
return Array.from(this.nodes.values());
|
|
33
|
+
}
|
|
34
|
+
hasNode(nodeId) {
|
|
35
|
+
return this.nodes.has(nodeId);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/graph/graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,OAAO,KAAK;IACR,KAAK,CAA8B;IACnC,KAAK,CAAwB,CAAC,mCAAmC;IAEzE,YAAY,KAAuB;QACjC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAE9B,cAAc;YACd,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;gBAC9C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,4CAA4C;YAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACrD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,YAAY,CAAC,MAAc;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,WAAW;QACT,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph structure validator
|
|
3
|
+
*/
|
|
4
|
+
import type { McpGraphConfig } from "../types/config.js";
|
|
5
|
+
export interface ValidationError {
|
|
6
|
+
message: string;
|
|
7
|
+
nodeId?: string;
|
|
8
|
+
toolName?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function validateGraph(config: McpGraphConfig): ValidationError[];
|
|
11
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/graph/validator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIzD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,EAAE,CA2EvE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph structure validator
|
|
3
|
+
*/
|
|
4
|
+
import { Graph } from "./graph.js";
|
|
5
|
+
export function validateGraph(config) {
|
|
6
|
+
const errors = [];
|
|
7
|
+
const graph = new Graph(config.nodes);
|
|
8
|
+
// Validate all tools have valid entry and exit nodes
|
|
9
|
+
for (const tool of config.tools) {
|
|
10
|
+
if (!graph.hasNode(tool.entryNode)) {
|
|
11
|
+
errors.push({
|
|
12
|
+
message: `Tool "${tool.name}" references non-existent entry node "${tool.entryNode}"`,
|
|
13
|
+
toolName: tool.name,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (!graph.hasNode(tool.exitNode)) {
|
|
17
|
+
errors.push({
|
|
18
|
+
message: `Tool "${tool.name}" references non-existent exit node "${tool.exitNode}"`,
|
|
19
|
+
toolName: tool.name,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
// Validate entry node is actually an entry node
|
|
23
|
+
const entryNode = graph.getNode(tool.entryNode);
|
|
24
|
+
if (entryNode && entryNode.type !== "entry") {
|
|
25
|
+
errors.push({
|
|
26
|
+
message: `Tool "${tool.name}" entry node "${tool.entryNode}" is not an entry node`,
|
|
27
|
+
toolName: tool.name,
|
|
28
|
+
nodeId: tool.entryNode,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// Validate exit node is actually an exit node
|
|
32
|
+
const exitNode = graph.getNode(tool.exitNode);
|
|
33
|
+
if (exitNode && exitNode.type !== "exit") {
|
|
34
|
+
errors.push({
|
|
35
|
+
message: `Tool "${tool.name}" exit node "${tool.exitNode}" is not an exit node`,
|
|
36
|
+
toolName: tool.name,
|
|
37
|
+
nodeId: tool.exitNode,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Validate all node references exist
|
|
42
|
+
for (const node of config.nodes) {
|
|
43
|
+
if ("next" in node && node.next) {
|
|
44
|
+
if (!graph.hasNode(node.next)) {
|
|
45
|
+
errors.push({
|
|
46
|
+
message: `Node "${node.id}" references non-existent next node "${node.next}"`,
|
|
47
|
+
nodeId: node.id,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (node.type === "switch") {
|
|
52
|
+
for (const condition of node.conditions) {
|
|
53
|
+
if (!graph.hasNode(condition.target)) {
|
|
54
|
+
errors.push({
|
|
55
|
+
message: `Switch node "${node.id}" references non-existent target "${condition.target}"`,
|
|
56
|
+
nodeId: node.id,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Validate exit nodes are reachable (basic check - can be enhanced)
|
|
63
|
+
for (const tool of config.tools) {
|
|
64
|
+
if (!isReachable(graph, tool.entryNode, tool.exitNode)) {
|
|
65
|
+
errors.push({
|
|
66
|
+
message: `Tool "${tool.name}" exit node "${tool.exitNode}" is not reachable from entry node "${tool.entryNode}"`,
|
|
67
|
+
toolName: tool.name,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return errors;
|
|
72
|
+
}
|
|
73
|
+
function isReachable(graph, startId, targetId) {
|
|
74
|
+
const visited = new Set();
|
|
75
|
+
const queue = [startId];
|
|
76
|
+
while (queue.length > 0) {
|
|
77
|
+
const current = queue.shift();
|
|
78
|
+
if (current === targetId) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
if (visited.has(current)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
visited.add(current);
|
|
85
|
+
const nextNodes = graph.getNextNodes(current);
|
|
86
|
+
queue.push(...nextNodes);
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/graph/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for mcpGraph
|
|
3
|
+
*
|
|
4
|
+
* All logging goes to stderr to avoid interfering with MCP server
|
|
5
|
+
* communication which uses stdout.
|
|
6
|
+
*/
|
|
7
|
+
interface Logger {
|
|
8
|
+
debug(message: string, ...args: unknown[]): void;
|
|
9
|
+
info(message: string, ...args: unknown[]): void;
|
|
10
|
+
warn(message: string, ...args: unknown[]): void;
|
|
11
|
+
error(message: string, ...args: unknown[]): void;
|
|
12
|
+
}
|
|
13
|
+
declare class ConsoleLogger implements Logger {
|
|
14
|
+
private formatMessage;
|
|
15
|
+
private log;
|
|
16
|
+
debug(message: string, ...args: unknown[]): void;
|
|
17
|
+
info(message: string, ...args: unknown[]): void;
|
|
18
|
+
warn(message: string, ...args: unknown[]): void;
|
|
19
|
+
error(message: string, ...args: unknown[]): void;
|
|
20
|
+
}
|
|
21
|
+
export declare const logger: ConsoleLogger;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,UAAU,MAAM;IACd,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAED,cAAM,aAAc,YAAW,MAAM;IACnC,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,GAAG;IAWX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAIhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGjD;AAGD,eAAO,MAAM,MAAM,eAAsB,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for mcpGraph
|
|
3
|
+
*
|
|
4
|
+
* All logging goes to stderr to avoid interfering with MCP server
|
|
5
|
+
* communication which uses stdout.
|
|
6
|
+
*/
|
|
7
|
+
class ConsoleLogger {
|
|
8
|
+
formatMessage(level, message) {
|
|
9
|
+
const timestamp = new Date().toISOString();
|
|
10
|
+
return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
|
11
|
+
}
|
|
12
|
+
log(level, message, ...args) {
|
|
13
|
+
const formattedMessage = this.formatMessage(level, message);
|
|
14
|
+
const logFn = level === 'error' ? console.error : console.warn;
|
|
15
|
+
if (args.length > 0) {
|
|
16
|
+
logFn(formattedMessage, ...args);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
logFn(formattedMessage);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
debug(message, ...args) {
|
|
23
|
+
this.log('debug', message, ...args);
|
|
24
|
+
}
|
|
25
|
+
info(message, ...args) {
|
|
26
|
+
this.log('info', message, ...args);
|
|
27
|
+
}
|
|
28
|
+
warn(message, ...args) {
|
|
29
|
+
this.log('warn', message, ...args);
|
|
30
|
+
}
|
|
31
|
+
error(message, ...args) {
|
|
32
|
+
this.log('error', message, ...args);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Export a singleton logger instance
|
|
36
|
+
export const logger = new ConsoleLogger();
|
|
37
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,aAAa;IACT,aAAa,CAAC,KAAe,EAAE,OAAe;QACpD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,OAAO,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;IAC9D,CAAC;IAEO,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,GAAG,IAAe;QAC9D,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAE/D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,CAAC;CACF;AAED,qCAAqC;AACrC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcpGraph - MCP server that runs a directed graph of MCP server calls
|
|
3
|
+
*/
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
import { loadConfig } from './config/loader.js';
|
|
6
|
+
import { validateGraph } from './graph/validator.js';
|
|
7
|
+
import { GraphExecutor } from './execution/executor.js';
|
|
8
|
+
import { McpClientManager } from './mcp/client-manager.js';
|
|
9
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
11
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
import { parseArgs } from 'node:util';
|
|
13
|
+
const { values } = parseArgs({
|
|
14
|
+
options: {
|
|
15
|
+
config: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
short: 'c',
|
|
18
|
+
default: 'config.yaml',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
async function main() {
|
|
23
|
+
try {
|
|
24
|
+
const configPath = values.config || 'config.yaml';
|
|
25
|
+
logger.info(`Loading configuration from: ${configPath}`);
|
|
26
|
+
const config = loadConfig(configPath);
|
|
27
|
+
const errors = validateGraph(config);
|
|
28
|
+
if (errors.length > 0) {
|
|
29
|
+
logger.error('Graph validation failed:');
|
|
30
|
+
for (const error of errors) {
|
|
31
|
+
logger.error(` - ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
logger.info(`Loaded configuration: ${config.server.name} v${config.server.version}`);
|
|
36
|
+
logger.info(`Tools defined: ${config.tools.map(t => t.name).join(', ')}`);
|
|
37
|
+
const clientManager = new McpClientManager();
|
|
38
|
+
const executor = new GraphExecutor(config, clientManager);
|
|
39
|
+
// Initialize MCP server
|
|
40
|
+
const server = new Server({
|
|
41
|
+
name: config.server.name,
|
|
42
|
+
version: config.server.version,
|
|
43
|
+
}, {
|
|
44
|
+
capabilities: {
|
|
45
|
+
tools: {},
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
// Register tools
|
|
49
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
50
|
+
tools: config.tools.map(tool => ({
|
|
51
|
+
name: tool.name,
|
|
52
|
+
description: tool.description,
|
|
53
|
+
inputSchema: tool.inputSchema,
|
|
54
|
+
})),
|
|
55
|
+
}));
|
|
56
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
57
|
+
const toolName = request.params.name;
|
|
58
|
+
const tool = config.tools.find(t => t.name === toolName);
|
|
59
|
+
if (!tool) {
|
|
60
|
+
throw new Error(`Tool not found: ${toolName}`);
|
|
61
|
+
}
|
|
62
|
+
logger.info(`Tool called: ${toolName}`);
|
|
63
|
+
const result = await executor.executeTool(toolName, request.params.arguments || {});
|
|
64
|
+
return {
|
|
65
|
+
content: [
|
|
66
|
+
{
|
|
67
|
+
type: 'text',
|
|
68
|
+
text: JSON.stringify(result),
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
structuredContent: result,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
const transport = new StdioServerTransport();
|
|
75
|
+
await server.connect(transport);
|
|
76
|
+
logger.info('mcpGraph MCP server running on stdio');
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logger.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
80
|
+
if (error instanceof Error && error.stack) {
|
|
81
|
+
logger.error(error.stack);
|
|
82
|
+
}
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
main().catch((error) => {
|
|
87
|
+
logger.error(`Fatal error: ${error instanceof Error ? error.message : String(error)}`);
|
|
88
|
+
if (error instanceof Error && error.stack) {
|
|
89
|
+
logger.error(error.stack);
|
|
90
|
+
}
|
|
91
|
+
process.exit(1);
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP client manager for external MCP servers
|
|
3
|
+
*/
|
|
4
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
|
+
export declare class McpClientManager {
|
|
6
|
+
private clients;
|
|
7
|
+
constructor();
|
|
8
|
+
getClient(serverName: string, command: string, args: string[]): Promise<Client>;
|
|
9
|
+
closeAll(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=client-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-manager.d.ts","sourceRoot":"","sources":["../../src/mcp/client-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAsB;;IAM/B,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B/E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAOhC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP client manager for external MCP servers
|
|
3
|
+
*/
|
|
4
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
6
|
+
import { logger } from "../logger.js";
|
|
7
|
+
export class McpClientManager {
|
|
8
|
+
clients;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.clients = new Map();
|
|
11
|
+
}
|
|
12
|
+
async getClient(serverName, command, args) {
|
|
13
|
+
if (this.clients.has(serverName)) {
|
|
14
|
+
return this.clients.get(serverName);
|
|
15
|
+
}
|
|
16
|
+
logger.info(`Creating MCP client for server: ${serverName}`);
|
|
17
|
+
const transport = new StdioClientTransport({
|
|
18
|
+
command,
|
|
19
|
+
args,
|
|
20
|
+
});
|
|
21
|
+
const client = new Client({
|
|
22
|
+
name: `mcpgraph-${serverName}`,
|
|
23
|
+
version: "0.1.0",
|
|
24
|
+
}, {
|
|
25
|
+
capabilities: {},
|
|
26
|
+
});
|
|
27
|
+
await client.connect(transport);
|
|
28
|
+
this.clients.set(serverName, client);
|
|
29
|
+
return client;
|
|
30
|
+
}
|
|
31
|
+
async closeAll() {
|
|
32
|
+
for (const [name, client] of this.clients.entries()) {
|
|
33
|
+
logger.info(`Closing MCP client: ${name}`);
|
|
34
|
+
await client.close();
|
|
35
|
+
}
|
|
36
|
+
this.clients.clear();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=client-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../src/mcp/client-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,OAAO,gBAAgB;IACnB,OAAO,CAAsB;IAErC;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,UAAkB,EAAE,OAAe,EAAE,IAAc;QACjE,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC;QACvC,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,mCAAmC,UAAU,EAAE,CAAC,CAAC;QAE7D,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;YACzC,OAAO;YACP,IAAI;SACL,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;YACE,IAAI,EAAE,YAAY,UAAU,EAAE;YAC9B,OAAO,EAAE,OAAO;SACjB,EACD;YACE,YAAY,EAAE,EAAE;SACjB,CACF,CAAC;QAEF,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAErC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,MAAM,CAAC,IAAI,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for mcpGraph configuration
|
|
3
|
+
*/
|
|
4
|
+
export interface McpGraphConfig {
|
|
5
|
+
version: string;
|
|
6
|
+
server: ServerMetadata;
|
|
7
|
+
tools: ToolDefinition[];
|
|
8
|
+
nodes: NodeDefinition[];
|
|
9
|
+
}
|
|
10
|
+
export interface ServerMetadata {
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
description: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ToolDefinition {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
inputSchema: JsonSchema;
|
|
19
|
+
outputSchema: JsonSchema;
|
|
20
|
+
entryNode: string;
|
|
21
|
+
exitNode: string;
|
|
22
|
+
}
|
|
23
|
+
export interface JsonSchema {
|
|
24
|
+
type: string;
|
|
25
|
+
properties?: Record<string, JsonSchemaProperty>;
|
|
26
|
+
required?: string[];
|
|
27
|
+
description?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface JsonSchemaProperty {
|
|
30
|
+
type: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
}
|
|
33
|
+
export type NodeDefinition = EntryNode | ExitNode | McpToolNode | TransformNode | SwitchNode;
|
|
34
|
+
export interface BaseNode {
|
|
35
|
+
id: string;
|
|
36
|
+
type: string;
|
|
37
|
+
next?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface EntryNode extends BaseNode {
|
|
40
|
+
type: "entry";
|
|
41
|
+
next: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ExitNode extends BaseNode {
|
|
44
|
+
type: "exit";
|
|
45
|
+
}
|
|
46
|
+
export interface McpToolNode extends BaseNode {
|
|
47
|
+
type: "mcp_tool";
|
|
48
|
+
server: string;
|
|
49
|
+
tool: string;
|
|
50
|
+
args: Record<string, unknown>;
|
|
51
|
+
next: string;
|
|
52
|
+
}
|
|
53
|
+
export interface TransformNode extends BaseNode {
|
|
54
|
+
type: "transform";
|
|
55
|
+
transform: {
|
|
56
|
+
expr: string;
|
|
57
|
+
};
|
|
58
|
+
next: string;
|
|
59
|
+
}
|
|
60
|
+
export interface SwitchNode extends BaseNode {
|
|
61
|
+
type: "switch";
|
|
62
|
+
conditions: SwitchCondition[];
|
|
63
|
+
}
|
|
64
|
+
export interface SwitchCondition {
|
|
65
|
+
rule?: JsonLogicRule;
|
|
66
|
+
target: string;
|
|
67
|
+
}
|
|
68
|
+
export type JsonLogicRule = unknown;
|
|
69
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,YAAY,EAAE,UAAU,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,QAAQ,GACR,WAAW,GACX,aAAa,GACb,UAAU,CAAC;AAEf,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAS,SAAQ,QAAQ;IACxC,IAAI,EAAE,MAAM,CAAC;CAEd;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAc,SAAQ,QAAQ;IAC7C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
|
|
3
|
+
# MCP Server Metadata
|
|
4
|
+
server:
|
|
5
|
+
name: "mcpGraph"
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
description: "MCP server that executes directed graphs of MCP tool calls"
|
|
8
|
+
|
|
9
|
+
# Tool Definitions
|
|
10
|
+
tools:
|
|
11
|
+
- name: "count_files"
|
|
12
|
+
description: "Counts the number of files in a directory"
|
|
13
|
+
inputSchema:
|
|
14
|
+
type: "object"
|
|
15
|
+
properties:
|
|
16
|
+
directory:
|
|
17
|
+
type: "string"
|
|
18
|
+
description: "The directory path to count files in"
|
|
19
|
+
required:
|
|
20
|
+
- directory
|
|
21
|
+
outputSchema:
|
|
22
|
+
type: "object"
|
|
23
|
+
properties:
|
|
24
|
+
count:
|
|
25
|
+
type: "number"
|
|
26
|
+
description: "The number of files in the directory"
|
|
27
|
+
entryNode: "entry_count_files"
|
|
28
|
+
exitNode: "exit_count_files"
|
|
29
|
+
|
|
30
|
+
# Graph Nodes
|
|
31
|
+
nodes:
|
|
32
|
+
# Entry node: Receives tool arguments
|
|
33
|
+
- id: "entry_count_files"
|
|
34
|
+
type: "entry"
|
|
35
|
+
next: "list_directory_node"
|
|
36
|
+
|
|
37
|
+
# List directory contents
|
|
38
|
+
- id: "list_directory_node"
|
|
39
|
+
type: "mcp_tool"
|
|
40
|
+
server: "filesystem"
|
|
41
|
+
tool: "list_directory"
|
|
42
|
+
args:
|
|
43
|
+
path: "$.input.directory"
|
|
44
|
+
next: "count_files_node"
|
|
45
|
+
|
|
46
|
+
# Transform and count files
|
|
47
|
+
- id: "count_files_node"
|
|
48
|
+
type: "transform"
|
|
49
|
+
transform:
|
|
50
|
+
expr: |
|
|
51
|
+
{ "count": $count($split(list_directory_node, "\n")) }
|
|
52
|
+
next: "exit_count_files"
|
|
53
|
+
|
|
54
|
+
# Exit node: Returns the count
|
|
55
|
+
- id: "exit_count_files"
|
|
56
|
+
type: "exit"
|
|
57
|
+
|