1- import { isStandardSchema } from '@modelcontextprotocol/core' ;
1+ import type { JSONRPCMessage } from '@modelcontextprotocol/core' ;
2+ import { InMemoryTransport , isStandardSchema , LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/core' ;
23import { describe , expect , it , vi } from 'vitest' ;
34import * as z from 'zod/v4' ;
45import { McpServer } from '../../src/index.js' ;
56
67describe ( 'registerTool/registerPrompt accept raw Zod shape (auto-wrapped)' , ( ) => {
7- it ( 'registerTool accepts a raw shape for inputSchema, auto-wraps, and does not warn' , ( ) => {
8- const warn = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
8+ it ( 'registerTool accepts a raw shape for inputSchema and auto-wraps it' , ( ) => {
99 const server = new McpServer ( { name : 't' , version : '1.0.0' } ) ;
1010
1111 server . registerTool ( 'a' , { inputSchema : { x : z . number ( ) } } , async ( { x } ) => ( {
@@ -19,9 +19,6 @@ describe('registerTool/registerPrompt accept raw Zod shape (auto-wrapped)', () =
1919 expect ( Object . keys ( tools ) ) . toEqual ( [ 'a' , 'b' ] ) ;
2020 // raw shape was wrapped into a Standard Schema (z.object)
2121 expect ( isStandardSchema ( tools [ 'a' ] ?. inputSchema ) ) . toBe ( true ) ;
22-
23- expect ( warn ) . not . toHaveBeenCalled ( ) ;
24- warn . mockRestore ( ) ;
2522 } ) ;
2623
2724 it ( 'registerTool accepts a raw shape for outputSchema and auto-wraps it' , ( ) => {
@@ -36,20 +33,18 @@ describe('registerTool/registerPrompt accept raw Zod shape (auto-wrapped)', () =
3633 expect ( isStandardSchema ( tools [ 'out' ] ?. outputSchema ) ) . toBe ( true ) ;
3734 } ) ;
3835
39- it ( 'registerTool with z.object() inputSchema also works without warning' , ( ) => {
40- const warn = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
36+ it ( 'registerTool with z.object() inputSchema also works (passthrough, no auto-wrap)' , ( ) => {
4137 const server = new McpServer ( { name : 't' , version : '1.0.0' } ) ;
4238
4339 server . registerTool ( 'c' , { inputSchema : z . object ( { x : z . number ( ) } ) } , async ( { x } ) => ( {
4440 content : [ { type : 'text' as const , text : String ( x ) } ]
4541 } ) ) ;
4642
47- expect ( warn ) . not . toHaveBeenCalled ( ) ;
48- warn . mockRestore ( ) ;
43+ const tools = ( server as unknown as { _registeredTools : Record < string , { inputSchema ?: unknown } > } ) . _registeredTools ;
44+ expect ( isStandardSchema ( tools [ 'c' ] ?. inputSchema ) ) . toBe ( true ) ;
4945 } ) ;
5046
51- it ( 'registerPrompt accepts a raw shape for argsSchema and does not warn' , ( ) => {
52- const warn = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
47+ it ( 'registerPrompt accepts a raw shape for argsSchema' , ( ) => {
5348 const server = new McpServer ( { name : 't' , version : '1.0.0' } ) ;
5449
5550 server . registerPrompt ( 'p' , { argsSchema : { topic : z . string ( ) } } , async ( { topic } ) => ( {
@@ -59,8 +54,48 @@ describe('registerTool/registerPrompt accept raw Zod shape (auto-wrapped)', () =
5954 const prompts = ( server as unknown as { _registeredPrompts : Record < string , { argsSchema ?: unknown } > } ) . _registeredPrompts ;
6055 expect ( Object . keys ( prompts ) ) . toContain ( 'p' ) ;
6156 expect ( isStandardSchema ( prompts [ 'p' ] ?. argsSchema ) ) . toBe ( true ) ;
57+ } ) ;
58+
59+ it ( 'callback receives validated, typed args end-to-end via tools/call' , async ( ) => {
60+ const server = new McpServer ( { name : 't' , version : '1.0.0' } ) ;
61+
62+ let received : { x : number } | undefined ;
63+ server . registerTool ( 'echo' , { inputSchema : { x : z . number ( ) } } , async args => {
64+ received = args ;
65+ return { content : [ { type : 'text' as const , text : String ( args . x ) } ] } ;
66+ } ) ;
67+
68+ const [ client , srv ] = InMemoryTransport . createLinkedPair ( ) ;
69+ await server . connect ( srv ) ;
70+ await client . start ( ) ;
71+
72+ const responses : JSONRPCMessage [ ] = [ ] ;
73+ client . onmessage = m => responses . push ( m ) ;
74+
75+ await client . send ( {
76+ jsonrpc : '2.0' ,
77+ id : 1 ,
78+ method : 'initialize' ,
79+ params : {
80+ protocolVersion : LATEST_PROTOCOL_VERSION ,
81+ capabilities : { } ,
82+ clientInfo : { name : 'c' , version : '1.0.0' }
83+ }
84+ } as JSONRPCMessage ) ;
85+ await client . send ( { jsonrpc : '2.0' , method : 'notifications/initialized' } as JSONRPCMessage ) ;
86+ await client . send ( {
87+ jsonrpc : '2.0' ,
88+ id : 2 ,
89+ method : 'tools/call' ,
90+ params : { name : 'echo' , arguments : { x : 7 } }
91+ } as JSONRPCMessage ) ;
92+
93+ await vi . waitFor ( ( ) => expect ( responses . some ( r => 'id' in r && r . id === 2 ) ) . toBe ( true ) ) ;
94+
95+ expect ( received ) . toEqual ( { x : 7 } ) ;
96+ const result = responses . find ( r => 'id' in r && r . id === 2 ) as { result ?: { content : Array < { text : string } > } } ;
97+ expect ( result . result ?. content [ 0 ] ?. text ) . toBe ( '7' ) ;
6298
63- expect ( warn ) . not . toHaveBeenCalled ( ) ;
64- warn . mockRestore ( ) ;
99+ await server . close ( ) ;
65100 } ) ;
66101} ) ;
0 commit comments