mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
fix(studio): derive Node MCP names from script entry points
This commit is contained in:
1 parent
77990ed9eb
commit
9097d2a036
3 files changed
+126
-1
No files matched your search
@@ -166,7 +166,7 @@ func NameFromArgv(command string, args []string) string {
|
||||
}
|
||||
}
|
||||
case "node":
|
||||
if operand := firstCommandOperand(args); operand != "" {
|
||||
if operand := nodeCommandOperand(args); operand != "" {
|
||||
candidate = operand
|
||||
}
|
||||
case "uv":
|
||||
@@ -221,6 +221,27 @@ func firstCommandOperand(args []string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func nodeCommandOperand(args []string) string {
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
switch {
|
||||
case arg == "--":
|
||||
if i+1 < len(args) {
|
||||
return args[i+1]
|
||||
}
|
||||
return ""
|
||||
case arg == "-", arg == "-e", arg == "--eval", arg == "-p", arg == "--print",
|
||||
strings.HasPrefix(arg, "--eval="), strings.HasPrefix(arg, "--print="):
|
||||
return ""
|
||||
case arg == "-r", arg == "--require", arg == "--import":
|
||||
i++
|
||||
case arg != "" && !strings.HasPrefix(arg, "-"):
|
||||
return arg
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SanitizeName reduces a derived name to the lowercase-and-dashes form config
|
||||
// and tool prefixes accept.
|
||||
func SanitizeName(raw string) string {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package mcpsetup
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNodeServerNameUsesScriptEntryPoint(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
args []string
|
||||
name string
|
||||
}{
|
||||
{[]string{"reasonix_server.js", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"--require", "./preload.cjs", "reasonix_server.js", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"-r", "./preload.cjs", "reasonix_server.js", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"--require=./preload.cjs", "reasonix_server.js", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"--import", "./preload.mjs", "reasonix_server.js", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"--import=./preload.mjs", "reasonix_server.js", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"--require", "./preload.cjs", "--import", "./preload.mjs", "reasonix_server.js"}, "reasonix-server"},
|
||||
{[]string{"--", "reasonix_server.js", "--require", "client-mode"}, "reasonix-server"},
|
||||
{[]string{"-e", "0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"--eval", "0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"--eval=0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"-p", "0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"--print", "0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"--print=true", "0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"--require", "./preload.cjs", "--eval", "0", "client-mode"}, "mcp-server"},
|
||||
{[]string{"-", "client-mode"}, "mcp-server"},
|
||||
{[]string{"--require", "./preload.cjs"}, "mcp-server"},
|
||||
{[]string{"--require"}, "mcp-server"},
|
||||
} {
|
||||
t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
|
||||
if got := NameFromArgv("node", tc.args); got != tc.name {
|
||||
t.Errorf("name = %q, want %q", got, tc.name)
|
||||
}
|
||||
entry, err := ParseArgs(append([]string{"--", "node"}, tc.args...))
|
||||
if err != nil || entry.Name != tc.name || entry.Command != "node" || !reflect.DeepEqual(entry.Args, tc.args) {
|
||||
t.Errorf("CLI entry = %+v, err=%v", entry, err)
|
||||
}
|
||||
explicit, err := ParseArgs(append([]string{"manual", "--", "node"}, tc.args...))
|
||||
if err != nil || explicit.Name != "manual" || !reflect.DeepEqual(explicit.Args, tc.args) {
|
||||
t.Errorf("explicit entry = %+v, err=%v", explicit, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
if got := NameFromArgv("npx", []string{"-p", "bootstrap", "demo-server"}); got != "demo-server" {
|
||||
t.Errorf("npx control = %q", got)
|
||||
}
|
||||
if got := NameFromArgv("python3", []string{"-m", "demo_server"}); got != "demo-server" {
|
||||
t.Errorf("Python control = %q", got)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package serve
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"reasonix/internal/contract/config"
|
||||
"reasonix/internal/session/control"
|
||||
)
|
||||
|
||||
func TestMCPParseNodeNameUsesScriptEntryPoint(t *testing.T) {
|
||||
ctrl := control.New(control.Options{})
|
||||
t.Cleanup(ctrl.Close)
|
||||
srv := httptest.NewServer(operatorHandler(New(ctrl, NewBroadcaster(), config.ServeConfig{})))
|
||||
t.Cleanup(srv.Close)
|
||||
for _, tc := range []struct {
|
||||
input string
|
||||
name string
|
||||
}{
|
||||
{"node --require ./preload.cjs reasonix_server.js client-mode", "reasonix-server"},
|
||||
{"node --require=./preload.cjs reasonix_server.js client-mode", "reasonix-server"},
|
||||
{"node --import ./preload.mjs reasonix_server.js client-mode", "reasonix-server"},
|
||||
{"node --import=./preload.mjs reasonix_server.js client-mode", "reasonix-server"},
|
||||
{"node --eval 0 client-mode", "mcp-server"},
|
||||
{"node - client-mode", "mcp-server"},
|
||||
} {
|
||||
resp := postJSON(t, srv.URL+"/mcp/parse", map[string]string{"input": tc.input})
|
||||
var got struct {
|
||||
Servers []draftServer `json:"servers"`
|
||||
Risks []draftRisk `json:"risks"`
|
||||
}
|
||||
err := json.NewDecoder(resp.Body).Decode(&got)
|
||||
resp.Body.Close()
|
||||
if err != nil || resp.StatusCode != http.StatusOK || len(got.Servers) != 1 {
|
||||
t.Fatalf("preview %q: status=%d body=%+v err=%v", tc.input, resp.StatusCode, got, err)
|
||||
}
|
||||
entry := got.Servers[0]
|
||||
if entry.Name != tc.name || entry.Transport != "stdio" || entry.Command+" "+strings.Join(entry.Args, " ") != tc.input {
|
||||
t.Errorf("preview %q = %+v, want name %q and original argv", tc.input, entry, tc.name)
|
||||
}
|
||||
if len(got.Risks) != 1 || got.Risks[0].Server != tc.name || got.Risks[0].Kind != "shell" || got.Risks[0].Detail != tc.input {
|
||||
t.Errorf("preview disclosure = %+v", got.Risks)
|
||||
}
|
||||
}
|
||||
if names := ctrl.ConfiguredMCPNames(); len(names) != 0 {
|
||||
t.Errorf("preview installed servers: %v", names)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user