-
Notifications
You must be signed in to change notification settings - Fork 5
chore: add snippet for prescribed tool with descriptions #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| # Prescribed Tools with Descriptions | ||
|
|
||
| This sample demonstrates how to use the `@tool` directive with prescribed operations that contains descriptions that can be used through to create MCP (Model Context Protocol) tools. | ||
|
|
||
|
||
| ## Overview | ||
|
|
||
| The sample implements a mock weather service API with a simple operations, Weather forecast for a city | ||
|
||
|
|
||
| The key feature demonstrated is how to create a prescribed tool with rich descriptions that help AI models understand how to use the tool effectively. | ||
|
|
||
| ## Schema Structure | ||
|
|
||
| The schema consists of: | ||
|
|
||
| 1. A main schema file (`index.graphql`) that defines: | ||
| - The GraphQL types for weather data | ||
| - The `@tool` directive that creates a prescribed tool | ||
| - The `@sdl` directive that includes persisted operations | ||
|
|
||
| 2. An operations file (`operations.graphql`) that contains: | ||
| - Documented GraphQL operations with descriptions | ||
|
||
| - Variable descriptions that are used by the tool | ||
|
|
||
| ## How Prescribed Tools Work | ||
|
|
||
| A prescribed tool is defined using the `@tool` directive with the `prescribed` argument pointing to a specific operation in a persisted document: | ||
|
|
||
| ```graphql | ||
| @tool( | ||
| name: "weather-lookup" | ||
| prescribed: "WeatherForecast" | ||
| ) | ||
| ``` | ||
|
|
||
| The operation itself can include descriptions: | ||
|
||
|
|
||
| ```graphql | ||
| """ | ||
| Get detailed weather forecast for a specific city | ||
| This operation provides a multi-day weather forecast including temperature, conditions, and other meteorological data | ||
| """ | ||
| query WeatherForecast( | ||
| """The name of the city to get weather forecast for""" | ||
| $city: String!, | ||
| """Number of days to forecast (1-7), defaults to 3 days""" | ||
| $days: Int = 3 | ||
| ) { | ||
| // operation details | ||
| } | ||
| ``` | ||
|
|
||
| ## MCP Tool Description | ||
|
|
||
| When deployed, this schema will expose a tool through the MCP endpoint with the following description: | ||
|
|
||
| ```json | ||
| { | ||
| "name": "weather-lookup", | ||
| "description": "Weather forecast lookup tool for cities and locations", | ||
| "inputSchema": { | ||
| "type": "object", | ||
| "properties": { | ||
| "variables": { | ||
| "properties": { | ||
| "city": { | ||
| "description": "The name of the city to get weather forecast for", | ||
| "type": "string" | ||
| }, | ||
| "days": { | ||
| "description": "Number of days to forecast (1-7), defaults to 3 days", | ||
| "type": "integer", | ||
| "default": 3 | ||
| } | ||
| }, | ||
| "required": ["city"], | ||
| "type": "object" | ||
| } | ||
| }, | ||
| "required": ["variables"] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Using the Tool | ||
|
|
||
| An AI model can use this tool by: | ||
|
|
||
| 1. Understanding the tool's purpose from its description | ||
| 2. Providing the required variables (city name and optionally number of days) | ||
| 3. Receiving structured weather forecast data in response | ||
|
|
||
| ## Benefits of Prescribed Tools with Descriptions | ||
|
|
||
| 1. **Improved AI Understanding**: Detailed descriptions help AI models understand the purpose and parameters of the tool. | ||
| 2. **Structured Input Validation**: The GraphQL schema ensures that inputs are properly validated. | ||
| 3. **Documentation**: The descriptions serve as both documentation for developers and instructions for AI models. | ||
|
|
||
| ### Testing as an MCP Tool | ||
|
|
||
| To test this as an MCP tool with AI models: | ||
|
|
||
| 1. Deploy the schema to StepZen using the command `stepzen deploy` | ||
| 2. [Connect Claude Desktop](https://modelcontextprotocol.io/docs/develop/connect-local-servers) to your StepZen MCP endpoint | ||
| 3. The tool will appear as `weather-lookup` and can be called by the AI model | ||
|
|
||
| **Example**: Interaction between MCP and the Claude UI. | ||
|
|
||
| <img width="563" height="360" alt="Image" src="https://github.com/user-attachments/assets/7da0cd20-2469-45cd-8a17-0891a1a03dec" /> | ||
|
|
||
| <img width="502" height="588" alt="Image" src="https://github.com/user-attachments/assets/cf499b7e-a3fe-433c-b837-bdde25441739" /> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| schema | ||
| @sdl( | ||
| files: [] | ||
| executables: [{ document: "operations.graphql", persist: true }] | ||
| ) | ||
| @tool(name: "weather-lookup", prescribed: "WeatherForecast") { | ||
| query: Query | ||
| } | ||
|
|
||
| type Query { | ||
| # Get weather forecast for a specific city | ||
| weatherForecast(city: String!, days: Int = 3): WeatherForecast | ||
| @value( | ||
| script: { | ||
| src: """ | ||
| function weatherForecast() { | ||
| const cities = { | ||
| "new york": { | ||
| name: "New York", | ||
| country: "United States", | ||
| latitude: 40.7128, | ||
| longitude: -74.0060, | ||
| timezone: "America/New_York", | ||
| population: 8804190 | ||
| }, | ||
| "london": { | ||
| name: "London", | ||
| country: "United Kingdom", | ||
| latitude: 51.5074, | ||
| longitude: -0.1278, | ||
| timezone: "Europe/London", | ||
| population: 8982000 | ||
| }, | ||
| "tokyo": { | ||
| name: "Tokyo", | ||
| country: "Japan", | ||
| latitude: 35.6762, | ||
| longitude: 139.6503, | ||
| timezone: "Asia/Tokyo", | ||
| population: 13960000 | ||
| }, | ||
| "sydney": { | ||
| name: "Sydney", | ||
| country: "Australia", | ||
| latitude: -33.8688, | ||
| longitude: 151.2093, | ||
| timezone: "Australia/Sydney", | ||
| population: 5312000 | ||
| } | ||
| }; | ||
|
|
||
| // Default to 3 days if not specified or out of range | ||
| const daysToForecast = days < 1 || days > 7 ? 3 : days; | ||
|
|
||
| const normalizedCity = city.toLowerCase(); | ||
| const cityData = cities[normalizedCity] || { | ||
| name: city, | ||
| country: "Unknown", | ||
| latitude: 0, | ||
| longitude: 0, | ||
| timezone: "UTC", | ||
| population: null | ||
| }; | ||
|
|
||
| // Fixed forecast patterns for each city | ||
| const forecastPatterns = { | ||
| "new york": [ | ||
| { conditions: "Partly Cloudy", high: 22, low: 15, precipitation: 20, humidity: 65, windSpeed: 12, windDirection: "NW" }, | ||
| { conditions: "Sunny", high: 24, low: 16, precipitation: 5, humidity: 55, windSpeed: 8, windDirection: "W" }, | ||
| { conditions: "Cloudy", high: 20, low: 14, precipitation: 30, humidity: 70, windSpeed: 15, windDirection: "NE" }, | ||
| { conditions: "Rain", high: 18, low: 12, precipitation: 75, humidity: 85, windSpeed: 18, windDirection: "E" }, | ||
| { conditions: "Partly Cloudy", high: 23, low: 16, precipitation: 15, humidity: 60, windSpeed: 10, windDirection: "SW" }, | ||
| { conditions: "Sunny", high: 25, low: 17, precipitation: 0, humidity: 50, windSpeed: 7, windDirection: "W" }, | ||
| { conditions: "Thunderstorm", high: 21, low: 15, precipitation: 90, humidity: 90, windSpeed: 25, windDirection: "S" } | ||
| ], | ||
| "london": [ | ||
| { conditions: "Cloudy", high: 16, low: 10, precipitation: 40, humidity: 75, windSpeed: 14, windDirection: "SW" }, | ||
| { conditions: "Rain", high: 15, low: 9, precipitation: 65, humidity: 80, windSpeed: 16, windDirection: "W" }, | ||
| { conditions: "Partly Cloudy", high: 17, low: 11, precipitation: 25, humidity: 70, windSpeed: 12, windDirection: "NW" }, | ||
| { conditions: "Cloudy", high: 16, low: 10, precipitation: 35, humidity: 75, windSpeed: 13, windDirection: "SW" }, | ||
| { conditions: "Rain", high: 14, low: 8, precipitation: 70, humidity: 85, windSpeed: 18, windDirection: "W" }, | ||
| { conditions: "Partly Cloudy", high: 18, low: 12, precipitation: 20, humidity: 65, windSpeed: 11, windDirection: "NW" }, | ||
| { conditions: "Sunny", high: 19, low: 13, precipitation: 10, humidity: 60, windSpeed: 9, windDirection: "N" } | ||
| ], | ||
| "tokyo": [ | ||
| { conditions: "Sunny", high: 26, low: 19, precipitation: 5, humidity: 60, windSpeed: 10, windDirection: "E" }, | ||
| { conditions: "Partly Cloudy", high: 25, low: 18, precipitation: 15, humidity: 65, windSpeed: 12, windDirection: "SE" }, | ||
| { conditions: "Cloudy", high: 23, low: 17, precipitation: 30, humidity: 70, windSpeed: 14, windDirection: "S" }, | ||
| { conditions: "Rain", high: 22, low: 16, precipitation: 60, humidity: 80, windSpeed: 16, windDirection: "SW" }, | ||
| { conditions: "Partly Cloudy", high: 24, low: 18, precipitation: 20, humidity: 65, windSpeed: 11, windDirection: "E" }, | ||
| { conditions: "Sunny", high: 27, low: 20, precipitation: 5, humidity: 55, windSpeed: 9, windDirection: "NE" }, | ||
| { conditions: "Cloudy", high: 24, low: 18, precipitation: 25, humidity: 68, windSpeed: 13, windDirection: "SE" } | ||
| ], | ||
| "sydney": [ | ||
| { conditions: "Sunny", high: 28, low: 20, precipitation: 10, humidity: 60, windSpeed: 15, windDirection: "NE" }, | ||
| { conditions: "Partly Cloudy", high: 27, low: 19, precipitation: 15, humidity: 65, windSpeed: 14, windDirection: "E" }, | ||
| { conditions: "Sunny", high: 29, low: 21, precipitation: 5, humidity: 55, windSpeed: 13, windDirection: "NE" }, | ||
| { conditions: "Partly Cloudy", high: 26, low: 19, precipitation: 20, humidity: 70, windSpeed: 16, windDirection: "SE" }, | ||
| { conditions: "Cloudy", high: 24, low: 18, precipitation: 35, humidity: 75, windSpeed: 18, windDirection: "S" }, | ||
| { conditions: "Rain", high: 22, low: 17, precipitation: 70, humidity: 85, windSpeed: 20, windDirection: "SW" }, | ||
| { conditions: "Partly Cloudy", high: 25, low: 18, precipitation: 25, humidity: 70, windDirection: "W", windSpeed: 17 } | ||
| ] | ||
| }; | ||
|
|
||
| // Get pattern for city or use default | ||
| const pattern = forecastPatterns[normalizedCity] || forecastPatterns["new york"]; | ||
|
|
||
| // Generate forecast for the requested number of days | ||
| const forecast = []; | ||
| const today = new Date(); | ||
|
|
||
| for (let i = 0; i < daysToForecast; i++) { | ||
| const forecastDate = new Date(); | ||
| forecastDate.setDate(today.getDate() + i); | ||
|
|
||
| const dayPattern = pattern[i % pattern.length]; | ||
|
|
||
| forecast.push({ | ||
| date: forecastDate.toISOString().split('T')[0], | ||
| sunrise: "06:25 AM", | ||
| sunset: "06:35 PM", | ||
| high: { | ||
| celsius: dayPattern.high, | ||
| fahrenheit: Math.round(dayPattern.high * 9 / 5 + 32) | ||
| }, | ||
| low: { | ||
| celsius: dayPattern.low, | ||
| fahrenheit: Math.round(dayPattern.low * 9 / 5 + 32) | ||
| }, | ||
| conditions: dayPattern.conditions, | ||
| precipitation: dayPattern.precipitation, | ||
| humidity: dayPattern.humidity, | ||
| windSpeed: dayPattern.windSpeed, | ||
| windDirection: dayPattern.windDirection | ||
| }); | ||
| } | ||
|
|
||
| return { | ||
| city: cityData, | ||
| forecast: forecast, | ||
| }; | ||
| } | ||
| weatherForecast() | ||
| """ | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| type WeatherForecast { | ||
| city: City! | ||
| forecast: [DailyForecast!]! | ||
| lastUpdated: DateTime | ||
| } | ||
|
|
||
| type City { | ||
| name: String! | ||
| country: String! | ||
| latitude: Float! | ||
| longitude: Float! | ||
| timezone: String! | ||
| population: Int | ||
| } | ||
|
|
||
| type DailyForecast { | ||
| date: Date! | ||
| sunrise: String! | ||
| sunset: String! | ||
| high: Temperature! | ||
| low: Temperature! | ||
| conditions: String! | ||
| precipitation: Float! | ||
| humidity: Int! | ||
| windSpeed: Float! | ||
| windDirection: String! | ||
| } | ||
|
|
||
| type Temperature { | ||
| celsius: Float! | ||
| fahrenheit: Float! | ||
| } | ||
|
|
||
| scalar Date | ||
| scalar DateTime |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| """ | ||
| Get detailed weather forecast for a specific city | ||
| This operation provides a multi-day weather forecast including temperature, conditions, and other meteorological data | ||
| """ | ||
| query WeatherForecast( | ||
| """The name of the city to get weather forecast for""" | ||
| $city: String!, | ||
| """Number of days to forecast (1-7), defaults to 3 days""" | ||
| $days: Int = 3 | ||
| ) { | ||
| weatherForecast(city: $city, days: $days) { | ||
| city { | ||
| name | ||
| country | ||
| timezone | ||
| } | ||
| forecast { | ||
| date | ||
| high { | ||
| celsius | ||
| fahrenheit | ||
| } | ||
| low { | ||
| celsius | ||
| fahrenheit | ||
| } | ||
| conditions | ||
| precipitation | ||
| humidity | ||
| windSpeed | ||
| windDirection | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "endpoint": "api/miscellaneous" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"prescribed tools"
"persisted operations"
are the terms
Not "prescribed operations"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to qualify "operation" as "GraphQL operation" (with a link to the spec) as the first mention.