What a Server Offers
A server can expose three different things. The useful distinction is who decides when each is used:
| Decided by | What it's for | |
|---|---|---|
| Tools | The AI model | Actions the assistant chooses to take, like sending an email or running a query |
| Resources | The application | Information pulled into context, such as a file, a schema, or a record |
| Prompts | The user | Templates you trigger deliberately, usually as slash commands |
Most coverage of MCP only discusses tools, which is about a third of the picture. Resources are how an assistant gets context rather than capability, and prompts are how a server ships ready-made workflows to the person typing.
A tool definition is small. It has a name, a description written for the model to read, and a schema describing its inputs. The description is not documentation. It is what the model uses to decide whether to call the tool at all, so it does real work.
For developers: what a tool call looks like
Discovery is tools/list, invocation is tools/call. Results come back as typed content blocks: text, image, audio, or a link to a resource.
// ← tools/list: what the server offers
{
"tools": [
{
"name": "get_weather",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City name or zip code" }
},
"required": ["location"]
}
}
]
}
// → tools/call: the assistant invokes it
{ "name": "get_weather", "arguments": { "location": "New York" } }
// ← the result
{
"content": [
{ "type": "text", "text": "New York: 72°F, partly cloudy" }
],
"isError": false
}Note isError. A tool that ran but failed sensibly (a bad date, an upstream service down) reports that inside a normal result, so the model can read the message and correct itself. A malformed request is a separate kind of error aimed at the developer. Collapsing both into one status code, as REST does, loses that distinction.