Skip to content

Commit 442f1d4

Browse files
- Added robot test MCP HTTP Server List Services Tool.
- Added robot test `MCP HTTP Server List Resources Tool`. - Added robot test `MCP HTTP Server List Methods Tool`. - Added robot test `MCP HTTP Server Query Tool`.
1 parent b2ac4ea commit 442f1d4

File tree

4 files changed

+100
-21
lines changed

4 files changed

+100
-21
lines changed

internal/stackql/mcpbackend/mcp_service_stackql.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ func (b *stackqlMCPService) extractQueryResults(query string, rowLimit int) ([]m
363363
sqlRowStream := resp.GetSQLResult()
364364
if sqlRowStream == nil {
365365
ok = false
366+
break
366367
}
367368
for {
368369
row, err := sqlRowStream.Read()

pkg/mcp_server/dto.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ type GreetInput struct {
8181
}
8282

8383
type HierarchyInput struct {
84-
Provider string `json:"provider" yaml:"provider"`
85-
Service string `json:"service" yaml:"service"`
86-
Resource string `json:"resource" yaml:"resource"`
87-
Method string `json:"method" yaml:"method"`
88-
RowLimit int `json:"row_limit" yaml:"row_limit"`
89-
Format string `json:"format" yaml:"format"`
84+
Provider string `json:"provider,omitempty" yaml:"provider,omitempty"`
85+
Service string `json:"service,omitempty" yaml:"service,omitempty"`
86+
Resource string `json:"resource,omitempty" yaml:"resource,omitempty"`
87+
Method string `json:"method,omitempty" yaml:"method,omitempty"`
88+
RowLimit int `json:"row_limit,omitempty" yaml:"row_limit,omitempty"`
89+
Format string `json:"format,omitempty" yaml:"format,omitempty"`
9090
// Parameters map[string]any `json:"parameters,omitempty" yaml:"parameters,omitempty"`
9191
}
9292

@@ -98,25 +98,25 @@ type ServerInfoOutput struct {
9898

9999
type QueryInput struct {
100100
SQL string `json:"sql" yaml:"sql"`
101-
RowLimit int `json:"row_limit" yaml:"row_limit"`
102-
Format string `json:"format" yaml:"format"`
101+
RowLimit int `json:"row_limit,omitempty" yaml:"row_limit,omitempty"`
102+
Format string `json:"format,omitempty" yaml:"format,omitempty"`
103103
// Parameters map[string]any `json:"parameters,omitempty" yaml:"parameters,omitempty"`
104104
}
105105

106106
type QueryJSONInput struct {
107107
SQL string `json:"sql" yaml:"sql"`
108-
RowLimit int `json:"row_limit" yaml:"row_limit"`
108+
RowLimit int `json:"row_limit,omitempty" yaml:"row_limit,omitempty"`
109109
// Parameters map[string]any `json:"parameters,omitempty" yaml:"parameters,omitempty"`
110110
}
111111

112112
type ListSchemasInput struct {
113-
IncludeSystem bool `json:"include_system" yaml:"include_system"`
114-
IncludeTemp bool `json:"include_temp" yaml:"include_temp"`
115-
RequireUsage bool `json:"require_usage" yaml:"require_usage"`
116-
RowLimit int `json:"row_limit" yaml:"row_limit"`
113+
IncludeSystem bool `json:"include_system,omitempty" yaml:"include_system,omitempty"`
114+
IncludeTemp bool `json:"include_temp,omitempty" yaml:"include_temp,omitempty"`
115+
RequireUsage bool `json:"require_usage,omitempty" yaml:"require_usage,omitempty"`
116+
RowLimit int `json:"row_limit,omitempty" yaml:"row_limit,omitempty"`
117117
NameLike *string `json:"name_like,omitempty" yaml:"name_like,omitempty"`
118-
CaseSensitive bool `json:"case_sensitive" yaml:"case_sensitive"`
119-
Format string `json:"format" yaml:"format"`
118+
CaseSensitive bool `json:"case_sensitive,omitempty" yaml:"case_sensitive,omitempty"`
119+
Format string `json:"format,omitempty" yaml:"format,omitempty"`
120120
}
121121

122122
type ListSchemasPageInput struct {
@@ -133,18 +133,18 @@ type ListSchemasPageInput struct {
133133
type ListTablesInput struct {
134134
Hierarchy *HierarchyInput `json:"hierarchy,omitempty" yaml:"hierarchy,omitempty"`
135135
NameLike *string `json:"name_like,omitempty" yaml:"name_like,omitempty"`
136-
CaseSensitive bool `json:"case_sensitive" yaml:"case_sensitive"`
136+
CaseSensitive bool `json:"case_sensitive,omitempty" yaml:"case_sensitive,omitempty"`
137137
TableTypes []string `json:"table_types,omitempty" yaml:"table_types,omitempty"`
138-
RowLimit int `json:"row_limit" yaml:"row_limit"`
139-
Format string `json:"format" yaml:"format"`
138+
RowLimit int `json:"row_limit,omitempty" yaml:"row_limit,omitempty"`
139+
Format string `json:"format,omitempty" yaml:"format,omitempty"`
140140
}
141141

142142
type ListTablesPageInput struct {
143143
Hierarchy *HierarchyInput `json:"hierarchy,omitempty" yaml:"hierarchy,omitempty"`
144144
NameLike *string `json:"name_like,omitempty" yaml:"name_like,omitempty"`
145-
CaseSensitive bool `json:"case_sensitive" yaml:"case_sensitive"`
145+
CaseSensitive bool `json:"case_sensitive,omitempty" yaml:"case_sensitive,omitempty"`
146146
TableTypes []string `json:"table_types,omitempty" yaml:"table_types,omitempty"`
147-
PageSize int `json:"page_size" yaml:"page_size"`
147+
PageSize int `json:"page_size,omitempty" yaml:"page_size,omitempty"`
148148
Cursor *string `json:"cursor,omitempty" yaml:"cursor,omitempty"`
149-
Format string `json:"format" yaml:"format"`
149+
Format string `json:"format,omitempty" yaml:"format,omitempty"`
150150
}

pkg/mcp_server/server.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,25 @@ func newMCPServer(config *Config, backend Backend, logger *logrus.Logger) (MCPSe
372372
},
373373
)
374374

375+
mcp.AddTool(
376+
server,
377+
&mcp.Tool{
378+
Name: "list_methods",
379+
Description: "List methods for a resource.",
380+
},
381+
func(ctx context.Context, req *mcp.CallToolRequest, args HierarchyInput) (*mcp.CallToolResult, any, error) {
382+
result, err := backend.ListMethods(ctx, args)
383+
if err != nil {
384+
return nil, nil, err
385+
}
386+
return &mcp.CallToolResult{
387+
Content: []mcp.Content{
388+
&mcp.TextContent{Text: result},
389+
},
390+
}, result, nil
391+
},
392+
)
393+
375394
mcp.AddTool(
376395
server,
377396
&mcp.Tool{

test/robot/functional/mcp.robot

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Start MCP HTTP Server
1212
... {"server": {"transport": "http", "address": "127.0.0.1:9912"} }
1313
... \-\-registry
1414
... ${REGISTRY_NO_VERIFY_CFG_JSON_STR}
15+
... \-\-auth
16+
... ${AUTH_CFG_STR}
1517
Sleep 5s
1618

1719
*** Settings ***
@@ -60,3 +62,60 @@ MCP HTTP Server List Providers Tool
6062
Should Contain ${result.stdout} local_openssl
6163
Should Be Equal As Integers ${result.rc} 0
6264

65+
66+
MCP HTTP Server List Services Tool
67+
Pass Execution If "%{IS_SKIP_MCP_TEST=false}" == "true" Some platforms do not have the MCP client available
68+
Sleep 5s
69+
${result}= Run Process ${STACKQL_MCP_CLIENT_EXE}
70+
... exec
71+
... \-\-client\-type\=http
72+
... \-\-url\=http://127.0.0.1:9912
73+
... \-\-exec.action list_services
74+
... \-\-exec.args {"provider": "google"}
75+
... stdout=${CURDIR}${/}tmp${/}MCP-HTTP-Server-List-Services.txt
76+
... stderr=${CURDIR}${/}tmp${/}MCP-HTTP-Server-List-Services-stderr.txt
77+
Should Contain ${result.stdout} YouTube Analytics API
78+
Should Be Equal As Integers ${result.rc} 0
79+
80+
MCP HTTP Server List Resources Tool
81+
Pass Execution If "%{IS_SKIP_MCP_TEST=false}" == "true" Some platforms do not have the MCP client available
82+
Sleep 5s
83+
${result}= Run Process ${STACKQL_MCP_CLIENT_EXE}
84+
... exec
85+
... \-\-client\-type\=http
86+
... \-\-url\=http://127.0.0.1:9912
87+
... \-\-exec.action list_resources
88+
... \-\-exec.args {"provider": "google", "service": "cloudresourcemanager"}
89+
... stdout=${CURDIR}${/}tmp${/}MCP-HTTP-Server-List-Resources.txt
90+
... stderr=${CURDIR}${/}tmp${/}MCP-HTTP-Server-List-Resources-stderr.txt
91+
Should Contain ${result.stdout} projects
92+
Should Be Equal As Integers ${result.rc} 0
93+
94+
MCP HTTP Server List Methods Tool
95+
Pass Execution If "%{IS_SKIP_MCP_TEST=false}" == "true" Some platforms do not have the MCP client available
96+
Sleep 5s
97+
${result}= Run Process ${STACKQL_MCP_CLIENT_EXE}
98+
... exec
99+
... \-\-client\-type\=http
100+
... \-\-url\=http://127.0.0.1:9912
101+
... \-\-exec.action list_methods
102+
... \-\-exec.args {"provider": "google", "service": "compute", "resource": "instances"}
103+
... stdout=${CURDIR}${/}tmp${/}MCP-HTTP-Server-List-Methods.txt
104+
... stderr=${CURDIR}${/}tmp${/}MCP-HTTP-Server-List-Methods-stderr.txt
105+
Should Contain ${result.stdout} getScreenshot
106+
Should Be Equal As Integers ${result.rc} 0
107+
108+
MCP HTTP Server Query Tool
109+
Pass Execution If "%{IS_SKIP_MCP_TEST=false}" == "true" Some platforms do not have the MCP client available
110+
Sleep 5s
111+
${result}= Run Process ${STACKQL_MCP_CLIENT_EXE}
112+
... exec
113+
... \-\-client\-type\=http
114+
... \-\-url\=http://127.0.0.1:9912
115+
... \-\-exec.action query_v2
116+
... \-\-exec.args {"sql": "SELECT assetType, count(*) as asset_count FROM google.cloudasset.assets WHERE parentType \= 'projects' and parent \= 'testing-project' GROUP BY assetType order by count(*) desc, assetType desc;"}
117+
... stdout=${CURDIR}${/}tmp${/}MCP-HTTP-Server-Query-Tool.txt
118+
... stderr=${CURDIR}${/}tmp${/}MCP-HTTP-Server-Query-Tool-stderr.txt
119+
Should Contain ${result.stdout} cloudkms.googleapis.com
120+
Should Be Equal As Integers ${result.rc} 0
121+

0 commit comments

Comments
 (0)