Skip to content

Commit c3331a1

Browse files
Merge pull request #24 from actionforge/mcp-server
Add MCP server with debug tools and WebSocket bridge
2 parents bf44862 + b574606 commit c3331a1

11 files changed

Lines changed: 1120 additions & 0 deletions

File tree

cmd/cmd_mcp.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
8+
mcpserver "github.com/actionforge/actrun-cli/mcp"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
// buildMCPInstructions generates the MCP server instructions from the
13+
// actual flags registered on cmdRoot so they stay in sync automatically.
14+
func buildMCPInstructions() string {
15+
var b strings.Builder
16+
17+
b.WriteString("This MCP server provides tools for debugging and running ActionForge graph (.act) files interactively. ")
18+
b.WriteString("Use the debug_* tools to step through graph execution node by node, set breakpoints, and inspect state.\n\n")
19+
20+
b.WriteString("If you just need to run a graph without debugging, use the actrun CLI directly instead of this MCP server:\n\n")
21+
fmt.Fprintf(&b, " %s\n\n", cmdRoot.Use)
22+
23+
b.WriteString("Available flags:\n")
24+
// Include both persistent and local flags from the root command.
25+
b.WriteString(cmdRoot.PersistentFlags().FlagUsages())
26+
b.WriteString(cmdRoot.LocalNonPersistentFlags().FlagUsages())
27+
28+
b.WriteString("\nTo pass arguments to the graph itself, append them after the file: actrun file.act arg1 arg2\n")
29+
b.WriteString("Use '--' to separate actrun flags from graph arguments: actrun --env-file .env file.act -- --graph-flag")
30+
31+
return b.String()
32+
}
33+
34+
var cmdMcp = &cobra.Command{
35+
Use: "mcp",
36+
Short: "Start the MCP server (stdio transport).",
37+
Long: `Starts an MCP server over stdio that exposes debug tools for bridging between an AI agent and an actrun local debug session (WebSocket). Configure this as an MCP server in your AI tool with: {"command": "actrun", "args": ["mcp"]}`,
38+
Args: cobra.NoArgs,
39+
Run: func(cmd *cobra.Command, args []string) {
40+
if err := mcpserver.RunMCPServer(buildMCPInstructions()); err != nil {
41+
fmt.Fprintf(os.Stderr, "MCP server error: %v\n", err)
42+
os.Exit(1)
43+
}
44+
},
45+
}
46+
47+
func init() {
48+
cmdRoot.AddCommand(cmdMcp)
49+
}

examples/mcp-debug-example.act

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
editor:
2+
version:
3+
created: v1.34.0
4+
entry: start
5+
type: generic
6+
nodes:
7+
- id: start
8+
type: core/start@v1
9+
position:
10+
x: -200
11+
y: 0
12+
- id: greeting-text
13+
type: core/const-string@v1
14+
position:
15+
x: -200
16+
y: 200
17+
inputs:
18+
value: "Hello from MCP debug session!"
19+
- id: print-greeting
20+
type: core/print@v1
21+
position:
22+
x: 200
23+
y: 0
24+
inputs:
25+
values[0]: null
26+
color: fg_green
27+
# Group node: contains two inner print steps to demonstrate step-into / step-out
28+
- id: my-group
29+
type: core/group@v1
30+
position:
31+
x: 500
32+
y: 0
33+
graph:
34+
entry: group-inputs
35+
type: group
36+
nodes:
37+
- id: group-inputs
38+
type: core/group-inputs@v1
39+
position:
40+
x: 10
41+
y: 60
42+
- id: group-outputs
43+
type: core/group-outputs@v1
44+
position:
45+
x: 600
46+
y: 60
47+
- id: inner-text
48+
type: core/const-string@v1
49+
position:
50+
x: 200
51+
y: 200
52+
inputs:
53+
value: "Inside the group!"
54+
- id: inner-print
55+
type: core/print@v1
56+
position:
57+
x: 400
58+
y: 60
59+
inputs:
60+
values[0]: null
61+
color: fg_cyan
62+
connections:
63+
- src:
64+
node: inner-text
65+
port: result
66+
dst:
67+
node: inner-print
68+
port: values[0]
69+
executions:
70+
- src:
71+
node: group-inputs
72+
port: exec-in
73+
dst:
74+
node: inner-print
75+
port: exec
76+
- src:
77+
node: inner-print
78+
port: exec
79+
dst:
80+
node: group-outputs
81+
port: exec-out
82+
inputs:
83+
exec-in:
84+
type: ''
85+
index: 0
86+
exec: true
87+
outputs:
88+
exec-out:
89+
name: ''
90+
type: ''
91+
index: 0
92+
exec: true
93+
- id: done-text
94+
type: core/const-string@v1
95+
position:
96+
x: 800
97+
y: 200
98+
inputs:
99+
value: "Done! Debug session complete."
100+
- id: print-done
101+
type: core/print@v1
102+
position:
103+
x: 1000
104+
y: 0
105+
inputs:
106+
values[0]: null
107+
color: fg_yellow
108+
connections:
109+
- src:
110+
node: greeting-text
111+
port: result
112+
dst:
113+
node: print-greeting
114+
port: values[0]
115+
isLoop: false
116+
- src:
117+
node: done-text
118+
port: result
119+
dst:
120+
node: print-done
121+
port: values[0]
122+
isLoop: false
123+
executions:
124+
- src:
125+
node: start
126+
port: exec
127+
dst:
128+
node: print-greeting
129+
port: exec
130+
isLoop: false
131+
- src:
132+
node: print-greeting
133+
port: exec
134+
dst:
135+
node: my-group
136+
port: exec-in
137+
isLoop: false
138+
- src:
139+
node: my-group
140+
port: exec-out
141+
dst:
142+
node: print-done
143+
port: exec
144+
isLoop: false

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
github.com/gorilla/websocket v1.5.3
2020
github.com/inconshreveable/mousetrap v1.1.0
2121
github.com/joho/godotenv v1.5.1
22+
github.com/mark3labs/mcp-go v0.44.0
2223
github.com/pkg/errors v0.9.1
2324
github.com/rhysd/actionlint v1.7.10
2425
github.com/rossmacarthur/cases v0.3.0
@@ -66,7 +67,9 @@ require (
6667
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect
6768
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect
6869
github.com/aws/smithy-go v1.24.0 // indirect
70+
github.com/bahlo/generic-list-go v0.2.0 // indirect
6971
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
72+
github.com/buger/jsonparser v1.1.1 // indirect
7073
github.com/cespare/xxhash/v2 v2.3.0 // indirect
7174
github.com/clipperhouse/stringish v0.1.1 // indirect
7275
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
@@ -91,10 +94,12 @@ require (
9194
github.com/google/s2a-go v0.1.9 // indirect
9295
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
9396
github.com/googleapis/gax-go/v2 v2.16.0 // indirect
97+
github.com/invopop/jsonschema v0.13.0 // indirect
9498
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
9599
github.com/kevinburke/ssh_config v1.4.0 // indirect
96100
github.com/klauspost/compress v1.18.2 // indirect
97101
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
102+
github.com/mailru/easyjson v0.7.7 // indirect
98103
github.com/mattn/go-colorable v0.1.14 // indirect
99104
github.com/mattn/go-isatty v0.0.20 // indirect
100105
github.com/mattn/go-runewidth v0.0.19 // indirect
@@ -110,10 +115,13 @@ require (
110115
github.com/robfig/cron/v3 v3.0.1 // indirect
111116
github.com/sergi/go-diff v1.4.0 // indirect
112117
github.com/skeema/knownhosts v1.3.2 // indirect
118+
github.com/spf13/cast v1.7.1 // indirect
119+
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
113120
github.com/xanzy/ssh-agent v0.3.3 // indirect
114121
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
115122
github.com/xdg-go/scram v1.2.0 // indirect
116123
github.com/xdg-go/stringprep v1.0.4 // indirect
124+
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
117125
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
118126
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
119127
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 // indirect

go.sum

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,12 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX
7373
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk=
7474
github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
7575
github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
76+
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
77+
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
7678
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
7779
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
80+
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
81+
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
7882
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
7983
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
8084
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
@@ -124,6 +128,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
124128
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
125129
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
126130
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
131+
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
132+
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
127133
github.com/gage-technologies/mistral-go v1.1.0 h1:POv1wM9jA/9OBXGV2YdPi9Y/h09+MjCbUF+9hRYlVUI=
128134
github.com/gage-technologies/mistral-go v1.1.0/go.mod h1:tF++Xt7U975GcLlzhrjSQb8l/x+PrriO9QEdsgm9l28=
129135
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
@@ -168,10 +174,13 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLW
168174
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
169175
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
170176
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
177+
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
178+
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
171179
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
172180
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
173181
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
174182
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
183+
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
175184
github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
176185
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
177186
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
@@ -185,6 +194,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
185194
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
186195
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
187196
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
197+
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
198+
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
199+
github.com/mark3labs/mcp-go v0.44.0 h1:OlYfcVviAnwNN40QZUrrzU0QZjq3En7rCU5X09a/B7I=
200+
github.com/mark3labs/mcp-go v0.44.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw=
188201
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
189202
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
190203
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -240,6 +253,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
240253
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
241254
github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
242255
github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
256+
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
257+
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
243258
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
244259
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
245260
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -255,6 +270,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
255270
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
256271
github.com/tmc/langchaingo v0.1.14 h1:o1qWBPigAIuFvrG6cjTFo0cZPFEZ47ZqpOYMjM15yZc=
257272
github.com/tmc/langchaingo v0.1.14/go.mod h1:aKKYXYoqhIDEv7WKdpnnCLRaqXic69cX9MnDUk72378=
273+
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
274+
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
258275
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
259276
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
260277
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
@@ -263,6 +280,8 @@ github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=
263280
github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8=
264281
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
265282
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
283+
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
284+
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
266285
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
267286
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
268287
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=

0 commit comments

Comments
 (0)