add black-box debug harness
This commit is contained in:
82
internal/harness/mcp_client.go
Normal file
82
internal/harness/mcp_client.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package harness
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type MCPClient struct {
|
||||
conn net.Conn
|
||||
r *bufio.Reader
|
||||
mu sync.Mutex
|
||||
next int
|
||||
}
|
||||
|
||||
type RPCError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data any `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (e *RPCError) Error() string {
|
||||
return fmt.Sprintf("json-rpc error %d: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
func DialMCP(socket string) (*MCPClient, error) {
|
||||
conn, err := net.Dial("unix", socket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := conn.Write([]byte("{\"patterm_identity\":\"harness\"}\n")); err != nil {
|
||||
_ = conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return &MCPClient{conn: conn, r: bufio.NewReader(conn)}, nil
|
||||
}
|
||||
|
||||
func (c *MCPClient) Close() error {
|
||||
if c == nil || c.conn == nil {
|
||||
return nil
|
||||
}
|
||||
return c.conn.Close()
|
||||
}
|
||||
|
||||
func (c *MCPClient) Call(method string, params any) (json.RawMessage, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.next++
|
||||
req := map[string]any{
|
||||
"jsonrpc": "2.0",
|
||||
"id": c.next,
|
||||
"method": method,
|
||||
}
|
||||
if params != nil {
|
||||
req["params"] = params
|
||||
}
|
||||
b, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, '\n')
|
||||
if _, err := c.conn.Write(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
line, err := c.r.ReadBytes('\n')
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp struct {
|
||||
Result json.RawMessage `json:"result"`
|
||||
Error *RPCError `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(line, &resp); err != nil {
|
||||
return nil, fmt.Errorf("parse response: %w: %s", err, string(line))
|
||||
}
|
||||
if resp.Error != nil {
|
||||
return nil, resp.Error
|
||||
}
|
||||
return resp.Result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user