Skip to content

Commit c635e03

Browse files
committed
improve instructions
1 parent 5b46f69 commit c635e03

File tree

2 files changed

+242
-1
lines changed

2 files changed

+242
-1
lines changed
Lines changed: 233 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,233 @@
1-
# Advanced Tool Config
1+
# Advanced Tools
2+
3+
## Tool Annotations
4+
5+
Tool annotations are metadata attached to each tool definition. They help clients and users understand the tool's behavior, especially regarding side effects, safety, and intended use. Annotations do **not** affect the tool's execution. They are hints for UI, approval flows, and documentation.
6+
7+
<callout-warning>
8+
Annotations are *not* security features. They are advisory only and should not
9+
be relied on for access control or sandboxing.
10+
</callout-warning>
11+
12+
### Why Use Annotations?
13+
14+
- **UX clarity:** Help users understand what a tool does before approving its use.
15+
- **Safety:** Warn about potentially destructive or open-world actions.
16+
- **Automation:** Allow clients to group, filter, or require extra approval for certain tools.
17+
18+
### Example Tool Definition: Launch Real-Life Confetti
19+
20+
Here's a fun (and slightly dangerous) example of a tool that launches a real confetti cannon in the physical world:
21+
22+
```ts
23+
{
24+
name: 'launch_confetti',
25+
description:
26+
'Launch a real confetti cannon in the physical world to celebrate! (Warning: may make a mess)',
27+
inputSchema: {
28+
type: 'object',
29+
properties: {
30+
color: { type: 'string', description: 'The color of the confetti' },
31+
intensity: {
32+
type: 'string',
33+
enum: ['low', 'medium', 'high'],
34+
description: 'How much confetti to launch',
35+
},
36+
location: {
37+
type: 'string',
38+
description:
39+
"Where to launch the confetti (e.g., 'main office', 'living room')",
40+
},
41+
},
42+
required: ['color', 'location'],
43+
},
44+
annotations: {
45+
title: 'Launch Real-Life Confetti',
46+
readOnlyHint: false,
47+
destructiveHint: true,
48+
idempotentHint: false,
49+
openWorldHint: true,
50+
},
51+
}
52+
```
53+
54+
- `readOnlyHint: false` - This tool physically changes the environment (and makes a mess!).
55+
- `destructiveHint: true` - Launching confetti can be considered a destructive action (cleanup required).
56+
- `openWorldHint: true` - This tool literally interacts with the real world, not just the local system/service provider.
57+
- `idempotentHint: false` - This tool is not idempotent because it makes a mess (and the cannon may need a reload to work again).
58+
59+
<callout-warning>
60+
A tool like this should require explicit user approval and be used with
61+
caution. Imagine the consequences of launching confetti in the wrong place at
62+
the wrong time!
63+
</callout-warning>
64+
65+
### How Annotations Affect the Client
66+
67+
Clients can use annotations to:
68+
69+
- Display warnings or require confirmation for destructive tools
70+
- Group or filter tools (e.g., show only read-only tools)
71+
- Provide friendlier names in the UI
72+
- Decide when to allow automation or require human approval
73+
74+
<callout-success>
75+
Annotations make it easier to build safe, user-friendly interfaces for tool
76+
invocation.
77+
</callout-success>
78+
79+
### Best Practices
80+
81+
1. **Be accurate about side effects:** Mark tools as `readOnlyHint: true` only if they never modify state.
82+
2. **Use descriptive titles:** The `title` annotation should be clear and human-friendly.
83+
3. **Indicate idempotency:** Use `idempotentHint: true` only if repeated calls with the same arguments are safe and have no extra effect.
84+
4. **Set open/closed world hints:** Use `openWorldHint: true` for tools that interact with the internet or external systems.
85+
5. **Remember: annotations are hints!** Never rely on them for security or correctness.
86+
87+
<callout-muted>
88+
Annotations are for humans and UIs, not for enforcing security or correctness.
89+
</callout-muted>
90+
91+
### Learn More 📜
92+
93+
For a full list of available annotations and their meanings, see the [official MCP documentation on tool annotations](https://modelcontextprotocol.io/docs/concepts/tools#tool-annotations).
94+
95+
## Structured Output and Output Schemas
96+
97+
Structured output allows tools to return rich, machine-validated data instead of just plain text. By defining an `outputSchema` for a tool, the server ensures that all tool responses conform to a specific structure, making it easier for clients and LLMs to consume, validate, and act on the results.
98+
99+
### Why Use Structured Output?
100+
101+
- **Reliability:** Ensures tool responses are predictable and machine-parseable.
102+
- **Validation:** Automatic schema validation prevents malformed or incomplete data from propagating.
103+
- **Automation:** Enables downstream automation, UI rendering, and chaining of tool results.
104+
- **Safety:** Reduces the risk of misinterpretation or injection by strictly defining expected output.
105+
106+
### How It Works
107+
108+
1. **Tool Definition:** The tool specifies an `outputSchema` (JSON Schema) describing the expected result structure.
109+
2. **Tool Execution:** When the tool is called, the server validates the output against the schema before returning it to the client.
110+
3. **Client Consumption:** Clients and LLMs can safely parse and use the structured result, knowing it matches the schema.
111+
4. **Error Handling:** If the output does not match the schema, an error is returned instead of invalid data.
112+
113+
### Example Tool with Output Schema
114+
115+
Suppose we have a tool that generates a random fantasy character profile:
116+
117+
```ts
118+
{
119+
name: 'generate_fantasy_character',
120+
description:
121+
'Creates a random fantasy character profile for games or stories.',
122+
inputSchema: {
123+
type: 'object',
124+
properties: {
125+
theme: {
126+
type: 'string',
127+
description:
128+
'Optional theme for the character (e.g., "forest", "fire", "ice")',
129+
},
130+
},
131+
required: [],
132+
},
133+
outputSchema: {
134+
type: 'object',
135+
properties: {
136+
name: { type: 'string', description: "The character's name" },
137+
species: {
138+
type: 'string',
139+
description: 'The fantasy species (e.g., elf, orc, dragon)',
140+
},
141+
characterClass: {
142+
type: 'string',
143+
description:
144+
"The character's class or role (e.g., wizard, rogue, paladin)",
145+
},
146+
abilities: {
147+
type: 'array',
148+
items: { type: 'string' },
149+
description: 'A list of special abilities or powers',
150+
},
151+
},
152+
required: ['name', 'species', 'characterClass', 'abilities'],
153+
},
154+
}
155+
```
156+
157+
### Example Request/Response with Structured Content
158+
159+
#### Request
160+
161+
```json
162+
{
163+
"jsonrpc": "2.0",
164+
"id": 99,
165+
"method": "tools/call",
166+
"params": {
167+
"name": "generate_fantasy_character",
168+
"arguments": {
169+
"theme": "forest"
170+
}
171+
}
172+
}
173+
```
174+
175+
#### Response
176+
177+
```json
178+
{
179+
"jsonrpc": "2.0",
180+
"id": 99,
181+
"result": {
182+
"content": [
183+
{
184+
"type": "text",
185+
"text": "{\"name\": \"Lirael Mosswhisper\", \"species\": \"Elf\", \"characterClass\": \"Druid\", \"abilities\": [\"Speak with Animals\", \"Vine Whip\", \"Forest Camouflage\"]}"
186+
}
187+
],
188+
"structuredContent": {
189+
"name": "Lirael Mosswhisper",
190+
"species": "Elf",
191+
"characterClass": "Druid",
192+
"abilities": ["Speak with Animals", "Vine Whip", "Forest Camouflage"]
193+
}
194+
}
195+
}
196+
```
197+
198+
### Validation Flow
199+
200+
Below is a sequence diagram showing how structured content is validated:
201+
202+
```mermaid
203+
sequenceDiagram
204+
participant User
205+
participant App
206+
participant LLM
207+
participant Client
208+
participant Server
209+
User->>App: Enter prompt
210+
App->>LLM: Send prompt
211+
LLM-->>App: Tool call request (expects structured output)
212+
App->>Client: Forward tool call
213+
Client->>Server: JSON-RPC tool call
214+
Server-->>Client: JSON-RPC response (with structuredContent)
215+
Note right of Server: Validate output against outputSchema
216+
alt Output valid
217+
Client-->>App: Structured result
218+
App->>LLM: Structured result
219+
LLM-->>App: Generation (uses structured data)
220+
App-->>User: Display structured result
221+
else Output invalid
222+
Client-->>App: Error (schema validation failed)
223+
App->>User: Show error
224+
end
225+
```
226+
227+
### Best Practices
228+
229+
1. **Define clear output schemas:** Use JSON Schema to describe all possible fields and types.
230+
2. **Validate on the server:** Always validate tool output before returning to the client (the SDK does this for us).
231+
3. **Handle validation errors gracefully:** Inform users or clients when output does not match the schema (the SDK does this for us).
232+
233+
For more details, see the [official MCP documentation on structured content and output schemas](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content).

exercises/README.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,13 @@ and the [introduction](https://modelcontextprotocol.io/introduction). These
2424
resources provide a deep dive into the protocol, its design principles, and
2525
practical implementation tips.
2626

27+
<callout-danger>
28+
**NOTE**: At the time of this writing, most clients don't support the features
29+
that we're going to be learning about in this workshop. So a lot of what we'll
30+
be doing is theoretical, and the knowledge you acquire in this workshop won't
31+
be immediately practical until we get more clients that support these
32+
features. That said, when we do get these features, you'll be ready to hit the
33+
ground running.
34+
</callout-danger>
35+
2736
Ready to build even better AI connected apps? Then let's get going!

0 commit comments

Comments
 (0)