Skip to content

Commit a2c288a

Browse files
committed
feat: search and fetch mcp tools
1 parent 219d1b4 commit a2c288a

File tree

6 files changed

+387
-8
lines changed

6 files changed

+387
-8
lines changed

coderd/coderd.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,8 +996,12 @@ func New(options *Options) *API {
996996
r.Use(
997997
httpmw.RequireExperimentWithDevBypass(api.Experiments, codersdk.ExperimentOAuth2, codersdk.ExperimentMCPServerHTTP),
998998
)
999+
9991000
// MCP HTTP transport endpoint with mandatory authentication
1000-
r.Mount("/http", api.mcpHTTPHandler())
1001+
r.Mount("/http", api.standardMCPHTTPHandler())
1002+
// ChatGPT gets a dedicated endpoint with a limited set of tools.
1003+
// See the docstring of the chatgptMCPHTTPHandler for more details.
1004+
r.Mount("/chatgpt", api.chatgptMCPHTTPHandler())
10011005
})
10021006
})
10031007

coderd/mcp/mcp.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
6767
s.streamableServer.ServeHTTP(w, r)
6868
}
6969

70-
// RegisterTools registers all available MCP tools with the server
71-
func (s *Server) RegisterTools(client *codersdk.Client) error {
70+
// RegisterTools registers MCP tools with the server
71+
func (s *Server) RegisterTools(client *codersdk.Client, tools []toolsdk.GenericTool) error {
7272
if client == nil {
7373
return xerrors.New("client cannot be nil: MCP HTTP server requires authenticated client")
7474
}
@@ -81,7 +81,7 @@ func (s *Server) RegisterTools(client *codersdk.Client) error {
8181

8282
// Register all available tools, but exclude tools that require dependencies not available in the
8383
// remote MCP context
84-
for _, tool := range toolsdk.All {
84+
for _, tool := range tools {
8585
if tool.Name == toolsdk.ToolNameReportTask {
8686
continue
8787
}

coderd/mcp/mcp_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ func TestMCPHTTP_ToolRegistration(t *testing.T) {
110110
require.NoError(t, err)
111111

112112
// Test registering tools with nil client should return error
113-
err = server.RegisterTools(nil)
113+
err = server.RegisterTools(nil, toolsdk.All)
114114
require.Error(t, err)
115115
require.Contains(t, err.Error(), "client cannot be nil", "Should reject nil client with appropriate error message")
116116

117117
// Test registering tools with valid client should succeed
118118
client := &codersdk.Client{}
119-
err = server.RegisterTools(client)
119+
err = server.RegisterTools(client, toolsdk.All)
120120
require.NoError(t, err)
121121

122122
// Verify that all expected tools are available in the toolsdk

coderd/mcp_http.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import (
99
"github.com/coder/coder/v2/coderd/httpmw"
1010
"github.com/coder/coder/v2/coderd/mcp"
1111
"github.com/coder/coder/v2/codersdk"
12+
"github.com/coder/coder/v2/codersdk/toolsdk"
1213
)
1314

1415
// mcpHTTPHandler creates the MCP HTTP transport handler
15-
func (api *API) mcpHTTPHandler() http.Handler {
16+
func (api *API) mcpHTTPHandler(tools []toolsdk.GenericTool) http.Handler {
1617
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1718
// Create MCP server instance for each request
1819
mcpServer, err := mcp.NewServer(api.Logger.Named("mcp"))
@@ -29,11 +30,41 @@ func (api *API) mcpHTTPHandler() http.Handler {
2930
authenticatedClient.SetSessionToken(httpmw.APITokenFromRequest(r))
3031

3132
// Register tools with authenticated client
32-
if err := mcpServer.RegisterTools(authenticatedClient); err != nil {
33+
if err := mcpServer.RegisterTools(authenticatedClient, tools); err != nil {
3334
api.Logger.Warn(r.Context(), "failed to register MCP tools", slog.Error(err))
3435
}
3536

3637
// Handle the MCP request
3738
mcpServer.ServeHTTP(w, r)
3839
})
3940
}
41+
42+
// standardMCPHTTPHandler sets up the MCP HTTP transport handler for the standard tools.
43+
// Standard tools are all tools except for the report task, ChatGPT search, and ChatGPT fetch tools.
44+
func (api *API) standardMCPHTTPHandler() http.Handler {
45+
mcpTools := []toolsdk.GenericTool{}
46+
for _, tool := range toolsdk.All {
47+
if tool.Name == toolsdk.ToolNameReportTask ||
48+
tool.Name == toolsdk.ToolNameChatGPTSearch || tool.Name == toolsdk.ToolNameChatGPTFetch {
49+
continue
50+
}
51+
mcpTools = append(mcpTools, tool)
52+
}
53+
return api.mcpHTTPHandler(mcpTools)
54+
}
55+
56+
// chatgptMCPHTTPHandler sets up the MCP HTTP transport handler for the ChatGPT tools.
57+
// ChatGPT tools are the search and fetch tools as defined in https://platform.openai.com/docs/mcp.
58+
// We do not expose any extra ones because ChatGPT has an undocumented "Safety Scan" feature.
59+
// In my experiments, if I included extra tools in the MCP server, ChatGPT would refuse
60+
// to add Coder as a connector.
61+
func (api *API) chatgptMCPHTTPHandler() http.Handler {
62+
mcpTools := []toolsdk.GenericTool{}
63+
for _, tool := range toolsdk.All {
64+
if !(tool.Name == toolsdk.ToolNameChatGPTSearch || tool.Name == toolsdk.ToolNameChatGPTFetch) {
65+
continue
66+
}
67+
mcpTools = append(mcpTools, tool)
68+
}
69+
return api.mcpHTTPHandler(mcpTools)
70+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy