Skip to content
Closed
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
10 changes: 5 additions & 5 deletions docs/resources/agents_mcp_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: |-
~> Warning
This resource is only compatible with Coder version 2.37.0 https://github.com/coder/coder/releases/tag/v2.37.0 and later.
-> _wo attributes are write-only https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments: their values are sent to Coder but never stored in Terraform state. This resource therefore requires Terraform 1.11 or later.
Configures an organization-scoped MCP server for Coder Agents. Import IDs use <organization_id>/<id>. Changing url, auth_type, oauth2_token_url, oauth2_revocation_url, or oauth2_client_id invalidates users' stored OAuth tokens.
Configures an organization-scoped MCP server for Coder Agents. Import IDs use <organization-name>/<slug>. Changing url, auth_type, oauth2_token_url, oauth2_revocation_url, or oauth2_client_id invalidates users' stored OAuth tokens.
Coder runs OAuth2 discovery and dynamic client registration only when a server is created with auth_type = "oauth2" and no manual endpoints; updates never re-run discovery. To switch an existing server from manual OAuth2 configuration back to discovery, replace the resource (for example with terraform apply -replace). Removing the manual OAuth2 attributes from configuration leaves the stored values unmanaged rather than clearing them.
---

Expand All @@ -20,7 +20,7 @@ This resource is only compatible with Coder version [2.37.0](https://github.com/

-> `_wo` attributes are [write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments): their values are sent to Coder but never stored in Terraform state. This resource therefore requires Terraform 1.11 or later.

Configures an organization-scoped MCP server for Coder Agents. Import IDs use `<organization_id>/<id>`. Changing `url`, `auth_type`, `oauth2_token_url`, `oauth2_revocation_url`, or `oauth2_client_id` invalidates users' stored OAuth tokens.
Configures an organization-scoped MCP server for Coder Agents. Import IDs use `<organization-name>/<slug>`. Changing `url`, `auth_type`, `oauth2_token_url`, `oauth2_revocation_url`, or `oauth2_client_id` invalidates users' stored OAuth tokens.

Coder runs OAuth2 discovery and dynamic client registration only when a server is created with `auth_type = "oauth2"` and no manual endpoints; updates never re-run discovery. To switch an existing server from manual OAuth2 configuration back to discovery, replace the resource (for example with `terraform apply -replace`). Removing the manual OAuth2 attributes from configuration leaves the stored values unmanaged rather than clearing them.

Expand Down Expand Up @@ -100,14 +100,14 @@ Import is supported using the following syntax:
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:

```shell
# The ID must contain the organization UUID and MCP server configuration UUID.
$ terraform import coderd_agents_mcp_server.example <organization-id>/<mcp-server-id>
# The ID must contain the organization name and the MCP server slug.
$ terraform import coderd_agents_mcp_server.example <organization-name>/<slug>
```
Alternatively, in Terraform v1.5.0 and later, an [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used:

```terraform
import {
to = coderd_agents_mcp_server.example
id = "<organization-id>/<mcp-server-id>"
id = "<organization-name>/<slug>"
}
```
6 changes: 3 additions & 3 deletions examples/resources/coderd_agents_mcp_server/import.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# The ID must contain the organization UUID and MCP server configuration UUID.
$ terraform import coderd_agents_mcp_server.example <organization-id>/<mcp-server-id>
# The ID must contain the organization name and the MCP server slug.
$ terraform import coderd_agents_mcp_server.example <organization-name>/<slug>
```
Alternatively, in Terraform v1.5.0 and later, an [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used:

```terraform
import {
to = coderd_agents_mcp_server.example
id = "<organization-id>/<mcp-server-id>"
id = "<organization-name>/<slug>"
}
27 changes: 20 additions & 7 deletions internal/provider/agents_mcp_server_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func (r *AgentsMCPServerResource) Schema(ctx context.Context, req resource.Schem
MarkdownDescription: "~> This resource is experimental. Changes are expected, and it is not recommended for production use.\n\n" +
"~> **Warning**\nThis resource is only compatible with Coder version [" + agentsMCPServerMinVersion + "](https://github.com/coder/coder/releases/tag/v" + agentsMCPServerMinVersion + ") and later.\n\n" +
"-> `_wo` attributes are [write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments): their values are sent to Coder but never stored in Terraform state. This resource therefore requires Terraform 1.11 or later.\n\n" +
"Configures an organization-scoped MCP server for Coder Agents. Import IDs use `<organization_id>/<id>`. Changing `url`, `auth_type`, `oauth2_token_url`, `oauth2_revocation_url`, or `oauth2_client_id` invalidates users' stored OAuth tokens.\n\n" +
"Configures an organization-scoped MCP server for Coder Agents. Import IDs use `<organization-name>/<slug>`. Changing `url`, `auth_type`, `oauth2_token_url`, `oauth2_revocation_url`, or `oauth2_client_id` invalidates users' stored OAuth tokens.\n\n" +
"Coder runs OAuth2 discovery and dynamic client registration only when a server is created with `auth_type = \"oauth2\"` and no manual endpoints; updates never re-run discovery. To switch an existing server from manual OAuth2 configuration back to discovery, replace the resource (for example with `terraform apply -replace`). Removing the manual OAuth2 attributes from configuration leaves the stored values unmanaged rather than clearing them.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Expand Down Expand Up @@ -602,20 +602,33 @@ func (r *AgentsMCPServerResource) Delete(ctx context.Context, req resource.Delet
func (r *AgentsMCPServerResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
parts := strings.Split(req.ID, "/")
if len(parts) != 2 {
resp.Diagnostics.AddError("Invalid Import ID", "Expected `<organization_id>/<id>`.")
resp.Diagnostics.AddError("Invalid Import ID", "Expected `<organization-name>/<slug>`.")
return
}
organizationID, err := uuid.Parse(parts[0])
org, err := r.data.Client.OrganizationByName(ctx, parts[0])
if err != nil {
resp.Diagnostics.AddError("Invalid Import ID", fmt.Sprintf("Unable to parse organization ID as UUID: %s", err))
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to get organization %q: %s", parts[0], err))
return
}
id, err := uuid.Parse(parts[1])
// Slugs are unique per organization, but the get-by-ID endpoint only
// accepts UUIDs, so resolve the slug from the organization's list.
configs, err := r.data.Client.MCPServerConfigs(ctx, org.ID)
if err != nil {
resp.Diagnostics.AddError("Invalid Import ID", fmt.Sprintf("Unable to parse MCP server ID as UUID: %s", err))
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to list MCP servers for organization %q: %s", parts[0], err))
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("organization_id"), organizationID.String())...)
var id uuid.UUID
for _, config := range configs {
if config.Slug == parts[1] {
id = config.ID
break
}
}
if id == uuid.Nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("No MCP server with slug %q exists in organization %q.", parts[1], parts[0]))
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("organization_id"), org.ID.String())...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), id.String())...)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/provider/agents_mcp_server_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ resource "terraform_data" "nullendpoint" {
if !ok {
return "", fmt.Errorf("coderd_agents_mcp_server.test not found in state")
}
return rs.Primary.Attributes["organization_id"] + "/" + rs.Primary.ID, nil
return organizations[0].Name + "/" + rs.Primary.Attributes["slug"], nil
},
ImportStateVerifyIgnore: []string{
"oauth2_client_secret_wo",
Expand Down