@@ -31,15 +31,20 @@ import {
3131 ServerNotification ,
3232 ToolAnnotations ,
3333 LoggingMessageNotification ,
34+ CreateTaskResult ,
35+ GetTaskResult ,
36+ Result ,
37+ TASK_META_KEY ,
3438 CompleteRequestPrompt ,
3539 CompleteRequestResourceTemplate ,
3640 assertCompleteRequestPrompt ,
3741 assertCompleteRequestResourceTemplate
3842} from '../types.js' ;
3943import { Completable , CompletableDef } from './completable.js' ;
4044import { UriTemplate , Variables } from '../shared/uriTemplate.js' ;
41- import { RequestHandlerExtra } from '../shared/protocol.js' ;
45+ import { RequestHandlerExtra , RequestTaskStore } from '../shared/protocol.js' ;
4246import { Transport } from '../shared/transport.js' ;
47+ import { isTerminal } from '../shared/task.js' ;
4348
4449/**
4550 * High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
@@ -836,6 +841,51 @@ export class McpServer {
836841 ) ;
837842 }
838843
844+ /**
845+ * Registers a task-based tool with a config object and callback.
846+ */
847+ registerToolTask < InputArgs extends ZodRawShape , OutputArgs extends ZodRawShape > (
848+ name : string ,
849+ config : {
850+ title ?: string ;
851+ description ?: string ;
852+ inputSchema ?: InputArgs ;
853+ outputSchema ?: OutputArgs ;
854+ annotations ?: ToolAnnotations ;
855+ _meta ?: Record < string , unknown > ;
856+ } ,
857+ handler : ToolTaskHandler < InputArgs >
858+ ) : RegisteredTool {
859+ // TODO: Attach to individual request handlers and remove this wrapper
860+ const cb : ToolCallback < InputArgs > = ( async ( ...args ) => {
861+ const [ inputArgs , extra ] = args ;
862+
863+ const taskStore = extra . taskStore ;
864+ if ( ! taskStore ) {
865+ throw new Error ( 'Task store is not available' ) ;
866+ }
867+
868+ const taskMetadata = extra . _meta ?. [ TASK_META_KEY ] ;
869+ const taskId = taskMetadata ?. taskId ;
870+ if ( ! taskId ) {
871+ throw new Error ( 'No task ID provided' ) ;
872+ }
873+
874+ // Internal polling to allow using this interface before internals are hooked up
875+ const taskExtra = { ...extra , taskId, taskStore } ;
876+ let task = await handler . createTask ( inputArgs , taskExtra ) ;
877+ do {
878+ await new Promise ( resolve => setTimeout ( resolve , task . pollInterval ?? 5000 ) ) ;
879+ task = await handler . getTask ( inputArgs , taskExtra ) ;
880+ } while ( ! isTerminal ( task . status ) ) ;
881+
882+ const result : CallToolResult = await handler . getTaskResult ( inputArgs , taskExtra ) ;
883+ return result ;
884+ } ) as ToolCallback < InputArgs > ;
885+
886+ return this . registerTool ( name , { ...config , annotations : { ...config . annotations , taskHint : true } } , cb ) ;
887+ }
888+
839889 /**
840890 * Registers a zero-argument prompt `name`, which will run the given function when the client calls it.
841891 * @deprecated Use `registerPrompt` instead.
@@ -1044,6 +1094,21 @@ export type ToolCallback<Args extends undefined | ZodRawShape | ZodType<object>
10441094 ? ( args : T , extra : RequestHandlerExtra < ServerRequest , ServerNotification > ) => CallToolResult | Promise < CallToolResult >
10451095 : ( extra : RequestHandlerExtra < ServerRequest , ServerNotification > ) => CallToolResult | Promise < CallToolResult > ;
10461096
1097+ export interface TaskRequestHandlerExtra extends RequestHandlerExtra < ServerRequest , ServerNotification > {
1098+ taskId : string ;
1099+ taskStore : RequestTaskStore ;
1100+ }
1101+
1102+ export type TaskRequestHandler < SendResultT extends Result , Args extends undefined | ZodRawShape = undefined > = Args extends ZodRawShape
1103+ ? ( args : z . objectOutputType < Args , ZodTypeAny > , extra : TaskRequestHandlerExtra ) => SendResultT | Promise < SendResultT >
1104+ : ( extra : TaskRequestHandlerExtra ) => SendResultT | Promise < SendResultT > ;
1105+
1106+ export interface ToolTaskHandler < Args extends undefined | ZodRawShape = undefined > {
1107+ createTask : TaskRequestHandler < CreateTaskResult , Args > ;
1108+ getTask : TaskRequestHandler < GetTaskResult , Args > ;
1109+ getTaskResult : TaskRequestHandler < CallToolResult , Args > ;
1110+ }
1111+
10471112export type RegisteredTool = {
10481113 title ?: string ;
10491114 description ?: string ;
0 commit comments