summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKit Langton <[email protected]>2026-04-17 16:25:49 -0400
committerGitHub <[email protected]>2026-04-17 20:25:49 +0000
commit11fa257549a1094b43d25f014e54557ed6aab660 (patch)
tree42779d7cf1c6946e5b5cdd000f02af0b96c3ddfe
parent6af8ab0df201e245fac503aa8822750662ebf6b9 (diff)
downloadopencode-11fa257549a1094b43d25f014e54557ed6aab660.tar.gz
opencode-11fa257549a1094b43d25f014e54557ed6aab660.zip
refactor(config): migrate mcp schemas to Effect Schema.Class (#23163)
-rw-r--r--packages/opencode/src/config/config.ts2
-rw-r--r--packages/opencode/src/config/mcp.ts118
-rw-r--r--packages/opencode/src/server/routes/instance/mcp.ts2
3 files changed, 58 insertions, 64 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 459f76961..258500d7b 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -178,7 +178,7 @@ export const Info = z
.record(
z.string(),
z.union([
- ConfigMCP.Info,
+ ConfigMCP.Info.zod,
z
.object({
enabled: z.boolean(),
diff --git a/packages/opencode/src/config/mcp.ts b/packages/opencode/src/config/mcp.ts
index 5036cd6e4..8b77bc4c2 100644
--- a/packages/opencode/src/config/mcp.ts
+++ b/packages/opencode/src/config/mcp.ts
@@ -1,68 +1,62 @@
-import z from "zod"
+import { Schema } from "effect"
+import { zod } from "@/util/effect-zod"
+import { withStatics } from "@/util/schema"
-export const Local = z
- .object({
- type: z.literal("local").describe("Type of MCP server connection"),
- command: z.string().array().describe("Command and arguments to run the MCP server"),
- environment: z
- .record(z.string(), z.string())
- .optional()
- .describe("Environment variables to set when running the MCP server"),
- enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
- timeout: z
- .number()
- .int()
- .positive()
- .optional()
- .describe("Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified."),
- })
- .strict()
- .meta({
- ref: "McpLocalConfig",
- })
+export class Local extends Schema.Class<Local>("McpLocalConfig")({
+ type: Schema.Literal("local").annotate({ description: "Type of MCP server connection" }),
+ command: Schema.mutable(Schema.Array(Schema.String)).annotate({
+ description: "Command and arguments to run the MCP server",
+ }),
+ environment: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({
+ description: "Environment variables to set when running the MCP server",
+ }),
+ enabled: Schema.optional(Schema.Boolean).annotate({
+ description: "Enable or disable the MCP server on startup",
+ }),
+ timeout: Schema.optional(Schema.Number).annotate({
+ description: "Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.",
+ }),
+}) {
+ static readonly zod = zod(this)
+}
-export const OAuth = z
- .object({
- clientId: z
- .string()
- .optional()
- .describe("OAuth client ID. If not provided, dynamic client registration (RFC 7591) will be attempted."),
- clientSecret: z.string().optional().describe("OAuth client secret (if required by the authorization server)"),
- scope: z.string().optional().describe("OAuth scopes to request during authorization"),
- redirectUri: z
- .string()
- .optional()
- .describe("OAuth redirect URI (default: http://127.0.0.1:19876/mcp/oauth/callback)."),
- })
- .strict()
- .meta({
- ref: "McpOAuthConfig",
- })
-export type OAuth = z.infer<typeof OAuth>
+export class OAuth extends Schema.Class<OAuth>("McpOAuthConfig")({
+ clientId: Schema.optional(Schema.String).annotate({
+ description: "OAuth client ID. If not provided, dynamic client registration (RFC 7591) will be attempted.",
+ }),
+ clientSecret: Schema.optional(Schema.String).annotate({
+ description: "OAuth client secret (if required by the authorization server)",
+ }),
+ scope: Schema.optional(Schema.String).annotate({ description: "OAuth scopes to request during authorization" }),
+ redirectUri: Schema.optional(Schema.String).annotate({
+ description: "OAuth redirect URI (default: http://127.0.0.1:19876/mcp/oauth/callback).",
+ }),
+}) {
+ static readonly zod = zod(this)
+}
-export const Remote = z
- .object({
- type: z.literal("remote").describe("Type of MCP server connection"),
- url: z.string().describe("URL of the remote MCP server"),
- enabled: z.boolean().optional().describe("Enable or disable the MCP server on startup"),
- headers: z.record(z.string(), z.string()).optional().describe("Headers to send with the request"),
- oauth: z
- .union([OAuth, z.literal(false)])
- .optional()
- .describe("OAuth authentication configuration for the MCP server. Set to false to disable OAuth auto-detection."),
- timeout: z
- .number()
- .int()
- .positive()
- .optional()
- .describe("Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified."),
- })
- .strict()
- .meta({
- ref: "McpRemoteConfig",
- })
+export class Remote extends Schema.Class<Remote>("McpRemoteConfig")({
+ type: Schema.Literal("remote").annotate({ description: "Type of MCP server connection" }),
+ url: Schema.String.annotate({ description: "URL of the remote MCP server" }),
+ enabled: Schema.optional(Schema.Boolean).annotate({
+ description: "Enable or disable the MCP server on startup",
+ }),
+ headers: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({
+ description: "Headers to send with the request",
+ }),
+ oauth: Schema.optional(Schema.Union([OAuth, Schema.Literal(false)])).annotate({
+ description: "OAuth authentication configuration for the MCP server. Set to false to disable OAuth auto-detection.",
+ }),
+ timeout: Schema.optional(Schema.Number).annotate({
+ description: "Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.",
+ }),
+}) {
+ static readonly zod = zod(this)
+}
-export const Info = z.discriminatedUnion("type", [Local, Remote])
-export type Info = z.infer<typeof Info>
+export const Info = Schema.Union([Local, Remote])
+ .annotate({ discriminator: "type" })
+ .pipe(withStatics((s) => ({ zod: zod(s) })))
+export type Info = Schema.Schema.Type<typeof Info>
export * as ConfigMCP from "./mcp"
diff --git a/packages/opencode/src/server/routes/instance/mcp.ts b/packages/opencode/src/server/routes/instance/mcp.ts
index 197185bde..b42cfb531 100644
--- a/packages/opencode/src/server/routes/instance/mcp.ts
+++ b/packages/opencode/src/server/routes/instance/mcp.ts
@@ -54,7 +54,7 @@ export const McpRoutes = lazy(() =>
"json",
z.object({
name: z.string(),
- config: ConfigMCP.Info,
+ config: ConfigMCP.Info.zod,
}),
),
async (c) => {