Skip to content

Commit 16020bf

Browse files
author
Ratnakar Asara
committed
add snippet for prescribed operations and variables descriptions
Signed-off-by: Ratnakar Asara <rasara@us.ibm.com>
1 parent ea04590 commit 16020bf

File tree

6 files changed

+431
-3
lines changed

6 files changed

+431
-3
lines changed

executable/persisted/tests/Test.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ const {
99

1010
testDescription = getTestDescription("snippets", __dirname);
1111

12-
const requestsFile = path.join(path.dirname(__dirname), "operations.graphql");
13-
const requests = fs.readFileSync(requestsFile, "utf8").toString();
14-
1512
describe(testDescription, function () {
1613
const tests = [
1714
{
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Prescribed Tools with Descriptions
2+
3+
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.
4+
5+
## Overview
6+
7+
The sample implements a mock weather service API with a simple operations, Weather forecast for a city
8+
9+
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.
10+
11+
## Schema Structure
12+
13+
The schema consists of:
14+
15+
1. A main schema file (`index.graphql`) that defines:
16+
- The GraphQL types for weather data
17+
- The `@tool` directive that creates a prescribed tool
18+
- The `@sdl` directive that includes persisted operations
19+
20+
2. An operations file (`operations.graphql`) that contains:
21+
- Documented GraphQL operations with descriptions
22+
- Variable descriptions that are used by the tool
23+
24+
## How Prescribed Tools Work
25+
26+
A prescribed tool is defined using the `@tool` directive with the `prescribed` argument pointing to a specific operation in a persisted document:
27+
28+
```graphql
29+
@tool(
30+
name: "weather-lookup"
31+
prescribed: "WeatherForecast"
32+
)
33+
```
34+
35+
The operation itself can include descriptions:
36+
37+
```graphql
38+
"""
39+
Get detailed weather forecast for a specific city
40+
This operation provides a multi-day weather forecast including temperature, conditions, and other meteorological data
41+
"""
42+
query WeatherForecast(
43+
"""The name of the city to get weather forecast for"""
44+
$city: String!,
45+
"""Number of days to forecast (1-7), defaults to 3 days"""
46+
$days: Int = 3
47+
) {
48+
// operation details
49+
}
50+
```
51+
52+
## MCP Tool Description
53+
54+
When deployed, this schema will expose a tool through the MCP endpoint with the following description:
55+
56+
```json
57+
{
58+
"name": "weather-lookup",
59+
"description": "Weather forecast lookup tool for cities and locations",
60+
"inputSchema": {
61+
"type": "object",
62+
"properties": {
63+
"variables": {
64+
"properties": {
65+
"city": {
66+
"description": "The name of the city to get weather forecast for",
67+
"type": "string"
68+
},
69+
"days": {
70+
"description": "Number of days to forecast (1-7), defaults to 3 days",
71+
"type": "integer",
72+
"default": 3
73+
}
74+
},
75+
"required": ["city"],
76+
"type": "object"
77+
}
78+
},
79+
"required": ["variables"]
80+
}
81+
}
82+
```
83+
84+
## Using the Tool
85+
86+
An AI model can use this tool by:
87+
88+
1. Understanding the tool's purpose from its description
89+
2. Providing the required variables (city name and optionally number of days)
90+
3. Receiving structured weather forecast data in response
91+
92+
## Benefits of Prescribed Tools with Descriptions
93+
94+
1. **Improved AI Understanding**: Detailed descriptions help AI models understand the purpose and parameters of the tool.
95+
2. **Structured Input Validation**: The GraphQL schema ensures that inputs are properly validated.
96+
3. **Documentation**: The descriptions serve as both documentation for developers and instructions for AI models.
97+
98+
## Testing
99+
100+
You can test this tool by:
101+
102+
1. Deploying the schema to StepZen using the command `stepzen deploy`
103+
2. Making requests to the MCP endpoint with tool calls
104+
3. Verifying that the tool returns properly structured weather data.
105+
106+
107+
108+
Sydney, defaults to 3 days
109+
110+
curl \
111+
--header "Authorization: Apikey $(stepzen whoami --apikey)" \
112+
--header "Content-Type: application/json" \
113+
'https://changjaeto.us-east-a.ibm.stepzen.net/api/miscellaneous/graphql?documentId=sha256:1bc7a3eefaa1f9dc0a3bbe2eba6cdcbf393aac3b1273a036b885ac1407eac11a&operationName=WeatherForecast&variables=%7B%22city%22%3A%20%22Sydney%22%7D'
114+
115+
116+
Sydney, 1 day
117+
118+
curl \
119+
--header "Authorization: Apikey $(stepzen whoami --apikey)" \
120+
--header "Content-Type: application/json" \
121+
'https://changjaeto.us-east-a.ibm.stepzen.net/api/miscellaneous/graphql?documentId=sha256:1bc7a3eefaa1f9dc0a3bbe2eba6cdcbf393aac3b1273a036b885ac1407eac11a&operationName=WeatherForecast&variables=%7B%22city%22%3A%20%22Sydney%22%2C%20%22days%22%3A%201%7D'
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
schema
2+
@sdl(
3+
files: []
4+
executables: [{ document: "operations.graphql", persist: true }]
5+
)
6+
@tool(name: "weather-lookup", prescribed: "WeatherForecast") {
7+
query: Query
8+
}
9+
10+
type Query {
11+
# Get weather forecast for a specific city
12+
weatherForecast(city: String!, days: Int = 3): WeatherForecast
13+
@value(
14+
script: {
15+
src: """
16+
function weatherForecast() {
17+
const cities = {
18+
"new york": {
19+
name: "New York",
20+
country: "United States",
21+
latitude: 40.7128,
22+
longitude: -74.0060,
23+
timezone: "America/New_York",
24+
population: 8804190
25+
},
26+
"london": {
27+
name: "London",
28+
country: "United Kingdom",
29+
latitude: 51.5074,
30+
longitude: -0.1278,
31+
timezone: "Europe/London",
32+
population: 8982000
33+
},
34+
"tokyo": {
35+
name: "Tokyo",
36+
country: "Japan",
37+
latitude: 35.6762,
38+
longitude: 139.6503,
39+
timezone: "Asia/Tokyo",
40+
population: 13960000
41+
},
42+
"sydney": {
43+
name: "Sydney",
44+
country: "Australia",
45+
latitude: -33.8688,
46+
longitude: 151.2093,
47+
timezone: "Australia/Sydney",
48+
population: 5312000
49+
}
50+
};
51+
52+
// Default to 3 days if not specified or out of range
53+
const daysToForecast = days < 1 || days > 7 ? 3 : days;
54+
55+
const normalizedCity = city.toLowerCase();
56+
const cityData = cities[normalizedCity] || {
57+
name: city,
58+
country: "Unknown",
59+
latitude: 0,
60+
longitude: 0,
61+
timezone: "UTC",
62+
population: null
63+
};
64+
65+
// Fixed forecast patterns for each city
66+
const forecastPatterns = {
67+
"new york": [
68+
{ conditions: "Partly Cloudy", high: 22, low: 15, precipitation: 20, humidity: 65, windSpeed: 12, windDirection: "NW" },
69+
{ conditions: "Sunny", high: 24, low: 16, precipitation: 5, humidity: 55, windSpeed: 8, windDirection: "W" },
70+
{ conditions: "Cloudy", high: 20, low: 14, precipitation: 30, humidity: 70, windSpeed: 15, windDirection: "NE" },
71+
{ conditions: "Rain", high: 18, low: 12, precipitation: 75, humidity: 85, windSpeed: 18, windDirection: "E" },
72+
{ conditions: "Partly Cloudy", high: 23, low: 16, precipitation: 15, humidity: 60, windSpeed: 10, windDirection: "SW" },
73+
{ conditions: "Sunny", high: 25, low: 17, precipitation: 0, humidity: 50, windSpeed: 7, windDirection: "W" },
74+
{ conditions: "Thunderstorm", high: 21, low: 15, precipitation: 90, humidity: 90, windSpeed: 25, windDirection: "S" }
75+
],
76+
"london": [
77+
{ conditions: "Cloudy", high: 16, low: 10, precipitation: 40, humidity: 75, windSpeed: 14, windDirection: "SW" },
78+
{ conditions: "Rain", high: 15, low: 9, precipitation: 65, humidity: 80, windSpeed: 16, windDirection: "W" },
79+
{ conditions: "Partly Cloudy", high: 17, low: 11, precipitation: 25, humidity: 70, windSpeed: 12, windDirection: "NW" },
80+
{ conditions: "Cloudy", high: 16, low: 10, precipitation: 35, humidity: 75, windSpeed: 13, windDirection: "SW" },
81+
{ conditions: "Rain", high: 14, low: 8, precipitation: 70, humidity: 85, windSpeed: 18, windDirection: "W" },
82+
{ conditions: "Partly Cloudy", high: 18, low: 12, precipitation: 20, humidity: 65, windSpeed: 11, windDirection: "NW" },
83+
{ conditions: "Sunny", high: 19, low: 13, precipitation: 10, humidity: 60, windSpeed: 9, windDirection: "N" }
84+
],
85+
"tokyo": [
86+
{ conditions: "Sunny", high: 26, low: 19, precipitation: 5, humidity: 60, windSpeed: 10, windDirection: "E" },
87+
{ conditions: "Partly Cloudy", high: 25, low: 18, precipitation: 15, humidity: 65, windSpeed: 12, windDirection: "SE" },
88+
{ conditions: "Cloudy", high: 23, low: 17, precipitation: 30, humidity: 70, windSpeed: 14, windDirection: "S" },
89+
{ conditions: "Rain", high: 22, low: 16, precipitation: 60, humidity: 80, windSpeed: 16, windDirection: "SW" },
90+
{ conditions: "Partly Cloudy", high: 24, low: 18, precipitation: 20, humidity: 65, windSpeed: 11, windDirection: "E" },
91+
{ conditions: "Sunny", high: 27, low: 20, precipitation: 5, humidity: 55, windSpeed: 9, windDirection: "NE" },
92+
{ conditions: "Cloudy", high: 24, low: 18, precipitation: 25, humidity: 68, windSpeed: 13, windDirection: "SE" }
93+
],
94+
"sydney": [
95+
{ conditions: "Sunny", high: 28, low: 20, precipitation: 10, humidity: 60, windSpeed: 15, windDirection: "NE" },
96+
{ conditions: "Partly Cloudy", high: 27, low: 19, precipitation: 15, humidity: 65, windSpeed: 14, windDirection: "E" },
97+
{ conditions: "Sunny", high: 29, low: 21, precipitation: 5, humidity: 55, windSpeed: 13, windDirection: "NE" },
98+
{ conditions: "Partly Cloudy", high: 26, low: 19, precipitation: 20, humidity: 70, windSpeed: 16, windDirection: "SE" },
99+
{ conditions: "Cloudy", high: 24, low: 18, precipitation: 35, humidity: 75, windSpeed: 18, windDirection: "S" },
100+
{ conditions: "Rain", high: 22, low: 17, precipitation: 70, humidity: 85, windSpeed: 20, windDirection: "SW" },
101+
{ conditions: "Partly Cloudy", high: 25, low: 18, precipitation: 25, humidity: 70, windDirection: "W", windSpeed: 17 }
102+
]
103+
};
104+
105+
// Get pattern for city or use default
106+
const pattern = forecastPatterns[normalizedCity] || forecastPatterns["new york"];
107+
108+
// Generate forecast for the requested number of days
109+
const forecast = [];
110+
const today = new Date();
111+
112+
for (let i = 0; i < daysToForecast; i++) {
113+
const forecastDate = new Date();
114+
forecastDate.setDate(today.getDate() + i);
115+
116+
const dayPattern = pattern[i % pattern.length];
117+
118+
forecast.push({
119+
date: forecastDate.toISOString().split('T')[0],
120+
sunrise: "06:25 AM",
121+
sunset: "06:35 PM",
122+
high: {
123+
celsius: dayPattern.high,
124+
fahrenheit: Math.round(dayPattern.high * 9 / 5 + 32)
125+
},
126+
low: {
127+
celsius: dayPattern.low,
128+
fahrenheit: Math.round(dayPattern.low * 9 / 5 + 32)
129+
},
130+
conditions: dayPattern.conditions,
131+
precipitation: dayPattern.precipitation,
132+
humidity: dayPattern.humidity,
133+
windSpeed: dayPattern.windSpeed,
134+
windDirection: dayPattern.windDirection
135+
});
136+
}
137+
138+
return {
139+
city: cityData,
140+
forecast: forecast,
141+
};
142+
}
143+
weatherForecast()
144+
"""
145+
}
146+
)
147+
}
148+
149+
type WeatherForecast {
150+
city: City!
151+
forecast: [DailyForecast!]!
152+
lastUpdated: DateTime
153+
}
154+
155+
type City {
156+
name: String!
157+
country: String!
158+
latitude: Float!
159+
longitude: Float!
160+
timezone: String!
161+
population: Int
162+
}
163+
164+
type DailyForecast {
165+
date: Date!
166+
sunrise: String!
167+
sunset: String!
168+
high: Temperature!
169+
low: Temperature!
170+
conditions: String!
171+
precipitation: Float!
172+
humidity: Int!
173+
windSpeed: Float!
174+
windDirection: String!
175+
}
176+
177+
type Temperature {
178+
celsius: Float!
179+
fahrenheit: Float!
180+
}
181+
182+
scalar Date
183+
scalar DateTime
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
Get detailed weather forecast for a specific city
3+
This operation provides a multi-day weather forecast including temperature, conditions, and other meteorological data
4+
"""
5+
query WeatherForecast(
6+
"""The name of the city to get weather forecast for"""
7+
$city: String!,
8+
"""Number of days to forecast (1-7), defaults to 3 days"""
9+
$days: Int = 3
10+
) {
11+
weatherForecast(city: $city, days: $days) {
12+
city {
13+
name
14+
country
15+
timezone
16+
}
17+
forecast {
18+
date
19+
high {
20+
celsius
21+
fahrenheit
22+
}
23+
low {
24+
celsius
25+
fahrenheit
26+
}
27+
conditions
28+
precipitation
29+
humidity
30+
windSpeed
31+
windDirection
32+
}
33+
}
34+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"endpoint": "api/miscellaneous"
3+
}

0 commit comments

Comments
 (0)