Skip to content

Commit ccc3a6a

Browse files
committed
tests
1 parent a2c288a commit ccc3a6a

File tree

2 files changed

+663
-0
lines changed

2 files changed

+663
-0
lines changed

coderd/mcp/mcp_e2e_test.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,155 @@ func TestMCPHTTP_E2E_OAuth2_EndToEnd(t *testing.T) {
12151215
})
12161216
}
12171217

1218+
func TestMCPHTTP_E2E_ChatGPTEndpoint(t *testing.T) {
1219+
t.Parallel()
1220+
1221+
// Setup Coder server with authentication
1222+
coderClient, closer, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
1223+
IncludeProvisionerDaemon: true,
1224+
})
1225+
defer closer.Close()
1226+
1227+
user := coderdtest.CreateFirstUser(t, coderClient)
1228+
1229+
// Create template and workspace for testing search functionality
1230+
version := coderdtest.CreateTemplateVersion(t, coderClient, user.OrganizationID, nil)
1231+
coderdtest.AwaitTemplateVersionJobCompleted(t, coderClient, version.ID)
1232+
template := coderdtest.CreateTemplate(t, coderClient, user.OrganizationID, version.ID)
1233+
1234+
// Create MCP client pointing to the ChatGPT endpoint
1235+
mcpURL := api.AccessURL.String() + "/api/experimental/mcp/chatgpt"
1236+
1237+
// Configure client with authentication headers using RFC 6750 Bearer token
1238+
mcpClient, err := mcpclient.NewStreamableHttpClient(mcpURL,
1239+
transport.WithHTTPHeaders(map[string]string{
1240+
"Authorization": "Bearer " + coderClient.SessionToken(),
1241+
}))
1242+
require.NoError(t, err)
1243+
defer func() {
1244+
if closeErr := mcpClient.Close(); closeErr != nil {
1245+
t.Logf("Failed to close MCP client: %v", closeErr)
1246+
}
1247+
}()
1248+
1249+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
1250+
defer cancel()
1251+
1252+
// Start client
1253+
err = mcpClient.Start(ctx)
1254+
require.NoError(t, err)
1255+
1256+
// Initialize connection
1257+
initReq := mcp.InitializeRequest{
1258+
Params: mcp.InitializeParams{
1259+
ProtocolVersion: mcp.LATEST_PROTOCOL_VERSION,
1260+
ClientInfo: mcp.Implementation{
1261+
Name: "test-chatgpt-client",
1262+
Version: "1.0.0",
1263+
},
1264+
},
1265+
}
1266+
1267+
result, err := mcpClient.Initialize(ctx, initReq)
1268+
require.NoError(t, err)
1269+
require.Equal(t, mcpserver.MCPServerName, result.ServerInfo.Name)
1270+
require.Equal(t, mcp.LATEST_PROTOCOL_VERSION, result.ProtocolVersion)
1271+
require.NotNil(t, result.Capabilities)
1272+
1273+
// Test tool listing - should only have search and fetch tools for ChatGPT
1274+
tools, err := mcpClient.ListTools(ctx, mcp.ListToolsRequest{})
1275+
require.NoError(t, err)
1276+
require.NotEmpty(t, tools.Tools)
1277+
1278+
// Verify we have exactly the ChatGPT tools and no others
1279+
var foundTools []string
1280+
for _, tool := range tools.Tools {
1281+
foundTools = append(foundTools, tool.Name)
1282+
}
1283+
1284+
// ChatGPT endpoint should only expose search and fetch tools
1285+
assert.Contains(t, foundTools, toolsdk.ToolNameChatGPTSearch, "Should have ChatGPT search tool")
1286+
assert.Contains(t, foundTools, toolsdk.ToolNameChatGPTFetch, "Should have ChatGPT fetch tool")
1287+
assert.Len(t, foundTools, 2, "ChatGPT endpoint should only expose search and fetch tools")
1288+
1289+
// Should NOT have other tools that are available in the standard endpoint
1290+
assert.NotContains(t, foundTools, toolsdk.ToolNameGetAuthenticatedUser, "Should not have authenticated user tool")
1291+
assert.NotContains(t, foundTools, toolsdk.ToolNameListWorkspaces, "Should not have list workspaces tool")
1292+
1293+
t.Logf("ChatGPT endpoint tools: %v", foundTools)
1294+
1295+
// Test search tool - search for templates
1296+
var searchTool *mcp.Tool
1297+
for _, tool := range tools.Tools {
1298+
if tool.Name == toolsdk.ToolNameChatGPTSearch {
1299+
searchTool = &tool
1300+
break
1301+
}
1302+
}
1303+
require.NotNil(t, searchTool, "Expected to find search tool")
1304+
1305+
// Execute search for templates
1306+
searchReq := mcp.CallToolRequest{
1307+
Params: mcp.CallToolParams{
1308+
Name: searchTool.Name,
1309+
Arguments: map[string]any{
1310+
"query": "templates",
1311+
},
1312+
},
1313+
}
1314+
1315+
searchResult, err := mcpClient.CallTool(ctx, searchReq)
1316+
require.NoError(t, err)
1317+
require.NotEmpty(t, searchResult.Content)
1318+
1319+
// Verify the search result contains our template
1320+
assert.Len(t, searchResult.Content, 1)
1321+
if textContent, ok := searchResult.Content[0].(mcp.TextContent); ok {
1322+
assert.Equal(t, "text", textContent.Type)
1323+
assert.Contains(t, textContent.Text, template.ID.String(), "Search result should contain our test template")
1324+
t.Logf("Search result: %s", textContent.Text)
1325+
} else {
1326+
t.Errorf("Expected TextContent type, got %T", searchResult.Content[0])
1327+
}
1328+
1329+
// Test fetch tool
1330+
var fetchTool *mcp.Tool
1331+
for _, tool := range tools.Tools {
1332+
if tool.Name == toolsdk.ToolNameChatGPTFetch {
1333+
fetchTool = &tool
1334+
break
1335+
}
1336+
}
1337+
require.NotNil(t, fetchTool, "Expected to find fetch tool")
1338+
1339+
// Execute fetch for the template
1340+
fetchReq := mcp.CallToolRequest{
1341+
Params: mcp.CallToolParams{
1342+
Name: fetchTool.Name,
1343+
Arguments: map[string]any{
1344+
"id": fmt.Sprintf("template:%s", template.ID.String()),
1345+
},
1346+
},
1347+
}
1348+
1349+
fetchResult, err := mcpClient.CallTool(ctx, fetchReq)
1350+
require.NoError(t, err)
1351+
require.NotEmpty(t, fetchResult.Content)
1352+
1353+
// Verify the fetch result contains template details
1354+
assert.Len(t, fetchResult.Content, 1)
1355+
if textContent, ok := fetchResult.Content[0].(mcp.TextContent); ok {
1356+
assert.Equal(t, "text", textContent.Type)
1357+
assert.Contains(t, textContent.Text, template.Name, "Fetch result should contain template name")
1358+
assert.Contains(t, textContent.Text, template.ID.String(), "Fetch result should contain template ID")
1359+
t.Logf("Fetch result contains template data")
1360+
} else {
1361+
t.Errorf("Expected TextContent type, got %T", fetchResult.Content[0])
1362+
}
1363+
1364+
t.Logf("ChatGPT endpoint E2E test successful: search and fetch tools working correctly")
1365+
}
1366+
12181367
// Helper function to parse URL safely in tests
12191368
func mustParseURL(t *testing.T, rawURL string) *url.URL {
12201369
u, err := url.Parse(rawURL)

0 commit comments

Comments
 (0)