code wiki / (root) / nx_mcp_envelope.nx

nx_mcp_envelope.nx source

↩ module page · 62 lines · 3036 B

1// Native MCP envelope selection. Reuses the estate value parser. 2// Spans refer to original request bytes; nested params cannot supply envelope fields. 3import "nx_value_parse_json.nx" 4struct NxMcpEnvelope { id_off: i64, id_len: i64, method_off: i64, method_len: i64 } 5const NX_MCP_ENVELOPE_BYTES: i64 = 4 * 8 6func nme_equal(v: *NxValue, s: *u8, n: i64) -> i64 { 7 if v == 0 as *NxValue { return 0 } 8 if v.kind != NX_VAL_STRING { return 0 } 9 return nx_value_bytes_equal(v.str_ptr, v.str_len, s, n) 10} 11// 1=request, 2=initialized notification, 0=invalid or unsupported notification. 12func nme_read(src: *u8, n: i64, e: *NxMcpEnvelope) -> i64 { 13 e.id_off = 0; e.id_len = 0; e.method_off = 0; e.method_len = 0 14 let verdict: *i64 = sys_mmap(8) as *i64 15 let root: *NxValue = nx_value_parse_json(src, n, verdict) 16 if verdict[0] != NX_VAL_PARSE_OK { return 0 } 17 if root == 0 as *NxValue { return 0 } 18 if root.kind != NX_VAL_OBJECT { return 0 } 19 var ids: i64 = 0; var methods: i64 = 0; var versions: i64 = 0 20 var id_key: *u8 = 0 as *u8 21 var k: i64 = 0 22 while k < root.n_items { 23 if nx_value_bytes_equal(root.keys_ptr[k], root.key_lens_ptr[k], "id", 2) == 1 { ids = ids + 1; id_key = root.keys_ptr[k] } 24 if nx_value_bytes_equal(root.keys_ptr[k], root.key_lens_ptr[k], "method", 6) == 1 { methods = methods + 1 } 25 if nx_value_bytes_equal(root.keys_ptr[k], root.key_lens_ptr[k], "jsonrpc", 7) == 1 { versions = versions + 1 } 26 k = k + 1 27 } 28 if ids > 1 { return 0 } 29 if methods != 1 { return 0 } 30 if versions != 1 { return 0 } 31 if nme_equal(nx_value_object_get(root, "jsonrpc", 7), "2.0", 3) != 1 { return 0 } 32 let method: *NxValue = nx_value_object_get(root, "method", 6) 33 if method == 0 as *NxValue { return 0 } 34 if method.kind != NX_VAL_STRING { return 0 } 35 e.method_off = (method.str_ptr as i64) - (src as i64) 36 e.method_len = method.str_len 37 if ids == 0 { 38 if nme_equal(method, "notifications/initialized", 25) != 1 { return 0 } 39 let params: *NxValue = nx_value_object_get(root, "params", 6) 40 if params != 0 as *NxValue { if params.kind != NX_VAL_OBJECT { return 0 } } 41 return 2 42 } 43 let id: *NxValue = nx_value_object_get(root, "id", 2) 44 if id == 0 as *NxValue { return 0 } 45 if id.kind == NX_VAL_STRING { 46 e.id_off = (id.str_ptr as i64) - (src as i64) - 1 47 e.id_len = id.str_len + 2 48 } else { 49 if id.kind != NX_VAL_INT { return 0 } 50 var p: i64 = (id_key as i64) - (src as i64) + 3 51 while p < n { if src[p] == 58 as u8 { p = p + 1; break } p = p + 1 } 52 while p < n { if nx_val_parse_is_ws(src[p] as i64) == 0 { break } p = p + 1 } 53 e.id_off = p 54 if p < n { if src[p] == 45 as u8 { p = p + 1 } } 55 while p < n { if nx_val_parse_is_digit(src[p] as i64) == 0 { break } p = p + 1 } 56 e.id_len = p - e.id_off 57 } 58 if e.id_off < 0 { return 0 } 59 if e.id_len <= 0 { return 0 } 60 if e.id_off + e.id_len > n { return 0 } 61 return 1 62}