From c2f87853c6a8133efbcbdc48c3c2f0967f8cfb58 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" <219766164+opencode-agent[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 14:15:40 -0500 Subject: [PATCH] fix(core): drop tool name and namespace length caps (#53586) Co-authored-by: rekram1-node <63023139+rekram1-node@users.noreply.github.com> --- packages/core/src/tool.ts | 4 ++-- packages/core/test/mcp.test.ts | 7 +++---- packages/core/test/tool-registry.test.ts | 22 ---------------------- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/packages/core/src/tool.ts b/packages/core/src/tool.ts index 5e2ca8401aa..a07468a61e1 100644 --- a/packages/core/src/tool.ts +++ b/packages/core/src/tool.ts @@ -308,7 +308,7 @@ function registrationError(tool: Tool.Info) { if (error) return error } const name = normalizedName(tool) - if (!/^[A-Za-z0-9_-]{1,128}$/.test(name)) return new RegistrationError({ name, message: `Invalid tool name: ${name}` }) + if (!/^[A-Za-z0-9_-]+$/.test(name)) return new RegistrationError({ name, message: `Invalid tool name: ${name}` }) const id = effectiveName(tool) if (tool.options?.codemode === false && id === "execute") return new RegistrationError({ name: id, message: 'Tool name "execute" is reserved for CodeMode' }) @@ -321,7 +321,7 @@ function registrationError(tool: Tool.Info) { } function namespaceError(name: string) { - if (name.split(".").every((segment) => /^[A-Za-z0-9_-]{1,64}$/.test(segment))) return + if (name.split(".").every((segment) => /^[A-Za-z0-9_-]+$/.test(segment))) return return new RegistrationError({ name, message: `Invalid tool namespace: ${JSON.stringify(name)}` }) } diff --git a/packages/core/test/mcp.test.ts b/packages/core/test/mcp.test.ts index 314b81fcb8a..5d500e5a608 100644 --- a/packages/core/test/mcp.test.ts +++ b/packages/core/test/mcp.test.ts @@ -2106,7 +2106,7 @@ test("serializes concurrent MCP lifecycle operations", async () => { ) }) -testEffect(Layer.empty).live("isolates invalid MCP tools and preserves plugin transforms through catalog updates", () => +testEffect(Layer.empty).live("preserves plugin transforms through MCP catalog updates", () => Effect.gen(function* () { const tool = (server: string, name: string, description = name) => ({ @@ -2117,8 +2117,7 @@ testEffect(Layer.empty).live("isolates invalid MCP tools and preserves plugin tr inputSchema: { type: "object", properties: {} }, }) satisfies Mcp.Tool const healthy = [tool("demo", "search"), tool("other", "lookup")] - const namespace = tool("x".repeat(65), "lookup") - const catalog = yield* Ref.make([tool("demo", "x".repeat(129)), ...healthy, namespace]) + const catalog = yield* Ref.make(healthy) yield* Effect.gen(function* () { const registry = yield* Tool.Service @@ -2147,7 +2146,7 @@ testEffect(Layer.empty).live("isolates invalid MCP tools and preserves plugin tr editor.remove("repaired_lookup") }) - yield* Ref.set(catalog, [tool("demo", "y".repeat(129)), ...healthy, tool("demo", "added"), namespace]) + yield* Ref.set(catalog, [...healthy, tool("demo", "added")]) yield* bus.publish(McpEvent.ToolsChanged, { server: "demo" }) yield* waitForTool(registry, "demo_added") expect((yield* toolDefinitions(registry)).map((tool) => tool.name)).toEqual([ diff --git a/packages/core/test/tool-registry.test.ts b/packages/core/test/tool-registry.test.ts index f77e05a6630..ebda546cbc6 100644 --- a/packages/core/test/tool-registry.test.ts +++ b/packages/core/test/tool-registry.test.ts @@ -329,7 +329,6 @@ describe("Tool", () => { { before: make(), "": make(), - ["x".repeat(129)]: make(), "echo.tool": constant("first"), echo_tool: constant("last"), execute: make(), @@ -346,27 +345,6 @@ describe("Tool", () => { }), ) - it.effect("registers 128-character MCP tool names in Code Mode", () => - Effect.gen(function* () { - const service = yield* Tool.Service - const name = "x".repeat(128) - yield* transform(service, { [name]: make(), ["x".repeat(129)]: make() }, { namespace: "cloudflare" }) - - const snapshot = yield* service.snapshot() - expect(codeModeListings(snapshot.codeModeCatalog!).map((tool) => tool.path)).toEqual([`cloudflare.${name}`]) - const result = yield* snapshot.execute({ - ...call("execute"), - call: { - type: "tool-call", - id: "call-long-mcp-name", - name: "execute", - input: { code: `return (await tools.cloudflare[${JSON.stringify(name)}]({ text: "hello" })).text` }, - }, - }) - expect(result.content).toEqual([{ type: "text", text: "hello" }]) - }), - ) - it.effect("executes native tools without requiring letter-leading names or namespace segments", () => Effect.gen(function* () { const service = yield* Tool.Service