Skip to main content

Overview

Syncline implements the Model Context Protocol (MCP) v2024-11-05 for AI agent integration. MCP uses JSON-RPC 2.0 over stdio (standard input/output) for communication.

Transport

Connection

Communication happens over stdio (standard input/output):
  • Input: JSON-RPC requests sent to the server’s stdin
  • Output: JSON-RPC responses sent from the server’s stdout
Each message is a single line of JSON followed by a newline character (\n).
┌──────────┐         stdin          ┌──────────┐
│          │ ───────────────────────>│          │
│  Client  │                         │  Server  │
│  (Agent) │<────────────────────────│(Syncline)│
└──────────┘         stdout         └──────────┘

JSON-RPC 2.0 Format

Request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "method_name",
  "params": {
    "key": "value"
  }
}
jsonrpc
string
required
Must be "2.0"
id
number | string
required
Unique identifier for the request. Used to match responses.
method
string
required
The method to call (e.g., "tools/list", "tools/call")
params
object
Optional parameters for the method

Response (Success)

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "data": "value"
  }
}
jsonrpc
string
required
Must be "2.0"
id
number | string
required
Matches the request id
result
any
required
The result of the method call

Response (Error)

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32600,
    "message": "Invalid request",
    "data": {
      "details": "Additional error information"
    }
  }
}
error.code
number
required
Standard JSON-RPC error code
error.message
string
required
Human-readable error message
error.data
any
Optional additional error information

Protocol Flow

1. Initialize

The client must initialize the connection before calling tools. Request:
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "my-agent",
      "version": "1.0.0"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "syncline",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": {
        "listChanged": false
      }
    }
  }
}

2. List Tools

Discover available tools. Request:
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}
Response:
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "find_mutual_availability",
        "description": "Find time slots where all attendees are available",
        "inputSchema": {
          "type": "object",
          "properties": {
            "attendees": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "email"
              },
              "description": "Array of attendee email addresses"
            },
            "duration_minutes": {
              "type": "number",
              "default": 30,
              "description": "Meeting duration in minutes"
            }
          },
          "required": ["attendees"]
        }
      },
      {
        "name": "schedule_meeting",
        "description": "Create a calendar event with Google Meet link",
        "inputSchema": {
          "type": "object",
          "properties": {
            "attendees": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "email"
              }
            },
            "start_time": {
              "type": "string",
              "format": "date-time",
              "description": "ISO 8601 datetime"
            },
            "title": {
              "type": "string",
              "description": "Meeting title"
            },
            "duration_minutes": {
              "type": "number",
              "default": 30
            }
          },
          "required": ["attendees", "start_time", "title"]
        }
      },
      {
        "name": "check_availability",
        "description": "Check a user's calendar for busy/free time slots",
        "inputSchema": {
          "type": "object",
          "properties": {
            "email": {
              "type": "string",
              "format": "email"
            },
            "start_date": {
              "type": "string",
              "format": "date-time"
            },
            "end_date": {
              "type": "string",
              "format": "date-time"
            }
          },
          "required": ["email", "start_date", "end_date"]
        }
      },
      {
        "name": "update_preferences",
        "description": "Update user scheduling preferences",
        "inputSchema": {
          "type": "object",
          "properties": {
            "email": {
              "type": "string",
              "format": "email"
            },
            "preferences": {
              "type": "object",
              "description": "Preferences object with work hours, buffer time, etc."
            }
          },
          "required": ["email", "preferences"]
        }
      }
    ]
  }
}

3. Call Tool

Execute a tool with arguments. Request:
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "find_mutual_availability",
    "arguments": {
      "attendees": ["alice@example.com", "bob@example.com"],
      "duration_minutes": 30
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"slots\": [\n    {\n      \"start_time\": \"2025-01-22T14:00:00-08:00\",\n      \"end_time\": \"2025-01-22T14:30:00-08:00\",\n      \"score\": 0.95,\n      \"match_quality\": \"excellent\",\n      \"attendee_quality\": {\n        \"alice@example.com\": 0.96,\n        \"bob@example.com\": 0.94\n      }\n    }\n  ],\n  \"total_found\": 5\n}"
      }
    ]
  }
}

Available Methods

initialize

Initialize the MCP session. Request:
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "client-name",
      "version": "1.0.0"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "syncline",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": { "listChanged": false }
    }
  }
}

tools/list

List all available tools. Request:
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}
Response: Returns array of tool schemas (see example above)

tools/call

Execute a tool. Request:
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "tool_name",
    "arguments": {
      "arg1": "value1"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"result\": \"data\"}"
      }
    ]
  }
}

Tool Schemas

find_mutual_availability

Find time slots where all attendees are available. Input Schema:
{
  "type": "object",
  "properties": {
    "attendees": {
      "type": "array",
      "items": { "type": "string", "format": "email" },
      "description": "Email addresses of attendees"
    },
    "duration_minutes": {
      "type": "number",
      "default": 30,
      "description": "Meeting duration in minutes"
    },
    "earliest_time": {
      "type": "string",
      "format": "date-time",
      "description": "Optional earliest acceptable time"
    },
    "latest_time": {
      "type": "string",
      "format": "date-time",
      "description": "Optional latest acceptable time"
    }
  },
  "required": ["attendees"]
}
Output Format:
{
  "slots": [
    {
      "start_time": "2025-01-22T14:00:00-08:00",
      "end_time": "2025-01-22T14:30:00-08:00",
      "score": 0.95,
      "match_quality": "excellent"
    }
  ],
  "total_found": 5
}

schedule_meeting

Create a calendar event with Google Meet. Input Schema:
{
  "type": "object",
  "properties": {
    "attendees": {
      "type": "array",
      "items": { "type": "string", "format": "email" }
    },
    "start_time": {
      "type": "string",
      "format": "date-time",
      "description": "ISO 8601 datetime"
    },
    "title": {
      "type": "string",
      "description": "Meeting title"
    },
    "duration_minutes": {
      "type": "number",
      "default": 30
    },
    "description": {
      "type": "string",
      "description": "Optional meeting description"
    }
  },
  "required": ["attendees", "start_time", "title"]
}
Output Format:
{
  "meeting_id": "evt_abc123",
  "google_meet_link": "https://meet.google.com/abc-defg-hij",
  "calendar_event_link": "https://calendar.google.com/calendar/event?eid=...",
  "start_time": "2025-01-22T14:00:00-08:00",
  "end_time": "2025-01-22T14:30:00-08:00"
}

check_availability

Check a user’s calendar. Input Schema:
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email"
    },
    "start_date": {
      "type": "string",
      "format": "date-time"
    },
    "end_date": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": ["email", "start_date", "end_date"]
}
Output Format:
{
  "email": "alice@example.com",
  "free_slots": [
    {
      "start": "2025-01-22T09:00:00-08:00",
      "end": "2025-01-22T10:00:00-08:00"
    }
  ],
  "busy_slots": [
    {
      "start": "2025-01-22T10:00:00-08:00",
      "end": "2025-01-22T11:00:00-08:00",
      "title": "Team Standup"
    }
  ]
}

update_preferences

Update user scheduling preferences. Input Schema:
{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "format": "email"
    },
    "preferences": {
      "type": "object",
      "properties": {
        "work_hours": { "type": "object" },
        "timezone": { "type": "string" },
        "buffer_minutes": { "type": "number" },
        "energy_pattern": { "type": "string" }
      }
    }
  },
  "required": ["email", "preferences"]
}
Output Format:
{
  "email": "alice@example.com",
  "preferences": {
    "work_hours": {
      "monday": { "enabled": true, "start": "09:00", "end": "17:00" }
    },
    "timezone": "America/New_York",
    "buffer_minutes": 15
  },
  "updated_at": "2025-01-20T10:30:00Z"
}

Error Codes

Standard JSON-RPC 2.0 error codes:
-32700
Parse error
Invalid JSON received
-32600
Invalid request
Request is not a valid JSON-RPC 2.0 request
-32601
Method not found
The requested method does not exist
-32602
Invalid params
Invalid method parameters
-32603
Internal error
Server internal error

Error Response Example

{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "field": "attendees",
      "reason": "Must provide at least 2 attendees"
    }
  }
}

Implementation Example

Python

import json
import subprocess
import sys

def send_request(process, method, params, request_id):
    request = {
        "jsonrpc": "2.0",
        "id": request_id,
        "method": method,
        "params": params
    }

    # Send request
    process.stdin.write(json.dumps(request) + "\n")
    process.stdin.flush()

    # Read response
    response_line = process.stdout.readline()
    return json.loads(response_line)

# Start MCP server
process = subprocess.Popen(
    ["npx", "-y", "@kekwanulabs/syncline-mcp-server"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True,
    env={"SYNCLINE_API_KEY": "sk_live_your_key"}
)

# Initialize
response = send_request(process, "initialize", {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {"name": "my-agent", "version": "1.0.0"}
}, 1)

print("Initialized:", response)

# List tools
response = send_request(process, "tools/list", {}, 2)
print("Tools:", [tool["name"] for tool in response["result"]["tools"]])

# Call tool
response = send_request(process, "tools/call", {
    "name": "find_mutual_availability",
    "arguments": {
        "attendees": ["alice@example.com", "bob@example.com"],
        "duration_minutes": 30
    }
}, 3)

print("Result:", response["result"]["content"][0]["text"])

# Cleanup
process.terminate()

Node.js

import { spawn } from "child_process";
import readline from "readline";

const process = spawn("npx", ["-y", "@kekwanulabs/syncline-mcp-server"], {
  env: { ...process.env, SYNCLINE_API_KEY: "sk_live_your_key" }
});

const rl = readline.createInterface({
  input: process.stdout,
  output: process.stdin
});

function sendRequest(method, params, id) {
  const request = {
    jsonrpc: "2.0",
    id,
    method,
    params
  };

  process.stdin.write(JSON.stringify(request) + "\n");
}

rl.on("line", (line) => {
  const response = JSON.parse(line);
  console.log("Response:", response);
});

// Initialize
sendRequest("initialize", {
  protocolVersion: "2024-11-05",
  capabilities: {},
  clientInfo: { name: "my-agent", version: "1.0.0" }
}, 1);

// List tools
sendRequest("tools/list", {}, 2);

// Call tool
sendRequest("tools/call", {
  name: "find_mutual_availability",
  arguments: {
    attendees: ["alice@example.com", "bob@example.com"],
    duration_minutes: 30
  }
}, 3);

Best Practices

Request IDs

Use unique, incrementing request IDs:
let requestId = 1;

function callTool(name, args) {
  const id = requestId++;
  sendRequest("tools/call", { name, arguments: args }, id);
  return id;
}

Error Handling

Always check for error responses:
response = send_request(process, "tools/call", {...}, 1)

if "error" in response:
    print(f"Error {response['error']['code']}: {response['error']['message']}")
else:
    result = response["result"]

Timeout Handling

Implement timeouts for requests:
const timeout = 30000; // 30 seconds

const responsePromise = new Promise((resolve) => {
  rl.once("line", (line) => resolve(JSON.parse(line)));
});

const timeoutPromise = new Promise((_, reject) => {
  setTimeout(() => reject(new Error("Request timeout")), timeout);
});

try {
  const response = await Promise.race([responsePromise, timeoutPromise]);
} catch (error) {
  console.error("Request failed:", error);
}