Skip to content
Open
66 changes: 25 additions & 41 deletions docs/reference/file-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,35 +137,6 @@ timeout: 10m
- `1h` - 1 hour
- `1h30m` - 1 hour 30 minutes

#### `mcp_servers` (optional, standard field)

**Type:** Map (from server name to server configuration)
**Purpose:** Specifies the MCP (Model Context Protocol) servers that the task should use; stored in frontmatter output but does not filter rules

The `mcp_servers` field is a **standard frontmatter field** following the industry standard for MCP server definition. It does not act as a selector. The field is a map where keys are server names and values are server configurations.

**Example:**
```yaml
---
mcp_servers:
filesystem:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"]
git:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-git"]
database:
type: http
url: https://api.example.com/mcp
headers:
Authorization: Bearer token123
---
```

**Note:** The format follows the MCP specification for server identification. Each server configuration includes a `type` field (e.g., "stdio", "http", "sse") and other fields specific to that transport type.

#### `agent` (optional, standard field)

**Type:** String
Expand Down Expand Up @@ -625,25 +596,38 @@ agent: cursor
- If task/CLI specifies `agent: cursor`, only rules with `agent: cursor` or no agent field are included
- Rules without an agent field are considered generic and always included (unless other selectors exclude them)

#### `mcp_servers` (rule metadata)
#### `mcp_server` (rule metadata)

Specifies MCP servers that need to be running for this rule. Does not filter rules. The field is a map where keys are server names and values are server configurations.
Specifies an MCP server configuration for this rule. Each rule can specify one MCP server configuration with standard and arbitrary custom fields. Does not filter rules.

**Important:** MCP servers are specified in rules only, not in tasks. Tasks select rules (and thus MCP servers) via selectors.

```yaml
---
mcp_servers:
filesystem:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem"]
database:
type: http
url: https://api.example.com/mcp
mcp_server:
command: python
args: ["-m", "server"]
env:
PYTHON_PATH: /usr/bin/python3
custom_config:
host: localhost
port: 5432
---
# Metadata indicating required MCP servers
# Rule with MCP server configuration
```

**Note:** This field is informational and does not affect rule selection.
**Standard configuration fields:**
- `command`: The executable to run (e.g., "npx", "python", "docker")
- `args`: Array of command-line arguments
- `env`: Map of environment variables
- `type`: Connection protocol - "stdio" (default), "http", or "sse"
- `url`: Endpoint URL (required for HTTP/SSE types)
- `headers`: Custom HTTP headers (for HTTP/SSE types)

**Additional arbitrary fields:**
You can include any custom fields for your specific server needs (e.g., `custom_config`, `monitoring`, `cache_enabled`, etc.). All fields are preserved in the configuration.

**Note:** This field is metadata and does not affect rule selection.

#### `expand` (optional)

Expand Down
108 changes: 48 additions & 60 deletions examples/agents/tasks/example-mcp-arbitrary-fields.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,58 @@
---
task_name: example-mcp-arbitrary-fields
agent: cursor
mcp_servers:
# Example with standard fields only
filesystem:
type: stdio
command: filesystem

# Example with standard fields plus arbitrary custom fields
custom-database:
type: stdio
command: database-mcp
args: ["--verbose"]
# Arbitrary fields below
cache_enabled: true
max_cache_size: 1000
connection_pool_size: 10

# Example HTTP server with custom metadata
api-server:
type: http
url: https://api.example.com
headers:
Authorization: Bearer token123
# Arbitrary fields below
api_version: v2
rate_limit: 100
timeout_seconds: 30
retry_policy: exponential
region: us-west-2

# Example with nested custom configuration
advanced-server:
type: stdio
command: python
args: ["-m", "server"]
env:
PYTHON_PATH: /usr/bin/python3
# Arbitrary nested fields below
custom_config:
host: localhost
port: 5432
ssl: true
pool:
min: 2
max: 10
monitoring:
enabled: true
metrics_port: 9090
---

# Example Task with Arbitrary MCP Server Fields
# Example Rule with MCP Server Configuration

This example demonstrates how rules can specify MCP server configuration with arbitrary custom fields.

Note: MCP servers are specified in rules, not in tasks. Tasks can select which rules (and thus which MCP servers) to use via selectors.

## The `mcp_server` Field in Rules

Rules can specify a single MCP server configuration with both standard and arbitrary custom fields.

The `mcp_server` field, when present in a rule, specifies that rule's single MCP server configuration with both standard and arbitrary custom fields. Tasks cannot define MCP servers directly.

**Standard fields:**
- `command`: The executable to run (e.g., "python", "npx", "docker")
- `args`: Array of command-line arguments
- `env`: Environment variables for the server process
- `type`: Connection protocol ("stdio", "http", "sse") - optional, defaults to stdio
- `url`: Endpoint URL for HTTP/SSE types
- `headers`: Custom HTTP headers for HTTP/SSE types

## Example Rule with MCP Server

```yaml
---
rule_name: python-mcp-server
mcp_server:
command: python
args: ["-m", "server"]
env:
PYTHON_PATH: /usr/bin/python3
custom_config:
host: localhost
port: 5432
ssl: true
pool:
min: 2
max: 10
monitoring:
enabled: true
metrics_port: 9090
---

# Python MCP Server Rule

This task demonstrates the ability to add arbitrary fields to MCP server configurations, just like we can with FrontMatter.
This rule provides the Python MCP server configuration.
```

## Why Arbitrary Fields?

Different MCP servers may need different configuration options beyond the standard fields (`type`, `command`, `args`, `env`, `url`, `headers`). Arbitrary fields allow you to:
Different MCP servers may need different configuration options beyond the standard fields. Arbitrary fields allow you to:

1. **Add custom metadata**: Version info, regions, endpoints, etc.
2. **Configure behavior**: Caching, retry policies, timeouts, rate limits
Expand All @@ -65,7 +61,7 @@ Different MCP servers may need different configuration options beyond the standa

## How It Works

The `MCPServerConfig` struct now includes a `Content` field (similar to `BaseFrontMatter`) that captures all fields from YAML/JSON:
The `MCPServerConfig` struct includes a `Content` field that captures all fields from YAML/JSON:

```go
type MCPServerConfig struct {
Expand All @@ -82,12 +78,4 @@ type MCPServerConfig struct {
}
```

## Example Usage

The examples above show:
- **Simple custom fields**: `cache_enabled`, `max_cache_size`
- **API configuration**: `api_version`, `rate_limit`, `timeout_seconds`
- **Nested objects**: `custom_config` with sub-fields like `host`, `port`, `ssl`
- **Multiple custom sections**: `custom_config` and `monitoring` as separate objects

All these fields are preserved when the configuration is parsed and can be accessed via the `Content` map.
All fields (both standard and custom) are preserved when the configuration is parsed and can be accessed via the struct fields or the `Content` map.
8 changes: 0 additions & 8 deletions examples/agents/tasks/example-with-standard-fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ language: go
model: anthropic.claude-sonnet-4-20250514-v1-0
single_shot: false
timeout: 10m
mcp_servers:
filesystem:
type: stdio
command: filesystem
git:
type: stdio
command: git
selectors:
stage: implementation
---
Expand All @@ -34,7 +27,6 @@ These fields are stored in frontmatter and passed through to output, but do NOT
- **model**: `anthropic.claude-sonnet-4-20250514-v1-0` - AI model to use for this task
- **single_shot**: `false` - Task can be run multiple times
- **timeout**: `10m` - Task timeout as time.Duration (10 minutes)
- **mcp_servers**: `[filesystem, git]` - MCP servers required for this task

## Custom Selectors

Expand Down
6 changes: 3 additions & 3 deletions pkg/codingcontext/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ func main() {

// Access MCP server configurations
mcpServers := result.MCPServers()
for name, config := range mcpServers {
fmt.Printf("MCP Server %s: %s\n", name, config.Command)
for i, config := range mcpServers {
fmt.Printf("MCP Server %d: %s\n", i, config.Command)
}
}
```
Expand All @@ -139,7 +139,7 @@ Result holds the assembled context from running a task:
- `Agent Agent` - The agent used (from task frontmatter or option)

**Methods:**
- `MCPServers() MCPServerConfigs` - Returns all MCP server configurations from rules and task
- `MCPServers() []MCPServerConfig` - Returns all MCP server configurations from rules as a slice

#### `Markdown[T]`

Expand Down
8 changes: 2 additions & 6 deletions pkg/codingcontext/markdown/frontmatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ type TaskFrontMatter struct {
// Does not filter rules, metadata only
Timeout string `yaml:"timeout,omitempty" json:"timeout,omitempty"`

// MCPServers maps server names to their configurations
// Does not filter rules, metadata only
MCPServers mcp.MCPServerConfigs `yaml:"mcp_servers,omitempty" json:"mcp_servers,omitempty"`

// Resume indicates if this task should be resumed
Resume bool `yaml:"resume,omitempty" json:"resume,omitempty"`

Expand Down Expand Up @@ -120,9 +116,9 @@ type RuleFrontMatter struct {
// Agent specifies which AI agent this rule is intended for
Agent string `yaml:"agent,omitempty" json:"agent,omitempty"`

// MCPServers maps server names to their configurations
// MCPServer specifies a single MCP server configuration
// Metadata only, does not filter
MCPServers mcp.MCPServerConfigs `yaml:"mcp_servers,omitempty" json:"mcp_servers,omitempty"`
MCPServer mcp.MCPServerConfig `yaml:"mcp_server,omitempty" json:"mcp_server,omitempty"`

// RuleName is an optional identifier for the rule file
RuleName string `yaml:"rule_name,omitempty" json:"rule_name,omitempty"`
Expand Down
19 changes: 10 additions & 9 deletions pkg/codingcontext/markdown/frontmatter_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@ agent: cursor
TaskNames: []string{"test-task"},
Languages: []string{"go", "python"},
Agent: "copilot",
MCPServers: mcp.MCPServerConfigs{
"database": {
Type: mcp.TransportTypeStdio,
Command: "database-server",
},
MCPServer: mcp.MCPServerConfig{
Type: mcp.TransportTypeStdio,
Command: "database-server",
Args: []string{"--port", "5432"},
},
RuleName: "test-rule",
},
Expand All @@ -65,10 +64,12 @@ languages:
- go
- python
agent: copilot
mcp_servers:
database:
type: stdio
command: database-server
mcp_server:
type: stdio
command: database-server
args:
- --port
- "5432"
rule_name: test-rule
`,
},
Expand Down
25 changes: 1 addition & 24 deletions pkg/codingcontext/markdown/frontmatter_task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"testing"

"github.com/goccy/go-yaml"
"github.com/kitproj/coding-context-cli/pkg/codingcontext/mcp"
)

func TestTaskFrontMatter_Marshal(t *testing.T) {
Expand Down Expand Up @@ -33,11 +32,7 @@ func TestTaskFrontMatter_Marshal(t *testing.T) {
Model: "gpt-4",
SingleShot: true,
Timeout: "10m",
MCPServers: mcp.MCPServerConfigs{
"filesystem": {Type: mcp.TransportTypeStdio, Command: "filesystem-server"},
"git": {Type: mcp.TransportTypeStdio, Command: "git-server"},
},
Resume: false,
Resume: false,
Selectors: map[string]any{
"stage": "implementation",
},
Expand All @@ -49,13 +44,6 @@ languages:
model: gpt-4
single_shot: true
timeout: 10m
mcp_servers:
filesystem:
type: stdio
command: filesystem-server
git:
type: stdio
command: git-server
selectors:
stage: implementation
`,
Expand Down Expand Up @@ -142,13 +130,6 @@ languages:
model: gpt-4
single_shot: true
timeout: 10m
mcp_servers:
filesystem:
type: stdio
command: filesystem-server
git:
type: stdio
command: git-server
selectors:
stage: implementation
`,
Expand All @@ -161,10 +142,6 @@ selectors:
Model: "gpt-4",
SingleShot: true,
Timeout: "10m",
MCPServers: mcp.MCPServerConfigs{
"filesystem": {Type: mcp.TransportTypeStdio, Command: "filesystem-server"},
"git": {Type: mcp.TransportTypeStdio, Command: "git-server"},
},
Selectors: map[string]any{
"stage": "implementation",
},
Expand Down
Loading