ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
main.c File Reference

Go to the source code of this file.

Functions

int mcp_server_main (void)

Function Documentation

◆ mcp_server_main()

int mcp_server_main ( void )

Definition at line 21 of file mcp-server/main.c.

21 {
22 if (strcmp(GET_OPTION(mcp_transport), "http") && strcmp(GET_OPTION(mcp_transport), "stdio"))
23 return SET_ERRNO(ERROR_CONFIG, "--transport must be http or stdio");
24 mcp_server_t *s = SAFE_CALLOC(1, sizeof(*s), mcp_server_t *);
25 s->policy = (mcp_policy_t){.hosted = !strcmp(GET_OPTION(mcp_transport), "http"),
26 .restricted = GET_OPTION(mcp_server_restricted),
27 .address = GET_OPTION(address),
28 .address6 = GET_OPTION(address6),
29 .port = GET_OPTION(port),
30 .origin = GET_OPTION(http_origin),
31 .tls_cert = GET_OPTION(tls_cert),
32 .tls_key = GET_OPTION(tls_key),
33 .tls_password = GET_OPTION(tls_key_password),
34 .max_jobs = (unsigned)GET_OPTION(max_clients),
35 .downloads_url_prefix = GET_OPTION(mcp_downloads_url_prefix)};
37 const char *prefix = s->policy.downloads_url_prefix;
38 const char *authority = !strncmp(prefix, "https://", sizeof("https://") - 1) ? prefix + 8
39 : !strncmp(prefix, "http://", sizeof("http://") - 1) ? prefix + 7
40 : NULL;
41 if (!authority || !*authority || *authority == '/' || strpbrk(prefix, " \t\r\n?#")) {
42 SAFE_FREE(s);
43 return SET_ERRNO(ERROR_CONFIG, "--downloads-url-prefix must be an HTTP(S) URL without query or fragment");
44 }
45 }
46 if (s->policy.restricted && s->policy.hosted) {
47 const char *override = GET_OPTION(mcp_downloads_dir);
48 char *data_dir = NULL;
49 if (override && *override) {
50 SAFE_STRNCPY(s->policy.downloads_dir, override, sizeof(s->policy.downloads_dir));
51 } else {
52 data_dir = platform_get_data_dir();
53 if (!data_dir) {
54 SAFE_FREE(s);
55 return SET_ERRNO(ERROR_CONFIG, "Cannot determine MCP data directory");
56 }
57 SAFE_SNPRINTF(s->policy.downloads_dir, sizeof(s->policy.downloads_dir), "%s/downloads", data_dir);
58 SAFE_FREE(data_dir);
59 }
60 asciichat_error_t directory_error = platform_mkdir_recursive(s->policy.downloads_dir, 0700);
61 if (directory_error != ASCIICHAT_OK) {
62 SAFE_FREE(s);
63 return directory_error;
64 }
65 uv_fs_t resolved;
66 int rc = uv_fs_realpath(NULL, &resolved, s->policy.downloads_dir, NULL);
67 if (rc < 0 || strlen((const char *)resolved.ptr) >= sizeof(s->policy.downloads_dir)) {
68 uv_fs_req_cleanup(&resolved);
69 SAFE_FREE(s);
70 return SET_ERRNO(ERROR_CONFIG, "Cannot resolve MCP downloads directory");
71 }
72 SAFE_STRNCPY(s->policy.downloads_dir, (const char *)resolved.ptr, sizeof(s->policy.downloads_dir));
73 uv_fs_req_cleanup(&resolved);
74 }
76 unsigned available_cpus = uv_available_parallelism();
77 if (!available_cpus)
78 available_cpus = 1;
79 if (!s->policy.max_jobs || s->policy.max_jobs > available_cpus)
80 s->policy.max_jobs = available_cpus;
81 if (s->policy.hosted && (!!s->policy.tls_cert[0] != !!s->policy.tls_key[0])) {
82 asciichat_error_t err = SET_ERRNO(ERROR_CONFIG, "MCP HTTPS requires both --tls-cert and --tls-key");
83 log_error("MCP HTTPS requires both --tls-cert and --tls-key");
84 SAFE_FREE(s);
85 return err;
86 }
87 // Initialize immutable registry metadata before worker threads are started.
89 if (sodium_init() < 0 || mutex_init(&s->output_mutex, "mcp.output")) {
90 SAFE_FREE(s);
91 return SET_ERRNO(ERROR_INVALID_STATE, "Cannot initialize MCP server");
92 }
93 s->jobs = SAFE_CALLOC(s->policy.max_jobs, sizeof(*s->jobs), mcp_job_t *);
94 if (!s->jobs) {
95 mutex_destroy(&s->output_mutex);
96 SAFE_FREE(s);
97 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate MCP render jobs");
98 }
99 log_info("MCP server started (%s, %s capabilities, %u render jobs)", s->policy.hosted ? "HTTP" : "stdio",
100 s->policy.restricted ? "restricted" : "local", s->policy.max_jobs);
101 if (s->policy.hosted) {
102 platform_systemd_notify_status("MCP HTTP listener started");
103 platform_systemd_notify_ready();
104 }
105 stats_runtime_set_provider(mcp_stats_view, s);
107 stats_runtime_set_provider(NULL, NULL);
108 for (unsigned i = 0; i < s->policy.max_jobs; ++i)
109 if (s->jobs[i].renderer_job.started)
111 mcp_jobs_reap(s, true);
113 mutex_destroy(&s->output_mutex);
114 SAFE_FREE(s->jobs);
115 SAFE_FREE(s);
116 return err;
117}
#define SET_ERRNO(code,...)
void registry_init_size(void)
Initialize registry size and metadata.
Definition core.c:108
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:423
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_SNPRINTF(buffer, buffer_size,...)
Definition common.h:507
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_INVALID_STATE
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_CONFIG
Definition error_codes.h:52
#define log_error(...)
Log an ERROR message.
Definition log/log.h:634
#define log_info(...)
Log an INFO message.
Definition log/log.h:608
void log_set_terminal_output(bool enabled)
Control stderr output to terminal.
Definition log.c:746
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
asciichat_error_t mcp_http_run(mcp_server_t *s)
Definition http.c:233
void http_renderer_job_cancel(http_renderer_job_t *job)
struct mcp_server mcp_server_t
The useful part of mcp job is in server, message, response, request: together they describe what is p...
struct mcp_job mcp_job_t
When code needs to work with mcp policy, it keeps hosted, restricted, address, address6 here instead ...
void mcp_jobs_reap(mcp_server_t *server, bool all)
asciichat_error_t mcp_stdio_run(mcp_server_t *server)
Definition stdio.c:31
void mcp_stdio_release(void)
Definition stdio.c:13
void stats_runtime_set_provider(stats_provider_fn provider, void *data)
Definition runtime.c:126
http_renderer_job_t renderer_job
Definition mcp.h:67
const char * tls_key
Definition mcp.h:40
unsigned max_jobs
Definition mcp.h:41
const char * tls_cert
Definition mcp.h:40
char downloads_dir[PLATFORM_MAX_PATH_LENGTH]
Definition mcp.h:44
const char * downloads_url_prefix
Definition mcp.h:45
bool restricted
Definition mcp.h:37
bool hosted
Definition mcp.h:36
mutex_t output_mutex
Definition mcp.h:83
mcp_job_t * jobs
Definition mcp.h:82
mcp_policy_t policy
Definition mcp.h:81

References ASCIICHAT_OK, mcp_policy_t::downloads_dir, mcp_policy_t::downloads_url_prefix, ERROR_CONFIG, ERROR_INVALID_STATE, ERROR_MEMORY, GET_OPTION, mcp_policy_t::hosted, http_renderer_job_cancel(), mcp_server::jobs, log_error, log_info, log_set_terminal_output(), mcp_policy_t::max_jobs, mcp_http_run(), mcp_jobs_reap(), mcp_stdio_release(), mcp_stdio_run(), mcp_server::output_mutex, mcp_server::policy, registry_init_size(), mcp_job::renderer_job, mcp_policy_t::restricted, SAFE_CALLOC, SAFE_FREE, SAFE_SNPRINTF, SAFE_STRNCPY, SET_ERRNO, http_renderer_job::started, stats_runtime_set_provider(), mcp_policy_t::tls_cert, and mcp_policy_t::tls_key.