Commit 79efd78
Changed files (1)
cmd
del
cmd/del/main.go
@@ -150,8 +150,13 @@ IMPORTANT: Use tools first, then provide natural markdown responses based on res
go func() {
if err := d.startMCPMemory(); err != nil {
d.emit(StreamMessage{
- Type: MessageTypeSystem,
- Error: fmt.Sprintf("Warning: Failed to initialize memory system: %v", err),
+ Type: MessageTypeSystem,
+ Content: fmt.Sprintf("Warning: Failed to initialize memory system: %v", err),
+ })
+ } else {
+ d.emit(StreamMessage{
+ Type: MessageTypeSystem,
+ Content: "â
Memory system initialized successfully",
})
}
}()
@@ -400,73 +405,86 @@ func (d *Del) registerTools() {
// MCP Server Management
func (d *Del) startMCPMemory() error {
- cmd := exec.Command("/usr/local/bin/mcp-memory")
-
- stdin, err := cmd.StdinPipe()
- if err != nil {
- return fmt.Errorf("failed to create stdin pipe: %v", err)
- }
-
- stdout, err := cmd.StdoutPipe()
- if err != nil {
- return fmt.Errorf("failed to create stdout pipe: %v", err)
- }
-
- if err := cmd.Start(); err != nil {
- return fmt.Errorf("failed to start mcp-memory: %v", err)
+ // Simple test to verify mcp-memory is available
+ testCmd := exec.Command("/usr/local/bin/mcp-memory", "--help")
+ if err := testCmd.Run(); err != nil {
+ return fmt.Errorf("mcp-memory not available: %v", err)
}
+ // Mark memory as available (we'll use exec calls instead of persistent process)
d.mcpMemory = &MCPServer{
name: "mcp-memory",
command: "/usr/local/bin/mcp-memory",
- process: cmd,
- stdin: stdin,
- stdout: stdout,
}
- // Initialize MCP connection
- initReq := MCPRequest{
- JSONRPC: "2.0",
- ID: 1,
- Method: "initialize",
- Params: map[string]interface{}{
+ return nil
+}
+
+func (d *Del) callMCPTool(toolName string, args map[string]interface{}) (string, error) {
+ // Create the tool call request
+ reqJSON, err := json.Marshal(map[string]interface{}{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "initialize",
+ "params": map[string]interface{}{
"protocolVersion": "2024-11-05",
"capabilities": map[string]interface{}{"tools": map[string]interface{}{}},
"clientInfo": map[string]interface{}{"name": "del", "version": "1.0.0"},
},
+ })
+ if err != nil {
+ return "", fmt.Errorf("failed to marshal init request: %v", err)
}
- _, err = d.callMCP(d.mcpMemory, initReq)
- return err
-}
-
-func (d *Del) callMCP(server *MCPServer, req MCPRequest) (*MCPResponse, error) {
- // Send request
- reqJSON, err := json.Marshal(req)
+ toolReqJSON, err := json.Marshal(map[string]interface{}{
+ "jsonrpc": "2.0",
+ "id": 2,
+ "method": "tools/call",
+ "params": map[string]interface{}{
+ "name": toolName,
+ "arguments": args,
+ },
+ })
if err != nil {
- return nil, fmt.Errorf("failed to marshal request: %v", err)
+ return "", fmt.Errorf("failed to marshal tool request: %v", err)
}
- if _, err := server.stdin.Write(append(reqJSON, '\n')); err != nil {
- return nil, fmt.Errorf("failed to write request: %v", err)
+ // Execute mcp-memory with both requests
+ cmd := exec.Command("/usr/local/bin/mcp-memory")
+ cmd.Stdin = strings.NewReader(string(reqJSON) + "\n" + string(toolReqJSON) + "\n")
+
+ output, err := cmd.Output()
+ if err != nil {
+ return "", fmt.Errorf("mcp-memory execution failed: %v", err)
}
- // Read response
- scanner := bufio.NewScanner(server.stdout)
- if !scanner.Scan() {
- return nil, fmt.Errorf("failed to read response")
+ // Parse the responses (we want the second one - the tool result)
+ lines := strings.Split(strings.TrimSpace(string(output)), "\n")
+ if len(lines) < 2 {
+ return "", fmt.Errorf("unexpected MCP response format")
}
- var resp MCPResponse
- if err := json.Unmarshal(scanner.Bytes(), &resp); err != nil {
- return nil, fmt.Errorf("failed to unmarshal response: %v", err)
+ var toolResp MCPResponse
+ if err := json.Unmarshal([]byte(lines[1]), &toolResp); err != nil {
+ return "", fmt.Errorf("failed to parse tool response: %v", err)
}
- if resp.Error != nil {
- return nil, fmt.Errorf("MCP error %d: %s", resp.Error.Code, resp.Error.Message)
+ if toolResp.Error != nil {
+ return "", fmt.Errorf("MCP tool error %d: %s", toolResp.Error.Code, toolResp.Error.Message)
}
- return &resp, nil
+ // Extract content from result
+ if result, ok := toolResp.Result.(map[string]interface{}); ok {
+ if content, ok := result["content"].([]interface{}); ok && len(content) > 0 {
+ if textContent, ok := content[0].(map[string]interface{}); ok {
+ if text, ok := textContent["text"].(string); ok {
+ return text, nil
+ }
+ }
+ }
+ }
+
+ return fmt.Sprintf("Tool result: %v", toolResp.Result), nil
}
// Memory Tools
@@ -489,29 +507,19 @@ func (d *Del) remember(ctx context.Context, args map[string]interface{}, progres
}
if d.mcpMemory == nil {
- return "", fmt.Errorf("MCP memory not initialized")
+ return "", fmt.Errorf("MCP memory not initialized - please wait for initialization or restart Del")
}
// Create entity for this memory
- createReq := MCPRequest{
- JSONRPC: "2.0",
- ID: 2,
- Method: "tools/call",
- Params: map[string]interface{}{
- "name": "create_entities",
- "arguments": map[string]interface{}{
- "entities": []map[string]interface{}{
- {
- "name": entity,
- "entityType": "concept",
- "observations": []string{content},
- },
- },
+ result, err := d.callMCPTool("create_entities", map[string]interface{}{
+ "entities": []map[string]interface{}{
+ {
+ "name": entity,
+ "entityType": "concept",
+ "observations": []string{content},
},
},
- }
-
- resp, err := d.callMCP(d.mcpMemory, createReq)
+ })
if err != nil {
return "", fmt.Errorf("failed to create memory: %v", err)
}
@@ -523,7 +531,7 @@ func (d *Del) remember(ctx context.Context, args map[string]interface{}, progres
Content: "Memory stored successfully",
}
- return fmt.Sprintf("Remembered: %s\nStored as entity: %s\nResponse: %v", content, entity, resp.Result), nil
+ return fmt.Sprintf("Remembered: %s\nStored as entity: %s\nResult: %s", content, entity, result), nil
}
func (d *Del) recall(ctx context.Context, args map[string]interface{}, progress chan<- StreamMessage) (string, error) {
@@ -540,25 +548,13 @@ func (d *Del) recall(ctx context.Context, args map[string]interface{}, progress
}
if d.mcpMemory == nil {
- return "", fmt.Errorf("MCP memory not initialized")
- }
-
- // Search memory
- searchReq := MCPRequest{
- JSONRPC: "2.0",
- ID: 3,
- Method: "tools/call",
- Params: map[string]interface{}{
- "name": "search_nodes",
- "arguments": map[string]interface{}{
- "query": query,
- },
- },
+ return "", fmt.Errorf("MCP memory not initialized - please wait for initialization or restart Del")
}
- resp, err := d.callMCP(d.mcpMemory, searchReq)
+ // Search memory using read_graph for now (search_nodes seems to have issues)
+ result, err := d.callMCPTool("read_graph", map[string]interface{}{})
if err != nil {
- return "", fmt.Errorf("failed to search memory: %v", err)
+ return "", fmt.Errorf("failed to read memory: %v", err)
}
progress <- StreamMessage{
@@ -568,7 +564,7 @@ func (d *Del) recall(ctx context.Context, args map[string]interface{}, progress
Content: "Memory search completed",
}
- return fmt.Sprintf("Memory search for '%s':\n%v", query, resp.Result), nil
+ return fmt.Sprintf("Memory search for '%s':\n%s", query, result), nil
}
func (d *Del) forget(ctx context.Context, args map[string]interface{}, progress chan<- StreamMessage) (string, error) {
@@ -585,23 +581,13 @@ func (d *Del) forget(ctx context.Context, args map[string]interface{}, progress
}
if d.mcpMemory == nil {
- return "", fmt.Errorf("MCP memory not initialized")
+ return "", fmt.Errorf("MCP memory not initialized - please wait for initialization or restart Del")
}
// Delete entity
- deleteReq := MCPRequest{
- JSONRPC: "2.0",
- ID: 4,
- Method: "tools/call",
- Params: map[string]interface{}{
- "name": "delete_entities",
- "arguments": map[string]interface{}{
- "entityIds": []string{entity},
- },
- },
- }
-
- resp, err := d.callMCP(d.mcpMemory, deleteReq)
+ result, err := d.callMCPTool("delete_entities", map[string]interface{}{
+ "entityIds": []string{entity},
+ })
if err != nil {
return "", fmt.Errorf("failed to delete memory: %v", err)
}
@@ -613,7 +599,7 @@ func (d *Del) forget(ctx context.Context, args map[string]interface{}, progress
Content: "Memory deleted successfully",
}
- return fmt.Sprintf("Forgot: %s\nResponse: %v", entity, resp.Result), nil
+ return fmt.Sprintf("Forgot: %s\nResult: %s", entity, result), nil
}
func (d *Del) readFile(ctx context.Context, args map[string]interface{}, progress chan<- StreamMessage) (string, error) {
@@ -2675,6 +2661,8 @@ func (d *Del) renderUI() {
case MessageTypeSystem:
if msg.Error != "" {
fmt.Printf("â Error: %s\n", msg.Error)
+ } else if msg.Content != "" {
+ fmt.Printf("âšī¸ %s\n", msg.Content)
}
}
}
@@ -2719,18 +2707,7 @@ func (d *Del) Start(ctx context.Context) {
}
func (d *Del) cleanup() {
- if d.mcpMemory != nil {
- if d.mcpMemory.stdin != nil {
- d.mcpMemory.stdin.Close()
- }
- if d.mcpMemory.stdout != nil {
- d.mcpMemory.stdout.Close()
- }
- if d.mcpMemory.process != nil {
- d.mcpMemory.process.Process.Kill()
- d.mcpMemory.process.Wait()
- }
- }
+ // No cleanup needed for exec-based MCP calls
}
func main() {