Skip to content

Commit 6c33f81

Browse files
committed
feat: introduce context-based Store access and OAuth client listing tool
- Pass the Store instance through MCPServer and set it on the request context for both HTTP and Stdio servers - Add WithStore and StoreFromContext utilities for context-based Store access - Implement a new MCP tool for listing OAuth clients in pkg/operation/oauth/client.go - Register the list_oauth_clients tool in the authentication tools setup Signed-off-by: appleboy <appleboy.tw@gmail.com>
1 parent 9f905bf commit 6c33f81

File tree

4 files changed

+75
-2
lines changed

4 files changed

+75
-2
lines changed

03-oauth-mcp/oauth-server/server.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ import (
3232
// MCPServer wraps the underlying MCP server instance.
3333
type MCPServer struct {
3434
server *server.MCPServer
35+
store core.Store
3536
}
3637

3738
// NewMCPServer creates and configures a new MCPServer instance.
3839
// Registers the make_authenticated_request and show_auth_token tools.
39-
func NewMCPServer() *MCPServer {
40+
func NewMCPServer(store core.Store) *MCPServer {
4041
mcpServer := server.NewMCPServer(
4142
"example-oauth-server",
4243
"1.0.0",
@@ -50,6 +51,7 @@ func NewMCPServer() *MCPServer {
5051

5152
return &MCPServer{
5253
server: mcpServer,
54+
store: store,
5355
}
5456
}
5557

@@ -59,6 +61,7 @@ func (s *MCPServer) ServeHTTP() *server.StreamableHTTPServer {
5961
return server.NewStreamableHTTPServer(s.server,
6062
server.WithHeartbeatInterval(30*time.Second),
6163
server.WithHTTPContextFunc(func(ctx context.Context, r *http.Request) context.Context {
64+
ctx = core.WithStore(ctx, s.store)
6265
ctx = core.AuthFromRequest(ctx, r)
6366
return core.WithRequestID(ctx)
6467
}),
@@ -69,6 +72,7 @@ func (s *MCPServer) ServeHTTP() *server.StreamableHTTPServer {
6972
// auth token from the environment into the context.
7073
func (s *MCPServer) ServeStdio() error {
7174
return server.ServeStdio(s.server, server.WithStdioContextFunc(func(ctx context.Context) context.Context {
75+
ctx = core.WithStore(ctx, s.store)
7276
ctx = core.AuthFromEnv(ctx)
7377
return core.WithRequestID(ctx)
7478
}))
@@ -152,7 +156,7 @@ func main() {
152156
}
153157
}
154158

155-
mcpServer := NewMCPServer()
159+
mcpServer := NewMCPServer(oauthStore)
156160
router := gin.Default()
157161
router.Use(corsMiddleware())
158162

pkg/core/core.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ type AuthKey struct{}
1616
// RequestIDKey is a custom context key type for storing the request ID in context.
1717
type RequestIDKey struct{}
1818

19+
// StoreKey is a custom context key type for storing the Store in context.
20+
type StoreKey struct{}
21+
1922
// WithRequestID returns a new context with a generated request ID set.
2023
func WithRequestID(ctx context.Context) context.Context {
2124
reqID := uuid.New().String()
@@ -59,3 +62,18 @@ func LoggerFromCtx(ctx context.Context) *slog.Logger {
5962
}
6063
return slog.Default()
6164
}
65+
66+
// WithStore returns a new context with the provided Store set.
67+
func WithStore(ctx context.Context, store Store) context.Context {
68+
return context.WithValue(ctx, StoreKey{}, store)
69+
}
70+
71+
// StoreFromContext retrieves the Store from the context.
72+
// Returns the Store interface if present, or an error if missing.
73+
func StoreFromContext(ctx context.Context) (Store, error) {
74+
store, ok := ctx.Value(StoreKey{}).(Store)
75+
if !ok {
76+
return nil, fmt.Errorf("missing store")
77+
}
78+
return store, nil
79+
}

pkg/operation/oauth/client.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Package oauth provides MCP tools for managing OAuth clients.
2+
package oauth
3+
4+
import (
5+
"context"
6+
"encoding/json"
7+
8+
"github.com/go-training/mcp-workshop/pkg/core"
9+
"github.com/mark3labs/mcp-go/mcp"
10+
)
11+
12+
// ListOAuthClientsTool defines the MCP tool for listing all OAuth clients.
13+
var ListOAuthClientsTool = mcp.NewTool("list_oauth_clients",
14+
mcp.WithDescription("List all OAuth clients"),
15+
)
16+
17+
// HandleListOAuthClientsTool is an MCP tool handler that retrieves and returns
18+
// a list of all registered OAuth clients from the store.
19+
func HandleListOAuthClientsTool(
20+
ctx context.Context,
21+
_ mcp.CallToolRequest,
22+
) (*mcp.CallToolResult, error) {
23+
logger := core.LoggerFromCtx(ctx)
24+
logger.Info("Handling list_oauth_clients tool")
25+
26+
store, err := core.StoreFromContext(ctx)
27+
if err != nil {
28+
logger.Error("Missing store from context", "error", err)
29+
return nil, err
30+
}
31+
32+
clients, err := store.GetClients(ctx)
33+
if err != nil {
34+
logger.Error("Failed to get clients from store", "error", err)
35+
return nil, err
36+
}
37+
38+
data, err := json.Marshal(clients)
39+
if err != nil {
40+
logger.Error("Failed to marshal clients to JSON", "error", err)
41+
return nil, err
42+
}
43+
44+
logger.Info("Successfully retrieved OAuth clients")
45+
return mcp.NewToolResultText(string(data)), nil
46+
}

pkg/operation/operation.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package operation
33
import (
44
"github.com/go-training/mcp-workshop/pkg/operation/caculator"
55
"github.com/go-training/mcp-workshop/pkg/operation/echo"
6+
"github.com/go-training/mcp-workshop/pkg/operation/oauth"
67
"github.com/go-training/mcp-workshop/pkg/operation/token"
78

89
"github.com/mark3labs/mcp-go/server"
@@ -50,6 +51,10 @@ func RegisterAuthTool(s *server.MCPServer) {
5051
Tool: token.ShowAuthTokenTool,
5152
Handler: token.HandleShowAuthTokenTool,
5253
})
54+
tool.RegisterRead(server.ServerTool{
55+
Tool: oauth.ListOAuthClientsTool,
56+
Handler: oauth.HandleListOAuthClientsTool,
57+
})
5358

5459
s.AddTools(tool.Tools()...)
5560
}

0 commit comments

Comments
 (0)