mcp: uncomment test, change struct{} to any (#341)

Address comments on #325.
This commit is contained in:
Jonathan Amsterdam 2025-08-21 10:18:52 -04:00 • committed by GitHub
commit 5b1f328fd4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 163 additions and 206 deletions

View file

@ -482,34 +482,34 @@ func (k knowledgeBase) AddObservations(ctx context.Context, req *mcp.ServerReque
}, nil }, nil
} }
func (k knowledgeBase) DeleteEntities(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args DeleteEntitiesArgs) (*mcp.CallToolResult, struct{}, error) { func (k knowledgeBase) DeleteEntities(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args DeleteEntitiesArgs) (*mcp.CallToolResult, any, error) {
var res mcp.CallToolResult var res mcp.CallToolResult
err := k.deleteEntities(args.EntityNames) err := k.deleteEntities(args.EntityNames)
if err != nil { if err != nil {
return nil, struct{}{}, err return nil, nil, err
} }
res.Content = []mcp.Content{ res.Content = []mcp.Content{
&mcp.TextContent{Text: "Entities deleted successfully"}, &mcp.TextContent{Text: "Entities deleted successfully"},
} }
return &res, struct{}{}, nil return &res, nil, nil
} }
func (k knowledgeBase) DeleteObservations(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args DeleteObservationsArgs) (*mcp.CallToolResult, struct{}, error) { func (k knowledgeBase) DeleteObservations(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args DeleteObservationsArgs) (*mcp.CallToolResult, any, error) {
var res mcp.CallToolResult var res mcp.CallToolResult
err := k.deleteObservations(args.Deletions) err := k.deleteObservations(args.Deletions)
if err != nil { if err != nil {
return nil, struct{}{}, err return nil, nil, err
} }
res.Content = []mcp.Content{ res.Content = []mcp.Content{
&mcp.TextContent{Text: "Observations deleted successfully"}, &mcp.TextContent{Text: "Observations deleted successfully"},
} }
return &res, struct{}{}, nil return &res, nil, nil
} }
func (k knowledgeBase) DeleteRelations(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args DeleteRelationsArgs) (*mcp.CallToolResult, struct{}, error) { func (k knowledgeBase) DeleteRelations(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args DeleteRelationsArgs) (*mcp.CallToolResult, struct{}, error) {
@ -554,8 +554,7 @@ func (k knowledgeBase) SearchNodes(ctx context.Context, req *mcp.ServerRequest[*
&mcp.TextContent{Text: "Nodes searched successfully"}, &mcp.TextContent{Text: "Nodes searched successfully"},
} }
res.StructuredContent = graph return &res, graph, nil
return &res, KnowledgeGraph{}, nil
} }
func (k knowledgeBase) OpenNodes(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args OpenNodesArgs) (*mcp.CallToolResult, KnowledgeGraph, error) { func (k knowledgeBase) OpenNodes(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParams], args OpenNodesArgs) (*mcp.CallToolResult, KnowledgeGraph, error) {

View file

@ -427,203 +427,161 @@ func TestFileFormatting(t *testing.T) {
} }
// TestMCPServerIntegration tests the knowledge base through MCP server layer. // TestMCPServerIntegration tests the knowledge base through MCP server layer.
// func TestMCPServerIntegration(t *testing.T) { func TestMCPServerIntegration(t *testing.T) {
// for name, newStore := range stores() { for name, newStore := range stores() {
// t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
// s := newStore(t) s := newStore(t)
// kb := knowledgeBase{s: s} kb := knowledgeBase{s: s}
// // Create mock server session // Create mock server session
// ctx := context.Background() ctx := context.Background()
// serverSession := &mcp.ServerSession{}
// // Test CreateEntities through MCP createResult, out, err := kb.CreateEntities(ctx, nil, CreateEntitiesArgs{
// createEntitiesParams := &mcp.CallToolParamsFor[CreateEntitiesArgs]{ Entities: []Entity{
// Arguments: CreateEntitiesArgs{ {
// Entities: []Entity{ Name: "TestPerson",
// { EntityType: "Person",
// Name: "TestPerson", Observations: []string{"Likes testing"},
// EntityType: "Person", },
// Observations: []string{"Likes testing"}, },
// }, })
// }, if err != nil {
// }, t.Fatalf("MCP CreateEntities failed: %v", err)
// } }
if createResult.IsError {
t.Fatalf("MCP CreateEntities returned error: %v", createResult.Content)
}
if len(out.Entities) != 1 {
t.Errorf("expected 1 entity created, got %d", len(out.Entities))
}
// createResult, err := kb.CreateEntities(ctx, requestFor(serverSession, createEntitiesParams)) // Test ReadGraph through MCP
// if err != nil { readResult, outg, err := kb.ReadGraph(ctx, nil, nil)
// t.Fatalf("MCP CreateEntities failed: %v", err) if err != nil {
// } t.Fatalf("MCP ReadGraph failed: %v", err)
// if createResult.IsError { }
// t.Fatalf("MCP CreateEntities returned error: %v", createResult.Content) if readResult.IsError {
// } t.Fatalf("MCP ReadGraph returned error: %v", readResult.Content)
// if len(createResult.StructuredContent.Entities) != 1 { }
// t.Errorf("expected 1 entity created, got %d", len(createResult.StructuredContent.Entities)) if len(outg.Entities) != 1 {
// } t.Errorf("expected 1 entity in graph, got %d", len(outg.Entities))
}
// // Test ReadGraph through MCP relationsResult, outr, err := kb.CreateRelations(ctx, nil, CreateRelationsArgs{
// readParams := &mcp.CallToolParamsFor[struct{}]{} Relations: []Relation{
// readResult, err := kb.ReadGraph(ctx, requestFor(serverSession, readParams)) {
// if err != nil { From: "TestPerson",
// t.Fatalf("MCP ReadGraph failed: %v", err) To: "Testing",
// } RelationType: "likes",
// if readResult.IsError { },
// t.Fatalf("MCP ReadGraph returned error: %v", readResult.Content) },
// } })
// if len(readResult.StructuredContent.Entities) != 1 { if err != nil {
// t.Errorf("expected 1 entity in graph, got %d", len(readResult.StructuredContent.Entities)) t.Fatalf("MCP CreateRelations failed: %v", err)
// } }
if relationsResult.IsError {
t.Fatalf("MCP CreateRelations returned error: %v", relationsResult.Content)
}
if len(outr.Relations) != 1 {
t.Errorf("expected 1 relation created, got %d", len(outr.Relations))
}
// // Test CreateRelations through MCP obsResult, outo, err := kb.AddObservations(ctx, nil, AddObservationsArgs{
// createRelationsParams := &mcp.CallToolParamsFor[CreateRelationsArgs]{ Observations: []Observation{
// Arguments: CreateRelationsArgs{ {
// Relations: []Relation{ EntityName: "TestPerson",
// { Contents: []string{"Works remotely", "Drinks coffee"},
// From: "TestPerson", },
// To: "Testing", },
// RelationType: "likes", })
// }, if err != nil {
// }, t.Fatalf("MCP AddObservations failed: %v", err)
// }, }
// } if obsResult.IsError {
t.Fatalf("MCP AddObservations returned error: %v", obsResult.Content)
}
if len(outo.Observations) != 1 {
t.Errorf("expected 1 observation result, got %d", len(outo.Observations))
}
// relationsResult, err := kb.CreateRelations(ctx, requestFor(serverSession, createRelationsParams)) searchResult, outg, err := kb.SearchNodes(ctx, nil, SearchNodesArgs{
// if err != nil { Query: "coffee",
// t.Fatalf("MCP CreateRelations failed: %v", err) })
// } if err != nil {
// if relationsResult.IsError { t.Fatalf("MCP SearchNodes failed: %v", err)
// t.Fatalf("MCP CreateRelations returned error: %v", relationsResult.Content) }
// } if searchResult.IsError {
// if len(relationsResult.StructuredContent.Relations) != 1 { t.Fatalf("MCP SearchNodes returned error: %v", searchResult.Content)
// t.Errorf("expected 1 relation created, got %d", len(relationsResult.StructuredContent.Relations)) }
// } if len(outg.Entities) != 1 {
t.Errorf("expected 1 entity from search, got %d", len(outg.Entities))
}
// // Test AddObservations through MCP openResult, outg, err := kb.OpenNodes(ctx, nil, OpenNodesArgs{
// addObsParams := &mcp.CallToolParamsFor[AddObservationsArgs]{ Names: []string{"TestPerson"},
// Arguments: AddObservationsArgs{ })
// Observations: []Observation{ if err != nil {
// { t.Fatalf("MCP OpenNodes failed: %v", err)
// EntityName: "TestPerson", }
// Contents: []string{"Works remotely", "Drinks coffee"}, if openResult.IsError {
// }, t.Fatalf("MCP OpenNodes returned error: %v", openResult.Content)
// }, }
// }, if len(outg.Entities) != 1 {
// } t.Errorf("expected 1 entity from open, got %d", len(outg.Entities))
}
// obsResult, err := kb.AddObservations(ctx, requestFor(serverSession, addObsParams)) deleteObsResult, _, err := kb.DeleteObservations(ctx, nil, DeleteObservationsArgs{
// if err != nil { Deletions: []Observation{
// t.Fatalf("MCP AddObservations failed: %v", err) {
// } EntityName: "TestPerson",
// if obsResult.IsError { Observations: []string{"Works remotely"},
// t.Fatalf("MCP AddObservations returned error: %v", obsResult.Content) },
// } },
// if len(obsResult.StructuredContent.Observations) != 1 { })
// t.Errorf("expected 1 observation result, got %d", len(obsResult.StructuredContent.Observations)) if err != nil {
// } t.Fatalf("MCP DeleteObservations failed: %v", err)
}
if deleteObsResult.IsError {
t.Fatalf("MCP DeleteObservations returned error: %v", deleteObsResult.Content)
}
// // Test SearchNodes through MCP deleteRelResult, _, err := kb.DeleteRelations(ctx, nil, DeleteRelationsArgs{
// searchParams := &mcp.CallToolParamsFor[SearchNodesArgs]{ Relations: []Relation{
// Arguments: SearchNodesArgs{ {
// Query: "coffee", From: "TestPerson",
// }, To: "Testing",
// } RelationType: "likes",
},
},
})
if err != nil {
t.Fatalf("MCP DeleteRelations failed: %v", err)
}
if deleteRelResult.IsError {
t.Fatalf("MCP DeleteRelations returned error: %v", deleteRelResult.Content)
}
// searchResult, err := kb.SearchNodes(ctx, requestFor(serverSession, searchParams)) deleteEntResult, _, err := kb.DeleteEntities(ctx, nil, DeleteEntitiesArgs{
// if err != nil { EntityNames: []string{"TestPerson"},
// t.Fatalf("MCP SearchNodes failed: %v", err) })
// } if err != nil {
// if searchResult.IsError { t.Fatalf("MCP DeleteEntities failed: %v", err)
// t.Fatalf("MCP SearchNodes returned error: %v", searchResult.Content) }
// } if deleteEntResult.IsError {
// if len(searchResult.StructuredContent.Entities) != 1 { t.Fatalf("MCP DeleteEntities returned error: %v", deleteEntResult.Content)
// t.Errorf("expected 1 entity from search, got %d", len(searchResult.StructuredContent.Entities)) }
// }
// // Test OpenNodes through MCP // Verify final state
// openParams := &mcp.CallToolParamsFor[OpenNodesArgs]{ _, outg, err = kb.ReadGraph(ctx, nil, nil)
// Arguments: OpenNodesArgs{ if err != nil {
// Names: []string{"TestPerson"}, t.Fatalf("Final MCP ReadGraph failed: %v", err)
// }, }
// } if len(outg.Entities) != 0 {
t.Errorf("expected empty graph after deletion, got %d entities", len(outg.Entities))
// openResult, err := kb.OpenNodes(ctx, requestFor(serverSession, openParams)) }
// if err != nil { })
// t.Fatalf("MCP OpenNodes failed: %v", err) }
// } }
// if openResult.IsError {
// t.Fatalf("MCP OpenNodes returned error: %v", openResult.Content)
// }
// if len(openResult.StructuredContent.Entities) != 1 {
// t.Errorf("expected 1 entity from open, got %d", len(openResult.StructuredContent.Entities))
// }
// // Test DeleteObservations through MCP
// deleteObsParams := &mcp.CallToolParamsFor[DeleteObservationsArgs]{
// Arguments: DeleteObservationsArgs{
// Deletions: []Observation{
// {
// EntityName: "TestPerson",
// Observations: []string{"Works remotely"},
// },
// },
// },
// }
// deleteObsResult, err := kb.DeleteObservations(ctx, requestFor(serverSession, deleteObsParams))
// if err != nil {
// t.Fatalf("MCP DeleteObservations failed: %v", err)
// }
// if deleteObsResult.IsError {
// t.Fatalf("MCP DeleteObservations returned error: %v", deleteObsResult.Content)
// }
// // Test DeleteRelations through MCP
// deleteRelParams := &mcp.CallToolParamsFor[DeleteRelationsArgs]{
// Arguments: DeleteRelationsArgs{
// Relations: []Relation{
// {
// From: "TestPerson",
// To: "Testing",
// RelationType: "likes",
// },
// },
// },
// }
// deleteRelResult, err := kb.DeleteRelations(ctx, requestFor(serverSession, deleteRelParams))
// if err != nil {
// t.Fatalf("MCP DeleteRelations failed: %v", err)
// }
// if deleteRelResult.IsError {
// t.Fatalf("MCP DeleteRelations returned error: %v", deleteRelResult.Content)
// }
// // Test DeleteEntities through MCP
// deleteEntParams := &mcp.CallToolParamsFor[DeleteEntitiesArgs]{
// Arguments: DeleteEntitiesArgs{
// EntityNames: []string{"TestPerson"},
// },
// }
// deleteEntResult, err := kb.DeleteEntities(ctx, requestFor(serverSession, deleteEntParams))
// if err != nil {
// t.Fatalf("MCP DeleteEntities failed: %v", err)
// }
// if deleteEntResult.IsError {
// t.Fatalf("MCP DeleteEntities returned error: %v", deleteEntResult.Content)
// }
// // Verify final state
// finalRead, err := kb.ReadGraph(ctx, requestFor(serverSession, readParams))
// if err != nil {
// t.Fatalf("Final MCP ReadGraph failed: %v", err)
// }
// if len(finalRead.StructuredContent.Entities) != 0 {
// t.Errorf("expected empty graph after deletion, got %d entities", len(finalRead.StructuredContent.Entities))
// }
// })
// }
// }
// TestMCPErrorHandling tests error scenarios through MCP layer. // TestMCPErrorHandling tests error scenarios through MCP layer.
func TestMCPErrorHandling(t *testing.T) { func TestMCPErrorHandling(t *testing.T) {

View file

@ -60,7 +60,7 @@ func TestStreamableTransports(t *testing.T) {
return nil, nil, nil return nil, nil, nil
} }
AddTool(server, &Tool{Name: "hang"}, hang) AddTool(server, &Tool{Name: "hang"}, hang)
AddTool(server, &Tool{Name: "sample"}, func(ctx context.Context, req *ServerRequest[*CallToolParams], args map[string]any) (*CallToolResult, any, error) { AddTool(server, &Tool{Name: "sample"}, func(ctx context.Context, req *ServerRequest[*CallToolParams], args any) (*CallToolResult, any, error) {
// Test that we can make sampling requests during tool handling. // Test that we can make sampling requests during tool handling.
// //
// Try this on both the request context and a background context, so // Try this on both the request context and a background context, so