@@ -53775,6 +53775,147 @@ var ExperimentalServerTasks = class {
5377553775 requestStream(request, resultSchema, options) {
5377653776 return this._server.requestStream(request, resultSchema, options);
5377753777 }
53778+ /**
53779+ * Sends a sampling request and returns an AsyncGenerator that yields response messages.
53780+ * The generator is guaranteed to end with either a 'result' or 'error' message.
53781+ *
53782+ * For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
53783+ * before the final result.
53784+ *
53785+ * @example
53786+ * ```typescript
53787+ * const stream = server.experimental.tasks.createMessageStream({
53788+ * messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
53789+ * maxTokens: 100
53790+ * }, {
53791+ * onprogress: (progress) => {
53792+ * // Handle streaming tokens via progress notifications
53793+ * console.log('Progress:', progress.message);
53794+ * }
53795+ * });
53796+ *
53797+ * for await (const message of stream) {
53798+ * switch (message.type) {
53799+ * case 'taskCreated':
53800+ * console.log('Task created:', message.task.taskId);
53801+ * break;
53802+ * case 'taskStatus':
53803+ * console.log('Task status:', message.task.status);
53804+ * break;
53805+ * case 'result':
53806+ * console.log('Final result:', message.result);
53807+ * break;
53808+ * case 'error':
53809+ * console.error('Error:', message.error);
53810+ * break;
53811+ * }
53812+ * }
53813+ * ```
53814+ *
53815+ * @param params - The sampling request parameters
53816+ * @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
53817+ * @returns AsyncGenerator that yields ResponseMessage objects
53818+ *
53819+ * @experimental
53820+ */
53821+ createMessageStream(params, options) {
53822+ const clientCapabilities = this._server.getClientCapabilities();
53823+ if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
53824+ throw new Error("Client does not support sampling tools capability.");
53825+ }
53826+ if (params.messages.length > 0) {
53827+ const lastMessage = params.messages[params.messages.length - 1];
53828+ const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
53829+ const hasToolResults = lastContent.some((c) => c.type === "tool_result");
53830+ const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : void 0;
53831+ const previousContent = previousMessage ? Array.isArray(previousMessage.content) ? previousMessage.content : [previousMessage.content] : [];
53832+ const hasPreviousToolUse = previousContent.some((c) => c.type === "tool_use");
53833+ if (hasToolResults) {
53834+ if (lastContent.some((c) => c.type !== "tool_result")) {
53835+ throw new Error("The last message must contain only tool_result content if any is present");
53836+ }
53837+ if (!hasPreviousToolUse) {
53838+ throw new Error("tool_result blocks are not matching any tool_use from the previous message");
53839+ }
53840+ }
53841+ if (hasPreviousToolUse) {
53842+ const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
53843+ const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
53844+ if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
53845+ throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
53846+ }
53847+ }
53848+ }
53849+ return this.requestStream({
53850+ method: "sampling/createMessage",
53851+ params
53852+ }, CreateMessageResultSchema, options);
53853+ }
53854+ /**
53855+ * Sends an elicitation request and returns an AsyncGenerator that yields response messages.
53856+ * The generator is guaranteed to end with either a 'result' or 'error' message.
53857+ *
53858+ * For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
53859+ * and 'taskStatus' messages before the final result.
53860+ *
53861+ * @example
53862+ * ```typescript
53863+ * const stream = server.experimental.tasks.elicitInputStream({
53864+ * mode: 'url',
53865+ * message: 'Please authenticate',
53866+ * elicitationId: 'auth-123',
53867+ * url: 'https://example.com/auth'
53868+ * }, {
53869+ * task: { ttl: 300000 } // Task-augmented for long-running auth flow
53870+ * });
53871+ *
53872+ * for await (const message of stream) {
53873+ * switch (message.type) {
53874+ * case 'taskCreated':
53875+ * console.log('Task created:', message.task.taskId);
53876+ * break;
53877+ * case 'taskStatus':
53878+ * console.log('Task status:', message.task.status);
53879+ * break;
53880+ * case 'result':
53881+ * console.log('User action:', message.result.action);
53882+ * break;
53883+ * case 'error':
53884+ * console.error('Error:', message.error);
53885+ * break;
53886+ * }
53887+ * }
53888+ * ```
53889+ *
53890+ * @param params - The elicitation request parameters
53891+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
53892+ * @returns AsyncGenerator that yields ResponseMessage objects
53893+ *
53894+ * @experimental
53895+ */
53896+ elicitInputStream(params, options) {
53897+ const clientCapabilities = this._server.getClientCapabilities();
53898+ const mode = params.mode ?? "form";
53899+ switch (mode) {
53900+ case "url": {
53901+ if (!clientCapabilities?.elicitation?.url) {
53902+ throw new Error("Client does not support url elicitation.");
53903+ }
53904+ break;
53905+ }
53906+ case "form": {
53907+ if (!clientCapabilities?.elicitation?.form) {
53908+ throw new Error("Client does not support form elicitation.");
53909+ }
53910+ break;
53911+ }
53912+ }
53913+ const normalizedParams = mode === "form" && params.mode === void 0 ? { ...params, mode: "form" } : params;
53914+ return this.requestStream({
53915+ method: "elicitation/create",
53916+ params: normalizedParams
53917+ }, ElicitResultSchema, options);
53918+ }
5377853919 /**
5377953920 * Gets the current status of a task.
5378053921 *
@@ -55870,6 +56011,7 @@ data:
5587056011 async handleGetRequest(req) {
5587156012 const acceptHeader = req.headers.get("accept");
5587256013 if (!acceptHeader?.includes("text/event-stream")) {
56014+ this.onerror?.(new Error("Not Acceptable: Client must accept text/event-stream"));
5587356015 return this.createJsonErrorResponse(406, -32e3, "Not Acceptable: Client must accept text/event-stream");
5587456016 }
5587556017 const sessionError = this.validateSession(req);
@@ -55887,6 +56029,7 @@ data:
5588756029 }
5588856030 }
5588956031 if (this._streamMapping.get(this._standaloneSseStreamId) !== void 0) {
56032+ this.onerror?.(new Error("Conflict: Only one SSE stream is allowed per session"));
5589056033 return this.createJsonErrorResponse(409, -32e3, "Conflict: Only one SSE stream is allowed per session");
5589156034 }
5589256035 const encoder = new TextEncoder();
@@ -55926,16 +56069,19 @@ data:
5592656069 */
5592756070 async replayEvents(lastEventId) {
5592856071 if (!this._eventStore) {
56072+ this.onerror?.(new Error("Event store not configured"));
5592956073 return this.createJsonErrorResponse(400, -32e3, "Event store not configured");
5593056074 }
5593156075 try {
5593256076 let streamId;
5593356077 if (this._eventStore.getStreamIdForEventId) {
5593456078 streamId = await this._eventStore.getStreamIdForEventId(lastEventId);
5593556079 if (!streamId) {
56080+ this.onerror?.(new Error("Invalid event ID format"));
5593656081 return this.createJsonErrorResponse(400, -32e3, "Invalid event ID format");
5593756082 }
5593856083 if (this._streamMapping.get(streamId) !== void 0) {
56084+ this.onerror?.(new Error("Conflict: Stream already has an active connection"));
5593956085 return this.createJsonErrorResponse(409, -32e3, "Conflict: Stream already has an active connection");
5594056086 }
5594156087 }
@@ -56001,14 +56147,16 @@ data:
5600156147`;
5600256148 controller.enqueue(encoder.encode(eventData));
5600356149 return true;
56004- } catch {
56150+ } catch (error2) {
56151+ this.onerror?.(error2);
5600556152 return false;
5600656153 }
5600756154 }
5600856155 /**
5600956156 * Handles unsupported requests (PUT, PATCH, etc.)
5601056157 */
5601156158 handleUnsupportedRequest() {
56159+ this.onerror?.(new Error("Method not allowed."));
5601256160 return new Response(JSON.stringify({
5601356161 jsonrpc: "2.0",
5601456162 error: {
@@ -56031,14 +56179,17 @@ data:
5603156179 try {
5603256180 const acceptHeader = req.headers.get("accept");
5603356181 if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
56182+ this.onerror?.(new Error("Not Acceptable: Client must accept both application/json and text/event-stream"));
5603456183 return this.createJsonErrorResponse(406, -32e3, "Not Acceptable: Client must accept both application/json and text/event-stream");
5603556184 }
5603656185 const ct = req.headers.get("content-type");
5603756186 if (!ct || !ct.includes("application/json")) {
56187+ this.onerror?.(new Error("Unsupported Media Type: Content-Type must be application/json"));
5603856188 return this.createJsonErrorResponse(415, -32e3, "Unsupported Media Type: Content-Type must be application/json");
5603956189 }
5604056190 const requestInfo = {
56041- headers: Object.fromEntries(req.headers.entries())
56191+ headers: Object.fromEntries(req.headers.entries()),
56192+ url: new URL(req.url)
5604256193 };
5604356194 let rawMessage;
5604456195 if (options?.parsedBody !== void 0) {
@@ -56047,6 +56198,7 @@ data:
5604756198 try {
5604856199 rawMessage = await req.json();
5604956200 } catch {
56201+ this.onerror?.(new Error("Parse error: Invalid JSON"));
5605056202 return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON");
5605156203 }
5605256204 }
@@ -56058,14 +56210,17 @@ data:
5605856210 messages = [JSONRPCMessageSchema.parse(rawMessage)];
5605956211 }
5606056212 } catch {
56213+ this.onerror?.(new Error("Parse error: Invalid JSON-RPC message"));
5606156214 return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON-RPC message");
5606256215 }
5606356216 const isInitializationRequest = messages.some(isInitializeRequest);
5606456217 if (isInitializationRequest) {
5606556218 if (this._initialized && this.sessionId !== void 0) {
56219+ this.onerror?.(new Error("Invalid Request: Server already initialized"));
5606656220 return this.createJsonErrorResponse(400, -32600, "Invalid Request: Server already initialized");
5606756221 }
5606856222 if (messages.length > 1) {
56223+ this.onerror?.(new Error("Invalid Request: Only one initialization request is allowed"));
5606956224 return this.createJsonErrorResponse(400, -32600, "Invalid Request: Only one initialization request is allowed");
5607056225 }
5607156226 this.sessionId = this.sessionIdGenerator?.();
@@ -56191,13 +56346,16 @@ data:
5619156346 return void 0;
5619256347 }
5619356348 if (!this._initialized) {
56349+ this.onerror?.(new Error("Bad Request: Server not initialized"));
5619456350 return this.createJsonErrorResponse(400, -32e3, "Bad Request: Server not initialized");
5619556351 }
5619656352 const sessionId = req.headers.get("mcp-session-id");
5619756353 if (!sessionId) {
56354+ this.onerror?.(new Error("Bad Request: Mcp-Session-Id header is required"));
5619856355 return this.createJsonErrorResponse(400, -32e3, "Bad Request: Mcp-Session-Id header is required");
5619956356 }
5620056357 if (sessionId !== this.sessionId) {
56358+ this.onerror?.(new Error("Session not found"));
5620156359 return this.createJsonErrorResponse(404, -32001, "Session not found");
5620256360 }
5620356361 return void 0;
@@ -56218,6 +56376,7 @@ data:
5621856376 validateProtocolVersion(req) {
5621956377 const protocolVersion = req.headers.get("mcp-protocol-version");
5622056378 if (protocolVersion !== null && !SUPPORTED_PROTOCOL_VERSIONS.includes(protocolVersion)) {
56379+ this.onerror?.(new Error(`Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`));
5622156380 return this.createJsonErrorResponse(400, -32e3, `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${SUPPORTED_PROTOCOL_VERSIONS.join(", ")})`);
5622256381 }
5622356382 return void 0;
0 commit comments