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}