code wiki / (root) / nx_mcp_call.nx

nx_mcp_call.nx

buildroot/runtime/nx_mcp_call.nx

15107 B272 linesdepth 20pulls 137 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_mcp_call.nx -- the SOVEREIGN MCP client: POST a JSON-RPC tools/call to /mcp over our own TLS-1.3 and PRINT the response body. Fills the gap surfaced 2026-07-17 ([[reference-sovereign-mcp-call-client-gap-2026-07-17]]): nx_mgmt_client's `call` sends x-www-form-urlencoded (built for /api/login) so it mis-frames a JSON tools/call (status=0); this client sends Content-Type: application/json + Accept + X-Nishi-Cap and echoes the body. ✅PROVEN 2026-07-17: `tools/call` WORKS end-to-end -- nishi_search returned real search hits, and nx_dataplane_census returned 655 flat-file-debt rows (56KB, HTTP 200, isError:false) over sovereign TLS /mcp with a least-authority cap. `initialize`/`tools/list`/`tools/call` all work; the sovereign JSON POST /mcp + response-parse + body-print are complete. nx_mgmt_client CANNOT do this (it sends x-www-form-urlencoded -> the daemon mis-frames the JSON -> status=0). That form-encoding -- NOT a daemon bug -- is why the doctrine's "raw tools/call via nx_mgmt_client" path always failed. ⚠fork-exec tools are SLOW (census ~16s) so a client needs patience; ⚠tools whose ELF FORKS CHILDREN (e.g. nx_status -> nx_hostctl sub-forks) return empty because tr_run_capture (nx_tool_run.nx:21) dups the pipe to stdout/stderr but does NOT close the inherited request SOCKET fd before execve -> forked grandchildren hold the connection open -> no clean close (a SEPARATE daemon fix: add a close-fds-3..N loop in the child). Non-forking tools (search, census) work today. tool_name "__initialize__" sends an initialize (open, no cap) probe. [[reference-sovereign-mcp-call-client-gap-2026-07-17]] nx_mcp_call <base_url> <tool_name> <cap_file> [args_json_fragment] e.g. nx_mcp_call https://nishifamily.com nx_dataplane_census /tmp/capfile args_json_fragment (optional) is spliced into arguments after _cap, e.g. "argv":["a","b"] REUSE (compose, don't rebuild TLS): copies nx_mgmt_client's PROVEN transport (build_request/send_drain/req) verbatim -- renamed mc_* -- flipping ONLY the content-type. DRY debt: extract the shared transport into a no-main lib later (nx_mgmt_client has a main(), so it can't be imported today). license_tier: ORIGINAL

dependencies 10 imports · 0 importers

nx_acme_http.nx nx_itoa_lib.nx nx_https_url_for_fetch.nx nx_https_url_connect.nx nx_tls13_client_session_run.nx nx_tls13_client_session.nx nx_tls13.nx nx_tls13_record.nx nx_tls13_read_record_from_fd.nx nx_csprng.nx nx_mcp_call.nx

imports: nx_acme_http.nxnx_itoa_lib.nxnx_https_url_for_fetch.nxnx_https_url_connect.nxnx_tls13_client_session_run.nxnx_tls13_client_session.nxnx_tls13.nxnx_tls13_record.nxnx_tls13_read_record_from_fd.nxnx_csprng.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main mc_puts nx_trust_store_load_from_c sys_mmap sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_close nx_nss_certdata_parse sys_mmap ↻ _pat_class_cert _pat_value_octal _pat_end _find_newline _starts_with _parse_octal_line sys_mmap ↻ _is_space _decode_octal_escape _is_octal trust_store_alloc sys_mmap ↻ nx_x509_trust_store_load sys_mmap ↻ x509_parse sys_mmap ↻ asn1_cursor_init asn1_expect_tag sys_mmap ↻ asn1_read_tlv_header asn1_read_tag asn1_read_length asn1_read_length ↻ x509_read_tlv sys_mmap ↻ asn1_expect_tag ↻ x509_read_alg_id sys_mmap ↻

structs

none

consts

32const MC_MAGIC_16384: i64 = 16384
33const MC_MAGIC_16645: i64 = 16645
34const MC_MAGIC_4194304: i64 = 4194304
35const MC_MAGIC_8192: i64 = 8192
36const MC_MAGIC_8191: i64 = 8191
37const MC_MAGIC_65536: i64 = 65536
38const MC_MAGIC_4096: i64 = 4096
39const MC_MAGIC_131072: i64 = 131072
40const MC_MAGIC_1048576: i64 = 1048576
42const MC_CONNECT_FAIL: i64 = 0 - 11
43const MC_HANDSHAKE_FAIL: i64 = 0 - 12

functions

45func mc_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
called by 1: main
50func mc_putn(v: i64) -> i64 { nxi_out(v); return 0 }
called by 1: main calls 1: nxi_out
51func mc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 1: main
52func mc_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o + i] = s[i]; i = i + 1 } return o + i }
53func mc_catb(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { d[o + i] = s[i]; i = i + 1 } return o + i }
54func mc_catn(d: *u8, o: i64, v: i64) -> i64
called by 1: mc_build_request
63func mc_write_n(fd: i64, buf: *u8, n: i64) -> i64
called by 1: mc_send_drain
72func mc_read_file(path: *u8, out: *u8, cap: i64) -> i64
called by 1: main calls 1: sys_read
84func mc_rtrim_nl(buf: *u8, n: i64) -> i64
called by 1: main
93func mc_join_url(base_url: *u8, suffix: *u8, out: *u8) -> i64
called by 1: main calls 1: mc_cat
103func mc_build_request(method: *u8, method_len: i64, path: *u8, path_len: i64, host: *u8, host_len: i64, cap: *u8, cap_len: i64, ct: *u8, ct_len: i64, body: *u8, body_len: i64, out: *u8) -> i64
called by 1: main calls 3: mc_catbmc_catmc_catn
131func mc_send_drain(s: *Tls13ClientSession, fd: i64, req: *u8, req_len: i64, out: *u8, out_cap: i64) -> i64
177func mc_req(store: *TrustStore, full_url: *u8, target: *NxHttpsTarget, req: *u8, req_len: i64, out: *u8, out_cap: i64) -> i64
201func main(argc: i64, argv: *i64) -> i64