Skip to content

Commit 144aa49

Browse files
Set explicit ReadOnlyHint, DestructiveHint, and OpenWorldHint on all tools (#63)
OpenAI's verification process defaults omitted annotations to destructive, causing most tools to be flagged incorrectly. This adds explicit values for all three hints across all 25 tools. GitOrigin-RevId: bb9e8ad029266240f5e5f27cd092c3168d9f1f22
1 parent 7af461e commit 144aa49

7 files changed

Lines changed: 113 additions & 85 deletions

File tree

pkg/deploy/tools.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ func listDeploys(deployRepo *Repo) server.ServerTool {
2525
Tool: mcp.NewTool("list_deploys",
2626
mcp.WithDescription("List deploys matching the provided filters. If no filters are provided, all deploys for the service are returned."),
2727
mcp.WithToolAnnotation(mcp.ToolAnnotation{
28-
Title: "List deploys",
29-
ReadOnlyHint: pointers.From(true),
30-
IdempotentHint: pointers.From(true),
31-
OpenWorldHint: pointers.From(true),
28+
Title: "List deploys",
29+
ReadOnlyHint: pointers.From(true),
30+
DestructiveHint: pointers.From(false),
31+
IdempotentHint: pointers.From(true),
32+
OpenWorldHint: pointers.From(true),
3233
}),
3334
mcp.WithString("serviceId",
3435
mcp.Required(),
@@ -95,10 +96,11 @@ func getDeploy(deployRepo *Repo) server.ServerTool {
9596
Tool: mcp.NewTool("get_deploy",
9697
mcp.WithDescription("Retrieve the details of a particular deploy for a particular service."),
9798
mcp.WithToolAnnotation(mcp.ToolAnnotation{
98-
Title: "Get deploy details",
99-
ReadOnlyHint: pointers.From(true),
100-
IdempotentHint: pointers.From(true),
101-
OpenWorldHint: pointers.From(true),
99+
Title: "Get deploy details",
100+
ReadOnlyHint: pointers.From(true),
101+
DestructiveHint: pointers.From(false),
102+
IdempotentHint: pointers.From(true),
103+
OpenWorldHint: pointers.From(true),
102104
}),
103105
mcp.WithString("serviceId",
104106
mcp.Required(),

pkg/keyvalue/tools.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ func listKeyValue(keyValueRepo *Repo) server.ServerTool {
2828
Tool: mcp.NewTool("list_key_value",
2929
mcp.WithDescription("List all Key Value instances in your Render account"),
3030
mcp.WithToolAnnotation(mcp.ToolAnnotation{
31-
Title: "List Key Value instances",
32-
ReadOnlyHint: pointers.From(true),
33-
IdempotentHint: pointers.From(true),
34-
OpenWorldHint: pointers.From(true),
31+
Title: "List Key Value instances",
32+
ReadOnlyHint: pointers.From(true),
33+
DestructiveHint: pointers.From(false),
34+
IdempotentHint: pointers.From(true),
35+
OpenWorldHint: pointers.From(true),
3536
}),
3637
),
3738
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
@@ -59,10 +60,11 @@ func getKeyValue(keyValueRepo *Repo) server.ServerTool {
5960
Tool: mcp.NewTool("get_key_value",
6061
mcp.WithDescription("Retrieve a Key Value instance by ID"),
6162
mcp.WithToolAnnotation(mcp.ToolAnnotation{
62-
Title: "Get Key Value instance details",
63-
ReadOnlyHint: pointers.From(true),
64-
IdempotentHint: pointers.From(true),
65-
OpenWorldHint: pointers.From(true),
63+
Title: "Get Key Value instance details",
64+
ReadOnlyHint: pointers.From(true),
65+
DestructiveHint: pointers.From(false),
66+
IdempotentHint: pointers.From(true),
67+
OpenWorldHint: pointers.From(true),
6668
}),
6769
mcp.WithString("keyValueId",
6870
mcp.Required(),
@@ -95,10 +97,11 @@ func createKeyValue(keyValueRepo *Repo) server.ServerTool {
9597
Tool: mcp.NewTool("create_key_value",
9698
mcp.WithDescription("Create a new Key Value instance in your Render account"),
9799
mcp.WithToolAnnotation(mcp.ToolAnnotation{
98-
Title: "Create Key Value instance",
99-
ReadOnlyHint: pointers.From(false),
100-
IdempotentHint: pointers.From(false),
101-
OpenWorldHint: pointers.From(true),
100+
Title: "Create Key Value instance",
101+
ReadOnlyHint: pointers.From(false),
102+
DestructiveHint: pointers.From(false),
103+
IdempotentHint: pointers.From(false),
104+
OpenWorldHint: pointers.From(true),
102105
}),
103106
mcp.WithString("name",
104107
mcp.Required(),

pkg/logs/tools.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ func listLogs(logRepo *LogRepo) server.ServerTool {
3232
"Provide the nextStartTime and nextEndTime timestamps as the startTime and endTime query parameters to fetch the next page of logs. "+
3333
"You can query for logs across multiple resources, but all resources must be in the same region and belong to the same owner."),
3434
mcp.WithToolAnnotation(mcp.ToolAnnotation{
35-
Title: "List logs",
36-
ReadOnlyHint: pointers.From(true),
37-
IdempotentHint: pointers.From(true),
38-
OpenWorldHint: pointers.From(true),
35+
Title: "List logs",
36+
ReadOnlyHint: pointers.From(true),
37+
DestructiveHint: pointers.From(false),
38+
IdempotentHint: pointers.From(true),
39+
OpenWorldHint: pointers.From(true),
3940
}),
4041
mcp.WithArray("resource",
4142
mcp.Required(),
@@ -237,10 +238,11 @@ func listLogLabelValues(logRepo *LogRepo) server.ServerTool {
237238
"You can query for logs across multiple resources, but all resources must be in the same region and belong to the same owner.",
238239
),
239240
mcp.WithToolAnnotation(mcp.ToolAnnotation{
240-
Title: "List log label values",
241-
ReadOnlyHint: pointers.From(true),
242-
IdempotentHint: pointers.From(true),
243-
OpenWorldHint: pointers.From(true),
241+
Title: "List log label values",
242+
ReadOnlyHint: pointers.From(true),
243+
DestructiveHint: pointers.From(false),
244+
IdempotentHint: pointers.From(true),
245+
OpenWorldHint: pointers.From(true),
244246
}),
245247
mcp.WithString("label",
246248
mcp.Required(),

pkg/metrics/tools.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ func getMetrics(metricsRepo *Repo) server.ServerTool {
3232
"Limits and targets help understand resource constraints and autoscaling thresholds. "+
3333
"Metrics may be empty if the metric is not valid for the given resource."),
3434
mcp.WithToolAnnotation(mcp.ToolAnnotation{
35-
Title: "Get resource metrics",
36-
ReadOnlyHint: pointers.From(true),
37-
OpenWorldHint: pointers.From(true),
35+
Title: "Get resource metrics",
36+
ReadOnlyHint: pointers.From(true),
37+
DestructiveHint: pointers.From(false),
38+
OpenWorldHint: pointers.From(true),
3839
}),
3940
mcp.WithString("resourceId",
4041
mcp.Required(),

pkg/owner/tools.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ func listWorkspaces(ownerRepo *Repo) server.ServerTool {
2828
Tool: mcp.NewTool("list_workspaces",
2929
mcp.WithDescription("List the workspaces that you have access to"),
3030
mcp.WithToolAnnotation(mcp.ToolAnnotation{
31-
Title: "List workspaces",
32-
ReadOnlyHint: pointers.From(true),
33-
IdempotentHint: pointers.From(true),
34-
OpenWorldHint: pointers.From(true),
31+
Title: "List workspaces",
32+
ReadOnlyHint: pointers.From(true),
33+
DestructiveHint: pointers.From(false),
34+
IdempotentHint: pointers.From(true),
35+
OpenWorldHint: pointers.From(true),
3536
}),
3637
),
3738
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
@@ -69,9 +70,11 @@ func selectWorkspace() server.ServerTool {
6970
"as part of an automated process. Having the wrong workspace selected can lead to "+
7071
"destructive actions being performed on unintended resources."),
7172
mcp.WithToolAnnotation(mcp.ToolAnnotation{
72-
Title: "Select workspace",
73-
IdempotentHint: pointers.From(true),
74-
OpenWorldHint: pointers.From(true),
73+
Title: "Select workspace",
74+
ReadOnlyHint: pointers.From(false),
75+
DestructiveHint: pointers.From(false),
76+
IdempotentHint: pointers.From(true),
77+
OpenWorldHint: pointers.From(true),
7578
}),
7679
mcp.WithString("ownerID",
7780
mcp.Required(),
@@ -99,10 +102,11 @@ func getSelectedWorkspace() server.ServerTool {
99102
Tool: mcp.NewTool("get_selected_workspace",
100103
mcp.WithDescription("Get the currently selected workspace"),
101104
mcp.WithToolAnnotation(mcp.ToolAnnotation{
102-
Title: "Get selected workspace",
103-
ReadOnlyHint: pointers.From(true),
104-
IdempotentHint: pointers.From(true),
105-
OpenWorldHint: pointers.From(true),
105+
Title: "Get selected workspace",
106+
ReadOnlyHint: pointers.From(true),
107+
DestructiveHint: pointers.From(false),
108+
IdempotentHint: pointers.From(true),
109+
OpenWorldHint: pointers.From(true),
106110
}),
107111
),
108112
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {

pkg/postgres/tools.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ func listPostgresInstances(postgresRepo *Repo) server.ServerTool {
3232
Tool: mcp.NewTool("list_postgres_instances",
3333
mcp.WithDescription("List all Postgres databases in your Render account"),
3434
mcp.WithToolAnnotation(mcp.ToolAnnotation{
35-
Title: "List Postgres instances",
36-
ReadOnlyHint: pointers.From(true),
37-
IdempotentHint: pointers.From(true),
38-
OpenWorldHint: pointers.From(true),
35+
Title: "List Postgres instances",
36+
ReadOnlyHint: pointers.From(true),
37+
DestructiveHint: pointers.From(false),
38+
IdempotentHint: pointers.From(true),
39+
OpenWorldHint: pointers.From(true),
3940
}),
4041
),
4142
Handler: func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
@@ -63,10 +64,11 @@ func getPostgres(postgresRepo *Repo) server.ServerTool {
6364
Tool: mcp.NewTool("get_postgres",
6465
mcp.WithDescription("Retrieve a Postgres instance by ID"),
6566
mcp.WithToolAnnotation(mcp.ToolAnnotation{
66-
Title: "Get Postgres instance details",
67-
ReadOnlyHint: pointers.From(true),
68-
IdempotentHint: pointers.From(true),
69-
OpenWorldHint: pointers.From(true),
67+
Title: "Get Postgres instance details",
68+
ReadOnlyHint: pointers.From(true),
69+
DestructiveHint: pointers.From(false),
70+
IdempotentHint: pointers.From(true),
71+
OpenWorldHint: pointers.From(true),
7072
}),
7173
mcp.WithString("postgresId",
7274
mcp.Required(),
@@ -99,10 +101,11 @@ func createPostgres(postgresRepo *Repo) server.ServerTool {
99101
Tool: mcp.NewTool("create_postgres",
100102
mcp.WithDescription("Create a new Postgres instance in your Render account"),
101103
mcp.WithToolAnnotation(mcp.ToolAnnotation{
102-
Title: "Create Postgres instance",
103-
ReadOnlyHint: pointers.From(false),
104-
IdempotentHint: pointers.From(false),
105-
OpenWorldHint: pointers.From(true),
104+
Title: "Create Postgres instance",
105+
ReadOnlyHint: pointers.From(false),
106+
DestructiveHint: pointers.From(false),
107+
IdempotentHint: pointers.From(false),
108+
OpenWorldHint: pointers.From(true),
106109
}),
107110
mcp.WithString("name",
108111
mcp.Required(),
@@ -203,10 +206,11 @@ func queryPostgres(postgresRepo *Repo) server.ServerTool {
203206
mcp.WithDescription("Run a read-only SQL query against a Render-hosted Postgres database. "+
204207
"This tool creates a new connection for each query and closes it after the query completes."),
205208
mcp.WithToolAnnotation(mcp.ToolAnnotation{
206-
Title: "Query Postgres",
207-
ReadOnlyHint: pointers.From(true),
208-
IdempotentHint: pointers.From(true),
209-
OpenWorldHint: pointers.From(true),
209+
Title: "Query Postgres",
210+
ReadOnlyHint: pointers.From(true),
211+
DestructiveHint: pointers.From(false),
212+
IdempotentHint: pointers.From(true),
213+
OpenWorldHint: pointers.From(true),
210214
}),
211215
mcp.WithString("postgresId",
212216
mcp.Required(),

pkg/service/tools.go

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ func listServices(serviceRepo *Repo) server.ServerTool {
3535
Tool: mcp.NewTool("list_services",
3636
mcp.WithDescription("List all services in your Render account"),
3737
mcp.WithToolAnnotation(mcp.ToolAnnotation{
38-
Title: "List services",
39-
ReadOnlyHint: pointers.From(true),
40-
OpenWorldHint: pointers.From(true),
38+
Title: "List services",
39+
ReadOnlyHint: pointers.From(true),
40+
DestructiveHint: pointers.From(false),
41+
OpenWorldHint: pointers.From(true),
4142
}),
4243
mcp.WithBoolean("includePreviews",
4344
mcp.Description("Whether to include preview services in the response. Defaults to false."),
@@ -73,9 +74,10 @@ func getService(serviceRepo *Repo) server.ServerTool {
7374
Tool: mcp.NewTool("get_service",
7475
mcp.WithDescription("Get details about a specific service"),
7576
mcp.WithToolAnnotation(mcp.ToolAnnotation{
76-
Title: "Get service details",
77-
ReadOnlyHint: pointers.From(true),
78-
OpenWorldHint: pointers.From(true),
77+
Title: "Get service details",
78+
ReadOnlyHint: pointers.From(true),
79+
DestructiveHint: pointers.From(false),
80+
OpenWorldHint: pointers.From(true),
7981
}),
8082
mcp.WithString("serviceId",
8183
mcp.Required(),
@@ -114,10 +116,11 @@ func createWebService(serviceRepo *Repo) server.ServerTool {
114116
"It also only supports web services which don't use Docker, or a container registry."+
115117
"To create a service without those limitations, please use the dashboard at: "+config.DashboardURL()+"/web/new"),
116118
mcp.WithToolAnnotation(mcp.ToolAnnotation{
117-
Title: "Create web service",
118-
ReadOnlyHint: pointers.From(false),
119-
IdempotentHint: pointers.From(false),
120-
OpenWorldHint: pointers.From(true),
119+
Title: "Create web service",
120+
ReadOnlyHint: pointers.From(false),
121+
DestructiveHint: pointers.From(false),
122+
IdempotentHint: pointers.From(false),
123+
OpenWorldHint: pointers.From(true),
121124
}),
122125
mcp.WithString("name",
123126
mcp.Required(),
@@ -310,10 +313,11 @@ func createStaticSite(serviceRepo *Repo) server.ServerTool {
310313
"This tool is currently limited to support only a subset of the static site configuration parameters."+
311314
"To create a static site without those limitations, please use the dashboard at: "+config.DashboardURL()+"/static/new"),
312315
mcp.WithToolAnnotation(mcp.ToolAnnotation{
313-
Title: "Create static site",
314-
ReadOnlyHint: pointers.From(false),
315-
IdempotentHint: pointers.From(false),
316-
OpenWorldHint: pointers.From(true),
316+
Title: "Create static site",
317+
ReadOnlyHint: pointers.From(false),
318+
DestructiveHint: pointers.From(false),
319+
IdempotentHint: pointers.From(false),
320+
OpenWorldHint: pointers.From(true),
317321
}),
318322
mcp.WithString("name",
319323
mcp.Required(),
@@ -415,10 +419,11 @@ func createCronJob(serviceRepo *Repo) server.ServerTool {
415419
"It also only supports cron jobs which don't use Docker, or a container registry. "+
416420
"To create a cron job without those limitations, please use the dashboard at: "+config.DashboardURL()+"/create"),
417421
mcp.WithToolAnnotation(mcp.ToolAnnotation{
418-
Title: "Create cron job",
419-
ReadOnlyHint: pointers.From(false),
420-
IdempotentHint: pointers.From(false),
421-
OpenWorldHint: pointers.From(true),
422+
Title: "Create cron job",
423+
ReadOnlyHint: pointers.From(false),
424+
DestructiveHint: pointers.From(false),
425+
IdempotentHint: pointers.From(false),
426+
OpenWorldHint: pointers.From(true),
422427
}),
423428
mcp.WithString("name",
424429
mcp.Required(),
@@ -589,9 +594,11 @@ func updateWebService() server.ServerTool {
589594
Tool: mcp.NewTool("update_web_service",
590595
mcp.WithDescription("Update an existing web service in your Render account."),
591596
mcp.WithToolAnnotation(mcp.ToolAnnotation{
592-
Title: "Update web service",
593-
ReadOnlyHint: pointers.From(true),
594-
IdempotentHint: pointers.From(true),
597+
Title: "Update web service",
598+
ReadOnlyHint: pointers.From(true),
599+
DestructiveHint: pointers.From(false),
600+
IdempotentHint: pointers.From(true),
601+
OpenWorldHint: pointers.From(false),
595602
}),
596603
mcp.WithString("serviceId",
597604
mcp.Required(),
@@ -617,9 +624,11 @@ func updateStaticSite() server.ServerTool {
617624
Tool: mcp.NewTool("update_static_site",
618625
mcp.WithDescription("Update an existing static site in your Render account."),
619626
mcp.WithToolAnnotation(mcp.ToolAnnotation{
620-
Title: "Update static site",
621-
ReadOnlyHint: pointers.From(true),
622-
IdempotentHint: pointers.From(true),
627+
Title: "Update static site",
628+
ReadOnlyHint: pointers.From(true),
629+
DestructiveHint: pointers.From(false),
630+
IdempotentHint: pointers.From(true),
631+
OpenWorldHint: pointers.From(false),
623632
}),
624633
mcp.WithString("serviceId",
625634
mcp.Required(),
@@ -645,9 +654,11 @@ func updateCronJob() server.ServerTool {
645654
Tool: mcp.NewTool("update_cron_job",
646655
mcp.WithDescription("Update an existing cron job in your Render account."),
647656
mcp.WithToolAnnotation(mcp.ToolAnnotation{
648-
Title: "Update cron job",
649-
ReadOnlyHint: pointers.From(true),
650-
IdempotentHint: pointers.From(true),
657+
Title: "Update cron job",
658+
ReadOnlyHint: pointers.From(true),
659+
DestructiveHint: pointers.From(false),
660+
IdempotentHint: pointers.From(true),
661+
OpenWorldHint: pointers.From(false),
651662
}),
652663
mcp.WithString("serviceId",
653664
mcp.Required(),
@@ -678,6 +689,7 @@ func updateEnvVars(serviceRepo *Repo) server.ServerTool {
678689
"To replace all existing environment variables, set the 'replace' parameter to 'true'."),
679690
mcp.WithToolAnnotation(mcp.ToolAnnotation{
680691
Title: "Update environment variables",
692+
ReadOnlyHint: pointers.From(false),
681693
DestructiveHint: pointers.From(true),
682694
OpenWorldHint: pointers.From(true),
683695
}),

0 commit comments

Comments
 (0)