Add custom engine MCP configuration fields for flexible format generation#1497
Add custom engine MCP configuration fields for flexible format generation#1497
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
pelikhan
left a comment
There was a problem hiding this comment.
@copilot add two optional fields to the custom engine configuration:
- mcp config file : path to the config file.json
- mcp servers field: field name (mcpServers, servers, ...)
Update custom agentic engine to generate the MCP config file based on those fields
Use those fields to configure the way the MCP config file is generated for LLM
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Added the two optional fields to the custom engine configuration:
The custom engine now generates MCP config files based on these fields. Updated simonw-llm to use: engine:
id: custom
mcp-config-file: ~/.llm-tools-mcp/mcp.json
mcp-servers-field: serversThis generates the extension format directly without needing the Python transformation script. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot add a optional field to the custom engine "mcp-servers-shape: array" | "map", default is map. The option determines how the servers are stored in config |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Added The field determines the structure of the MCP configuration:
Updated simonw-llm to use |
pkg/workflow/custom_engine.go
Outdated
| if mcpServersShape == "array" { | ||
| // Extension format: { "servers": [ {...}, {...} ] } | ||
| yaml.WriteString(" {\n") | ||
| yaml.WriteString(" \"servers\": [\n") |
There was a problem hiding this comment.
Updated to use mcpServersField variable with value "servers" on line 172.
pkg/workflow/custom_engine.go
Outdated
| // Default map format: { "mcpServers": { "name": {...}, ... } } | ||
| yaml.WriteString(" {\n") | ||
| yaml.WriteString(fmt.Sprintf(" \"%s\": {\n", mcpServersField)) | ||
| yaml.WriteString(" \"mcpServers\": {\n") |
There was a problem hiding this comment.
Updated to use mcpServersField variable with value "mcpServers" on line 213.
| "type": "string", | ||
| "description": "Path to the MCP configuration file (custom engine only). Overrides the default path (/tmp/gh-aw/mcp-config/mcp-servers.json)." | ||
| }, | ||
| "mcp-servers-field": { |
There was a problem hiding this comment.
Kept mcp-servers-field in included_file_schema.json.
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot add ALSO support for mcp-servers-shape. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Added support for both |
| // mcp-servers-field takes precedence if both are provided | ||
| if workflowData.EngineConfig.MCPServersField != "" { | ||
| mcpServersField = workflowData.EngineConfig.MCPServersField | ||
| } else if workflowData.EngineConfig.MCPServersShape != "" { |
There was a problem hiding this comment.
@copilot the shape is separate from the field name. DO NOT ASSOCIATE THEM.
Problem
The simonw-LLM shared workflow was copying the MCP configuration file directly to
~/.llm-tools-mcp/mcp.json, but the llm-tools-mcp extension expects a different configuration format than what gh-aw generates.gh-aw generates (mcpServers object format):
{ "mcpServers": { "github": { "command": "docker", "args": ["run", "-i", "--rm", "ghcr.io/github/github-mcp-server:v0.18.0"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "..." } } } }llm-tools-mcp expects (servers array format):
{ "servers": [ { "name": "github", "transport": "stdio", "command": ["docker", "run", "-i", "--rm", "ghcr.io/github/github-mcp-server:v0.18.0"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "..." } } ] }Solution
Added three optional configuration fields to the custom engine that control MCP configuration generation:
mcp-config-file: Path to the MCP configuration file (custom engine only). Overrides the default path (/tmp/gh-aw/mcp-config/mcp-servers.json).mcp-servers-field: Field name for the MCP servers in the configuration file (custom engine only). Common values:"mcpServers"(default),"servers". The field value is directly used in the generated configuration structure.mcp-servers-shape: Shape of the MCP servers in the configuration file (custom engine only). Enum values:"array"|"map"(default:"map"). Provides a semantic alternative tomcp-servers-field.The custom engine now generates MCP configurations in either format based on these fields, eliminating the need for post-processing transformation scripts. Both
mcp-servers-fieldandmcp-servers-shapeare supported, withmcp-servers-fieldtaking precedence if both are specified.Implementation Details
Schema Changes:
main_workflow_schema.jsonandincluded_file_schema.jsonEngineConfigstruct withMCPConfigFile,MCPServersField, andMCPServersShapefieldsCustom Engine Updates:
RenderMCPConfigto support bothmcpServersobject format andserversarray formatmcp-servers-field(direct field name) andmcp-servers-shape(semantic enum)mcp-servers-fieldvalue is directly interpolated into the JSON structure using themcpServersFieldvariablemcp-servers-shapeis converted to the appropriate field name:"array"→"servers","map"→"mcpServers""mcpServers"field (backward compatible)simonw-llm Workflow:
Configuration Options
Users can choose any of these approaches:
Option 1: Use mcp-servers-field (direct field name)
Option 2: Use mcp-servers-shape (semantic enum)
Option 3: Use both (field takes precedence)
MCP Server Configuration Formats
mcp-servers-field: "servers"ormcp-servers-shape: "array": Generates{"servers": [{"name": "...", "transport": "stdio", "command": [...]}]}- suitable for extensions like llm-tools-mcpmcp-servers-field: "mcpServers"ormcp-servers-shape: "map"(default): Generates{"mcpServers": {"server-name": {"command": "...", "args": [...]}}}- standard gh-aw formatChanges
pkg/parser/schemas/main_workflow_schema.json: Addedmcp-config-file,mcp-servers-field, andmcp-servers-shapeto engine_config schemapkg/parser/schemas/included_file_schema.json: Added same fields for imported workflowspkg/workflow/engine.go: Updated EngineConfig struct and extraction logic for all three fieldspkg/workflow/custom_engine.go: Added support for both MCP config formats with array format rendering functions, supports both field and shape configuration with proper precedence.github/workflows/shared/simonw-llm.md: Configured to use new engine fields, removed transformation script.github/workflows/shared/simonw-llm.lock.yml: Recompiled with new configuration.github/workflows/issue-triage-llm.lock.yml: Recompiled with new configurationTesting
✅ All 64 workflows compile successfully
✅ Unit tests pass
✅ Integration tests pass
✅ MCP configuration generated in correct extension format
✅ Default "mcpServers" format works correctly (backward compatible)
✅ "servers" format generates correct extension format for simonw-llm
✅
mcp-servers-fieldworks correctly (direct field name approach)✅
mcp-servers-shape: arraygenerates{"servers": [...]}✅
mcp-servers-shape: mapgenerates{"mcpServers": {...}}✅ Precedence works correctly - field takes priority over shape
The custom engine now provides a flexible, declarative way to control MCP configuration generation without requiring post-processing scripts. Any workflow can specify the desired MCP config format using either the direct field name approach (
mcp-servers-field) or the semantic enum approach (mcp-servers-shape), based on user preference.Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.