Design a useful MCP tool
Write tool names, descriptions and JSON Schemas that models use correctly - and validate every call.
- Write a clear tool definition with name, description and input schema
- Add an output schema and return structured content
- Validate tool arguments at the server boundary
A tool definition is all the model knows about your tool, so it is effectively part of the prompt. It has:
name- unique within the server; 1–128 characters of letters, digits,_,-and.(e.g.get_weather,admin.tools.list),title- optional display name for people,description- what it does, when to use it, and any side effects,inputSchema- a JSON Schema object describing the arguments,outputSchema- optional schema for structured results,annotations- optional behavior hints (next lesson).
1{
2 "name": "get_forecast",
3 "title": "Weather forecast",
4 "description": "Get the daily weather forecast for a city for the next 1-7 days. Read-only.",
5 "inputSchema": {
6 "type": "object",
7 "properties": {
8 "city": {
9 "type": "string",
10 "description": "City name, e.g. \"Lisbon\"",
11 "minLength": 2
12 },
13 "days": {
14 "type": "integer",
15 "minimum": 1,
16 "maximum": 7
17 },
18 "units": {
19 "type": "string",
20 "enum": [
21 "celsius",
22 "fahrenheit"
23 ]
24 }
25 },
26 "required": [
27 "city"
28 ],
29 "additionalProperties": false
30 },
31 "outputSchema": {
32 "type": "object",
33 "properties": {
34 "city": {
35 "type": "string"
36 },
37 "highs": {
38 "type": "array",
39 "items": {
40 "type": "number"
41 }
42 }
43 },
44 "required": [
45 "city",
46 "highs"
47 ]
48 }
49}Try it
Up to 15 XPSchema playground
This is how the server reacts to the arguments a model sends. Try the presets, then write your own.
- Which mistakes become a tool execution error (
isError: true) that the model can read and fix? - What happens with arguments that aren’t even valid JSON?
- Remove
"additionalProperties": falsein your head: would"color": "red"then be accepted?
The tool definition the server shares (tools/list)
{
"name": "get_forecast",
"description": "Get the daily weather forecast for a city for the next 1-7 days.",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"minLength": 2
},
"days": {
"type": "integer",
"minimum": 1,
"maximum": 7
},
"units": {
"type": "string",
"enum": [
"celsius",
"fahrenheit"
]
}
},
"required": [
"city"
],
"additionalProperties": false
}
}The server’s responseSuccess
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "Forecast for Lisbon: 3 days of sunshine."
}
],
"isError": false
}
}Structured results
Results carry content - a list of text, image, audio or resource items for the model and user. If a tool declares an outputSchema, its result must also include structuredContent matching that schema, which programs can use directly. For older clients, the spec suggests also returning the same JSON as text content.
1{
2 "jsonrpc": "2.0",
3 "id": 5,
4 "result": {
5 "resultType": "complete",
6 "content": [
7 {
8 "type": "text",
9 "text": "{\"city\": \"Lisbon\", \"highs\": [24, 26, 23]}"
10 }
11 ],
12 "structuredContent": {
13 "city": "Lisbon",
14 "highs": [
15 24,
16 26,
17 23
18 ]
19 }
20 }
21}Key takeaways
Names are short and unique; descriptions say what, when, and with what side effects.
inputSchemais JSON Schema - userequired, types, ranges, enums andadditionalProperties: false.Validate every call on the server; return
structuredContentthat matchesoutputSchemawhen you declare one.
Lesson quiz
7 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: build an MCP server
Write Python in the editor and run it against sample inputs. Python runs locally in your browser using a WebAssembly runtime.
Validate tool arguments
The first line is a tool’s inputSchema (JSON) using only type: "object", properties with type of string, integer or boolean, and required. The second line is the arguments object.
Print valid, or one line per problem: first missing NAME for each required property that is absent (in required order), then wrong type NAME for each provided property whose type is wrong (in argument order). Note that in Python True is an int - a boolean is not a valid integer.
- Valid
- Missing and wrong
- Boolean is not an integer
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Check tool names
Read tool names, one per line, until the input ends. For each, print NAME ok if it is 1–128 characters long and uses only ASCII letters, digits, _, - and .; otherwise print NAME invalid. Names are compared exactly, so read each line without its newline only.
- Spec examples
- Bad characters
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…