Skip to content

[pull] main from coder:main #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
79cd80e
feat: add MCP tools for ChatGPT (#19102)
hugodutka Aug 4, 2025
40dbc55
fix: ignore goroutine leak for protocol lookup on windows (#19131)
sreya Aug 4, 2025
2a2851e
chore: check integrity of Go in Dockefile (#19130)
sreya Aug 4, 2025
5df3bf7
ci: bump the github-actions group with 6 updates (#19149)
dependabot[bot] Aug 4, 2025
8f538d4
chore: bump github.com/mark3labs/mcp-go from 0.34.0 to 0.36.0 (#19152)
dependabot[bot] Aug 4, 2025
b8e2344
chore(agent/agentcontainers): disable project autostart by default (#…
DanielleMaywood Aug 4, 2025
b4f2413
chore: bump github.com/aws/aws-sdk-go-v2 from 1.36.4 to 1.37.1 (#19151)
dependabot[bot] Aug 4, 2025
ce9b208
chore: bump github.com/fergusstrange/embedded-postgres from 1.31.0 to…
dependabot[bot] Aug 4, 2025
181c2f0
chore: bump github.com/coreos/go-oidc/v3 from 3.14.1 to 3.15.0 (#19156)
dependabot[bot] Aug 4, 2025
1ae5cac
chore: bump github.com/aws/aws-sdk-go-v2/config from 1.29.14 to 1.30.…
dependabot[bot] Aug 4, 2025
83aafd8
chore: bump google.golang.org/grpc from 1.73.0 to 1.74.2 (#19158)
dependabot[bot] Aug 4, 2025
06eaa00
chore: bump github.com/prometheus/client_golang from 1.22.0 to 1.23.0…
dependabot[bot] Aug 4, 2025
8a8c133
feat: update form-data dependency to 4.0.4 (#19128)
sreya Aug 4, 2025
75749ef
chore: update diagrams to meet new branding (#19164)
phorcys420 Aug 4, 2025
a02d1c1
docs: document how to start a remote MCP Coder server (#19150)
hugodutka Aug 4, 2025
dc395c3
chore: add openai icon (#19118)
35C4n0r Aug 4, 2025
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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ jobs:
# the check to pass. This is desired in PRs, but not in mainline.
- name: Publish to Chromatic (non-mainline)
if: github.ref != 'refs/heads/main' && github.repository_owner == 'coder'
uses: chromaui/action@4d8ebd13658d795114f8051e25c28d66f14886c6 # v13.1.2
uses: chromaui/action@58d9ffb36c90c97a02d061544ecc849cc4a242a9 # v13.1.3
env:
NODE_OPTIONS: "--max_old_space_size=4096"
STORYBOOK: true
Expand Down Expand Up @@ -826,7 +826,7 @@ jobs:
# infinitely "in progress" in mainline unless we re-review each build.
- name: Publish to Chromatic (mainline)
if: github.ref == 'refs/heads/main' && github.repository_owner == 'coder'
uses: chromaui/action@4d8ebd13658d795114f8051e25c28d66f14886c6 # v13.1.2
uses: chromaui/action@58d9ffb36c90c97a02d061544ecc849cc4a242a9 # v13.1.3
env:
NODE_OPTIONS: "--max_old_space_size=4096"
STORYBOOK: true
Expand Down Expand Up @@ -1127,7 +1127,7 @@ jobs:
# Setup GCloud for signing Windows binaries.
- name: Authenticate to Google Cloud
id: gcloud_auth
uses: google-github-actions/auth@140bb5113ffb6b65a7e9b937a81fa96cf5064462 # v2.1.11
uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12
with:
workload_identity_provider: ${{ secrets.GCP_CODE_SIGNING_WORKLOAD_ID_PROVIDER }}
service_account: ${{ secrets.GCP_CODE_SIGNING_SERVICE_ACCOUNT }}
Expand Down Expand Up @@ -1431,7 +1431,7 @@ jobs:
fetch-depth: 0

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@140bb5113ffb6b65a7e9b937a81fa96cf5064462 # v2.1.11
uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12
with:
workload_identity_provider: projects/573722524737/locations/global/workloadIdentityPools/github/providers/github
service_account: coder-ci@coder-dogfood.iam.gserviceaccount.com
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Setup Node
uses: ./.github/actions/setup-node

- uses: tj-actions/changed-files@055970845dd036d7345da7399b7e89f2e10f2b04 # v45.0.7
- uses: tj-actions/changed-files@c2ca2493190021783138cb8aac49bcee14b4bb89 # v45.0.7
id: changed-files
with:
files: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/dogfood.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:

- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@dde14ac574a8b9b1cedc59a1cf312788af43d8d8 # v8.2.1
uses: tj-actions/branch-names@5250492686b253f06fa55861556d1027b067aeb5 # v9.0.2

- name: "Branch name to Docker tag name"
id: docker-tag-name
Expand Down Expand Up @@ -129,7 +129,7 @@ jobs:
uses: ./.github/actions/setup-tf

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@140bb5113ffb6b65a7e9b937a81fa96cf5064462 # v2.1.11
uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12
with:
workload_identity_provider: projects/573722524737/locations/global/workloadIdentityPools/github/providers/github
service_account: coder-ci@coder-dogfood.iam.gserviceaccount.com
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly-gauntlet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- windows-2022
steps:
- name: Harden Runner
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ jobs:
# Setup GCloud for signing Windows binaries.
- name: Authenticate to Google Cloud
id: gcloud_auth
uses: google-github-actions/auth@140bb5113ffb6b65a7e9b937a81fa96cf5064462 # v2.1.11
uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12
with:
workload_identity_provider: ${{ secrets.GCP_CODE_SIGNING_WORKLOAD_ID_PROVIDER }}
service_account: ${{ secrets.GCP_CODE_SIGNING_SERVICE_ACCOUNT }}
Expand Down Expand Up @@ -696,7 +696,7 @@ jobs:
CODER_GPG_RELEASE_KEY_BASE64: ${{ secrets.GPG_RELEASE_KEY_BASE64 }}

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@140bb5113ffb6b65a7e9b937a81fa96cf5064462 # v2.1.11
uses: google-github-actions/auth@b7593ed2efd1c1617e1b0254da33b86225adb2a5 # v2.1.12
with:
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_ID_PROVIDER }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ jobs:

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
with:
sarif_file: results.sarif
6 changes: 3 additions & 3 deletions .github/workflows/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
uses: ./.github/actions/setup-go

- name: Initialize CodeQL
uses: github/codeql-action/init@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
with:
languages: go, javascript

Expand All @@ -48,7 +48,7 @@ jobs:
rm Makefile

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5

- name: Send Slack notification on failure
if: ${{ failure() }}
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
severity: "CRITICAL,HIGH"

- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
with:
sarif_file: trivy-results.sarif
category: "Trivy"
Expand Down
26 changes: 19 additions & 7 deletions agent/agentcontainers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ type API struct {
subAgentURL string
subAgentEnv []string

projectDiscovery bool // If we should perform project discovery or not.
projectDiscovery bool // If we should perform project discovery or not.
discoveryAutostart bool // If we should autostart discovered projects.

ownerName string
workspaceName string
Expand Down Expand Up @@ -144,7 +145,8 @@ func WithCommandEnv(ce CommandEnv) Option {
strings.HasPrefix(s, "CODER_AGENT_TOKEN=") ||
strings.HasPrefix(s, "CODER_AGENT_AUTH=") ||
strings.HasPrefix(s, "CODER_AGENT_DEVCONTAINERS_ENABLE=") ||
strings.HasPrefix(s, "CODER_AGENT_DEVCONTAINERS_PROJECT_DISCOVERY_ENABLE=")
strings.HasPrefix(s, "CODER_AGENT_DEVCONTAINERS_PROJECT_DISCOVERY_ENABLE=") ||
strings.HasPrefix(s, "CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE=")
})
return shell, dir, env, nil
}
Expand Down Expand Up @@ -287,6 +289,14 @@ func WithProjectDiscovery(projectDiscovery bool) Option {
}
}

// WithDiscoveryAutostart sets if the API should attempt to autostart
// projects that have been discovered
func WithDiscoveryAutostart(discoveryAutostart bool) Option {
return func(api *API) {
api.discoveryAutostart = discoveryAutostart
}
}

// ScriptLogger is an interface for sending devcontainer logs to the
// controlplane.
type ScriptLogger interface {
Expand Down Expand Up @@ -542,11 +552,13 @@ func (api *API) discoverDevcontainersInProject(projectPath string) error {
Container: nil,
}

config, err := api.dccli.ReadConfig(api.ctx, workspaceFolder, path, []string{})
if err != nil {
logger.Error(api.ctx, "read project configuration", slog.Error(err))
} else if config.Configuration.Customizations.Coder.AutoStart {
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusStarting
if api.discoveryAutostart {
config, err := api.dccli.ReadConfig(api.ctx, workspaceFolder, path, []string{})
if err != nil {
logger.Error(api.ctx, "read project configuration", slog.Error(err))
} else if config.Configuration.Customizations.Coder.AutoStart {
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusStarting
}
}

api.knownDevcontainers[workspaceFolder] = dc
Expand Down
70 changes: 70 additions & 0 deletions agent/agentcontainers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3792,6 +3792,7 @@ func TestDevcontainerDiscovery(t *testing.T) {
agentcontainers.WithContainerCLI(&fakeContainerCLI{}),
agentcontainers.WithDevcontainerCLI(mDCCLI),
agentcontainers.WithProjectDiscovery(true),
agentcontainers.WithDiscoveryAutostart(true),
)
api.Start()
defer api.Close()
Expand All @@ -3813,6 +3814,75 @@ func TestDevcontainerDiscovery(t *testing.T) {
// Then: We expect the mock infra to not fail.
})
}

t.Run("Disabled", func(t *testing.T) {
t.Parallel()
var (
ctx = testutil.Context(t, testutil.WaitShort)
logger = testutil.Logger(t)
mClock = quartz.NewMock(t)
mDCCLI = acmock.NewMockDevcontainerCLI(gomock.NewController(t))

fs = map[string]string{
"/home/coder/.git/HEAD": "",
"/home/coder/.devcontainer/devcontainer.json": "",
}

r = chi.NewRouter()
)

// We expect that neither `ReadConfig`, nor `Up` are called as we
// have explicitly disabled the agentcontainers API from attempting
// to autostart devcontainers that it discovers.
mDCCLI.EXPECT().ReadConfig(gomock.Any(),
"/home/coder",
"/home/coder/.devcontainer/devcontainer.json",
[]string{},
).Return(agentcontainers.DevcontainerConfig{
Configuration: agentcontainers.DevcontainerConfiguration{
Customizations: agentcontainers.DevcontainerCustomizations{
Coder: agentcontainers.CoderCustomization{
AutoStart: true,
},
},
},
}, nil).Times(0)

mDCCLI.EXPECT().Up(gomock.Any(),
"/home/coder",
"/home/coder/.devcontainer/devcontainer.json",
gomock.Any(),
).Return("", nil).Times(0)

api := agentcontainers.NewAPI(logger,
agentcontainers.WithClock(mClock),
agentcontainers.WithWatcher(watcher.NewNoop()),
agentcontainers.WithFileSystem(initFS(t, fs)),
agentcontainers.WithManifestInfo("owner", "workspace", "parent-agent", "/home/coder"),
agentcontainers.WithContainerCLI(&fakeContainerCLI{}),
agentcontainers.WithDevcontainerCLI(mDCCLI),
agentcontainers.WithProjectDiscovery(true),
agentcontainers.WithDiscoveryAutostart(false),
)
api.Start()
defer api.Close()
r.Mount("/", api.Routes())

// When: All expected dev containers have been found.
require.Eventuallyf(t, func() bool {
req := httptest.NewRequest(http.MethodGet, "/", nil).WithContext(ctx)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)

got := codersdk.WorkspaceAgentListContainersResponse{}
err := json.NewDecoder(rec.Body).Decode(&got)
require.NoError(t, err)

return len(got.Devcontainers) >= 1
}, testutil.WaitShort, testutil.IntervalFast, "dev containers never found")

// Then: We expect the mock infra to not fail.
})
})
}

Expand Down
43 changes: 26 additions & 17 deletions cli/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,24 @@ import (

func (r *RootCmd) workspaceAgent() *serpent.Command {
var (
auth string
logDir string
scriptDataDir string
pprofAddress string
noReap bool
sshMaxTimeout time.Duration
tailnetListenPort int64
prometheusAddress string
debugAddress string
slogHumanPath string
slogJSONPath string
slogStackdriverPath string
blockFileTransfer bool
agentHeaderCommand string
agentHeader []string
devcontainers bool
devcontainerProjectDiscovery bool
auth string
logDir string
scriptDataDir string
pprofAddress string
noReap bool
sshMaxTimeout time.Duration
tailnetListenPort int64
prometheusAddress string
debugAddress string
slogHumanPath string
slogJSONPath string
slogStackdriverPath string
blockFileTransfer bool
agentHeaderCommand string
agentHeader []string
devcontainers bool
devcontainerProjectDiscovery bool
devcontainerDiscoveryAutostart bool
)
cmd := &serpent.Command{
Use: "agent",
Expand Down Expand Up @@ -366,6 +367,7 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
DevcontainerAPIOptions: []agentcontainers.Option{
agentcontainers.WithSubAgentURL(r.agentURL.String()),
agentcontainers.WithProjectDiscovery(devcontainerProjectDiscovery),
agentcontainers.WithDiscoveryAutostart(devcontainerDiscoveryAutostart),
},
})

Expand Down Expand Up @@ -519,6 +521,13 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
Description: "Allow the agent to search the filesystem for devcontainer projects.",
Value: serpent.BoolOf(&devcontainerProjectDiscovery),
},
{
Flag: "devcontainers-discovery-autostart-enable",
Default: "false",
Env: "CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE",
Description: "Allow the agent to autostart devcontainer projects it discovers based on their configuration.",
Value: serpent.BoolOf(&devcontainerDiscoveryAutostart),
},
}

return cmd
Expand Down
4 changes: 4 additions & 0 deletions cli/testdata/coder_agent_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ OPTIONS:
--debug-address string, $CODER_AGENT_DEBUG_ADDRESS (default: 127.0.0.1:2113)
The bind address to serve a debug HTTP server.

--devcontainers-discovery-autostart-enable bool, $CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE (default: false)
Allow the agent to autostart devcontainer projects it discovers based
on their configuration.

--devcontainers-enable bool, $CODER_AGENT_DEVCONTAINERS_ENABLE (default: true)
Allow the agent to automatically detect running devcontainers.

Expand Down
36 changes: 32 additions & 4 deletions coderd/mcp/mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.streamableServer.ServeHTTP(w, r)
}

// RegisterTools registers all available MCP tools with the server
// Register all available MCP tools with the server excluding:
// - ReportTask - which requires dependencies not available in the remote MCP context
// - ChatGPT search and fetch tools, which are redundant with the standard tools.
func (s *Server) RegisterTools(client *codersdk.Client) error {
if client == nil {
return xerrors.New("client cannot be nil: MCP HTTP server requires authenticated client")
Expand All @@ -79,10 +81,36 @@ func (s *Server) RegisterTools(client *codersdk.Client) error {
return xerrors.Errorf("failed to initialize tool dependencies: %w", err)
}

// Register all available tools, but exclude tools that require dependencies not available in the
// remote MCP context
for _, tool := range toolsdk.All {
if tool.Name == toolsdk.ToolNameReportTask {
// the ReportTask tool requires dependencies not available in the remote MCP context
// the ChatGPT search and fetch tools are redundant with the standard tools.
if tool.Name == toolsdk.ToolNameReportTask ||
tool.Name == toolsdk.ToolNameChatGPTSearch || tool.Name == toolsdk.ToolNameChatGPTFetch {
continue
}

s.mcpServer.AddTools(mcpFromSDK(tool, toolDeps))
}
return nil
}

// ChatGPT tools are the search and fetch tools as defined in https://platform.openai.com/docs/mcp.
// We do not expose any extra ones because ChatGPT has an undocumented "Safety Scan" feature.
// In my experiments, if I included extra tools in the MCP server, ChatGPT would often - but not always -
// refuse to add Coder as a connector.
func (s *Server) RegisterChatGPTTools(client *codersdk.Client) error {
if client == nil {
return xerrors.New("client cannot be nil: MCP HTTP server requires authenticated client")
}

// Create tool dependencies
toolDeps, err := toolsdk.NewDeps(client)
if err != nil {
return xerrors.Errorf("failed to initialize tool dependencies: %w", err)
}

for _, tool := range toolsdk.All {
if tool.Name != toolsdk.ToolNameChatGPTSearch && tool.Name != toolsdk.ToolNameChatGPTFetch {
continue
}

Expand Down
Loading
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy