Skip to content

Conversation

@njhale njhale force-pushed the fix/composite-consistency branch 9 times, most recently from 87ae71c to a865690 Compare December 18, 2025 18:21
Keep component MCPServers and MCPServerInstances up-to-date with the
composite MCPServer's manifest in a controller handler instead of API
handlers.

Addresses:
- obot-platform#5127
- obot-platform#5084

Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com>
@njhale njhale force-pushed the fix/composite-consistency branch from e803f49 to b145bb4 Compare December 19, 2025 03:32
Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com>
Addresses obot-platform#4929

Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com>
entries

This change allows composite component servers to be launched after
their original CatalogEntry has been deleted.

Addresses obot-platform#5272

Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com>
Addresses obot-platform#4975

Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com>
@njhale njhale force-pushed the fix/composite-consistency branch from 84392d7 to fafeda9 Compare December 19, 2025 04:39
Signed-off-by: Nick Hale <4175918+njhale@users.noreply.github.com>
@njhale njhale marked this pull request as ready for review December 19, 2025 13:39
URLTemplate string `json:"urlTemplate,omitempty"` // URL template for user URLs
Hostname string `json:"hostname,omitempty"` // Optional: Hostname constraint the URL conforms to
Headers []MCPHeader `json:"headers,omitempty"` // Optional

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change

golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sync v0.19.0
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm surprised that go mod tidy doesn't do this, but if these are direct dependencies, then they should be in the first require block.

Comment on lines +187 to +190
// Remove and recreate the credential to update it
if err := gptClient.DeleteCredential(ctx, existing.Context, cred.ToolName); err != nil && !errors.As(err, &gptscript.ErrNotFound{}) {
return false, fmt.Errorf("failed to remove existing credential: %w", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
// Remove and recreate the credential to update it
if err := gptClient.DeleteCredential(ctx, existing.Context, cred.ToolName); err != nil && !errors.As(err, &gptscript.ErrNotFound{}) {
return false, fmt.Errorf("failed to remove existing credential: %w", err)
}

Comment on lines +529 to +540
if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
var latestServer v1.MCPServer
if err := req.Get(&latestServer, compositeServer.Namespace, existingServer.Name); err != nil {
return err
}

latestServer.Spec.Manifest = component.Manifest
latestServer = withNeedsURL(latestServer)
return req.Client.Update(req.Ctx, &latestServer)
}); err != nil {
return fmt.Errorf("failed to update existing component server: %w", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

If the updating of component servers was done in a different handler (that operated on the component itself), then we wouldn't need to retry here. We could just return the error and have the controller framework handle the retrying.


// listCompositeDeletionDependencies lists the composite MCP servers and catalog entries that depend on the given multi-user server.
func (m *MCPHandler) listCompositeDeletionDependencies(req api.Context, server v1.MCPServer) ([]compositeDeletionDependency, error) {
func (*MCPHandler) listCompositeDeletionDependencies(req api.Context, server v1.MCPServer) ([]compositeDeletionDependency, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func (*MCPHandler) listCompositeDeletionDependencies(req api.Context, server v1.MCPServer) ([]compositeDeletionDependency, error) {
func listCompositeDeletionDependencies(req api.Context, server v1.MCPServer) ([]compositeDeletionDependency, error) {

parentComps[comp.ComponentID()] = i
var (
manifestChanged bool
oldCompositeServer = compositeServer.DeepCopy()
Copy link
Contributor

Choose a reason for hiding this comment

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

If there is a reason why we are deep copying here, then can we add a comment about that? If there isn't, then can we remove it?

// triggerCompositeUpdate upgrades a composite server and all its component servers from the latest catalog entry
func (m *MCPHandler) triggerCompositeUpdate(req api.Context, server v1.MCPServer, entry v1.MCPServerCatalogEntry) error {
func (m *MCPHandler) triggerCompositeUpdate(req api.Context, compositeServer v1.MCPServer, entry v1.MCPServerCatalogEntry) error {
oldServer := compositeServer.DeepCopy()
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment here about deep copying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants