-
Notifications
You must be signed in to change notification settings - Fork 131
Add basic working set support #204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
pkg/db/workingset.go
Outdated
| func (servers *ServerList) Scan(value any) error { | ||
| str, ok := value.(string) | ||
| if !ok { | ||
| return errors.New("failed to scan server list") | ||
| } | ||
| return json.Unmarshal([]byte(str), &servers) | ||
| } | ||
|
|
||
| func (secrets SecretMap) Value() (driver.Value, error) { | ||
| b, err := json.Marshal(secrets) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return string(b), nil | ||
| } | ||
|
|
||
| func (secrets *SecretMap) Scan(value any) error { | ||
| str, ok := value.(string) | ||
| if !ok { | ||
| return errors.New("failed to scan secret list") | ||
| } | ||
| return json.Unmarshal([]byte(str), &secrets) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix Scan implementations to populate ServerList/SecretMap
Both ServerList.Scan and SecretMap.Scan pass &servers/&secrets to json.Unmarshal. Because servers is already a pointer (*ServerList), passing the address of that pointer gives **ServerList and json.Unmarshal only updates the local pointer variable, leaving the caller’s slice/map unchanged. Any read from the database will therefore return empty server and secret lists even though the JSON is valid. Unmarshal directly into the pointer (json.Unmarshal(..., servers) and json.Unmarshal(..., secrets)) so that retrieved working sets contain their stored values.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not totally sure why, but this does already work as is. I'll update it anyway.
pkg/workingset/workingset.go
Outdated
| } | ||
| } | ||
|
|
||
| return "", fmt.Errorf("failed to create working set id: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return "", fmt.Errorf("failed to create working set id: %w", err) | |
| return "", fmt.Errorf("failed to create working set id") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I trusted AI too much on that one lol
| } else { | ||
| id, err = createWorkingSetID(ctx, name, dao) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create working set id: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return fmt.Errorf("failed to create working set id: %w", err) | |
| return fmt.Errorf("failed to create working set id: %w", id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is actually correct, since we want to wrap the error given. id will just be blank if there's an error.
| workingSet.Servers[i] = s | ||
| } | ||
|
|
||
| if err := workingSet.Validate(); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: should we validate server uniqueness?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The db does have the id as the primary key, which ensures primary key uniqueness. Is there something else you were also thinking of?
pkg/db/workingset.go
Outdated
| if !ok { | ||
| return errors.New("failed to scan secret list") | ||
| } | ||
| return json.Unmarshal([]byte(str), &secrets) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Better to use secrets instead of &secrets?
I wasn't able to actually uncover a bug here because json.Unmarshal will automatically deference pointers until it gets the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that explains why both work. I'll switch it.
pkg/db/workingset.go
Outdated
| if !ok { | ||
| return errors.New("failed to scan server list") | ||
| } | ||
| return json.Unmarshal([]byte(str), &servers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Better to use servers instead of &servers?
Working Sets
Working sets allow you to organize and manage collections of MCP servers as a single unit.
See
docs/working-sets.mdfor more info and limitations of the current implementation.Tests will be coming in a follow up PR.
Quickstart