-
Notifications
You must be signed in to change notification settings - Fork 14
Added state-mcp #3671
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
Added state-mcp #3671
Conversation
Version 0.47.0-RC2
Version 0.47.0-RC3
Version 0.47.0-RC3
Version 0.47.1-RC1
…shell doesnt support it
# Conflicts: # go.mod
|
@samueld-activator flagged you for review mainly for the high level architecture, much of the actual business logic I suggest you defer to Mitchell for now. Of main interest to you will be: @mitchell-as This is introducing the state-mcp executable with basic handling for tool calling. I'm not entirely happy with how primer and the output package are being treated, but addressing that properly would be a significantly bigger refactor that I don't want to get into now. |
mitchell-as
left a comment
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.
There are failing unit tests that need to be addressed: https://github.com/ActiveState/cli/actions/runs/16231227928/job/45834291877?pr=3671#step:14:1021.
I've reviewed everything except the 'state-mcp' folder. I will do so after either Samuel weighs in on the architecture, or my other comments are addressed.
| func Categories() ToolCategories { | ||
| return ToolCategories{ | ||
| ToolCategoryDebug, | ||
| } |
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.
nit: Usually we like to return pointers to avoid copies each time this function is called.
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've gotten into the habit of only using pointers when I intend to track the underlying type across different areas of responsibility. I don't believe we ever had any rule around this.
I'd have preferred to make this a constant, but Go is a little weird about what things can be constants.
internal/runners/cve/cve.go
Outdated
| defer func() { | ||
| if rc := recover(); rc != nil { | ||
| logging.Error("Recovered from panic: %v", rc) | ||
| fmt.Printf("Recovered from panic: %v\n", rc) | ||
| } | ||
| }() |
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.
None of the other runners have this. This seems like a quick, cheap fix that hides a more serious problem. Ideally we would utilize defensive programming to avoid this scenario.
Perhaps this is leftover from a debug session to identify the problem? In that case, please remove it.
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.
Thanks for catching. I don't recall why I did this, probably was trying to debug.
| projectRegex := regexp.MustCompile(fmt.Sprintf("(?m:(^project:\\s*%s))", ProjectURLRe)) | ||
| lockString := fmt.Sprintf("%s@%s", branch, version) | ||
| lockUpdate := []byte(fmt.Sprintf("${1}\nlock: %s", lockString)) | ||
| lockUpdate := []byte(fmt.Sprintf(`${1}\nlock: %s`, lockString)) |
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 don't see why this was changed. Now there will be no newline in the string, but instead a literal '' followed by an 'n'.
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.
Sorry I don't recall. Some of these changes go back months. Probably had a previous change that I reverted.
| // expressed in its own file. | ||
| package hello | ||
|
|
||
| import ( |
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 don't understand why there are changes in this file. It's supposed to be a pretty complete example for a runner. These changes are stripping it down and minimizing its usefulness.
Please don't tell me you had an AI produce a good chunk of this PR and I'm the first one reviewing it.
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.
Because it required me to satisfy project dependencies that are inappropriate in an MCP context. I could have went the extra mile and mocked them anyway, but in reviewing this I didn't feel like it added any real value for the purposes of showing an example runner. I don't mind bringing it back and mocking it if you disagree.
No I did not have AI generate any significant parts. I use it mainly as a glorified auto completer. I will say I've found it useful to generate larger bits of logic when working with technologies I'm unfamiliar with, but that's obviously not the case here.
| w := NewWriteProxy(f.cfg.OutWriter, func(p []byte) { | ||
| f.history.Print = append(f.history.Print, string(p)) | ||
| }) |
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 wish there was a way to not have to construct this every single time this function is called. I can't think of one though...
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.
Yeah I went through a couple of different ideas and this one felt the least awkward, but definitely still awkward.
This goes back to my earlier comment; I'd like to address this better but I don't think I can reasonably do so without blowing up the scope of the mcp story significantly, so for now it'll have to be an annoyance that we get to later (which is starting to become a bit of a list wrt the output package..).
| _, err = HomeDir() | ||
| assert.Error(t, err) | ||
| assert.Contains(t, err.Error(), "HOME environment variable is unset") | ||
| assert.NoError(t, 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.
I feel like this change negates the value of the test since you've changed init() to check for environment variables.
Please consider either removing the test, or changing it to be more useful.
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 is testing that we get our home dir with no env vars set, I don't think it makes sense to remove it.
Note the error tells you to set your HOME dir as it's the one way a user could address this issue. That doesn't mean that the HOME dir not being set is the cause of the issue.
| u, err := user.Current() | ||
| if err == nil { | ||
| return u.HomeDir, 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.
What is the rationale for this change? This could potentially be very significant, as it affects every installation. I'm not very comfortable seeing this.
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 addresses running state tool or state-mcp without any environment variables. In the case of mcp it seems common that servers are ran without any env vars, and so relying on HOME will break them. user.Current() uses low level system bindings to retrieve the user info, rather than env vars. This is what all the refactoring in user and storage is about, and why configdir was removed.
This will be required for state-mcp, and I recall occasionally seeing rollbar errors about HOME not being set, so it will help there too.
I'm not too concerned with these changes, either way we rely on the system to tell us the home dir of the current user, it's just through a different channel. And configdir is a very dumb library, I looked into fixing its issues and found that it's so simplistic I was better off just copying the paths it used.
| "github.com/ActiveState/cli/internal/constants" | ||
| "github.com/ActiveState/cli/internal/osutils/user" | ||
| "github.com/google/uuid" | ||
| "github.com/shibukawa/configdir" |
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.
May I ask why we are no longer using this dependency and instead creating our own version?
Not sure why this is suddenly breaking. The cast library was updated, but the code paths for the errors I'm seeing were not..
mitchell-as
left a comment
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.
Looks good to me!
| func TestServerHello(t *testing.T) { | ||
| t.Skip(` | ||
| Fails due to state-svc not being detected when run as regular test, | ||
| works when running with debugger. Problem for another day. |
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.
Do we have a ticket to track this? Otherwise we might lose track of it.
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 going to leave it alone for now as this feels like a growing pain. This really isn't even a unit test if it relies on state-svc. It's just that we currently don't have a way to end to end test MCP. That'll be its own thing down the line I'm sure but it's not a burning need at the moment.
cmd/state/donotshipme/donotshipme.go
Outdated
| @@ -0,0 +1,17 @@ | |||
| package donotshipme | |||
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 don't understand why this is here or what it's supposed to do or prevent. Would you mind enlightening me? The panic still doesn't shed much light on it for me.
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.
HAH! Thanks for catching! Seems I already dropped the import of this so it shouldn't bite, but obviously forgot to clean this up.
This was from when it started out as a proof of concept. I was paranoid about this bleeding into our codebase somehow.
8ffadb2
https://activestatef.atlassian.net/browse/CP-945