Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/minor-add-linear-tools.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions docs/public/editor/autocomplete-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -1870,6 +1870,35 @@
}
}
},
"linear": {
"type": "null|object",
"desc": "Linear tools provided by Linear's official hosted MCP server",
"children": {
"token": {
"type": "string",
"desc": "Optional Linear API key or OAuth access token secret reference. Defaults to ${{ secrets.LINEAR_API_KEY }}.",
"leaf": true
},
"toolsets": {
"type": "string|array",
"desc": "Linear MCP toolset name(s) to enable. Toolsets are expanded to gateway-enforced allowed tools.",
"enum": ["all", "attachments", "comments", "customers", "cycles", "diffs", "documentation", "documents", "initiatives", "issues", "milestones", "projects", "status_updates", "teams", "users"],
"leaf": true,
"array": true
},
"allowed": {
"type": "array",
"desc": "List of allowed Linear MCP tool names or wildcard patterns. When toolsets are set, every pattern must match a tool in those toolsets.",
"array": true
},
"required": {
"type": "boolean",
"desc": "Whether failure to connect to Linear should fail MCP gateway startup. Defaults to true.",
"enum": [true, false],
"leaf": true
}
}
},
"jira": {
"type": "boolean|object",
"desc": "Jira tools provided by Atlassian's remote Rovo MCP service.",
Expand Down
185 changes: 176 additions & 9 deletions docs/src/content/docs/reference/frontmatter-full.md
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ on:
# Format 2: List of label names; the workflow fires when the triggering label
# matches any entry.
labels: []
# Array items: undefined
# Array items: A non-empty string value.

# Allow the bot-posted-menu / user-checks-box pattern: when a workflow posts a
# checkbox-menu comment as a GitHub App bot and a human maintainer edits it to
Expand Down Expand Up @@ -2511,7 +2511,7 @@ steps:
{}

# Format 2: array
steps: []
steps: [{"prompt":"Analyze the issue and create a plan"}]
# Array items: undefined

# Custom workflow steps to run at the very beginning of the agent job, before
Expand All @@ -2527,7 +2527,7 @@ pre-steps:
{}

# Format 2: array
pre-steps: []
pre-steps: [{"name":"Mint short-lived token","id":"mint","uses":"some-org/token-minting-action@v1","with":{"scope":"target-org/target-repo"}}]
# Array items: undefined

# Custom workflow steps to run immediately before AI execution, after all
Expand All @@ -2540,7 +2540,7 @@ pre-agent-steps:
{}

# Format 2: array
pre-agent-steps: []
pre-agent-steps: [{"name":"Prepare final context","run":"echo \"ready\""}]
# Array items: undefined

# Custom workflow steps to run after AI execution
Expand All @@ -2552,7 +2552,7 @@ post-steps:
{}

# Format 2: array
post-steps: []
post-steps: [{"name":"Verify Post-Steps Execution","run":"echo \"✅ Post-steps are executing correctly\"\necho \"This step runs after the AI agent completes\"\n"},{"name":"Upload Test Results","if":"always()","uses":"actions/upload-artifact@v4","with":{"name":"post-steps-test-results","path":"/tmp/gh-aw/","retention-days":1,"if-no-files-found":"ignore"}}]
# Array items: undefined

# AI engine configuration that specifies which AI processor interprets and
Expand Down Expand Up @@ -3696,7 +3696,8 @@ tools:
# Format 2: Array of GitHub MCP server toolset names to enable specific groups of
# GitHub API functionalities
toolsets: []
# Array items: undefined
# Array items: A GitHub MCP server toolset name that enables a specific group of
# GitHub API functionalities.

# Volume mounts for the containerized GitHub MCP server (format:
# 'host:container:mode' where mode is 'ro' for read-only or 'rw' for read-write).
Expand Down Expand Up @@ -4036,6 +4037,44 @@ tools:
# (optional)
features: "example-value"

# Linear tools provided by Linear's official hosted MCP server
# (optional)
# Accepted formats:

# Format 1: Enable Linear using the well-known LINEAR_API_KEY secret
linear: null

# Format 2: object
linear:
# Optional Linear API key or OAuth access token secret reference. Defaults to ${{
# secrets.LINEAR_API_KEY }}.
# (optional)
token: "${{ secrets.LINEAR_API_KEY }}"

# Linear MCP toolset name(s) to enable. Toolsets are expanded to gateway-enforced
# allowed tools.
# (optional)
# Accepted formats:

# Format 1: A Linear MCP toolset name that enables a related group of read-only
# Linear tools.
toolsets: "all"

# Format 2: Array of Linear MCP toolset names
toolsets: ["issues","projects"]
# Array items: A Linear MCP toolset name that enables a related group of read-only
# Linear tools.

# List of allowed Linear MCP tool names or wildcard patterns. When toolsets are
# set, every pattern must match a tool in those toolsets.
# (optional)
allowed: ["*"]
# Array of strings
Comment on lines +4068 to +4072

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 715b3f0e77: the generated Linear allowed example is now non-empty (["*"]) and valid against the schema.


# Whether failure to connect to Linear should fail MCP gateway startup. Defaults
# to true.
# (optional)
required: true
# Jira tools provided by Atlassian's remote Rovo MCP service. This integration
# supports non-interactive CI/CD authentication only.
# (optional)
Expand Down Expand Up @@ -4243,7 +4282,7 @@ tools:
timeout-minutes: 1

# Format 4: Array of cache-memory configurations for multiple caches
cache-memory: []
cache-memory: [{"id":"default","key":"memory-default"},{"id":"session","key":"memory-session"}]
# Array items: object

# Private-preview GitHub Drives configuration. Do not configure unless GitHub has
Expand Down Expand Up @@ -4512,7 +4551,7 @@ tools:
timeout-minutes: 1

# Format 4: Array of repo-memory configurations for multiple memory locations
repo-memory: []
repo-memory: [{"id":"default","branch-name":"memory/default"},{"id":"session","branch-name":"memory/session"}]
# Array items: object

# ⚠️ Experimental. Top-level Language Server Protocol (LSP) configuration for
Expand Down Expand Up @@ -8673,6 +8712,130 @@ safe-outputs:
# Format 2: Enable Jira label additions with default configuration.
jira-add-label: null

# Experimental. Create Linear issues through the isolated safe_outputs job.
# (optional)
linear-create-issue:
# Trusted Linear team model UUID.
team-id: "example-value"

# Maximum number of Linear issues to create (default: 1).
# (optional)
# Accepted formats:

# Format 1: integer
max: 1

# Format 2: string
max: "example-value"

# A boolean value that may also be specified as a GitHub Actions expression string
# that resolves to a boolean at runtime (e.g. '${{ inputs.my-flag }}').
# (optional)
# Accepted formats:

# Format 1: boolean
staged: true

# Format 2: GitHub Actions expression that resolves to a boolean at runtime
staged: "example-value"

# (optional)
# Accepted formats:

# Format 1: array
samples: []
# Array items: object

# Format 2: object
samples:
{}

# Experimental. Add comments to one trusted Linear issue through the isolated
# safe_outputs job.
# (optional)
linear-add-comment:
# Trusted Linear issue UUID or shorthand identifier such as ENG-123.
target: "example-value"

# Maximum number of Linear comments to add (default: 1).
# (optional)
# Accepted formats:

# Format 1: integer
max: 1

# Format 2: string
max: "example-value"

# A boolean value that may also be specified as a GitHub Actions expression string
# that resolves to a boolean at runtime (e.g. '${{ inputs.my-flag }}').
# (optional)
# Accepted formats:

# Format 1: boolean
staged: true

# Format 2: GitHub Actions expression that resolves to a boolean at runtime
staged: "example-value"

# (optional)
# Accepted formats:

# Format 1: array
samples: []
# Array items: object

# Format 2: object
samples:
{}

# Experimental. Update explicitly enabled fields on one trusted Linear issue
# through the isolated safe_outputs job.
# (optional)
linear-update-issue:
# Trusted Linear issue UUID or shorthand identifier such as ENG-123.
target: "example-value"

# Allow the agent to update the Linear issue title.
# (optional)
title: null

# Allow the agent to replace the Linear issue description.
# (optional)
body: null

# Maximum number of updates to apply (default: 1).
# (optional)
# Accepted formats:

# Format 1: integer
max: 1

# Format 2: string
max: "example-value"

# A boolean value that may also be specified as a GitHub Actions expression string
# that resolves to a boolean at runtime (e.g. '${{ inputs.my-flag }}').
# (optional)
# Accepted formats:

# Format 1: boolean
staged: true

# Format 2: GitHub Actions expression that resolves to a boolean at runtime
staged: "example-value"

# (optional)
# Accepted formats:

# Format 1: array
samples: []
# Array items: object

# Format 2: object
samples:
{}

# Enable AI agents to add comments to GitHub issues, pull requests, or
# discussions. Supports templating, cross-repository commenting, and automatic
# mentions.
Expand Down Expand Up @@ -19979,6 +20142,10 @@ safe-outputs:
# (optional)
github-token: "${{ secrets.GITHUB_TOKEN }}"

# Linear personal API key expression used only by the trusted safe_outputs job.
# (optional)
linear-token: "example-value"

# GitHub App credentials for minting installation access tokens. When configured,
# a token will be generated using the app credentials and used for all safe output
# operations.
Expand Down Expand Up @@ -22820,7 +22987,7 @@ checkout:

# Format 2: Multiple checkout configurations
checkout: []
# Array items: undefined
# Array items: Configuration for a single actions/checkout step

# Format 3: Set to false to disable the default checkout step. The agent job will
# not check out any repository (dev-mode checkouts are unaffected).
Expand Down
30 changes: 30 additions & 0 deletions docs/src/content/docs/reference/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,36 @@ tools:

See **[GitHub Tools Reference](/gh-aw/reference/github-tools/)** for complete configuration options.

### Linear Tools (`linear:`)

Connect to [Linear's official hosted MCP server](https://linear.app/docs/mcp) using the well-known `LINEAR_API_KEY` GitHub Actions secret:

```yaml wrap
tools:
linear: {}
```

Set `token` to use a different secret containing a Linear API key or OAuth access token. The integration uses Streamable HTTP through the MCP gateway and always uses Linear's server-enforced read-only endpoint. Use `allowed` to restrict tool names and `required: false` to make Linear connectivity best-effort:

```yaml wrap
tools:
linear:
token: ${{ secrets.CUSTOM_LINEAR_TOKEN }}
allowed: ["*"]
required: true
```

Use `toolsets` to enable related groups of tools without maintaining individual tool names:

```yaml wrap
tools:
linear:
toolsets: [issues, projects]
```

Supported toolsets are `all`, `attachments`, `comments`, `customers`, `cycles`, `diffs`, `documentation`, `documents`, `initiatives`, `issues`, `milestones`, `projects`, `status_updates`, `teams`, and `users`. The compiler expands toolsets into the gateway's allowed-tool list. If `allowed` is also set, each name or wildcard must match a tool in the selected toolsets.

The Linear credential is passed to the gateway as an environment variable and sent as an `Authorization: Bearer` header. It is not embedded in MCP configuration. Linear works with `tools.cli-proxy: true` like other remote MCP servers.
### Jira Tools (`jira:`)

Connect to Atlassian's official remote Rovo MCP endpoint from non-interactive GitHub Actions workloads. Browser OAuth, device login, and user-consent flows are not supported.
Expand Down
9 changes: 9 additions & 0 deletions pkg/cli/mcp_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ func validateServerSecrets(config parser.RegistryMCPServerConfig, verbose bool,
missingSecrets = append(missingSecrets, secret)
}
}
for _, secret := range availableSecrets {
if secret.Value == "" {
continue
}
for key, value := range config.Headers {
expression := "${{ secrets." + secret.Name + " }}"
config.Headers[key] = strings.ReplaceAll(value, expression, secret.Value)
}
}

// Display information about secrets
if verbose {
Expand Down
5 changes: 5 additions & 0 deletions pkg/constants/tool_constants.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package constants

const (
LinearMCPReadOnlyURL = "https://mcp.linear.app/mcp/readonly"
LinearMCPDefaultTokenExpr = "${{ secrets.LINEAR_API_KEY }}"
)

// AllowedExpressions contains the GitHub Actions expressions that can be used in workflow markdown content
// see https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#github-context
var AllowedExpressions = []string{
Expand Down
Loading