#include "mesh_sdk.h" #include #include #include static void say(json_t *m) { json_object_set_new(m, "jsonrpc", json_string("2.0")); char *text = json_dumps(m, JSON_COMPACT); fprintf(stdout, "%s\n", text); fflush(stdout); free(text); json_decref(m); } static json_t *as_schema(json_t *given) { if (!given || !json_is_object(given) || json_object_size(given) == 0) return json_pack("{s:s,s:{}}", "type", "object", "properties"); if (json_object_get(given, "type") || json_object_get(given, "properties")) return json_incref(given); return json_pack("{s:s,s:O}", "type", "object", "properties", given); } int mesh_serve(const char *name, const mesh_tool *tools, size_t count) { char *line = NULL; size_t cap = 0; ssize_t got; while ((got = getline(&line, &cap, stdin)) >= 0) { json_error_t err; json_t *req = json_loads(line, 0, &err); if (!req) continue; json_t *id = json_object_get(req, "id"); const char *method = json_string_value(json_object_get(req, "method")); json_t *params = json_object_get(req, "params"); if (!method) { json_decref(req); continue; } if (strcmp(method, "initialize") == 0) { say(json_pack("{s:O,s:{s:s,s:{s:{}},s:{s:s,s:s}}}", "id", id ? id : json_null(), "result", "protocolVersion", MESH_SDK_PROTOCOL, "capabilities", "tools", "serverInfo", "name", name, "version", "1")); } else if (strcmp(method, "notifications/initialized") == 0) { } else if (strcmp(method, "ping") == 0) { if (id) say(json_pack("{s:O,s:{}}", "id", id, "result")); } else if (strcmp(method, "tools/list") == 0) { json_t *listed = json_array(); for (size_t i = 0; i < count; i++) json_array_append_new(listed, json_pack("{s:s,s:s,s:o}", "name", tools[i].name, "description", tools[i].description, "inputSchema", as_schema(tools[i].input))); say(json_pack("{s:O,s:{s:o}}", "id", id ? id : json_null(), "result", "tools", listed)); } else if (strcmp(method, "tools/call") == 0) { const char *wanted = params ? json_string_value(json_object_get(params, "name")) : NULL; const mesh_tool *tool = NULL; for (size_t i = 0; wanted && i < count; i++) if (strcmp(tools[i].name, wanted) == 0) tool = &tools[i]; if (!tool) { char message[256]; snprintf(message, sizeof message, "%s has no tool %s", name, wanted ? wanted : ""); say(json_pack("{s:O,s:{s:i,s:s}}", "id", id ? id : json_null(), "error", "code", -32602, "message", message)); } else { json_t *args = params ? json_object_get(params, "arguments") : NULL; json_t *empty = args ? NULL : json_object(); char *error = NULL; json_t *result = tool->run(args ? args : empty, &error); if (empty) json_decref(empty); if (result) { char *text = json_dumps(result, JSON_COMPACT); say(json_pack("{s:O,s:{s:[{s:s,s:s}]}}", "id", id ? id : json_null(), "result", "content", "type", "text", "text", text)); free(text); json_decref(result); } else { say(json_pack("{s:O,s:{s:[{s:s,s:s}],s:b}}", "id", id ? id : json_null(), "result", "content", "type", "text", "text", error ? error : "the tool failed", "isError", 1)); free(error); } } } else if (id) { char message[256]; snprintf(message, sizeof message, "no %s", method); say(json_pack("{s:O,s:{s:i,s:s}}", "id", id, "error", "code", -32601, "message", message)); } json_decref(req); } free(line); return ferror(stdin) ? -1 : 0; }