ituoke/internal/mcpclient/agent_test.go

71 lines
1.9 KiB
Go

package mcpclient
import (
"context"
"errors"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"time"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
func TestAgentToolSessionsNamespacingDisableAndLeaseCancellation(t *testing.T) {
var calls atomic.Int32
server := newTestMCPServer(&calls)
remote := httptest.NewServer(mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server }, nil))
defer remote.Close()
service, _ := testService(t)
var ids []string
for _, name := range []string{"phone", "files"} {
view, err := service.SaveServer(ServerInput{Config: ServerConfig{Name: name, Transport: "http", URL: remote.URL, Enabled: true, TimeoutSeconds: 3}})
if err != nil {
t.Fatal(err)
}
ids = append(ids, view.Config.ID)
}
first, err := OpenTools(context.Background(), service, nil)
if err != nil {
t.Fatal(err)
}
defer first.Close()
if len(first.Tools()) != 4 {
t.Fatalf("tools: %d", len(first.Tools()))
}
unique := map[string]bool{}
for _, tool := range first.Tools() {
if unique[tool.Name] {
t.Fatal("duplicate tool name")
}
unique[tool.Name] = true
}
name := first.Tools()[0].Name
if _, err := first.Call(context.Background(), name, `{}`); err != nil {
t.Fatal(err)
}
second, err := OpenTools(context.Background(), service, nil)
if err != nil {
t.Fatal(err)
}
defer second.Close()
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond)
defer cancel()
if _, err := second.Call(ctx, second.Tools()[0].Name, `{}`); !errors.Is(err, context.DeadlineExceeded) {
t.Fatalf("waiting lease did not cancel: %v", err)
}
if calls.Load() != 1 {
t.Fatal("parallel action bypassed sequence lease")
}
if err := service.SetEnabled(ids[0], false); err != nil {
t.Fatal(err)
}
if _, err := first.Call(context.Background(), name, `{}`); err == nil {
t.Fatal("disabled service still executed")
}
if calls.Load() != 1 {
t.Fatal("disabled service was invoked")
}
}