#include #include #include #include "cli/cli.h" #include "mcp/server.h" #include "storage/store.h" #include "sys/system.h" #include "base/allocator.h" static void usage(FILE *stream) { fprintf(stream, "Usage: tiny-convmem-mcp --data-dir [command]\n" "Commands:\n" " (none) Run the MCP server (default)\n" " --import [--policy overwrite|reject]\n" " Import a JSONL export into the store\n" " --export [--session ] [--include-deleted]\n" " Export the store to a JSONL file (- for stdout)\n"); } static const char * find_argument(const tiny_sys_arguments_t *arguments, const char *name) { size_t index; for (index = 1; index + 1 < arguments->count; ++index) { if (strcmp(arguments->values[index], name) == 0) { return arguments->values[index + 1]; } } return NULL; } static int flag_present(const tiny_sys_arguments_t *arguments, const char *name) { size_t index; for (index = 1; index < arguments->count; ++index) { if (strcmp(arguments->values[index], name) == 0) { return 1; } } return 0; } static int run_server(tiny_store_t *store) { int result = tiny_convmem_server_run(stdin, stdout, store); if (result != 0) { fprintf(stderr, "tiny-convmem-mcp stopped with error code %d\n", result); } return result; } static int run_cli_command(tiny_store_t *store, const tiny_sys_arguments_t *arguments) { tiny_cli_options_t options = { 0 }; options.data_dir = arguments->values[2]; options.import_path = find_argument(arguments, "--import"); options.export_path = find_argument(arguments, "--export"); options.session_id = find_argument(arguments, "--session"); options.policy_name = find_argument(arguments, "--policy"); options.include_deleted = flag_present(arguments, "--include-deleted"); if (options.import_path) { return tiny_cli_import(store, &options); } if (options.export_path) { return tiny_cli_export(store, &options); } return 2; } static int run(const tiny_sys_arguments_t *arguments) { char *absolute; tiny_store_t *store = NULL; tiny_store_status_t status; int result; int server_mode = 0; if (arguments->count == 2 && strcmp(arguments->values[1], "--help") == 0) { usage(stdout); return 0; } if (arguments->count < 3 || strcmp(arguments->values[1], "--data-dir") != 0 || arguments->values[2][0] == '\0') { usage(stderr); return 2; } server_mode = (arguments->count == 3) || (arguments->count == 5 && strcmp(arguments->values[3], "--import") != 0 && strcmp(arguments->values[3], "--export") != 0); if (!server_mode && arguments->count < 5) { usage(stderr); return 2; } absolute = tiny_sys_path_absolute(arguments->values[2]); if (absolute == NULL) { fprintf(stderr, "unable to resolve --data-dir\n"); return 2; } status = tiny_store_open(&store, absolute); free(absolute); if (status != TINY_STORE_OK) { fprintf(stderr, "unable to open conversation store: %s\n", tiny_store_status_name(status)); return status == TINY_STORE_BUSY ? 3 : 1; } result = server_mode ? run_server(store) : run_cli_command(store, arguments); tiny_store_close(store); return result; } int main(int argc, char **argv) { tiny_sys_arguments_t arguments; int result; if (!tiny_sys_arguments_init(&arguments, argc, argv)) { fprintf(stderr, "unable to read process arguments\n"); return 2; } result = run(&arguments); tiny_sys_arguments_free(&arguments); return result; }