Skip to content

Commit 1035645

Browse files
Simplify MCP tool wait behavior/parameters (#119)
1 parent 6988f3a commit 1035645

File tree

2 files changed

+37
-82
lines changed

2 files changed

+37
-82
lines changed

internal/tiger/mcp/service_tools.go

Lines changed: 33 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ const (
2424
serviceTypeVector = "VECTOR"
2525
)
2626

27+
// Wait timeout for MCP tool operations
28+
const waitTimeout = 10 * time.Minute
29+
2730
// validServiceTypes returns a slice of all valid service type values
2831
func validServiceTypes() []string {
2932
return []string{
@@ -134,15 +137,14 @@ func (ServiceDetail) Schema() *jsonschema.Schema {
134137

135138
// ServiceCreateInput represents input for service_create
136139
type ServiceCreateInput struct {
137-
Name string `json:"name,omitempty"`
138-
Addons []string `json:"addons,omitempty"`
139-
Region *string `json:"region,omitempty"`
140-
CPUMemory string `json:"cpu_memory,omitempty"`
141-
Replicas int `json:"replicas,omitempty"`
142-
Wait bool `json:"wait,omitempty"`
143-
TimeoutMinutes int `json:"timeout_minutes,omitempty"`
144-
SetDefault bool `json:"set_default,omitempty"`
145-
WithPassword bool `json:"with_password,omitempty"`
140+
Name string `json:"name,omitempty"`
141+
Addons []string `json:"addons,omitempty"`
142+
Region *string `json:"region,omitempty"`
143+
CPUMemory string `json:"cpu_memory,omitempty"`
144+
Replicas int `json:"replicas,omitempty"`
145+
Wait bool `json:"wait,omitempty"`
146+
SetDefault bool `json:"set_default,omitempty"`
147+
WithPassword bool `json:"with_password,omitempty"`
146148
}
147149

148150
func (ServiceCreateInput) Schema() *jsonschema.Schema {
@@ -167,15 +169,10 @@ func (ServiceCreateInput) Schema() *jsonschema.Schema {
167169
schema.Properties["replicas"].Default = util.Must(json.Marshal(0))
168170
schema.Properties["replicas"].Examples = []any{0, 1, 2}
169171

170-
schema.Properties["wait"].Description = "Whether to wait for the service to be fully ready before returning. Default is false and is recommended because service creation can take a few minutes and it's usually better to return immediately. ONLY set to true if the user explicitly needs to use the service immediately to continue the same conversation."
172+
schema.Properties["wait"].Description = "Whether to wait for the service to be fully ready before returning. Default is false (recommended). Only set to true if your next steps require connecting to or querying this database. When true, waits up to 10 minutes."
171173
schema.Properties["wait"].Default = util.Must(json.Marshal(false))
172174
schema.Properties["wait"].Examples = []any{false, true}
173175

174-
schema.Properties["timeout_minutes"].Description = "Timeout in minutes when waiting for service to be ready. Only used when 'wait' is true."
175-
schema.Properties["timeout_minutes"].Minimum = util.Ptr(0.0)
176-
schema.Properties["timeout_minutes"].Default = util.Must(json.Marshal(30))
177-
schema.Properties["timeout_minutes"].Examples = []any{15, 30, 60}
178-
179176
schema.Properties["set_default"].Description = "Whether to set the newly created service as the default service. When true, the service will be set as the default for future commands."
180177
schema.Properties["set_default"].Default = util.Must(json.Marshal(true))
181178
schema.Properties["set_default"].Examples = []any{true, false}
@@ -198,15 +195,14 @@ func (ServiceCreateOutput) Schema() *jsonschema.Schema {
198195

199196
// ServiceForkInput represents input for service_fork
200197
type ServiceForkInput struct {
201-
ServiceID string `json:"service_id"`
202-
Name string `json:"name,omitempty"`
203-
ForkStrategy api.ForkStrategy `json:"fork_strategy"`
204-
TargetTime *time.Time `json:"target_time,omitempty"`
205-
CPUMemory string `json:"cpu_memory,omitempty"`
206-
Wait bool `json:"wait,omitempty"`
207-
TimeoutMinutes int `json:"timeout_minutes,omitempty"`
208-
SetDefault bool `json:"set_default,omitempty"`
209-
WithPassword bool `json:"with_password,omitempty"`
198+
ServiceID string `json:"service_id"`
199+
Name string `json:"name,omitempty"`
200+
ForkStrategy api.ForkStrategy `json:"fork_strategy"`
201+
TargetTime *time.Time `json:"target_time,omitempty"`
202+
CPUMemory string `json:"cpu_memory,omitempty"`
203+
Wait bool `json:"wait,omitempty"`
204+
SetDefault bool `json:"set_default,omitempty"`
205+
WithPassword bool `json:"with_password,omitempty"`
210206
}
211207

212208
func (ServiceForkInput) Schema() *jsonschema.Schema {
@@ -227,15 +223,10 @@ func (ServiceForkInput) Schema() *jsonschema.Schema {
227223
schema.Properties["cpu_memory"].Description = "CPU and memory allocation combination. Choose from the available configurations. If not specified, inherits from source service."
228224
schema.Properties["cpu_memory"].Enum = util.AnySlice(common.GetAllowedCPUMemoryConfigs().Strings())
229225

230-
schema.Properties["wait"].Description = "Whether to wait for the forked service to be fully ready before returning. Default is false and is recommended because forking can take several minutes. ONLY set to true if the user explicitly needs to use the forked service immediately to continue the same conversation."
226+
schema.Properties["wait"].Description = "Whether to wait for the forked service to be fully ready before returning. Default is false (recommended). Only set to true if your next steps require connecting to or querying this database. When true, waits up to 10 minutes."
231227
schema.Properties["wait"].Default = util.Must(json.Marshal(false))
232228
schema.Properties["wait"].Examples = []any{false, true}
233229

234-
schema.Properties["timeout_minutes"].Description = "Timeout in minutes when waiting for forked service to be ready. Only used when 'wait' is true."
235-
schema.Properties["timeout_minutes"].Minimum = util.Ptr(0.0)
236-
schema.Properties["timeout_minutes"].Default = util.Must(json.Marshal(30))
237-
schema.Properties["timeout_minutes"].Examples = []any{15, 30, 60}
238-
239230
schema.Properties["set_default"].Description = "Whether to set the newly forked service as the default service. When true, the forked service will be set as the default for future commands."
240231
schema.Properties["set_default"].Default = util.Must(json.Marshal(true))
241232
schema.Properties["set_default"].Examples = []any{true, false}
@@ -285,25 +276,19 @@ func (ServiceUpdatePasswordOutput) Schema() *jsonschema.Schema {
285276

286277
// ServiceStartInput represents input for service_start
287278
type ServiceStartInput struct {
288-
ServiceID string `json:"service_id"`
289-
Wait bool `json:"wait,omitempty"`
290-
TimeoutMinutes int `json:"timeout_minutes,omitempty"`
279+
ServiceID string `json:"service_id"`
280+
Wait bool `json:"wait,omitempty"`
291281
}
292282

293283
func (ServiceStartInput) Schema() *jsonschema.Schema {
294284
schema := util.Must(jsonschema.For[ServiceStartInput](nil))
295285

296286
setServiceIDSchemaProperties(schema)
297287

298-
schema.Properties["wait"].Description = "Whether to wait for the service to be fully started before returning. Default is false and is recommended because starting can take several minutes. ONLY set to true if the user explicitly needs to use the service immediately to continue the same conversation."
288+
schema.Properties["wait"].Description = "Whether to wait for the service to be fully started before returning. Default is false (recommended). Only set to true if your next steps require connecting to or querying this database. When true, waits up to 10 minutes."
299289
schema.Properties["wait"].Default = util.Must(json.Marshal(false))
300290
schema.Properties["wait"].Examples = []any{false, true}
301291

302-
schema.Properties["timeout_minutes"].Description = "Timeout in minutes when waiting for service to start. Only used when 'wait' is true."
303-
schema.Properties["timeout_minutes"].Minimum = util.Ptr(0.0)
304-
schema.Properties["timeout_minutes"].Default = util.Must(json.Marshal(10))
305-
schema.Properties["timeout_minutes"].Examples = []any{5, 10, 15}
306-
307292
return schema
308293
}
309294

@@ -319,25 +304,19 @@ func (ServiceStartOutput) Schema() *jsonschema.Schema {
319304

320305
// ServiceStopInput represents input for service_stop
321306
type ServiceStopInput struct {
322-
ServiceID string `json:"service_id"`
323-
Wait bool `json:"wait,omitempty"`
324-
TimeoutMinutes int `json:"timeout_minutes,omitempty"`
307+
ServiceID string `json:"service_id"`
308+
Wait bool `json:"wait,omitempty"`
325309
}
326310

327311
func (ServiceStopInput) Schema() *jsonschema.Schema {
328312
schema := util.Must(jsonschema.For[ServiceStopInput](nil))
329313

330314
setServiceIDSchemaProperties(schema)
331315

332-
schema.Properties["wait"].Description = "Whether to wait for the service to be fully stopped before returning. Default is false and is recommended because stopping can take several minutes. ONLY set to true if the user explicitly needs confirmation that the service is stopped to continue the same conversation."
316+
schema.Properties["wait"].Description = "Whether to wait for the service to be fully stopped before returning. Default is false (recommended). Only set to true if your next steps require confirmation that the service is stopped. When true, waits up to 10 minutes."
333317
schema.Properties["wait"].Default = util.Must(json.Marshal(false))
334318
schema.Properties["wait"].Examples = []any{false, true}
335319

336-
schema.Properties["timeout_minutes"].Description = "Timeout in minutes when waiting for service to stop. Only used when 'wait' is true."
337-
schema.Properties["timeout_minutes"].Minimum = util.Ptr(0.0)
338-
schema.Properties["timeout_minutes"].Default = util.Must(json.Marshal(10))
339-
schema.Properties["timeout_minutes"].Examples = []any{5, 10, 15}
340-
341320
return schema
342321
}
343322

@@ -391,10 +370,6 @@ The default type of service created depends on the user's plan:
391370
- Free plan: Creates a service with shared CPU/memory and the 'time-series' and 'ai' add-ons
392371
- Paid plans: Creates a service with 0.5 CPU / 2 GB memory and the 'time-series' add-on
393372
394-
Default behavior: Returns immediately while service provisions in background (recommended).
395-
Setting wait=true will block until the database is ready - only use if your next steps require connecting to or querying this database.
396-
timeout_minutes: Wait duration in minutes (only relevant with wait=true).
397-
398373
WARNING: Creates billable resources.`,
399374
InputSchema: ServiceCreateInput{}.Schema(),
400375
OutputSchema: ServiceCreateOutput{}.Schema(),
@@ -421,10 +396,6 @@ By default:
421396
- CPU and memory will be inherited from the source service
422397
- The forked service will be set as the default service
423398
424-
Default behavior: Returns immediately while service provisions in background (recommended).
425-
Setting wait=true will block until the database is ready - only use if your next steps require connecting to or querying this database.
426-
timeout_minutes: Wait duration in minutes (only relevant with wait=true).
427-
428399
WARNING: Creates billable resources.`,
429400
InputSchema: ServiceForkInput{}.Schema(),
430401
OutputSchema: ServiceForkOutput{}.Schema(),
@@ -456,11 +427,7 @@ WARNING: Creates billable resources.`,
456427
Title: "Start Database Service",
457428
Description: `Start a stopped database service.
458429
459-
This operation starts a service that is currently in a stopped/paused state. The service will transition to a ready state and become available for connections.
460-
461-
Default behavior: Returns immediately while service starts in background (recommended).
462-
Setting wait=true will block until the database is ready - only use if your next steps require connecting to or querying this database.
463-
timeout_minutes: Wait duration in minutes (only relevant with wait=true).`,
430+
This operation starts a service that is currently in a stopped/paused state. The service will transition to a ready state and become available for connections.`,
464431
InputSchema: ServiceStartInput{}.Schema(),
465432
OutputSchema: ServiceStartOutput{}.Schema(),
466433
Annotations: &mcp.ToolAnnotations{
@@ -476,11 +443,7 @@ timeout_minutes: Wait duration in minutes (only relevant with wait=true).`,
476443
Title: "Stop Database Service",
477444
Description: `Stop a running database service.
478445
479-
This operation stops a service that is currently running. The service will transition to a stopped/paused state and will no longer accept connections.
480-
481-
Default behavior: Returns immediately while service stops in background (recommended).
482-
Setting wait=true will block until the database is stopped - only use if your next steps require confirmation that the service is stopped.
483-
timeout_minutes: Wait duration in minutes (only relevant with wait=true).`,
446+
This operation stops a service that is currently running. The service will transition to a stopped/paused state and will no longer accept connections.`,
484447
InputSchema: ServiceStopInput{}.Schema(),
485448
OutputSchema: ServiceStopOutput{}.Schema(),
486449
Annotations: &mcp.ToolAnnotations{
@@ -668,7 +631,7 @@ func (s *Server) handleServiceCreate(ctx context.Context, req *mcp.CallToolReque
668631
TargetStatus: "READY",
669632
Service: &service,
670633
},
671-
Timeout: time.Duration(input.TimeoutMinutes) * time.Minute,
634+
Timeout: waitTimeout,
672635
TimeoutMsg: "service may still be provisioning",
673636
}); err != nil {
674637
message = fmt.Sprintf("Error: %s", err.Error())
@@ -796,7 +759,7 @@ func (s *Server) handleServiceFork(ctx context.Context, req *mcp.CallToolRequest
796759
TargetStatus: "READY",
797760
Service: &service,
798761
},
799-
Timeout: time.Duration(input.TimeoutMinutes) * time.Minute,
762+
Timeout: waitTimeout,
800763
TimeoutMsg: "service may still be provisioning",
801764
}); err != nil {
802765
message = fmt.Sprintf("Error: %s", err.Error())
@@ -907,7 +870,7 @@ func (s *Server) handleServiceStart(ctx context.Context, req *mcp.CallToolReques
907870
TargetStatus: "READY",
908871
Service: &service,
909872
},
910-
Timeout: time.Duration(input.TimeoutMinutes) * time.Minute,
873+
Timeout: waitTimeout,
911874
TimeoutMsg: "service may still be starting",
912875
}); err != nil {
913876
message = fmt.Sprintf("Error: %s", err.Error())
@@ -964,7 +927,7 @@ func (s *Server) handleServiceStop(ctx context.Context, req *mcp.CallToolRequest
964927
TargetStatus: "PAUSED",
965928
Service: &service,
966929
},
967-
Timeout: time.Duration(input.TimeoutMinutes) * time.Minute,
930+
Timeout: waitTimeout,
968931
TimeoutMsg: "service may still be stopping",
969932
}); err != nil {
970933
message = fmt.Sprintf("Error: %s", err.Error())

specs/spec_mcp.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,7 @@ Create a new database service.
176176
- `region` (string, optional): Region code
177177
- `cpu_memory` (string, optional): CPU and memory allocation combination (e.g., "shared/shared", "0.5 CPU/2GB", "2 CPU/8GB")
178178
- `replicas` (number, optional): Number of high-availability replicas - default: 0
179-
- `wait` (boolean, optional): Wait for service to be ready - default: false
180-
- `timeout` (number, optional): Timeout for waiting in minutes - default: 30
179+
- `wait` (boolean, optional): Wait for service to be ready (waits up to 10 minutes) - default: false
181180
- `set_default` (boolean, optional): Set the newly created service as the default service for future commands - default: true
182181
- `with_password` (boolean, optional): Include password in response and connection string - default: false
183182

@@ -197,8 +196,7 @@ Fork an existing database service to create a new independent copy.
197196
- `target_time` (string, optional): Target timestamp for point-in-time recovery in RFC3339 format (e.g., "2025-01-15T10:30:00Z"). Required when `fork_strategy` is `"PITR"`, forbidden otherwise.
198197
- `name` (string, optional): Name for the forked service - auto-generated if not provided
199198
- `cpu_memory` (string, optional): CPU and memory allocation combination (e.g., "0.5 CPU/2GB", "2 CPU/8GB"). If not specified, inherits from source service.
200-
- `wait` (boolean, optional): Wait for forked service to be ready - default: false
201-
- `timeout_minutes` (number, optional): Timeout for waiting in minutes - default: 30
199+
- `wait` (boolean, optional): Wait for forked service to be ready (waits up to 10 minutes) - default: false
202200
- `set_default` (boolean, optional): Set the forked service as the default service for future commands - default: true
203201
- `with_password` (boolean, optional): Include password in response and connection string - default: false
204202

@@ -222,25 +220,19 @@ Start a stopped database service.
222220

223221
**Parameters:**
224222
- `service_id` (string, required): Service ID to start
225-
- `wait` (boolean, optional): Wait for service to be fully started before returning - default: false
226-
- `timeout_minutes` (number, optional): Timeout for waiting in minutes - default: 10
223+
- `wait` (boolean, optional): Wait for service to be fully started before returning (waits up to 10 minutes). Default is false (recommended) - only set to true if your next steps require connecting to or querying this database.
227224

228225
**Returns:** Operation status with current service status and message.
229226

230-
**Default behavior:** Returns immediately while service starts in background (recommended). Setting `wait=true` will block until the database is ready - only use if your next steps require connecting to or querying this database.
231-
232227
#### `service_stop`
233228
Stop a running database service.
234229

235230
**Parameters:**
236231
- `service_id` (string, required): Service ID to stop
237-
- `wait` (boolean, optional): Wait for service to be fully stopped before returning - default: false
238-
- `timeout_minutes` (number, optional): Timeout for waiting in minutes - default: 10
232+
- `wait` (boolean, optional): Wait for service to be fully stopped before returning (waits up to 10 minutes). Default is false (recommended) - only set to true if your next steps require confirmation that the service is stopped.
239233

240234
**Returns:** Operation status with current service status and message.
241235

242-
**Default behavior:** Returns immediately while service stops in background (recommended). Setting `wait=true` will block until the database is stopped - only use if your next steps require confirmation that the service is stopped.
243-
244236
#### `service_restart`
245237
Restart a service.
246238

0 commit comments

Comments
 (0)