feat(server): expose runtime MCP controls over HTTP (#37712)

This commit is contained in:
Aiden Cline 2026-07-19 10:28:25 -05:00 committed by GitHub
commit fe9a936867
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 473 additions and 131 deletions

View file

@ -1,7 +1,8 @@
import { Mcp } from "@opencode-ai/schema/mcp"
import { Location } from "@opencode-ai/schema/location"
import { Schema } from "effect"
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
import { McpServerNotFoundError } from "../errors.js"
import { LocationQuery, locationQueryOpenApi } from "./location.js"
export const McpGroup = HttpApiGroup.make("server.mcp")
@ -19,6 +20,72 @@ export const McpGroup = HttpApiGroup.make("server.mcp")
}),
),
)
.add(
HttpApiEndpoint.put("mcp.add", "/api/mcp/:server", {
params: { server: Schema.String },
query: LocationQuery,
// Wrapped in a struct because the client codegen flattens payload fields and cannot
// represent a top-level union payload.
payload: Schema.Struct({ config: Mcp.ServerConfig }),
success: HttpApiSchema.NoContent,
})
.annotateMerge(locationQueryOpenApi)
.annotateMerge(
OpenApi.annotations({
identifier: "v2.mcp.add",
summary: "Add MCP server",
description: "Add an MCP server at runtime or replace an existing one, connecting it immediately.",
}),
),
)
.add(
HttpApiEndpoint.delete("mcp.remove", "/api/mcp/:server", {
params: { server: Schema.String },
query: LocationQuery,
success: HttpApiSchema.NoContent,
error: McpServerNotFoundError,
})
.annotateMerge(locationQueryOpenApi)
.annotateMerge(
OpenApi.annotations({
identifier: "v2.mcp.remove",
summary: "Remove MCP server",
description: "Stop an MCP server and remove it from the runtime set until restart.",
}),
),
)
.add(
HttpApiEndpoint.post("mcp.connect", "/api/mcp/:server/connect", {
params: { server: Schema.String },
query: LocationQuery,
success: HttpApiSchema.NoContent,
error: McpServerNotFoundError,
})
.annotateMerge(locationQueryOpenApi)
.annotateMerge(
OpenApi.annotations({
identifier: "v2.mcp.connect",
summary: "Connect MCP server",
description: "Connect an MCP server at runtime, overriding a disabled configuration until restart.",
}),
),
)
.add(
HttpApiEndpoint.post("mcp.disconnect", "/api/mcp/:server/disconnect", {
params: { server: Schema.String },
query: LocationQuery,
success: HttpApiSchema.NoContent,
error: McpServerNotFoundError,
})
.annotateMerge(locationQueryOpenApi)
.annotateMerge(
OpenApi.annotations({
identifier: "v2.mcp.disconnect",
summary: "Disconnect MCP server",
description: "Disconnect an MCP server at runtime, removing its tools until reconnected.",
}),
),
)
.add(
HttpApiEndpoint.get("mcp.resource.catalog", "/api/mcp/resource", {
query: LocationQuery,