Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5b93d38
Create Memory-graph.go
drQedwards Apr 20, 2026
7a0cf30
Create Peek.go
drQedwards Apr 20, 2026
7baaa7f
Add files via upload
drQedwards Apr 20, 2026
643341e
Update cmd/Memory-graph.go
drQedwards Apr 20, 2026
b5c37d6
Update cmd/Peek.go
drQedwards Apr 20, 2026
703838a
Create Tools.go
drQedwards Apr 20, 2026
22c9d4f
Update Tools.go
drQedwards Apr 20, 2026
aaf6007
Create Peek.go
drQedwards Apr 20, 2026
6345f35
Delete cmd/Internal/Memorygraph directory
drQedwards Apr 20, 2026
5d8f026
Update Peek.go
drQedwards Apr 20, 2026
03e6f4e
Update Memory-graph.go
drQedwards Apr 20, 2026
8bee89d
Create Memorygraph.go
drQedwards Apr 20, 2026
647451d
Create tools.go
drQedwards Apr 20, 2026
c35e370
Update Memorygraph.go
drQedwards Apr 20, 2026
8a8c24a
Add files via upload
drQedwards Apr 20, 2026
ca5f18e
Update and rename graph.go to memorygraph.go
drQedwards Apr 20, 2026
d643379
Delete internal/Memorygraph/Memorygraph.go
drQedwards Apr 20, 2026
970b03e
Merge pull request #1 from drQedwards/drQedwards-patch-1
drQedwards Apr 20, 2026
d860941
Rename memorygraph.go to Memory-graph.go
drQedwards Apr 20, 2026
c423945
Delete cmd/Memory-graph.go
drQedwards Apr 20, 2026
159d46d
Delete cmd/Peek.go
drQedwards Apr 20, 2026
ee44b50
Delete cmd/tools.go
drQedwards Apr 20, 2026
89a0375
Update server.go
drQedwards Apr 20, 2026
bfee75c
Update server.go
drQedwards Apr 20, 2026
a866825
Create memorygraph
drQedwards Apr 20, 2026
801dec4
Delete internal/memorygraph
drQedwards Apr 20, 2026
65fcf40
Rename Memory-graph.go to memory_graph.go
drQedwards Apr 20, 2026
7d517e2
Rename memory_graph.go to memory_graph.go
drQedwards Apr 20, 2026
228dc98
Create peek.go
drQedwards Apr 20, 2026
af84952
Create tools.go
drQedwards Apr 20, 2026
8ecd1e8
Delete internal/Memorygraph directory
drQedwards Apr 20, 2026
f496e91
Update server.go
drQedwards Apr 20, 2026
00c5557
Update internal/mcp/server.go
drQedwards Apr 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 170 additions & 1 deletion internal/mcp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"os"
"strings"

"github.com/supermodeltools/cli/internal/Memorygraph"

Check failure on line 12 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

no required module provides package github.com/supermodeltools/cli/internal/Memorygraph; to add it:

Check failure on line 12 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

no required module provides package github.com/supermodeltools/cli/internal/Memorygraph; to add it:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"github.com/supermodeltools/cli/internal/analyze"
"github.com/supermodeltools/cli/internal/api"
"github.com/supermodeltools/cli/internal/build"
Expand Down Expand Up @@ -113,6 +114,80 @@
},
},
},
{
Name: "upsert_memory_node",
Description: "Upsert a typed knowledge node into the persistent memory graph.",
InputSchema: toolSchema{
Type: "object",
Properties: map[string]schemaProp{
"type": {Type: "string", Description: "Node type: fact, concept, entity, event, procedure, context."},
"label": {Type: "string", Description: "Short unique label for the node."},
"content": {Type: "string", Description: "Full content body of the node."},
},
Required: []string{"type", "label", "content"},
},
},
{
Name: "create_relation",
Description: "Create a directed weighted edge between two memory graph nodes.",
InputSchema: toolSchema{
Type: "object",
Properties: map[string]schemaProp{
"source_id": {Type: "string", Description: "ID of the source node."},
"target_id": {Type: "string", Description: "ID of the target node."},
"relation": {Type: "string", Description: "Relation type, e.g. related_to, depends_on, part_of."},
"weight": {Type: "number", Description: "Edge weight between 0 and 1 (default 1.0)."},
},
Required: []string{"source_id", "target_id", "relation"},
},
},
{
Name: "search_memory_graph",
Description: "Score and retrieve nodes from the memory graph matching a query, with optional one-hop neighbor expansion.",
InputSchema: toolSchema{
Type: "object",
Properties: map[string]schemaProp{
"query": {Type: "string", Description: "Search query string."},
"max_depth": {Type: "integer", Description: "Max BFS depth for neighbor expansion (default 1)."},
"top_k": {Type: "integer", Description: "Maximum number of direct results to return (default 5)."},
},
Required: []string{"query"},
},
},
{
Name: "retrieve_with_traversal",
Description: "BFS traversal from a start node up to maxDepth, returning visited nodes with decayed relevance scores.",
InputSchema: toolSchema{
Type: "object",
Properties: map[string]schemaProp{
"start_node_id": {Type: "string", Description: "ID of the node to start traversal from."},
"max_depth": {Type: "integer", Description: "Maximum BFS depth (default 3)."},
},
Required: []string{"start_node_id"},
},
},
{
Name: "prune_stale_links",
Description: "Remove edges below a weight threshold and orphaned nodes from the memory graph.",
InputSchema: toolSchema{
Type: "object",
Properties: map[string]schemaProp{
"threshold": {Type: "number", Description: "Minimum edge weight to retain (default 0.1)."},
},
},
},
{
Name: "add_interlinked_context",
Description: "Bulk-insert nodes and optionally auto-create similarity edges (Jaccard ≥ 0.72) between them.",
InputSchema: toolSchema{
Type: "object",
Properties: map[string]schemaProp{
"items": {Type: "array", Description: "Array of {type, label, content, metadata} node objects to insert."},
"auto_link": {Type: "boolean", Description: "If true, auto-create similarity edges between inserted nodes."},
},
Required: []string{"items"},
},
},
}

// --- Server ------------------------------------------------------------------
Expand Down Expand Up @@ -226,7 +301,71 @@
return s.toolGetGraph(ctx, args)
default:
return "", fmt.Errorf("unknown tool: %s", name)
}
func (s *server) callTool(ctx context.Context, name string, args map[string]any) (string, error) {

Check failure on line 304 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected operand, found '.'

Check failure on line 304 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

missing ',' in argument list
switch name {

Check failure on line 305 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

missing ',' in argument list
case "analyze":

Check failure on line 306 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected operand, found 'case'
return s.toolAnalyze(ctx, args)

Check failure on line 307 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

missing ',' before newline in composite literal

Check failure on line 307 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

missing ',' in composite literal
case "dead_code":

Check failure on line 308 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected operand, found 'case'
return s.toolDeadCode(ctx, args)

Check failure on line 309 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

missing ',' before newline in composite literal

Check failure on line 309 in internal/mcp/server.go

View workflow job for this annotation

GitHub Actions / govulncheck

missing ',' in composite literal
case "blast_radius":
return s.toolBlastRadius(ctx, args)
case "get_graph":
return s.toolGetGraph(ctx, args)
case "upsert_memory_node":
return memorygraph.ToolUpsertMemoryNode(memorygraph.UpsertMemoryNodeOptions{
RootDir: s.dir,
Type: memorygraph.NodeType(strArg(args, "type")),
Label: strArg(args, "label"),
Content: strArg(args, "content"),
})
case "create_relation":
w := floatArg(args, "weight")
if w == 0 {
w = 1.0
}
return memorygraph.ToolCreateRelation(memorygraph.CreateRelationOptions{
RootDir: s.dir,
SourceID: strArg(args, "source_id"),
TargetID: strArg(args, "target_id"),
Relation: memorygraph.RelationType(strArg(args, "relation")),
Weight: w,
})
case "search_memory_graph":
topK := intArg(args, "top_k")
if topK == 0 {
topK = 5
}
return memorygraph.ToolSearchMemoryGraph(memorygraph.SearchMemoryGraphOptions{
RootDir: s.dir,
Query: strArg(args, "query"),
MaxDepth: intArg(args, "max_depth"),
TopK: topK,
})
case "retrieve_with_traversal":
return memorygraph.ToolRetrieveWithTraversal(memorygraph.RetrieveWithTraversalOptions{
RootDir: s.dir,
StartNodeID: strArg(args, "start_node_id"),
MaxDepth: intArg(args, "max_depth"),
})
case "prune_stale_links":
return memorygraph.ToolPruneStaleLinks(memorygraph.PruneStaleLinksOptions{
RootDir: s.dir,
Threshold: floatArg(args, "threshold"),
})
case "add_interlinked_context":
items, err := parseInterlinkedItems(args)
if err != nil {
return "", fmt.Errorf("add_interlinked_context: invalid items: %w", err)
}
return memorygraph.ToolAddInterlinkedContext(memorygraph.AddInterlinkedContextOptions{
RootDir: s.dir,
Items: items,
AutoLink: boolArg(args, "auto_link"),
})
default:
return "", fmt.Errorf("unknown tool: %s", name)
}
}
}

// toolAnalyze uploads the repo and runs the full analysis pipeline.
Expand Down Expand Up @@ -497,3 +636,33 @@
v, _ := args[key].(float64)
return int(v)
}
func strArg(args map[string]any, key string) string {
v, _ := args[key].(string)
return v
}

func floatArg(args map[string]any, key string) float64 {
v, _ := args[key].(float64)
return v
}

// parseInterlinkedItems re-encodes the raw args["items"] array and decodes it
// into the strongly-typed slice expected by ToolAddInterlinkedContext.
func parseInterlinkedItems(args map[string]any) ([]memorygraph.InterlinkedItem, error) {
raw, ok := args["items"]
if !ok || raw == nil {
return nil, fmt.Errorf("missing required field \"items\"")
}
b, err := json.Marshal(raw)
if err != nil {
return nil, err
}
var items []memorygraph.InterlinkedItem
if err := json.Unmarshal(b, &items); err != nil {
return nil, err
}
if len(items) == 0 {
return nil, fmt.Errorf("\"items\" must be a non-empty array")
}
return items, nil
}
Comment thread
drQedwards marked this conversation as resolved.
Loading
Loading