Skip to content

Commit 5571dbd

Browse files
committed
improve instructions
1 parent 10c0613 commit 5571dbd

File tree

2 files changed

+78
-7
lines changed

2 files changed

+78
-7
lines changed

exercises/02.elicitation/README.mdx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ Elicitation enables interactive workflows like confirming destructive actions, c
1111
dialogs, forms, or any interface that fits their platform.
1212
</callout-info>
1313

14+
## Elicitation Human-in-the-Loop vs. Tool Call Human-in-the-Loop
15+
16+
When the user makes a prompt and the LLM decides to call a tool, the application should check with the user before calling the tool.
17+
18+
<callout-success>
19+
Elicitation is specifically designed for **structured, mid-process
20+
interactions**. Unlike general chat or form submissions, elicitation happens
21+
when the MCP server is actively processing a request and realizes it needs
22+
more information to complete the task effectively.
23+
</callout-success>
24+
1425
## User Interaction Model
1526

1627
When an MCP server needs more information, it sends an `elicitation/create` request to the client, specifying:
@@ -112,11 +123,28 @@ sequenceDiagram
112123
Client->>Server: Forward selection
113124
```
114125

126+
## When to Use Elicitation
127+
128+
Elicitation is ideal for scenarios where:
129+
130+
- **Confirmation is needed** for destructive or irreversible actions
131+
- **Additional context** would improve the quality of the response
132+
- **User preferences** need to be clarified mid-process
133+
- **Multi-step workflows** require intermediate user input
134+
135+
<callout-warning>
136+
Don't use elicitation for information that could have been provided in the
137+
initial prompt. Elicitation should only be used when the server genuinely
138+
needs more information to complete the current task effectively.
139+
</callout-warning>
140+
115141
## Recommended Practices
116142

117143
- Use clear, concise messages for elicitation prompts.
118144
- Design schemas with only the fields you truly need (avoid requesting sensitive info).
119145
- Always handle accept, decline, and cancel actions.
146+
- Check client capabilities before attempting elicitation.
147+
- Use elicitation sparingly - it should enhance, not interrupt, the user experience.
120148

121149
## References
122150

exercises/04.long-running-tasks/README.mdx

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,19 +136,62 @@ For more details, see the [MCP Cancellation Documentation](https://modelcontextp
136136
Not everyone is familiar with signals and the `AbortController` API. Here's a simple example to illustrate how it works:
137137

138138
```js
139+
const { spawn } = require('child_process')
139140
const controller = new AbortController()
140141
const signal = controller.signal
141142

143+
// Track the child process that needs cleanup
144+
let childProcess = null
145+
146+
// Add an event listener to the signal - this is crucial for cleanup!
147+
signal.addEventListener('abort', () => {
148+
console.log('Signal was aborted! Killing child process...')
149+
if (childProcess) {
150+
childProcess.kill('SIGTERM')
151+
childProcess = null
152+
console.log('Child process killed')
153+
}
154+
})
155+
142156
async function doLongTask(signal) {
143-
for (let i = 0; i < 10; i++) {
144-
if (signal.aborted) {
145-
throw new Error('Operation cancelled')
157+
// Start a child process that processes data
158+
childProcess = spawn('data-processor', ['--input', 'large-dataset.csv', '--output', 'processed-data.json'], {
159+
stdio: ['pipe', 'pipe', 'pipe']
160+
})
161+
162+
try {
163+
// Listen to the child process output
164+
childProcess.stdout.on('data', (data) => {
165+
const output = data.toString().trim()
166+
console.log('Child output:', output)
167+
168+
if (output.includes('Processing complete!')) {
169+
console.log('All items processed successfully!')
170+
}
171+
})
172+
173+
// Wait for the child process to complete
174+
await new Promise((resolve, reject) => {
175+
childProcess.on('close', (code) => {
176+
if (code === 0) {
177+
resolve('Processing completed successfully')
178+
} else {
179+
reject(new Error(\`Child process exited with code \${code}\``))
180+
}
181+
})
182+
183+
childProcess.on('error', reject)
184+
})
185+
186+
return 'Done!'
187+
} finally {
188+
// Clean up child process when task completes normally
189+
if (childProcess) {
190+
childProcess.kill('SIGTERM')
191+
childProcess = null
192+
console.log('Child process cleaned up normally')
146193
}
147-
// Simulate work
148-
await new Promise((r) => setTimeout(r, 500))
149-
console.log(`Step ${i + 1} complete`)
150194
}
151-
return 'Done!'
152195
}
153196

154197
doLongTask(signal)

0 commit comments

Comments
 (0)