Loading
0x50Lesson 6 of 16

Design a useful MCP tool

Write tool names, descriptions and JSON Schemas that models use correctly - and validate every call.

22 min 7-question quiz 2 code exercises
By the end of this lesson you can
  • 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).
a tool definition
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 XP

Schema 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": false in 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.

structured result
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.

  • inputSchema is JSON Schema - use required, types, ranges, enums and additionalProperties: false.

  • Validate every call on the server; return structuredContent that matches outputSchema when 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.

Exercise 1

Validate tool arguments

+25 XP

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
main.py
Loading editor…

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.

Exercise 2

Check tool names

+25 XP

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
main.py
Loading editor…

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…