Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Toolset Name: `audit`

Toolset Name: `fme`

- `list_fme_workspaces`: List all FME workspaces
- `list_fme_workspaces`: List all FME workspaces (supports pagination via `offset` and `count`; default count: 20, max count: 1000)
- `list_fme_environments`: List environments for a specific workspace
- `list_fme_feature_flags`: List feature flags for a specific workspace
- `get_fme_feature_flag_definition`: Get the definition of a specific feature flag in an environment
Expand Down
13 changes: 10 additions & 3 deletions common/client/fme.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"context"
"fmt"
"strconv"

"github.com/harness/mcp-server/common/client/dto"
)
Expand All @@ -12,12 +13,18 @@ type FMEService struct {
Client *Client
}

// ListWorkspaces retrieves all FME workspaces
// ListWorkspaces retrieves FME workspaces with pagination support.
// GET https://api.split.io/internal/api/v2/workspaces
func (f *FMEService) ListWorkspaces(ctx context.Context) (*dto.FMEWorkspacesResponse, error) {
// offset specifies the number of items to skip; limit controls how many items to return (max 100).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks to be max 1000

func (f *FMEService) ListWorkspaces(ctx context.Context, offset, limit int) (*dto.FMEWorkspacesResponse, error) {
var response dto.FMEWorkspacesResponse

err := f.Client.Get(ctx, "internal/api/v2/workspaces", nil, nil, &response)
params := map[string]string{
"offset": strconv.Itoa(offset),
"limit": strconv.Itoa(limit),
}

err := f.Client.Get(ctx, "internal/api/v2/workspaces", params, nil, &response)
if err != nil {
return nil, fmt.Errorf("failed to list workspaces: %w", err)
}
Expand Down
26 changes: 25 additions & 1 deletion common/pkg/tools/fme.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,37 @@ import (
"github.com/mark3labs/mcp-go/server"
)

const (
fmeWorkspacesDefaultCount = 20
fmeWorkspacesMaxCount = 1000
)

// ListFMEWorkspacesTool creates a tool for listing FME workspaces
func ListFMEWorkspacesTool(config *config.McpServerConfig, fmeService *client.FMEService) (mcp.Tool, server.ToolHandlerFunc) {
return mcp.NewTool("list_fme_workspaces",
mcp.WithDescription("List Feature Management & Experimentation (FME) workspaces."),
mcp.WithNumber("offset",
mcp.Description("The number of workspaces to skip for pagination (default: 0)"),
),
mcp.WithNumber("count",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We could use "limit" to keep naming consistent with the API. Feel free to ignore this though

mcp.Description(fmt.Sprintf("The number of workspaces to return (default: %d, max: %d)", fmeWorkspacesDefaultCount, fmeWorkspacesMaxCount)),
),
),
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
workspaces, err := fmeService.ListWorkspaces(ctx)
offset, err := OptionalIntParam(request, "offset")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check for negative offset?

if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}

count, err := OptionalIntParamWithDefault(request, "count", fmeWorkspacesDefaultCount)
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
if count > fmeWorkspacesMaxCount {
count = fmeWorkspacesMaxCount
}

workspaces, err := fmeService.ListWorkspaces(ctx, offset, count)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to list FME workspaces: %v", err)), nil
}
Expand Down