@@ -79,14 +79,24 @@ func setServiceIDSchemaProperties(schema *jsonschema.Schema) {
7979 schema .Properties ["service_id" ].Pattern = "^[a-z0-9]{10}$"
8080}
8181
82+ // setWithPasswordSchemaProperties sets common with_password schema properties
83+ func setWithPasswordSchemaProperties (schema * jsonschema.Schema ) {
84+ schema .Properties ["with_password" ].Description = "Whether to include the password in the response and connection string."
85+ schema .Properties ["with_password" ].Default = util .Must (json .Marshal (false ))
86+ schema .Properties ["with_password" ].Examples = []any {false , true }
87+ }
88+
8289// ServiceGetInput represents input for service_get
8390type ServiceGetInput struct {
84- ServiceID string `json:"service_id"`
91+ ServiceID string `json:"service_id"`
92+ WithPassword bool `json:"with_password,omitempty"`
8593}
8694
8795func (ServiceGetInput ) Schema () * jsonschema.Schema {
8896 schema := util .Must (jsonschema.For [ServiceGetInput ](nil ))
8997 setServiceIDSchemaProperties (schema )
98+ setWithPasswordSchemaProperties (schema )
99+
90100 return schema
91101}
92102
@@ -101,17 +111,19 @@ func (ServiceGetOutput) Schema() *jsonschema.Schema {
101111
102112// ServiceDetail represents detailed service information
103113type ServiceDetail struct {
104- ServiceID string `json:"id" jsonschema:"Service identifier (10-character alphanumeric string)"`
105- Name string `json:"name"`
106- Status string `json:"status" jsonschema:"Service status (e.g., READY, PAUSED, CONFIGURING, UPGRADING)"`
107- Type string `json:"type"`
108- Region string `json:"region"`
109- Created string `json:"created,omitempty"`
110- Resources * ResourceInfo `json:"resources,omitempty"`
111- Replicas int `json:"replicas,omitempty" jsonschema:"Number of HA replicas (0=single node/no HA, 1+=HA enabled)"`
112- DirectEndpoint string `json:"direct_endpoint,omitempty" jsonschema:"Direct database connection endpoint"`
113- PoolerEndpoint string `json:"pooler_endpoint,omitempty" jsonschema:"Connection pooler endpoint"`
114- Paused bool `json:"paused"`
114+ ServiceID string `json:"id" jsonschema:"Service identifier (10-character alphanumeric string)"`
115+ Name string `json:"name"`
116+ Status string `json:"status" jsonschema:"Service status (e.g., READY, PAUSED, CONFIGURING, UPGRADING)"`
117+ Type string `json:"type"`
118+ Region string `json:"region"`
119+ Created string `json:"created,omitempty"`
120+ Resources * ResourceInfo `json:"resources,omitempty"`
121+ Replicas int `json:"replicas" jsonschema:"Number of HA replicas (0=single node/no HA, 1+=HA enabled)"`
122+ DirectEndpoint string `json:"direct_endpoint,omitempty" jsonschema:"Direct database connection endpoint"`
123+ PoolerEndpoint string `json:"pooler_endpoint,omitempty" jsonschema:"Connection pooler endpoint"`
124+ Paused bool `json:"paused"`
125+ Password string `json:"password,omitempty" jsonschema:"Password for tsdbadmin user (only included if with_password=true)"`
126+ ConnectionString string `json:"connection_string" jsonschema:"PostgreSQL connection string (password embedded only if with_password=true)"`
115127}
116128
117129func (ServiceDetail ) Schema () * jsonschema.Schema {
@@ -131,6 +143,7 @@ type ServiceCreateInput struct {
131143 Wait bool `json:"wait,omitempty"`
132144 TimeoutMinutes * int `json:"timeout_minutes,omitempty"`
133145 SetDefault bool `json:"set_default,omitempty"`
146+ WithPassword bool `json:"with_password,omitempty"`
134147}
135148
136149func (ServiceCreateInput ) Schema () * jsonschema.Schema {
@@ -174,6 +187,8 @@ func (ServiceCreateInput) Schema() *jsonschema.Schema {
174187 schema .Properties ["set_default" ].Default = util .Must (json .Marshal (true ))
175188 schema .Properties ["set_default" ].Examples = []any {true , false }
176189
190+ setWithPasswordSchemaProperties (schema )
191+
177192 return schema
178193}
179194
@@ -364,6 +379,19 @@ func (s *Server) handleServiceGet(ctx context.Context, req *mcp.CallToolRequest,
364379 Service : s .convertToServiceDetail (service ),
365380 }
366381
382+ // Always include connection string in ServiceDetail
383+ // Password is embedded in connection string only if with_password=true
384+ if details , err := password .GetConnectionDetails (service , password.ConnectionDetailsOptions {
385+ Pooled : false ,
386+ Role : "tsdbadmin" ,
387+ PasswordMode : password .GetPasswordMode (input .WithPassword ),
388+ }); err != nil {
389+ logging .Debug ("MCP: Failed to build connection string" , zap .Error (err ))
390+ } else {
391+ output .Service .Password = details .Password
392+ output .Service .ConnectionString = details .String ()
393+ }
394+
367395 return nil , output , nil
368396}
369397
@@ -481,21 +509,15 @@ func (s *Server) handleServiceCreate(ctx context.Context, req *mcp.CallToolReque
481509 serviceID := util .Deref (service .ServiceId )
482510 serviceStatus := util .DerefStr (service .Status )
483511
484- // Capture initial password from creation response and save it immediately
485- var initialPassword string
486- if service .InitialPassword != nil {
487- initialPassword = * service .InitialPassword
488- }
489-
490512 output := ServiceCreateOutput {
491513 Service : s .convertToServiceDetail (service ),
492514 Message : "Service creation request accepted. The service may still be provisioning." ,
493515 }
494516
495517 // Save password immediately after service creation, before any waiting
496518 // This ensures the password is stored even if the wait fails or is interrupted
497- if initialPassword != "" {
498- result , err := password .SavePasswordWithResult (api .Service (service ), initialPassword )
519+ if service . InitialPassword != nil {
520+ result , err := password .SavePasswordWithResult (api .Service (service ), * service . InitialPassword )
499521 output .PasswordStorage = & result
500522 if err != nil {
501523 logging .Debug ("MCP: Password storage failed" , zap .Error (err ))
@@ -504,6 +526,24 @@ func (s *Server) handleServiceCreate(ctx context.Context, req *mcp.CallToolReque
504526 }
505527 }
506528
529+ // Include password in ServiceDetail if requested
530+ if input .WithPassword {
531+ output .Service .Password = util .Deref (service .InitialPassword )
532+ }
533+
534+ // Always include connection string in ServiceDetail
535+ // Password is embedded in connection string only if with_password=true
536+ if details , err := password .GetConnectionDetails (api .Service (service ), password.ConnectionDetailsOptions {
537+ Pooled : false ,
538+ Role : "tsdbadmin" ,
539+ PasswordMode : password .GetPasswordMode (input .WithPassword ),
540+ InitialPassword : util .Deref (service .InitialPassword ),
541+ }); err != nil {
542+ logging .Debug ("MCP: Failed to build connection string" , zap .Error (err ))
543+ } else {
544+ output .Service .ConnectionString = details .String ()
545+ }
546+
507547 // Set as default service if requested (defaults to true)
508548 if input .SetDefault {
509549 if err := cfg .Set ("service_id" , serviceID ); err != nil {
0 commit comments