From 78032a641881b229cd8a00c07be63b09233d9af0 Mon Sep 17 00:00:00 2001 From: snowingfox <1503401882@qq.com> Date: Wed, 12 Aug 2026 03:52:55 +0000 Subject: [PATCH] fix(core): preserve per-tool argument type inference in provideExperimentalWebMcpTools Fixes #70125 --- goldens/public-api/core/index.api.md | 2 +- packages/core/src/webmcp/provide_tools.ts | 6 ++- .../core/test/strict_types/mcp_tools_spec.ts | 54 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 packages/core/test/strict_types/mcp_tools_spec.ts diff --git a/goldens/public-api/core/index.api.md b/goldens/public-api/core/index.api.md index d1002e1ec71a..0e9d31a239ee 100644 --- a/goldens/public-api/core/index.api.md +++ b/goldens/public-api/core/index.api.md @@ -1502,7 +1502,7 @@ export function provideCheckNoChangesConfig(options: { export function provideEnvironmentInitializer(initializerFn: () => void): EnvironmentProviders; // @public -export function provideExperimentalWebMcpTools(tools: WebMcpToolDescriptor[]): EnvironmentProviders; +export function provideExperimentalWebMcpTools(tools: { [K in keyof InputSchemas]: WebMcpToolDescriptor; }): EnvironmentProviders; // @public export function provideIdleServiceWith(useExisting: AbstractType | InjectionToken): EnvironmentProviders; diff --git a/packages/core/src/webmcp/provide_tools.ts b/packages/core/src/webmcp/provide_tools.ts index 0047f8a9a996..a7cf6084e436 100644 --- a/packages/core/src/webmcp/provide_tools.ts +++ b/packages/core/src/webmcp/provide_tools.ts @@ -26,8 +26,10 @@ import type {ToolDescriptor} from './types'; * or route providers. * @experimental */ -export function provideExperimentalWebMcpTools( - tools: ToolDescriptor[], +export function provideExperimentalWebMcpTools< + const InputSchemas extends readonly JsonSchemaForInference[], +>( + tools: {[K in keyof InputSchemas]: ToolDescriptor}, ): EnvironmentProviders { return makeEnvironmentProviders([ provideEnvironmentInitializer(() => { diff --git a/packages/core/test/strict_types/mcp_tools_spec.ts b/packages/core/test/strict_types/mcp_tools_spec.ts new file mode 100644 index 000000000000..0b7ccec656ac --- /dev/null +++ b/packages/core/test/strict_types/mcp_tools_spec.ts @@ -0,0 +1,54 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {provideExperimentalWebMcpTools} from '../../src/webmcp/provide_tools'; + +describe('provideExperimentalWebMcpTools', () => { + // Regression test for https://github.com/angular/angular/issues/70125 + // + // Each tool passed to `provideExperimentalWebMcpTools` must infer its own + // argument types from its own `inputSchema`. Previously the function inferred + // a single shared `InputSchema` for the whole array, so heterogeneous tools + // lost their `execute` argument types (each `args` was widened to + // `Record`), making the `arg1`/`arg2` accesses below type + // errors. This file intentionally fails to compile on the unfixed signature. + it('should preserve per-tool argument types for heterogeneous input schemas', () => { + provideExperimentalWebMcpTools([ + { + name: 'tool1', + description: 'Tool #1', + inputSchema: { + type: 'object', + properties: { + arg1: {type: 'number'}, + }, + required: ['arg1'], + }, + execute: (args) => { + const arg1 = args.arg1; // must be inferred as `number` + return `arg1 number value is ${arg1.toFixed()}`; + }, + }, + { + name: 'tool2', + description: 'Tool #2', + inputSchema: { + type: 'object', + properties: { + arg2: {type: 'string'}, + }, + required: ['arg2'], + }, + execute: (args) => { + const arg2 = args.arg2; // must be inferred as `string` + return `arg2 string value is ${arg2.trim()}`; + }, + }, + ]); + }); +});