diff --git a/internal/mcp/jsonrpc.go b/internal/mcp/jsonrpc.go new file mode 100644 index 0000000..e25f191 --- /dev/null +++ b/internal/mcp/jsonrpc.go @@ -0,0 +1,43 @@ +package mcp + +import "encoding/json" + +const ( + CodePermissionDenied = -32001 + CodeNotFound = -32002 + CodeConflict = -32003 + CodeValidation = -32004 + CodeUpstreamGitea = -32005 +) + +type Request struct { + JSONRPC string `json:"jsonrpc"` + ID any `json:"id,omitempty"` + Method string `json:"method"` + Params json.RawMessage `json:"params,omitempty"` +} + +type Response struct { + JSONRPC string `json:"jsonrpc"` + ID any `json:"id,omitempty"` + Result any `json:"result,omitempty"` + Error *RPCError `json:"error,omitempty"` +} + +type RPCError struct { + Code int `json:"code"` + Message string `json:"message"` + Data any `json:"data,omitempty"` +} + +func NewResponse(id any, result any) Response { + return Response{JSONRPC: "2.0", ID: id, Result: result} +} + +func NewErrorResponse(id any, code int, msg string, data any) Response { + return Response{ + JSONRPC: "2.0", + ID: id, + Error: &RPCError{Code: code, Message: msg, Data: data}, + } +} diff --git a/internal/mcp/jsonrpc_test.go b/internal/mcp/jsonrpc_test.go new file mode 100644 index 0000000..6242f7c --- /dev/null +++ b/internal/mcp/jsonrpc_test.go @@ -0,0 +1,26 @@ +package mcp_test + +import ( + "encoding/json" + "testing" + + "gitea.d-ma.be/mathias/gitea-mcp/internal/mcp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRequestUnmarshal(t *testing.T) { + raw := []byte(`{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}`) + var req mcp.Request + require.NoError(t, json.Unmarshal(raw, &req)) + assert.Equal(t, "2.0", req.JSONRPC) + assert.Equal(t, "initialize", req.Method) +} + +func TestErrorResponseShape(t *testing.T) { + resp := mcp.NewErrorResponse(1, mcp.CodePermissionDenied, "no", nil) + b, _ := json.Marshal(resp) + assert.JSONEq(t, + `{"jsonrpc":"2.0","id":1,"error":{"code":-32001,"message":"no"}}`, + string(b)) +}