Skip to main content
Glama
main.go11.8 kB
package main import ( "context" "encoding/json" "flag" "fmt" "os" "time" "github.com/ZanzyTHEbar/mcp-memory-libsql-go/internal/apptype" "github.com/modelcontextprotocol/go-sdk/mcp" ) type StepResult struct { Name string `json:"name"` Success bool `json:"success"` Error string `json:"error,omitempty"` ElapsedMs int64 `json:"elapsed_ms"` } type Report struct { SSEURL string `json:"sse_url"` StartedAt time.Time `json:"started_at"` DurationMs int64 `json:"duration_ms"` Steps []StepResult `json:"steps"` Passed bool `json:"passed"` } func main() { sseURL := flag.String("sse-url", "http://localhost:8080/sse", "SSE endpoint URL") project := flag.String("project", "default", "Project name to use") timeout := flag.Duration("timeout", 30*time.Second, "Overall timeout") flag.Parse() ctx, cancel := context.WithTimeout(context.Background(), *timeout) defer cancel() client := mcp.NewClient(&mcp.Implementation{Name: "integration-tester", Version: "dev"}, nil) transport := mcp.NewSSEClientTransport(*sseURL, nil) start := time.Now() report := Report{SSEURL: *sseURL, StartedAt: start} steps := make([]StepResult, 0, 16) // Connect tConn := time.Now() connRes := StepResult{Name: "connect"} session, err := client.Connect(ctx, transport) if err != nil { connRes.Success = false connRes.Error = err.Error() connRes.ElapsedMs = elapsedMsSince(tConn) steps = append(steps, connRes) report.Steps = steps report.DurationMs = elapsedMsSince(start) report.Passed = false enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") _ = enc.Encode(report) os.Exit(1) } defer session.Close() connRes.Success = true connRes.ElapsedMs = elapsedMsSince(tConn) steps = append(steps, connRes) // Individual steps steps = append(steps, runListTools(ctx, session)) steps = append(steps, runCreateEntities(ctx, session, *project)) steps = append(steps, runSearchNodes(ctx, session, *project, "n")) steps = append(steps, runReadGraph(ctx, session, *project)) steps = append(steps, runSeedGraph(ctx, session, *project)) steps = append(steps, runNeighbors(ctx, session, *project)) steps = append(steps, runWalk(ctx, session, *project)) steps = append(steps, runShortestPath(ctx, session, *project)) // DELETE tests on fresh instance steps = append(steps, runDeleteRelation(ctx, session, *project, "b", "c", "r")) steps = append(steps, runDeleteRelations(ctx, session, *project, []apptype.RelationTuple{{From: "a", To: "d", RelationType: "r"}})) steps = append(steps, runDeleteObservationsByContents(ctx, session, *project, "a", []string{"oa"})) steps = append(steps, runDeleteEntity(ctx, session, *project, "n1")) steps = append(steps, runDeleteEntities(ctx, session, *project, []string{"a", "b"})) // finalize report report.Steps = steps report.DurationMs = elapsedMsSince(start) report.Passed = true for _, s := range steps { if !s.Success { report.Passed = false break } } enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") _ = enc.Encode(report) if !report.Passed { os.Exit(1) } } func runListTools(ctx context.Context, session *mcp.ClientSession) StepResult { t0 := time.Now() res := StepResult{Name: "list_tools"} if _, err := session.ListTools(ctx, &mcp.ListToolsParams{}); err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runCreateEntities(ctx context.Context, session *mcp.ClientSession, project string) StepResult { t0 := time.Now() res := StepResult{Name: "create_entities"} args := apptype.CreateEntitiesArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Entities: []apptype.Entity{ {Name: "n1", EntityType: "t", Observations: []string{"o1"}}, {Name: "n2", EntityType: "t", Observations: []string{"o2"}}, }, } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "create_entities", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runSearchNodes(ctx context.Context, session *mcp.ClientSession, project, q string) StepResult { t0 := time.Now() res := StepResult{Name: "search_nodes"} args := apptype.SearchNodesArgs{ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Query: q, Limit: 10} raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "search_nodes", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runReadGraph(ctx context.Context, session *mcp.ClientSession, project string) StepResult { t0 := time.Now() res := StepResult{Name: "read_graph"} args := apptype.ReadGraphArgs{ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Limit: 10} raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "read_graph", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runSeedGraph(ctx context.Context, session *mcp.ClientSession, project string) StepResult { t0 := time.Now() res := StepResult{Name: "seed_graph"} // a,b,c,d ca := apptype.CreateEntitiesArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Entities: []apptype.Entity{ {Name: "a", EntityType: "t", Observations: []string{"oa"}}, {Name: "b", EntityType: "t", Observations: []string{"ob"}}, {Name: "c", EntityType: "t", Observations: []string{"oc"}}, {Name: "d", EntityType: "t", Observations: []string{"od"}}, }, } raw, _ := json.Marshal(ca) if _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "create_entities", Arguments: json.RawMessage(raw)}); err != nil { res.Success = false res.Error = fmt.Sprintf("create_entities seed: %v", err) res.ElapsedMs = elapsedMsSince(t0) return res } // relations: a->b, b->c, a->d cr := apptype.CreateRelationsArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Relations: []apptype.Relation{{From: "a", To: "b", RelationType: "r"}, {From: "b", To: "c", RelationType: "r"}, {From: "a", To: "d", RelationType: "r"}}, } rraw, _ := json.Marshal(cr) if _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "create_relations", Arguments: json.RawMessage(rraw)}); err != nil { res.Success = false res.Error = fmt.Sprintf("create_relations seed: %v", err) res.ElapsedMs = elapsedMsSince(t0) return res } res.Success = true res.ElapsedMs = elapsedMsSince(t0) return res } func runNeighbors(ctx context.Context, session *mcp.ClientSession, project string) StepResult { t0 := time.Now() res := StepResult{Name: "neighbors"} args := map[string]any{ "projectArgs": map[string]any{"projectName": project}, "names": []string{"a"}, "direction": "out", } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "neighbors", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runWalk(ctx context.Context, session *mcp.ClientSession, project string) StepResult { t0 := time.Now() res := StepResult{Name: "walk"} args := map[string]any{ "projectArgs": map[string]any{"projectName": project}, "names": []string{"a"}, "maxDepth": 2, "direction": "out", } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "walk", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runShortestPath(ctx context.Context, session *mcp.ClientSession, project string) StepResult { t0 := time.Now() res := StepResult{Name: "shortest_path"} args := map[string]any{ "projectArgs": map[string]any{"projectName": project}, "from": "a", "to": "c", "direction": "out", } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "shortest_path", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runDeleteRelation(ctx context.Context, session *mcp.ClientSession, project, from, to, relType string) StepResult { t0 := time.Now() res := StepResult{Name: "delete_relation"} args := apptype.DeleteRelationArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Source: from, Target: to, Type: relType, } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "delete_relation", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runDeleteRelations(ctx context.Context, session *mcp.ClientSession, project string, tuples []apptype.RelationTuple) StepResult { t0 := time.Now() res := StepResult{Name: "delete_relations"} args := apptype.DeleteRelationsArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Relations: tuples, } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "delete_relations", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runDeleteObservationsByContents(ctx context.Context, session *mcp.ClientSession, project, entity string, contents []string) StepResult { t0 := time.Now() res := StepResult{Name: "delete_observations"} args := apptype.DeleteObservationsArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, EntityName: entity, Contents: contents, } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "delete_observations", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runDeleteEntity(ctx context.Context, session *mcp.ClientSession, project, name string) StepResult { t0 := time.Now() res := StepResult{Name: "delete_entity"} args := apptype.DeleteEntityArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Name: name, } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "delete_entity", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } func runDeleteEntities(ctx context.Context, session *mcp.ClientSession, project string, names []string) StepResult { t0 := time.Now() res := StepResult{Name: "delete_entities"} args := apptype.DeleteEntitiesArgs{ ProjectArgs: apptype.ProjectArgs{ProjectName: project}, Names: names, } raw, _ := json.Marshal(args) _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "delete_entities", Arguments: json.RawMessage(raw)}) if err != nil { res.Success = false res.Error = err.Error() } else { res.Success = true } res.ElapsedMs = elapsedMsSince(t0) return res } // elapsedMsSince returns max(1ms, elapsed) to avoid zero durations on fast steps func elapsedMsSince(t0 time.Time) int64 { d := time.Since(t0) / time.Millisecond if d <= 0 { return 1 } return int64(d) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ZanzyTHEbar/mcp-memory-libsql-go'

If you have feedback or need assistance with the MCP directory API, please join our Discord server