Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion src/everything/docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
- `trigger-long-running-operation` (tools/trigger-trigger-long-running-operation.ts): Simulates a multi-step operation over a given `duration` and number of `steps`; reports progress via `notifications/progress` when a `progressToken` is provided by the client.
- `toggle-simulated-logging` (tools/toggle-simulated-logging.ts): Starts or stops simulated, random‑leveled logging for the invoking session. Respects the client’s selected minimum logging level.
- `toggle-subscriber-updates` (tools/toggle-subscriber-updates.ts): Starts or stops simulated resource update notifications for URIs the invoking session has subscribed to.
- `trigger-sampling-request` (tools/trigger-sampling-request.ts): Issues a `sampling/createMessage` request to the client/LLM using provided `prompt` and optional generation controls; returns the LLM’s response payload.
- `trigger-sampling-request` (tools/trigger-sampling-request.ts): Issues a `sampling/createMessage` request to the client/LLM using provided `prompt` and optional generation controls; returns the LLM's response payload.
- `simulate-research-query` (tools/simulate-research-query.ts): Demonstrates MCP Tasks (SEP-1686) with a simulated multi-stage research operation. Accepts `topic` and `ambiguous` parameters. Returns a task that progresses through stages with status updates. If `ambiguous` is true and client supports elicitation, pauses with `input_required` status to gather clarification.
- `trigger-sampling-request-async` (tools/trigger-sampling-request-async.ts): Demonstrates bidirectional tasks where the server sends a sampling request that the client executes as a background task. Server polls for status and retrieves the LLM result when complete. Requires client to support `tasks.requests.sampling.createMessage`.
- `trigger-elicitation-request-async` (tools/trigger-elicitation-request-async.ts): Demonstrates bidirectional tasks where the server sends an elicitation request that the client executes as a background task. Server polls while waiting for user input. Requires client to support `tasks.requests.elicitation.create`.

## Prompts

Expand Down Expand Up @@ -50,3 +53,50 @@
- Simulated logging is available but off by default.
- Use the `toggle-simulated-logging` tool to start/stop periodic log messages of varying levels (debug, info, notice, warning, error, critical, alert, emergency) per session.
- Clients can control the minimum level they receive via the standard MCP `logging/setLevel` request.

## Tasks (SEP-1686)

The server advertises support for MCP Tasks, enabling long-running operations with status tracking:

- **Capabilities advertised**: `tasks.list`, `tasks.cancel`, `tasks.requests.tools.call`
- **Task Store**: Uses `InMemoryTaskStore` from SDK experimental for task lifecycle management
- **Message Queue**: Uses `InMemoryTaskMessageQueue` for task-related messaging

### Task Lifecycle

1. Client calls `tools/call` with `task: true` parameter
2. Server returns `CreateTaskResult` with `taskId` instead of immediate result
3. Client polls `tasks/get` to check status and receive `statusMessage` updates
4. When status is `completed`, client calls `tasks/result` to retrieve the final result

### Task Statuses

- `working`: Task is actively processing
- `input_required`: Task needs additional input (demonstrated via elicitation side-channel)
- `completed`: Task finished successfully
- `failed`: Task encountered an error
- `cancelled`: Task was cancelled by client

### Demo Tools

**Server-side tasks (client calls server):**
Use the `simulate-research-query` tool to exercise the full task lifecycle. Set `ambiguous: true` to trigger the `input_required` flow with elicitation.

**Client-side tasks (server calls client):**
Use `trigger-sampling-request-async` or `trigger-elicitation-request-async` to demonstrate bidirectional tasks where the server sends requests that the client executes as background tasks. These require the client to advertise `tasks.requests.sampling.createMessage` or `tasks.requests.elicitation.create` capabilities respectively.

### Bidirectional Task Flow

MCP Tasks are bidirectional - both server and client can be task executors:

| Direction | Request Type | Task Executor | Demo Tool |
|-----------|--------------|---------------|-----------|
| Client -> Server | `tools/call` | Server | `simulate-research-query` |
| Server -> Client | `sampling/createMessage` | Client | `trigger-sampling-request-async` |
| Server -> Client | `elicitation/create` | Client | `trigger-elicitation-request-async` |

For client-side tasks:
1. Server sends request with task metadata (e.g., `_meta.task.ttl`)
2. Client creates task and returns `CreateTaskResult` with `taskId`
3. Server polls `tasks/get` for status updates
4. When complete, server calls `tasks/result` to retrieve the result
21 changes: 21 additions & 0 deletions src/everything/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import {
InMemoryTaskStore,
InMemoryTaskMessageQueue,
} from "@modelcontextprotocol/sdk/experimental";
import {
setSubscriptionHandlers,
stopSimulatedResourceUpdates,
Expand Down Expand Up @@ -32,6 +36,10 @@ export const createServer: () => ServerFactoryResponse = () => {
// Read the server instructions
const instructions = readInstructions();

// Create task store and message queue for task support
const taskStore = new InMemoryTaskStore();
const taskMessageQueue = new InMemoryTaskMessageQueue();

// Create the server
const server = new McpServer(
{
Expand All @@ -52,8 +60,19 @@ export const createServer: () => ServerFactoryResponse = () => {
listChanged: true,
},
logging: {},
tasks: {
list: {},
cancel: {},
requests: {
tools: {
call: {},
},
},
},
},
instructions,
taskStore,
taskMessageQueue,
}
);

Expand Down Expand Up @@ -89,6 +108,8 @@ export const createServer: () => ServerFactoryResponse = () => {
// Stop any simulated logging or resource updates that may have been initiated.
stopSimulatedLogging(sessionId);
stopSimulatedResourceUpdates(sessionId);
// Clean up task store timers
taskStore.cleanup();
},
} satisfies ServerFactoryResponse;
};
8 changes: 8 additions & 0 deletions src/everything/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { registerToggleSubscriberUpdatesTool } from "./toggle-subscriber-updates
import { registerTriggerElicitationRequestTool } from "./trigger-elicitation-request.js";
import { registerTriggerLongRunningOperationTool } from "./trigger-long-running-operation.js";
import { registerTriggerSamplingRequestTool } from "./trigger-sampling-request.js";
import { registerTriggerSamplingRequestAsyncTool } from "./trigger-sampling-request-async.js";
import { registerTriggerElicitationRequestAsyncTool } from "./trigger-elicitation-request-async.js";
import { registerSimulateResearchQueryTool } from "./simulate-research-query.js";

/**
* Register the tools with the MCP server.
Expand Down Expand Up @@ -42,4 +45,9 @@ export const registerConditionalTools = (server: McpServer) => {
registerGetRootsListTool(server);
registerTriggerElicitationRequestTool(server);
registerTriggerSamplingRequestTool(server);
// Task-based research tool (uses experimental tasks API)
registerSimulateResearchQueryTool(server);
// Bidirectional task tools - server sends requests that client executes as tasks
registerTriggerSamplingRequestAsyncTool(server);
registerTriggerElicitationRequestAsyncTool(server);
};
Loading