Skip to content

Commit 5f416a4

Browse files
committed
more context for better responses
1 parent 4565a3e commit 5f416a4

File tree

6 files changed

+511
-91
lines changed

6 files changed

+511
-91
lines changed

internal/mcp/prompts.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ func createWorkspacePrompt(_ context.Context, request mcp.GetPromptRequest) (*mc
207207
name := getArgOrDefault(args, "name", "my-project")
208208
projectType := getArgOrDefault(args, "type", "web")
209209
techStack := getArgOrDefault(args, "tech_stack", "")
210-
211210
prompt := fmt.Sprintf(`I want to set up a new Flow workspace for a %s project:
212211
213212
**Project Details:**

internal/mcp/resources.go

Lines changed: 120 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,64 +16,81 @@ import (
1616
)
1717

1818
var (
19-
//go:embed resources/info.md
20-
infoMD string
19+
//go:embed resources/concepts-guide.md
20+
conceptsMD string
21+
22+
//go:embed resources/file-types-guide.md
23+
fileTypesMD string
2124

2225
//go:embed resources/flowfile_schema.json
2326
flowFileSchema string
2427

28+
//go:embed resources/template_schema.json
29+
templateSchema string
30+
2531
//go:embed resources/workspace_schema.json
2632
workspaceSchema string
27-
28-
flowFileSchemaURI = "flow://schema/flowfile"
29-
workspaceConfigSchemaURI = "flow://schema/workspace"
3033
)
3134

3235
func addServerResources(srv *server.MCPServer) {
3336
getCtx := mcp.NewResource(
3437
"flow://context/current",
3538
"context",
3639
mcp.WithResourceDescription("Current flow execution context (workspace, namespace, vault)"),
37-
mcp.WithMIMEType("application/json"),
38-
)
40+
mcp.WithMIMEType("application/json"))
3941
srv.AddResource(getCtx, getContextResourceHandler)
4042

4143
getWorkspace := mcp.NewResourceTemplate(
4244
"flow://workspace/{name}",
4345
"workspace",
44-
mcp.WithTemplateDescription("Flow workspace configuration and details"),
45-
)
46+
mcp.WithTemplateDescription("Flow workspace configuration and details"))
4647
srv.AddResourceTemplate(getWorkspace, getWorkspaceResourceHandler)
4748

4849
getWorkspaceExecutables := mcp.NewResourceTemplate(
4950
"flow://workspace/{name}/executables",
5051
"workspace_executables",
51-
mcp.WithTemplateDescription("Flow executables for a given workspace"),
52-
)
52+
mcp.WithTemplateDescription("Flow executables for a given workspace"))
5353
srv.AddResourceTemplate(getWorkspaceExecutables, getWorkspaceExecutablesHandler)
5454

55-
getFlowInfo := mcp.NewResource(
56-
"flow://info",
57-
"flow_info",
58-
mcp.WithResourceDescription("Information about Flow and it's usage"),
59-
mcp.WithMIMEType("text/markdown"),
60-
)
61-
srv.AddResource(getFlowInfo, getFlowInfoResourceHandler)
55+
getExecutable := mcp.NewResourceTemplate(
56+
"flow://executable/{ref}",
57+
"executable",
58+
mcp.WithTemplateDescription("Flow executable details by reference"))
59+
srv.AddResourceTemplate(getExecutable, getExecutableResourceHandler)
60+
61+
getFlowConcepts := mcp.NewResource(
62+
"flow://guide/concepts",
63+
"flow_concepts",
64+
mcp.WithResourceDescription("Information about flow and it's usage"),
65+
mcp.WithMIMEType("text/markdown"))
66+
srv.AddResource(getFlowConcepts, getFlowConceptsResourceHandler)
67+
68+
getFlowFileTypes := mcp.NewResource(
69+
"flow://guide/file-types",
70+
"flow_file_types",
71+
mcp.WithResourceDescription("Information about flow file types and their usage"),
72+
mcp.WithMIMEType("text/markdown"))
73+
srv.AddResource(getFlowFileTypes, getFlowFileTypesResourceHandler)
6274

6375
getFlowFileSchema := mcp.NewResource(
64-
flowFileSchemaURI,
76+
"flow://schema/flowfile",
6577
"flowfile_schema",
6678
mcp.WithResourceDescription("Flow file (*.flow, *.flow.yaml, *.flow.yml) schema"),
67-
mcp.WithMIMEType("application/json"),
68-
)
79+
mcp.WithMIMEType("application/json"))
6980
srv.AddResource(getFlowFileSchema, getFlowFileSchemaResourceHandler)
7081

82+
getTemplateSchema := mcp.NewResource(
83+
"flow://schema/template",
84+
"template_schema",
85+
mcp.WithResourceDescription("Flow template (*.flow.tmpl, *.flow.yaml.tmpl, *.flow.yml.tmpl) schema"),
86+
mcp.WithMIMEType("application/json"))
87+
srv.AddResource(getTemplateSchema, getTemplateSchemaResourceHandler)
88+
7189
getWorkspaceSchema := mcp.NewResource(
72-
workspaceConfigSchemaURI,
90+
"flow://schema/workspace",
7391
"workspace_schema",
7492
mcp.WithResourceDescription("Flow workspace configuration (flow.yaml) schema"),
75-
mcp.WithMIMEType("application/json"),
76-
)
93+
mcp.WithMIMEType("application/json"))
7794
srv.AddResource(getWorkspaceSchema, getWorkspaceSchemaResourceHandler)
7895
}
7996

@@ -152,26 +169,49 @@ func getWorkspaceExecutablesHandler(_ context.Context, request mcp.ReadResourceR
152169
}, nil
153170
}
154171

155-
func extractWsName(uri string) (string, error) {
156-
// Assuming the URI is in the format "flow://workspace/{name}" or "flow://workspace/{name}/executables"
157-
if len(uri) < len("flow://workspace/") {
158-
return "", fmt.Errorf("invalid workspace URI: %s", uri)
172+
func getExecutableResourceHandler(_ context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
173+
executableVerb, executableID, err := extractExecutableRef(request.Params.URI)
174+
if err != nil {
175+
return nil, err
159176
}
160177

161-
wsName := uri[len("flow://workspace/"):]
162-
strings.TrimSuffix(wsName, "/executables")
163-
if wsName == "" {
164-
return "", fmt.Errorf("workspace name cannot be empty in URI: %s", uri)
178+
cmdArgs := []string{"browse", "--output", "json", executableVerb}
179+
if executableID != "" {
180+
cmdArgs = append(cmdArgs, executableID)
165181
}
166-
return wsName, nil
182+
cmd := exec.Command("flow", cmdArgs...)
183+
184+
output, err := cmd.CombinedOutput()
185+
if err != nil {
186+
ref := strings.Join([]string{executableVerb, executableID}, " ")
187+
return nil, fmt.Errorf("%s executable details retrieval failed: %s", ref, output)
188+
}
189+
190+
return []mcp.ResourceContents{
191+
mcp.TextResourceContents{
192+
URI: request.Params.URI,
193+
MIMEType: "application/json",
194+
Text: string(output),
195+
},
196+
}, nil
197+
}
198+
199+
func getFlowConceptsResourceHandler(_ context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
200+
return []mcp.ResourceContents{
201+
mcp.TextResourceContents{
202+
URI: request.Params.URI,
203+
MIMEType: "text/markdown",
204+
Text: conceptsMD,
205+
},
206+
}, nil
167207
}
168208

169-
func getFlowInfoResourceHandler(_ context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
209+
func getFlowFileTypesResourceHandler(_ context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
170210
return []mcp.ResourceContents{
171211
mcp.TextResourceContents{
172212
URI: request.Params.URI,
173213
MIMEType: "text/markdown",
174-
Text: infoMD,
214+
Text: fileTypesMD,
175215
},
176216
}, nil
177217
}
@@ -186,6 +226,16 @@ func getFlowFileSchemaResourceHandler(_ context.Context, request mcp.ReadResourc
186226
}, nil
187227
}
188228

229+
func getTemplateSchemaResourceHandler(_ context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
230+
return []mcp.ResourceContents{
231+
mcp.TextResourceContents{
232+
URI: request.Params.URI,
233+
MIMEType: "application/json",
234+
Text: templateSchema,
235+
},
236+
}, nil
237+
}
238+
189239
func getWorkspaceSchemaResourceHandler(_ context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
190240
return []mcp.ResourceContents{
191241
mcp.TextResourceContents{
@@ -195,3 +245,38 @@ func getWorkspaceSchemaResourceHandler(_ context.Context, request mcp.ReadResour
195245
},
196246
}, nil
197247
}
248+
249+
func extractWsName(uri string) (string, error) {
250+
// Assuming the URI is in the format "flow://workspace/{name}" or "flow://workspace/{name}/executables"
251+
if len(uri) < len("flow://workspace/") {
252+
return "", fmt.Errorf("invalid workspace URI: %s", uri)
253+
}
254+
255+
wsName := uri[len("flow://workspace/"):]
256+
strings.TrimSuffix(wsName, "/executables")
257+
if wsName == "" {
258+
return "", fmt.Errorf("workspace name cannot be empty in URI: %s", uri)
259+
}
260+
return wsName, nil
261+
}
262+
263+
func extractExecutableRef(uri string) (string, string, error) {
264+
if len(uri) < len("flow://executable/") {
265+
return "", "", fmt.Errorf("invalid executable URI: %s", uri)
266+
}
267+
268+
ref := uri[len("flow://executable/"):]
269+
if ref == "" {
270+
return "", "", fmt.Errorf("executable reference cannot be empty in URI: %s", uri)
271+
}
272+
273+
parts := strings.SplitN(ref, " ", 2)
274+
switch len(parts) {
275+
case 1:
276+
return parts[0], "", nil
277+
case 2:
278+
return parts[0], parts[1], nil
279+
default:
280+
return "", "", fmt.Errorf("invalid executable reference format in URI: %s", uri)
281+
}
282+
}
Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
# Flow Platform Concepts Guide
1+
# Flow Concepts Guide
22

33
## What is flow?
44

55
flow is a local-first, customizable CLI automation platform designed to streamline development and operations workflows.
66
It helps developers organize, discover, and execute tasks across projects through a unified interface.
77

8+
More comprehensive details can be found in the [flow documentation](https://flowexec.io).
9+
810
## Core Philosophy
911

1012
- **Local-First**: All data and execution happens on your machine
@@ -40,6 +42,16 @@ executables:
4042
text: production
4143
```
4244
45+
#### Executable References
46+
Executables are identified by its reference: combination of **Verb** and **ID**. The ID is in the form `<workspace>/<namespace>:<name>`.
47+
A full reference must be unique across all registered workspaces.
48+
49+
For instance:
50+
- `build app` - current workspace, root namespace
51+
- `build backend/app` - current workspace, backend namespace
52+
- `build my-project/backend:app` - specific workspace and namespace
53+
- `build` - current workspace, root namespace, no name set
54+
4355
### Verbs
4456
**Verbs** describe what action an executable performs. Flow groups related verbs together, allowing natural language-like commands.
4557
By default, flow provide the following verb alias groups:
@@ -57,41 +69,27 @@ Users can invoke executables using any verb using the CLI (e.g. `flow build app`
5769
### Workspaces
5870
**Workspaces** are project containers that organize related executables. Each workspace:
5971
- Has a root directory containing the workspace configuration file (`flow.yaml`)
60-
- Flow files can be located anywhere within the workspace directory
6172
- Can contain multiple namespaces (defined in flow files)
6273
- Provides isolation between projects
6374

64-
**Example workspace structure:**
65-
```
66-
my-project/
67-
├── flow.yaml # Workspace config
68-
├── backend.flow # Backend executables
69-
├── frontend.flow # Frontend executables
70-
└── deployment/
71-
└── k8s.flow # Deployment executables
72-
```
73-
7475
### Namespaces
7576
**Namespaces** provide logical grouping within workspaces. They help organize executables by:
7677
- Feature area (auth, payments, notifications)
7778
- Environment (dev, staging, production)
7879
- Technology stack (backend, frontend, mobile)
7980
- Team ownership (platform, product, data)
8081

81-
**Referencing executables:**
82-
- `VERB app` - current workspace, root namespace
83-
- `VERB backend/app` - current workspace, backend namespace
84-
- `VERB my-project/backend:app` - specific workspace and namespace
8582

8683
Executable names are optional. When not specified, the verb is used as the identifier,
8784
e.g. `flow build` refers to the executable with the verb "build" in the current workspace.
8885

89-
### Flow Files
86+
### Executable Definitions (Flow Files)
9087
**Flow files** (`.flow`, `.flow.yaml`, `.flow.yml`) are YAML configuration files that define executables. They support:
9188
- Multiple executables per file
9289
- Shared metadata (namespace, tags, descriptions)
9390
- Environment variable management
9491
- Conditional execution logic
92+
- Can be located anywhere within the workspace directory
9593

9694
### Secrets and Vaults
9795
**Vaults** provide secure secret storage with multiple encryption backends:
@@ -110,7 +108,27 @@ Executables reference secrets using `secretRef` parameters, keeping sensitive da
110108

111109
## Execution Model
112110

113-
### Command Structure
111+
### Sync
112+
113+
Anytime a new workspace is registered, an executable is added, or it's identifier changes, flow state will need to be synchronized.
114+
This ensures that the latest workspace and executable definitions are available in the cache for execution.
115+
This can be done using the `flow sync` command or with the `--sync` flag on any command.
116+
117+
### Management Commands
118+
119+
Flow provides a set of management commands to interact with workspaces, executables, and configurations:
120+
```bash
121+
flow config # Manage flow's user configuration (get, set, reset)
122+
flow workspace # Manage workspaces (add, get, switch, list, remove)
123+
flow browse # Discover executables (interactive TUI)
124+
flow vault # Manage secrets and vaults (create, edit, get, list, remove, switch)
125+
flow cache # Manage cache data (get, set, remove, list, clear)
126+
flow secret # Manage secrets (get, list, remove, set)
127+
flow template # Manage templates (add, generate, get, list)
128+
flow logs # View execution logs
129+
```
130+
131+
### Execution Command Structure
114132
```bash
115133
flow <verb> <reference> [arguments] [flags]
116134
```
@@ -129,16 +147,19 @@ serial:
129147
cmd: brew install mytool
130148
- if: env["CI"] == "true"
131149
cmd: run-ci-specific-setup
132-
- if: len(store["build-id"]) > 0
150+
- if: len(store["build-id"]) > 0 # checks the cache for a build ID key
133151
cmd: use-cached-build
134152
```
135153

136154
### State Management
137155
flow provides state persistence through:
138-
- **Cache**: Key-value store for sharing data between executables
156+
- **Cache**: Key-value store for sharing data between executables. State is only persisted during execution
157+
- Use `flow cache set KEY VALUE` and `flow cache get KEY` to manage cache entries within executable scripts
158+
- Users can also manage global keys outside the execution context using `flow cache` commands
139159
- **Context variables**: OS, architecture, workspace, and path information
140-
- **Environment inheritance**: Variables flow from parent to child executables
141-
- **Temporary directories**: Isolated scratch space for executable runs (set the `dir` to `f:tmp`)
160+
- **Environment inheritance**: Variables (`params` and `args`) flow from parent to child executables (for serial and parallel)
161+
- **Temporary directories**: Isolated scratch space for executable runs
162+
- A temporary directory is created for the execution when the executable's `dir` is set to `f:tmp`)
142163

143164
## Workflow Patterns
144165

0 commit comments

Comments
 (0)