Skip to content

Commit 8428662

Browse files
committed
feat: simplifies the mcp items by removing chaining for .handler functions
1 parent c2b57ce commit 8428662

9 files changed

Lines changed: 715 additions & 695 deletions

File tree

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,47 @@
1-
import type { CollectionTool, GlobalTool, Prompt, Tool, ToolInputSchema } from './types.js'
1+
import type { MaybePromise } from 'payload'
2+
3+
import type {
4+
CollectionTool,
5+
CollectionToolHandlerArgs,
6+
GlobalTool,
7+
GlobalToolHandlerArgs,
8+
MCPToolResponse,
9+
Prompt,
10+
PromptHandlerArgs,
11+
Tool,
12+
ToolHandlerArgs,
13+
ToolInputSchema,
14+
} from './types.js'
215

316
/**
4-
* Two-stage builder: pass the schema/metadata first, then chain `.handler(fn)`. Splitting the
5-
* call lets TypeScript resolve `TSchema` from `input` (call 1) before contextually typing the
6-
* handler (call 2). A single-call API hit a TS limitation where property order in the literal
7-
* decided whether `TSchema` was inferred or pinned to its default.
8-
*
9-
* defineCollectionTool({ description, input })
10-
* .handler(({ input }) => …) // ← input is fully typed here regardless of order
17+
* Identity helpers that exist solely so TypeScript infers `TSchema` from `input` (or
18+
* `argsSchema` for prompts) and then types the handler's `input` against it.
1119
*
12-
* Config and handler signatures are derived from `Tool` / `CollectionTool` / `GlobalTool` /
13-
* `Prompt` via `Omit` + indexed access so there's no duplication with `types.ts`.
20+
* The `NoInfer<>` wrapper on the handler's args is what makes this work in a single
21+
* call: it tells TS not to use the handler signature when inferring `TSchema`, so
22+
* inference is driven solely by the schema field.
1423
*/
1524

16-
export const defineTool = <
17-
TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
18-
>(
19-
args: Omit<Tool<TSchema>, 'handler'>,
20-
): { handler: (fn: Tool<TSchema>['handler']) => Tool } => ({
21-
handler: (fn) => ({ ...args, handler: fn }) as unknown as Tool,
22-
})
25+
export const defineTool = <TSchema extends ToolInputSchema | undefined = undefined>(
26+
tool: {
27+
handler: (args: ToolHandlerArgs<NoInfer<TSchema>>) => MaybePromise<MCPToolResponse>
28+
} & Omit<Tool<TSchema>, 'handler'>,
29+
): Tool => tool as unknown as Tool
2330

24-
export const defineCollectionTool = <
25-
TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
26-
>(
27-
args: Omit<CollectionTool<TSchema>, 'handler'>,
28-
): { handler: (fn: CollectionTool<TSchema>['handler']) => CollectionTool } => ({
29-
handler: (fn) => ({ ...args, handler: fn }) as unknown as CollectionTool,
30-
})
31+
export const defineCollectionTool = <TSchema extends ToolInputSchema | undefined = undefined>(
32+
tool: {
33+
handler: (args: CollectionToolHandlerArgs<NoInfer<TSchema>>) => MaybePromise<MCPToolResponse>
34+
} & Omit<CollectionTool<TSchema>, 'handler'>,
35+
): CollectionTool => tool as unknown as CollectionTool
3136

32-
export const defineGlobalTool = <
33-
TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined,
34-
>(
35-
args: Omit<GlobalTool<TSchema>, 'handler'>,
36-
): { handler: (fn: GlobalTool<TSchema>['handler']) => GlobalTool } => ({
37-
handler: (fn) => ({ ...args, handler: fn }) as unknown as GlobalTool,
38-
})
37+
export const defineGlobalTool = <TSchema extends ToolInputSchema | undefined = undefined>(
38+
tool: {
39+
handler: (args: GlobalToolHandlerArgs<NoInfer<TSchema>>) => MaybePromise<MCPToolResponse>
40+
} & Omit<GlobalTool<TSchema>, 'handler'>,
41+
): GlobalTool => tool as unknown as GlobalTool
3942

4043
export const definePrompt = <TSchema extends ToolInputSchema = ToolInputSchema>(
41-
args: Omit<Prompt<TSchema>, 'handler'>,
42-
): { handler: (fn: Prompt<TSchema>['handler']) => Prompt } => ({
43-
handler: (fn) => ({ ...args, handler: fn }) as unknown as Prompt,
44-
})
44+
prompt: {
45+
handler: (args: PromptHandlerArgs<NoInfer<TSchema>>) => ReturnType<Prompt<TSchema>['handler']>
46+
} & Omit<Prompt<TSchema>, 'handler'>,
47+
): Prompt => prompt as unknown as Prompt

0 commit comments

Comments
 (0)