MCP Tool Design

This skill should be used when the user asks to "define a tool", "create tool schema", "design inputSchema", "add tool annotations", "handle file uploads", "tool descriptions", "tool naming", or needs guidance on designing MCP tools for the OpenAI Apps SDK including schemas, annotations, and best practices.

16 stars

Best use case

MCP Tool Design is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

This skill should be used when the user asks to "define a tool", "create tool schema", "design inputSchema", "add tool annotations", "handle file uploads", "tool descriptions", "tool naming", or needs guidance on designing MCP tools for the OpenAI Apps SDK including schemas, annotations, and best practices.

Teams using MCP Tool Design should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/mcp-tool-design/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/design/mcp-tool-design/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/mcp-tool-design/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How MCP Tool Design Compares

Feature / AgentMCP Tool DesignStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

This skill should be used when the user asks to "define a tool", "create tool schema", "design inputSchema", "add tool annotations", "handle file uploads", "tool descriptions", "tool naming", or needs guidance on designing MCP tools for the OpenAI Apps SDK including schemas, annotations, and best practices.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# MCP Tool Design for OpenAI Apps SDK

## Overview

Tools are the primary interface between ChatGPT and your MCP server. Well-designed tools enable natural conversations, proper model behavior, and secure operations. This skill covers tool definition patterns, schema design, annotations, and best practices.

## Tool Definition Structure

Every tool requires these components:

| Field | Required | Purpose |
|-------|----------|---------|
| `name` | Yes | Machine-readable identifier |
| `description` | Yes | Human-readable explanation for the model |
| `inputSchema` | Yes | JSON Schema defining parameters |
| `annotations` | No | Behavioral hints (read-only, destructive, etc.) |
| `_meta` | No | Apps SDK extensions (file params, visibility) |

## Tool Naming Best Practices

**Do:**
- Use verb_noun format: `get_order`, `create_user`, `search_products`
- Be specific and descriptive: `get_order_status` not `get_status`
- Use lowercase with underscores
- Keep names under 64 characters

**Don't:**
- Use promotional language: `best_search`, `official_api`
- Use generic names: `do_thing`, `process`
- Include version numbers: `search_v2`

## Input Schema Design

### Basic Schema

```json
{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Search query to find products"
    },
    "limit": {
      "type": "integer",
      "description": "Maximum results to return",
      "default": 10
    }
  },
  "required": ["query"]
}
```

### Schema with Enums

```json
{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "enum": ["electronics", "clothing", "books"],
      "description": "Product category to filter by"
    }
  }
}
```

### Nested Objects

```json
{
  "type": "object",
  "properties": {
    "filter": {
      "type": "object",
      "properties": {
        "minPrice": { "type": "number" },
        "maxPrice": { "type": "number" }
      }
    }
  }
}
```

## Tool Annotations

Annotations inform ChatGPT about tool behavior and safety:

| Annotation | Default | Purpose |
|------------|---------|---------|
| `readOnlyHint` | false | Safe to auto-approve, no side effects |
| `destructiveHint` | false | May delete/overwrite data, requires confirmation |
| `openWorldHint` | false | Publishes to external systems |
| `idempotentHint` | false | Repeated calls have no additional effect |

### Python Example

```python
@mcp.tool(
    annotations={
        "readOnlyHint": True,
        "idempotentHint": True
    }
)
def get_user(user_id: str) -> dict:
    """Retrieve user information by ID."""
    return fetch_user(user_id)

@mcp.tool(
    annotations={
        "destructiveHint": True
    }
)
def delete_user(user_id: str) -> dict:
    """Permanently delete a user account."""
    return remove_user(user_id)
```

### TypeScript Example

```typescript
{
  name: "get_user",
  description: "Retrieve user information by ID",
  inputSchema: { /* ... */ },
  annotations: {
    readOnlyHint: true,
    idempotentHint: true
  }
}
```

## Apps SDK _meta Extensions

### Output Template

Link tools to widget UIs:

```python
@mcp.tool()
def get_dashboard() -> dict:
    return {
        "structuredContent": {"data": [...]},
        "_meta": {
            "openai/outputTemplate": "ui://widget/dashboard.html"
        }
    }
```

### Widget Accessibility

Enable widgets to call this tool:

```json
{
  "_meta": {
    "openai/widgetAccessible": true
  }
}
```

### Tool Visibility

Hide tools from the model (only callable from widgets):

```json
{
  "_meta": {
    "openai/visibility": "private"
  }
}
```

### File Parameters

Accept file uploads:

```json
{
  "name": "process_image",
  "inputSchema": {
    "type": "object",
    "properties": {
      "image": {
        "type": "object",
        "properties": {
          "download_url": { "type": "string" },
          "file_id": { "type": "string" }
        }
      }
    }
  },
  "_meta": {
    "openai/fileParams": ["image"]
  }
}
```

## Tool Description Guidelines

Descriptions help the model understand when and how to use tools:

**Good:**
```
"Search for products in the catalog. Returns matching products with prices and availability. Use when the user wants to find or browse products."
```

**Bad:**
```
"Search function"
```

### Description Components

1. **What it does** - Primary action
2. **What it returns** - Output format
3. **When to use** - Context for the model

## Response Patterns

### Standard Response

```python
return {
    "structuredContent": {
        "status": "success",
        "data": result
    },
    "content": [
        {"type": "text", "text": "Operation completed"}
    ]
}
```

### Response with Widget

```python
return {
    "structuredContent": {
        "summary": "Found 5 items"
    },
    "_meta": {
        "items": full_item_list,  # Widget-only data
        "openai/outputTemplate": "ui://widget/list.html"
    }
}
```

### Error Response

```python
return {
    "structuredContent": {
        "status": "error",
        "error": "Item not found"
    },
    "content": [
        {"type": "text", "text": "Could not find the requested item"}
    ],
    "isError": True
}
```

## Tool Filtering

Limit which tools the model sees to reduce context and improve accuracy:

```python
# Responses API configuration
{
    "type": "mcp",
    "server_url": "https://example.com/mcp",
    "allowed_tools": ["search", "get_details"],  # Only expose these
    "require_approval": "never"
}
```

## Validation Best Practices

1. **Validate early** - Check inputs at the start of tool handlers
2. **Return clear errors** - Explain what went wrong
3. **Use strict schemas** - Define all constraints in JSON Schema
4. **Document constraints** - Include limits in descriptions

```python
@mcp.tool()
def search(query: str, limit: int = 10) -> dict:
    """Search products. Query must be 1-100 chars, limit 1-50."""
    if not 1 <= len(query) <= 100:
        return {"error": "Query must be 1-100 characters"}
    if not 1 <= limit <= 50:
        return {"error": "Limit must be 1-50"}
    return perform_search(query, limit)
```

## Additional Resources

### Reference Files

For detailed patterns and examples:
- **`references/schema-patterns.md`** - Advanced JSON Schema patterns
- **`references/annotation-guide.md`** - Complete annotation reference

### Example Files

Working examples in `examples/`:
- **`examples/tool-definitions.py`** - Python tool examples
- **`examples/tool-definitions.ts`** - TypeScript tool examples

### Official Documentation

- Apps SDK Reference: https://developers.openai.com/apps-sdk/reference/
- JSON Schema: https://json-schema.org/understanding-json-schema/

Related Skills

project-frontend-design

16
from diegosouzapw/awesome-omni-skill

comprehensive design guide for the Meatballs project, combining high-quality frontend principles with the specific "Craft & Chao" design system. Use this skill for all frontend work in this project.

power-bi-report-design-best-practices

16
from diegosouzapw/awesome-omni-skill

Comprehensive Power BI report design and visualization best practices based on Microsoft guidance for creating effective, accessible, and performant reports and dashboards. Triggers on: **/*.{pbix,md,json,txt}

pencil-design

16
from diegosouzapw/awesome-omni-skill

Design UIs in Pencil (.pen files) and generate production code from them. Use when working with .pen files, designing screens or components in Pencil, or generating code from Pencil designs. Triggers on tasks involving Pencil, .pen files, design-to-code workflows, or UI design with the Pencil MCP tools.

mobile-first-design-rules

16
from diegosouzapw/awesome-omni-skill

Focuses on rules and best practices for mobile-first design and responsive typography using tailwind.

minimalist-portfolio-design

16
from diegosouzapw/awesome-omni-skill

Minimalist, typography-focused portfolio design system inspired by neo-brutalist and Swiss design principles. Emphasizes bold typography, generous whitespace, monochromatic color schemes, and elegant simplicity for developer/designer portfolios.

lp-design-spec

16
from diegosouzapw/awesome-omni-skill

Translate a feature requirement into a concrete frontend design specification mapped to the design system, theme tokens, and per-business brand language. Sits between fact-find and plan.

lean-systems-design

16
from diegosouzapw/awesome-omni-skill

Apply Elon Musk-inspired system design thinking for research, engineering, and business workflows: rigorously challenge requirements, delete steps, simplify/optimize what remains, accelerate iteration, then automate. Use when designing or revising systems, processes, or products that need lean, high-velocity execution.

kpi-dashboard-design

16
from diegosouzapw/awesome-omni-skill

Design effective KPI dashboards with metrics selection, visualization best practices, and real-time monitoring patterns. Use when building business dashboards, selecting metrics, or designing data ...

game-design

16
from diegosouzapw/awesome-omni-skill

Game design principles. GDD structure, balancing, player psychology, progression.

frontend-design

16
from diegosouzapw/awesome-omni-skill

Create distinctive, bold UI designs that avoid generic AI aesthetics. This skill should be used when users want frontend components with strong visual identity, creative typography, intentional color palettes, and production-grade animations - specifically to avoid the bland, safe, homogeneous "AI slop" that plagues most generated interfaces.

figma-design

16
from diegosouzapw/awesome-omni-skill

Access Figma designs, extract design systems, and retrieve component specifications. Use when implementing UI from Figma mockups, extracting design tokens, or analyzing design files.

faion-ui-designer

16
from diegosouzapw/awesome-omni-skill

UI design: wireframes, prototypes, design systems, visual design.