AI Skill Report Card

Implementing MCP Tools

A87·Sep 26, 2026·Source: Extension-page
14 / 15

Minimal MCP tool definition and server response:

JSON
{ "capabilities": { "tools": { "listChanged": true } } }
JSON
{ "name": "get_weather", "title": "Weather Information Provider", "description": "Get current weather information for a location", "inputSchema": { "type": "object", "properties": { "location": { "type": "string", "description": "City name or zip code" } }, "required": ["location"] } }

Tool call response (unstructured):

JSON
{ "jsonrpc": "2.0", "id": 2, "result": { "resultType": "complete", "content": [ { "type": "text", "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy" } ], "isError": false } }
Recommendation▾
Add a brief example of a client-side tool discovery/invocation flow to balance the server-heavy focus
14 / 15

Progress checklist for implementing an MCP tool-serving capability:

  • Declare tools capability (listChanged: true/false) in server capabilities
  • Define each tool: name, title, description, inputSchema, optional outputSchema, optional icons, optional annotations
  • Validate tool name against naming rules (see below)
  • Implement tools/list handler: paginated, deterministic ordering, no per-connection variance (auth-scoped variance is allowed)
  • Implement tools/call handler: validate arguments against inputSchema, execute, return content and/or structuredContent
  • If outputSchema defined, ensure structuredContent conforms and mirror it in a text content block for backwards compatibility
  • If tool requires additional user input mid-call, return resultType: "input_required" with inputRequests and requestState; handle retry with inputResponses
  • If tool list can change at runtime, send notifications/tools/list_changed to subscribed clients
  • If using Streamable HTTP transport and exposing routable parameters, add x-mcp-header annotations; validate constraints and reject invalid tools client-side
Recommendation▾
Include an error-response example (isError: true) to round out the content/response variations
17 / 20

Example 1 — Tool with output schema:

Input: Tool get_weather_data with outputSchema requiring temperature, conditions, humidity.

Output:

JSON
{ "jsonrpc": "2.0", "id": 5, "result": { "resultType": "complete", "content": [ { "type": "text", "text": "{\"temperature\": 22.5, \"conditions\": \"Partly cloudy\", \"humidity\": 65}" } ], "structuredContent": { "temperature": 22.5, "conditions": "Partly cloudy", "humidity": 65 } } }

Example 2 — Input-required flow (elicitation mid-call):

Input: Client calls get_weather for "New York"; server needs GitHub login first.

Output (server asks for input):

JSON
{ "jsonrpc": "2.0", "id": 2, "result": { "resultType": "input_required", "inputRequests": { "github_login": { "method": "elicitation/create", "params": { "mode": "form", "message": "Please provide your GitHub username", "requestedSchema": { "type": "object", "properties": { "name": { "type": "string" } }, "required": ["name"] } } } }, "requestState": "eyJsb2NhdGlvbiI6Ik5ldyBZb3JrIn0..." } }

Client retries with a new JSON-RPC id, including inputResponses and requestState.

Example 3 — x-mcp-header for HTTP routing:

Input: Tool parameter region should be mirrored as an HTTP header for load-balancer routing.

Output:

JSON
{ "region": { "type": "string", "x-mcp-header": "Region" } }

Call with "region": "us-west1" → client adds header Mcp-Param-Region: us-west1.

Recommendation▾
Consider a short troubleshooting/debugging section for common schema validation failures beyond the pitfalls list
  • Always include a human-in-the-loop confirmation before invoking tools with side effects; surface which tools are exposed and indicate invocation clearly in UI.
  • Use deterministic ordering in tools/list responses to support caching and LLM prompt cache hits.
  • Prefer {"type": "object", "additionalProperties": false} for parameterless tools (explicit, unambiguous).
  • Always mirror structuredContent into a text content block for backward compatibility with clients that don't parse structured output.
  • Keep tool names within 1–128 chars, using only [A-Za-z0-9_.-]; treat names as case-sensitive.
  • When aggregating tools from multiple servers, disambiguate collisions with a server-identifier prefix — never rely on serverInfo.name for uniqueness.
  • Treat tool annotations as untrusted metadata unless sourced from a trusted server.
  • Never mark sensitive parameters (passwords, tokens, PII) with x-mcp-header — header values are visible to intermediaries.
  • Validate x-mcp-header constraints strictly (field-name syntax, no control chars, case-insensitive uniqueness, primitive types only, safe integer range) and reject/log non-conforming tools rather than failing the whole list.
  • Don't vary the tools/list result per-connection or as a side effect of unrelated requests — only authorization-based filtering is allowed.
  • Don't reuse the same JSON-RPC id when retrying a tools/call after an input_required response — it MUST be different.
  • Don't apply x-mcp-header to number-typed parameters or to non-statically-reachable schema properties — only primitives (string, boolean, safe-range integer).
  • Don't skip outputSchema validation on the server side — structured content that doesn't conform breaks client contracts.
  • Don't assume tools with no listChanged declaration will never change — check the capability before relying on notifications.
  • Don't ignore x-mcp-header constraint violations silently on Streamable HTTP transport — reject the whole tool definition from tools/list, not just the bad header.
0
Grade AAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
17/20
Completeness
18/20
Format
15/15
Conciseness
13/15