or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

auth.mdindex.mdjsonrpc.mdmcp-client.mdmcp-protocol.mdmcp-server.mdmcp-transports.mdmcp-types.mdoauthex.md
tile.json

jsonrpc.mddocs/

JSON-RPC Utilities

The jsonrpc package provides low-level JSON-RPC v2 message handling utilities for MCP transport authors.

Overview

This package exposes core JSON-RPC v2 types and functions for encoding, decoding, and working with JSON-RPC messages. It is primarily used by custom transport implementations.

Package Information

import "github.com/modelcontextprotocol/go-sdk/jsonrpc"

Message Encoding and Decoding

EncodeMessage

Serializes a JSON-RPC message to its wire format.

func EncodeMessage(msg Message) ([]byte, error)

Parameters:

  • msg: A JSON-RPC message (Request or Response)

Returns:

  • []byte: Serialized JSON bytes
  • error: Error if serialization fails

Example:

import "github.com/modelcontextprotocol/go-sdk/jsonrpc"

// Create a request
req := &jsonrpc.Request{
    ID:     jsonrpc.ID{Str: "1"},
    Method: "tools/call",
    Params: map[string]any{
        "name": "greet",
        "arguments": map[string]any{"name": "Alice"},
    },
}

// Encode to wire format
data, err := jsonrpc.EncodeMessage(req)
if err != nil {
    log.Fatal(err)
}

// data is now JSON bytes ready to send over the wire

DecodeMessage

Deserializes JSON-RPC wire format data into a Message.

func DecodeMessage(data []byte) (Message, error)

Parameters:

  • data: JSON-encoded message bytes

Returns:

  • Message: Either a Request or Response
  • error: Error if deserialization fails

Example:

// Receive data from wire
data := []byte(`{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{}}`)

// Decode message
msg, err := jsonrpc.DecodeMessage(data)
if err != nil {
    log.Fatal(err)
}

// Check message type
switch m := msg.(type) {
case *jsonrpc.Request:
    fmt.Printf("Request: %s\n", m.Method)
case *jsonrpc.Response:
    fmt.Printf("Response ID: %v\n", m.ID)
}

Message Types

Message

Base interface for JSON-RPC messages.

type Message interface{}

A Message is either a Request or Response.

Request

Represents a JSON-RPC request.

type Request struct {
    ID     ID
    Method string
    Params any
}

Fields:

  • ID: Unique identifier for the request (can be string, number, or null)
  • Method: The method name to invoke
  • Params: Method parameters (any JSON-serializable value)

Note: The actual jsonrpc.Request type is a type alias to an internal implementation with additional fields. The above represents the logical structure.

Response

Represents a JSON-RPC response.

type Response struct {
    ID     ID
    Result any
    Error  *ResponseError
}

Fields:

  • ID: Identifier matching the request
  • Result: Result value (present on success)
  • Error: Error information (present on failure)

Note: The actual jsonrpc.Response type is a type alias to an internal implementation. The above represents the logical structure.

Request ID Handling

ID

Type representing a JSON-RPC request ID.

type ID struct {
    // Can represent string, number, or null ID
}

Request IDs can be:

  • String values
  • Numeric values (float64)
  • Null (for notifications)

MakeID

Coerces a Go value to a JSON-RPC ID.

func MakeID(v any) (ID, error)

Parameters:

  • v: Value to convert (should be nil, float64, or string)

Returns:

  • ID: Converted ID
  • error: Error if value is not a valid ID type

Example:

// String ID
id1, _ := jsonrpc.MakeID("request-123")

// Numeric ID
id2, _ := jsonrpc.MakeID(float64(42))

// Null ID (for notifications)
id3, _ := jsonrpc.MakeID(nil)

// Invalid type - returns error
_, err := jsonrpc.MakeID(true)
if err != nil {
    fmt.Println("Invalid ID type")
}

Usage in Custom Transports

The jsonrpc package is primarily used when implementing custom MCP transports. Here's an example of how it's used:

package main

import (
    "context"
    "fmt"
    "io"
    "github.com/modelcontextprotocol/go-sdk/jsonrpc"
    "github.com/modelcontextprotocol/go-sdk/mcp"
)

type MyTransport struct {
    reader io.Reader
    writer io.Writer
}

func (t *MyTransport) Connect(ctx context.Context) (mcp.Connection, error) {
    return &myConnection{
        reader: t.reader,
        writer: t.writer,
    }, nil
}

type myConnection struct {
    reader io.Reader
    writer io.Writer
}

func (c *myConnection) Read(ctx context.Context) (jsonrpc.Message, error) {
    // Read data from transport
    data := make([]byte, 4096)
    n, err := c.reader.Read(data)
    if err != nil {
        return nil, err
    }

    // Decode JSON-RPC message
    msg, err := jsonrpc.DecodeMessage(data[:n])
    if err != nil {
        return nil, fmt.Errorf("failed to decode message: %w", err)
    }

    return msg, nil
}

func (c *myConnection) Write(ctx context.Context, msg jsonrpc.Message) error {
    // Encode JSON-RPC message
    data, err := jsonrpc.EncodeMessage(msg)
    if err != nil {
        return fmt.Errorf("failed to encode message: %w", err)
    }

    // Write to transport
    _, err = c.writer.Write(data)
    return err
}

func (c *myConnection) Close() error {
    // Clean up resources
    return nil
}

func (c *myConnection) SessionID() string {
    return "my-session-id"
}

JSON-RPC v2 Specification

The jsonrpc package implements JSON-RPC 2.0 as specified in JSON-RPC 2.0 Specification.

Key features:

  • Request/response pattern
  • Batch requests (arrays of requests)
  • Notifications (requests without ID)
  • Error handling with structured error objects
  • Support for string, number, and null IDs

Message Format

Request Format

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/call",
  "params": {
    "name": "greet",
    "arguments": {"name": "Alice"}
  }
}

Response Format (Success)

{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "content": [
      {"type": "text", "text": "Hello, Alice!"}
    ]
  }
}

Response Format (Error)

{
  "jsonrpc": "2.0",
  "id": "1",
  "error": {
    "code": -32600,
    "message": "Invalid Request",
    "data": {}
  }
}

Notification Format

{
  "jsonrpc": "2.0",
  "method": "notifications/progress",
  "params": {
    "progressToken": "token-123",
    "progress": 50,
    "total": 100
  }
}

When to Use This Package

Use the jsonrpc package when:

  • Implementing custom MCP transports
  • Building low-level transport middleware
  • Debugging JSON-RPC messages
  • Implementing custom message routing

For most applications, you don't need to use this package directly - the built-in transports and high-level mcp package API are sufficient.