Skip to content

Commit ca4d688

Browse files
committed
improve instructions
1 parent 66ec954 commit ca4d688

File tree

11 files changed

+95
-103
lines changed

11 files changed

+95
-103
lines changed

epicshop/dev.js

Lines changed: 0 additions & 77 deletions
This file was deleted.

epicshop/mcp-dev/dev.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const inspectorProcess = execa('mcp-inspector', [], {
2929
SERVER_PORT: serverPort,
3030
CLIENT_PORT: clientPort,
3131
MCP_PROXY_TOKEN: sessionToken,
32+
MCP_AUTO_OPEN_ENABLED: 'false',
3233
ALLOWED_ORIGINS: [
3334
`http://localhost:${clientPort}`,
3435
`http://127.0.0.1:${clientPort}`,

exercises/01.advanced-tools/01.problem.annotations/README.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,5 @@ To support this, each tool should include an `annotations` property that describ
4646
📜 Please check [the table in the MCP docs](https://modelcontextprotocol.io/docs/concepts/tools#available-tool-annotations) for the default values and when each annotation is useful.
4747

4848
The goal is to make tool behavior obvious to both users and the UI. The more clearly this is communicated, the more empowered and comfortable users will feel using the mcp server's advanced features.
49+
50+
To test this in the MCP inspector, simply connect and click "Tools" and "List Tools," then check the annotations in the response.

exercises/01.advanced-tools/02.problem.structured/README.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,5 @@ Here's what a structured output response looks like:
6868
</callout-muted>
6969

7070
The goal: make every journaling action in EpicMe feel seamless, safe, and delightful—so users can focus on capturing their stories, not on deciphering cryptic responses.
71+
72+
To test this in the MCP inspector, simply connect and click "Tools" and "List Tools," then check the output schema in the response. Then you can run one of the tools and verify the output includes the structured content.

exercises/02.elicitation/01.problem/README.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,24 @@ if (!confirmed) {
4949
provides clear feedback (no sandwiches are harmed)!
5050
</callout-success>
5151
52+
Note you will also want to verify that the client has elicitation capabilities, and if they do not, then just proceed.
53+
54+
```ts
55+
// the server.server is how the MCP SDK exposes the underlying server
56+
// instance for more advanced APIs like this one.
57+
const capabilities = agent.server.server.getClientCapabilities()
58+
if (capabilities?.elicitation) {
59+
// do the elicitation
60+
} else {
61+
// proceed without elicitation
62+
}
63+
```
64+
5265
This approach ensures users are always in control of important actions, and the system responds with empathy and clarity.
5366
5467
Test this one out by using the `delete_tag` tool.
5568
5669
🐨 Kody will be there in <InlineFile file="src/tools.ts" /> to help you
5770
implement this.
71+
72+
The MCP Inspector [does not support elicitation yet](https://github.com/modelcontextprotocol/inspector/issues/524), so you can check that our capabilities check is working by running the `delete_tag` tool, but to verify your elicitation is working, you'll need to run the tests.

exercises/02.elicitation/01.problem/src/tools.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ export async function initializeTools(agent: EpicMeMCP) {
294294
const existingTag = await agent.db.getTag(id)
295295
invariant(existingTag, `Tag ID "${id}" not found`)
296296

297+
// 🐨 first check whether the client has the elicitInput capability, if it does then:
297298
// 🐨 Use agent.server.server.elicitInput to ask the user to confirm deletion of the tag.
298299
// - The message should be: `Are you sure you want to delete tag "${existingTag.name}" (ID: ${id})?`
299300
// - The requestedSchema should be an object with a boolean property "confirmed".

exercises/02.elicitation/01.solution/src/tools.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -294,31 +294,35 @@ export async function initializeTools(agent: EpicMeMCP) {
294294
const existingTag = await agent.db.getTag(id)
295295
invariant(existingTag, `Tag ID "${id}" not found`)
296296

297-
const result = await agent.server.server.elicitInput({
298-
message: `Are you sure you want to delete tag "${existingTag.name}" (ID: ${id})?`,
299-
requestedSchema: {
300-
type: 'object',
301-
properties: {
302-
confirmed: {
303-
type: 'boolean',
304-
description: 'Whether to confirm the action',
297+
const capabilities = agent.server.server.getClientCapabilities()
298+
if (capabilities?.elicitation) {
299+
const result = await agent.server.server.elicitInput({
300+
message: `Are you sure you want to delete tag "${existingTag.name}" (ID: ${id})?`,
301+
requestedSchema: {
302+
type: 'object',
303+
properties: {
304+
confirmed: {
305+
type: 'boolean',
306+
description: 'Whether to confirm the action',
307+
},
305308
},
306309
},
307-
},
308-
})
309-
const confirmed =
310-
result.action === 'accept' && result.content?.confirmed === true
311-
if (!confirmed) {
312-
const structuredContent = { success: false, tag: existingTag }
313-
return {
314-
structuredContent,
315-
content: [
316-
createTextContent(
317-
`Deleting tag "${existingTag.name}" (ID: ${id}) rejected by the user.`,
318-
),
319-
createTagResourceLink(existingTag),
320-
createTextContent(structuredContent),
321-
],
310+
})
311+
312+
const confirmed =
313+
result.action === 'accept' && result.content?.confirmed === true
314+
if (!confirmed) {
315+
const structuredContent = { success: false, tag: existingTag }
316+
return {
317+
structuredContent,
318+
content: [
319+
createTextContent(
320+
`Deleting tag "${existingTag.name}" (ID: ${id}) rejected by the user.`,
321+
),
322+
createTagResourceLink(existingTag),
323+
createTextContent(structuredContent),
324+
],
325+
}
322326
}
323327
}
324328

exercises/03.sampling/01.problem.simple/README.mdx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ And don't forget to call it when the user creates a new journal entry!
3131
Here's an example of how to check if the client supports sampling:
3232

3333
```ts
34-
const clientCapabilities = agent.server.server.getClientCapabilities()
35-
if (!clientCapabilities?.sampling) {
34+
// the server.server is how the MCP SDK exposes the underlying server
35+
// instance for more advanced APIs like this one.
36+
const capabilities = agent.server.server.getClientCapabilities()
37+
if (!capabilities?.sampling) {
3638
console.error('Client does not support sampling, skipping sampling request')
3739
return
3840
}
@@ -49,3 +51,23 @@ The `maxTokens` option references the max tokens the model should return.
4951
This step will help you get comfortable with the basic request/response flow for
5052
sampling in MCP, and set the stage for more advanced prompt engineering in the
5153
next step.
54+
55+
There are tests to help verify your sampling request is working.
56+
57+
To test this in the MCP inspector:
58+
59+
- run the `create_entry` tool
60+
- check the "Sampling" navigation tab and you should have a sampling request
61+
- at this point, YOU are the LLM. You can copy paste this into your response:
62+
63+
```json
64+
{
65+
"model": "stub-model",
66+
"stopReason": "endTurn",
67+
"role": "assistant",
68+
"content": {
69+
"type": "text",
70+
"text": "Good job!"
71+
}
72+
}
73+
```

exercises/03.sampling/02.problem.advanced/README.mdx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,23 @@ for a new journal entry.
9191

9292
This step will help you practice prompt engineering for structured outputs, and
9393
show you how to use the full power of MCP's sampling API for real-world tasks.
94+
95+
There are tests to help verify your sampling request is working.
96+
97+
To test this in the MCP inspector:
98+
99+
- run the `create_entry` tool
100+
- check the "Sampling" navigation tab and you should have a sampling request
101+
- at this point, YOU are the LLM. You can copy paste this into your response:
102+
103+
```json
104+
{
105+
"model": "stub-model",
106+
"stopReason": "endTurn",
107+
"role": "assistant",
108+
"content": {
109+
"type": "text",
110+
"text": "[{\"id\":2},{\"id\":4},{\"name\":\"Beach\",\"description\":\"Activities or experiences at the beach, including sand, water, and seaside fun\"}]"
111+
}
112+
}
113+
```

exercises/04.long-running-tasks/01.problem.progress/README.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ sequenceDiagram
5858

5959
The goal is to make waiting feel like part of the experience, not a chore. Progress updates turn a long-running task into a journey the user can follow, one delicious layer at a time.
6060

61-
Test this one out by using the `create_wrapped_video` tool.
61+
Test this one out in the MCP inspector by using the `create_wrapped_video` tool.
6262

6363
<callout-info>
6464
**NOTE**: This particular tool requires ffmpeg to be installed globally on

0 commit comments

Comments
 (0)