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 └──────────┘
Request
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"method" : "method_name" ,
"params" : {
"key" : "value"
}
}
Unique identifier for the request. Used to match responses.
The method to call (e.g., "tools/list", "tools/call")
Optional parameters for the method
Response (Success)
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" : {
"data" : "value"
}
}
The result of the method call
Response (Error)
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"error" : {
"code" : -32600 ,
"message" : "Invalid request" ,
"data" : {
"details" : "Additional error information"
}
}
}
Standard JSON-RPC error code
Human-readable error message
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
}
}
}
}
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" ]
}
}
]
}
}
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 }
}
}
}
List all available tools.
Request:
{
"jsonrpc" : "2.0" ,
"id" : 2 ,
"method" : "tools/list" ,
"params" : {}
}
Response: Returns array of tool schemas (see example above)
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 \" }"
}
]
}
}
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:
Request is not a valid JSON-RPC 2.0 request
The requested method does not exist
Invalid method parameters
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 );
}
Python Client Build agents with Python
Node.js Client Build agents with Node.js
Claude Integration Use with Claude Desktop