MCP (Model Context Protocol)
MCP tools implement the Model Context Protocol — a standard that lets AI agents discover and invoke capabilities at runtime. When you publish an MCP tool, any agent that speaks JSON-RPC 2.0 can list what your tool exposes and call it without needing a custom integration.
MCP tools can be written in Python, JavaScript, or Lua.
How it works
An MCP tool receives a JSON-RPC 2.0 request as its event and must return a JSON-RPC 2.0 response. Your handler is responsible for routing all methods — including initialize.
The platform passes the entire JSON-RPC request to your handler:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}Your handler must return a matching JSON-RPC response:
{ "jsonrpc": "2.0", "id": 1, "result": { ... }}Supported methods
Implement whichever methods your MCP server needs:
| Method | Description |
|---|---|
initialize | Handshake — must be implemented |
ping | Health check |
tools/list | Return available tools and their schemas |
tools/call | Execute a specific tool |
resources/list | List available resources |
resources/read | Read a specific resource |
resources/templates/list | List resource templates |
prompts/list | List available prompts |
prompts/get | Get a specific prompt |
completion/complete | Handle completion requests |
At minimum implement initialize, tools/list, and tools/call.
Python example
import json
def ok(_id, result): return {"jsonrpc": "2.0", "id": _id, "result": result}
def err(_id, code, message): return {"jsonrpc": "2.0", "id": _id, "error": {"code": code, "message": message}}
TOOLS_SPEC = [ { "name": "echo", "description": "Echo back the input string.", "inputSchema": { "type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"] } }]
def handle_initialize(req): return ok(req.get("id"), { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "my-mcp-server", "version": "1.0.0"} })
def handle_tools_list(req): return ok(req.get("id"), {"tools": TOOLS_SPEC})
def handle_tools_call(req): params = req.get("params", {}) name = params.get("name") args = params.get("arguments", {})
if name == "echo": return ok(req.get("id"), { "content": [{"type": "text", "text": args.get("text", "")}] })
return err(req.get("id"), -32602, f"Unknown tool: {name}")
METHODS = { "initialize": handle_initialize, "tools/list": handle_tools_list, "tools/call": handle_tools_call,}
def cortexone_handler(event, context=None): req = json.loads(event) if isinstance(event, str) else event
if req.get("jsonrpc") != "2.0": return err(req.get("id"), -32600, "Invalid Request")
handler = METHODS.get(req.get("method")) if not handler: return err(req.get("id"), -32601, f"Method not found: {req.get('method')}")
return handler(req)JavaScript example
function ok(id, result) { return { jsonrpc: "2.0", id: id, result: result };}
function err(id, code, message) { return { jsonrpc: "2.0", id: id, error: { code: code, message: message } };}
var TOOLS_SPEC = [ { name: "echo", description: "Echo back the input string.", inputSchema: { type: "object", properties: { text: { type: "string" } }, required: ["text"] } }];
function handle_initialize(req) { return ok(req.id, { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "my-mcp-server", version: "1.0.0" } });}
function handle_tools_list(req) { return ok(req.id, { tools: TOOLS_SPEC });}
function handle_tools_call(req) { var name = req.params.name; var args = req.params.arguments;
if (name === "echo") { return ok(req.id, { content: [{ type: "text", text: args.text }] }); }
return err(req.id, -32602, "Unknown tool: " + name);}
var METHODS = { "initialize": handle_initialize, "tools/list": handle_tools_list, "tools/call": handle_tools_call};
function cortexone_handler(event) { var req = typeof event === "string" ? JSON.parse(event) : event; var handler = METHODS[req.method]; if (!handler) return err(req.id, -32601, "Method not found: " + req.method); return handler(req);}Lua example
local function ok(id, result) return { jsonrpc = "2.0", id = id, result = result }end
local function err(id, code, message) return { jsonrpc = "2.0", id = id, error = { code = code, message = message } }end
local TOOLS_SPEC = { { name = "echo", description = "Echo back the input string.", inputSchema = { type = "object", properties = { text = { type = "string" } }, required = { "text" } } }}
local function handle_initialize(req) return ok(req.id, { protocolVersion = "2024-11-05", capabilities = { tools = {} }, serverInfo = { name = "my-mcp-server", version = "1.0.0" } })end
local function handle_tools_list(req) return ok(req.id, { tools = TOOLS_SPEC })end
local function handle_tools_call(req) local name = req.params.name local args = req.params.arguments
if name == "echo" then return ok(req.id, { content = {{ type = "text", text = args.text }} }) end
return err(req.id, -32602, "Unknown tool: " .. tostring(name))end
local METHODS = { ["initialize"] = handle_initialize, ["tools/list"] = handle_tools_list, ["tools/call"] = handle_tools_call}
function cortexone_handler(event, context) local req = type(event) == "string" and json.decode(event) or event
local handler = METHODS[req.method] if not handler then return err(req.id, -32601, "Method not found: " .. tostring(req.method)) end
return handler(req)endInvoking an MCP tool
MCP tools use the same invoke endpoint as all other tools:
curl 'https://cortexconnect.rival.io/api/v1/functions/{function_id}/{version}/invoke' \ --header 'Authorization: <your_api_key>' \ --header 'Content-Type: application/json' \ --data '{ "event": { "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} } }'Error codes
| Code | Meaning |
|---|---|
-32700 | Parse error — invalid JSON |
-32600 | Invalid request |
-32601 | Method not found |
-32602 | Invalid params |
-32603 | Internal error |
Notes
- Your handler must implement
initialize— the platform does not handle it automatically. - Return a JSON-RPC error (not an HTTP error) for unknown methods or bad params.
- MCP tools follow the same pricing, versioning, and publishing workflow as function tools.
- JavaScript restriction applies: synchronous only, no
async/await.