|
| 1 | +--- |
| 2 | +title: "Tool annotations" |
| 3 | +description: "Add behavior hints to Gram Functions so AI models and clients can make better decisions about tool invocation." |
| 4 | +--- |
| 5 | + |
| 6 | +## What are tool annotations? |
| 7 | + |
| 8 | +In the [Model Context Protocol](https://modelcontextprotocol.io/docs/concepts/tools#tool-annotations), tools are model-controlled primitives that let AI models invoke server-side functionality. While tool names, descriptions, and input schemas tell a model *what* a tool does, annotations tell clients *how* the tool behaves — whether it reads or writes data, whether it's destructive, and whether it reaches out to external systems. |
| 9 | + |
| 10 | +This matters because MCP clients use annotations to build safer, more intuitive interfaces. A client might auto-approve a tool marked as read-only, require confirmation for destructive operations, or batch idempotent calls without worry. Without annotations, clients have to assume the worst — that every tool is potentially destructive and open-world. |
| 11 | + |
| 12 | +The Gram Functions Framework supports MCP tool annotations directly in tool definitions. Add annotations to any tool using the `annotations` property: |
| 13 | + |
| 14 | +```typescript |
| 15 | +import { Gram } from "@gram-ai/functions"; |
| 16 | +import * as z from "zod/mini"; |
| 17 | + |
| 18 | +const gram = new Gram().tool({ |
| 19 | + name: "delete_user", |
| 20 | + description: "Permanently delete a user account", |
| 21 | + inputSchema: { userId: z.string() }, |
| 22 | + annotations: { |
| 23 | + title: "Delete User", |
| 24 | + destructiveHint: true, |
| 25 | + readOnlyHint: false, |
| 26 | + idempotentHint: true, |
| 27 | + openWorldHint: false, |
| 28 | + }, |
| 29 | + async execute(ctx, input) { |
| 30 | + await deleteUser(input.userId); |
| 31 | + return ctx.json({ deleted: true }); |
| 32 | + }, |
| 33 | +}); |
| 34 | + |
| 35 | +export default gram; |
| 36 | +``` |
| 37 | + |
| 38 | +## Available fields |
| 39 | + |
| 40 | +| Field | Type | Default | Description | |
| 41 | +| --- | --- | --- | --- | |
| 42 | +| `title` | `string` | — | Human-readable display name for the tool | |
| 43 | +| `readOnlyHint` | `boolean` | `false` | Tool does not modify its environment | |
| 44 | +| `destructiveHint` | `boolean` | `true` | Tool may perform destructive updates | |
| 45 | +| `idempotentHint` | `boolean` | `false` | Repeated calls with the same arguments have no additional effect | |
| 46 | +| `openWorldHint` | `boolean` | `true` | Tool interacts with external entities | |
| 47 | + |
| 48 | +All annotation properties are **hints**. They are not guaranteed to be accurate, and clients should not rely on them for security decisions. |
| 49 | + |
| 50 | +## Default behavior |
| 51 | + |
| 52 | +When no annotations are specified, Gram applies conservative defaults: tools are assumed to be potentially destructive and open-world. Specify annotations explicitly to give clients more accurate information about tool behavior. |
| 53 | + |
| 54 | +```typescript |
| 55 | +// A read-only tool that only queries data |
| 56 | +const gram = new Gram().tool({ |
| 57 | + name: "get_weather", |
| 58 | + description: "Get current weather for a city", |
| 59 | + inputSchema: { city: z.string() }, |
| 60 | + annotations: { |
| 61 | + readOnlyHint: true, |
| 62 | + destructiveHint: false, |
| 63 | + openWorldHint: true, |
| 64 | + }, |
| 65 | + async execute(ctx, input) { |
| 66 | + const weather = await fetchWeather(input.city); |
| 67 | + return ctx.json(weather); |
| 68 | + }, |
| 69 | +}); |
| 70 | +``` |
| 71 | + |
| 72 | +## Annotations with MCP SDK passthrough |
| 73 | + |
| 74 | +Annotations defined on Gram Functions are automatically forwarded when tools are exposed through MCP servers. No additional configuration is needed — the annotations set in the tool definition are passed through to MCP clients as part of the tool listing. |
| 75 | + |
| 76 | +## Next steps |
| 77 | + |
| 78 | +- Learn more about the [Functions Framework](/docs/mcp/build/gram-functions/functions-framework) |
| 79 | +- [Build and deploy](/docs/mcp/build/gram-functions/build-deploy) Gram Functions |
0 commit comments