# mcpGraph
MCP server that executes directed graphs of MCP server calls.
> **📖 Learn More:** Read [**mcpGraph: A No-Code Alternative to "Code Mode"**](docs/no-code-code-mode.md) to understand how mcpGraph provides the context efficiency and accuracy of Code Mode while maintaining the security and observability of a no-code solution.
> **🎥 Watch the Demo:** Check out the [**mcpGraph Overview and mcpGraphUX Demo**](https://youtu.be/eyC7OzuB6c4) video to see mcpGraph in action and explore the visual debugging capabilities of mcpGraphUX.
> **🎥 Watch the Demo:** Check out the [**mcpGraphToolkit Deep Dive**](https://youtu.be/gR7s0MD8Gro) video to see an agent autonomously build, test, and deploy orchestration tools—"Code Mode" without the code.
## Overview
mcpGraph is an MCP (Model Context Protocol) server that exposes tools defined by declarative YAML configurations. Each tool executes a directed graph of nodes that can call other MCP tools, transform data, and make routing decisions, all without embedding a full programming language.
**Key Features:**
- **Declarative Configuration**: Define tools and their execution graphs in YAML
- **Data Transformation**: Use [JSONata](https://jsonata.org/) expressions to transform data between nodes
- **Conditional Routing**: Use [JSON Logic](https://jsonlogic.com/) for conditional branching
- **Observable**: Every transformation and decision is traceable
- **No Embedded Code**: All logic expressed using standard expression languages ([JSONata](https://jsonata.org/), [JSON Logic](https://jsonlogic.com/))
**Related Tools:**
- **mcpGraphUX**: A visual debugging and development environment for mcpGraph. Visualize graph structures, animate through active nodes during execution, set breakpoints, and inspect node inputs and outputs. See the [mcpGraphUX repository](https://github.com/TeamSparkAI/mcpGraph-ux) for details.
- **mcpGraphToolkit**: An MCP server that provides tools for building, testing, and managing mcpGraph tools. Use it to discover available MCP servers, test expressions, and create graph tools interactively. See [mcpGraphToolkit Overview](docs/toolkit.md) for details.
## Example
Here's a simple example that counts files in a directory:
```yaml
version: "1.0"
# MCP Server Metadata
server:
name: "fileUtils"
version: "1.0.0"
title: "File utilities"
instructions: "This server provides file utility tools for counting files and calculating total file sizes in directories."
# Optional: Execution limits to prevent infinite loops
executionLimits:
maxNodeExecutions: 1000 # Maximum total node executions (default: 1000)
maxExecutionTimeMs: 300000 # Maximum execution time in milliseconds (default: 300000 = 5 minutes)
# MCP Servers used by the graph
mcpServers:
filesystem:
command: "npx"
args:
- "-y"
- "@modelcontextprotocol/server-filesystem"
- "./tests/counting"
# Tool Definitions
tools:
- name: "count_files"
description: "Counts the number of files in a directory"
inputSchema:
type: "object"
properties:
directory:
type: "string"
description: "The directory path to count files in"
required:
- directory
outputSchema:
type: "object"
properties:
count:
type: "number"
description: "The number of files in the directory"
nodes:
# Entry node: Receives tool arguments
- id: "entry"
type: "entry"
next: "list_directory_node"
# List directory contents
- id: "list_directory_node"
type: "mcp"
server: "filesystem"
tool: "list_directory"
args:
path:
expr: "$.entry.directory"
next: "count_files_node"
# Transform and count files
- id: "count_files_node"
type: "transform"
transform:
expr: '{ "count": $count($split($.list_directory_node.content, "\n")) }'
next: "exit"
# Exit node: Returns the count
- id: "exit"
type: "exit"
```
This graph:
1. Receives a directory path as input
2. Calls the filesystem MCP server's `list_directory` tool
3. Transforms the result to count files using JSONata
4. Returns the count
## Node Types
- **`entry`**: Entry point for a tool's graph execution. Receives tool arguments.
- **Output**: The tool input arguments (passed through as-is)
- **`mcp`**: Calls an MCP tool on an internal or external MCP server.
- **Output**: The MCP tool's response (parsed from the tool's content)
- **`transform`**: Applies [JSONata](https://jsonata.org/) expressions to transform data between nodes.
- **Output**: The result of evaluating the JSONata expression
- **Expression Format**: The `expr` field is a string containing a JSONata expression. Use single-quoted strings for simple expressions: `expr: '{ "result": "value" }'`. Use block scalars (`|`) for complex multi-line expressions to improve readability.
- **`switch`**: Uses [JSON Logic](https://jsonlogic.com/) to conditionally route to different nodes. Note: `var` operations in JSON Logic rules are evaluated using JSONata, allowing full JSONata expression support.
- **Output**: The node ID of the target node that was routed to (string)
- **`exit`**: Exit point that returns the final result to the MCP tool caller.
- **Output**: The output from the previous node in the execution history
## Execution History & Debugging
mcpGraph maintains a complete execution history for each tool execution, enabling powerful debugging and introspection capabilities:
- **Execution History**: Every node execution is recorded with timing, outputs, and a unique `executionIndex` (sequential: 0, 1, 2, ...)
- **Context Structure**: Context for expressions is built from history - a flat structure where each node ID maps to its latest output
- Simple notation: `$.node_id` accesses the latest output of a node
- When nodes execute multiple times (loops), context shows the most recent execution
- History functions provide access to all executions, not just the latest
- **Time-Travel Debugging**: Get the context that was available to any specific execution using `getContextForExecution(executionIndex)`
- **History Functions**: Use JSONata functions to access execution history:
- `$previousNode()` - Get the previous node's output
- `$previousNode(index)` - Get the node that executed N steps before current
- `$executionCount(nodeName)` - Count how many times a node executed
- `$nodeExecution(nodeName, index)` - Get a specific execution of a node (0 = first, -1 = last)
- `$nodeExecutions(nodeName)` - Get all executions of a node as an array
- **Loop Support**: Nodes can execute multiple times in loops, with each execution tracked separately in history
See [docs/introspection-debugging.md](docs/introspection-debugging.md) for detailed documentation on debugging features.
**Context Access:**
- All node outputs are accessible by node ID (e.g., `$.entry.directory`, `$.list_directory_node`)
- Latest execution wins: `$.increment_node` returns the most recent output when a node executes multiple times
- History functions are available in all JSONata expressions (including those used in JSON Logic `var` operations)
### JSONata Expression Format
The `expr` field in transform nodes is a string containing a JSONata expression. In YAML, you can use either:
- **Single-quoted strings** (`'...'`) for simple, single-line expressions:
```yaml
transform:
expr: '{ "count": $count($split($.list_directory_node.content, "\n")) }'
```
This keeps the expression on one line and is ideal for simple transformations.
- **Block scalars** (`|`) for complex, multi-line expressions:
```yaml
transform:
expr: |
$executionCount("increment_node") = 0
? { "counter": 1, "sum": 1, "target": $.entry_sum.n }
: { "counter": $nodeExecution("increment_node", -1).counter + 1, ... }
```
This improves readability for expressions with conditional logic, nested objects, or multiple operations.
Both forms work identically - the expression is evaluated as a string by JSONata. Use single quotes for simple expressions and block scalars for complex ones to improve readability.
## For Developers
If you're interested in contributing to mcpGraph or working with the source code, see [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, development guidelines, and project structure.
## Installation
Install mcpGraph from npm:
```bash
npm install -g mcpgraph
```
Or install locally in your project:
```bash
npm install mcpgraph
```
## Configuration
### Execution Limits
mcpGraph supports cyclical graphs, which requires guardrails to prevent infinite loops. Execution limits can be configured at the graph level:
```yaml
version: "1.0"
server:
name: "myServer" # Required: unique identifier
version: "1.0.0" # Required: server version
title: "My MCP server" # Optional: display name (defaults to name if not provided)
instructions: "Instructions for using this server" # Optional: server usage instructions
# Optional: Execution limits to prevent infinite loops
executionLimits:
maxNodeExecutions: 1000 # Maximum total node executions (default: 1000)
maxExecutionTimeMs: 300000 # Maximum execution time in milliseconds (default: 300000 = 5 minutes)
tools:
# ... tool definitions ...
```
**Execution Limits:**
- **`maxNodeExecutions`** (optional): Maximum number of node executions across the entire graph. Default: `1000`. If execution reaches this limit, an error is thrown.
- **`maxExecutionTimeMs`** (optional): Maximum wall-clock time for graph execution in milliseconds. Default: `300000` (5 minutes). If execution exceeds this time, an error is thrown.
Both limits are checked before each node execution. If either limit is exceeded, execution stops immediately with a clear error message indicating which limit was hit.
**Note:** These limits are optional. If not specified, the defaults apply. They can be set to higher values for long-running batch jobs or lower values for quick operations.
### As an MCP Server
To use `mcpgraph` as an MCP server in an MCP client (such as Claude Desktop), add it to your MCP client's configuration file.
#### Claude Desktop Configuration
Add `mcpgraph` to your Claude Desktop MCP configuration (typically located at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, or `%APPDATA%\Claude\claude_desktop_config.json` on Windows):
```json
{
"mcpServers": {
"mcpgraph": {
"command": "mcpgraph",
"args": [
"-g",
"/path/to/your/config.yaml"
]
}
}
}
```
Or if not installed (run from npm):
```json
{
"mcpServers": {
"mcpgraph": {
"command": "npx",
"args": [
"-y",
"mcpgraph",
"-g",
"/path/to/your/config.yaml"
]
}
}
}
```
**Note:** Replace `/path/to/your/config.yaml` with the actual path to your YAML configuration file. The `-g` (or `--graph`) flag specifies the graph configuration file to use.
### Programmatic API
The `mcpgraph` package exports a programmatic API that can be used in your own applications (e.g., for building a UX server or other interfaces):
```typescript
import { McpGraphApi } from 'mcpgraph';
// Create an API instance (loads and validates config)
const api = new McpGraphApi('path/to/config.yaml');
// List all available tools
const tools = api.listTools();
// Execute a tool
const result = await api.executeTool('count_files', {
directory: './tests/counting',
});
// Clean up resources
await api.close();
```
See [`examples/api-usage.ts`](examples/api-usage.ts) for a complete example.
## Documentation
- [Contributing Guide](CONTRIBUTING.md) - Setup, development, and contribution guidelines
- [Design Document](docs/design.md) - Complete design and architecture
- [Implementation](docs/implementation.md) - Implementation details and architecture
- [Introspection & Debugging](docs/introspection-debugging.md) - Guide for building visualizer applications and debuggers