@@ -136,3 +136,115 @@ export fn cf_record_type_is_proxyable(record_type_int: c_int) c_int {
136136export fn cf_proxied_provides_ipv6 (proxied : c_int ) c_int {
137137 return if (proxied != 0 ) 1 else 0 ;
138138}
139+
140+ // ═══════════════════════════════════════════════════════════════════════
141+ // Standard ABI (ADR-0005 four symbols + ADR-0006 invoke)
142+ // ═══════════════════════════════════════════════════════════════════════
143+
144+ const shim = @import ("cartridge_shim" );
145+
146+ const CARTRIDGE_NAME_PTR : [* :0 ]const u8 = "cloudflare-mcp" ;
147+ const CARTRIDGE_VERSION_PTR : [* :0 ]const u8 = "0.1.0" ;
148+
149+ export fn boj_cartridge_init () callconv (.c ) c_int {
150+ return 0 ;
151+ }
152+
153+ export fn boj_cartridge_deinit () callconv (.c ) void {}
154+
155+ export fn boj_cartridge_name () callconv (.c ) [* :0 ]const u8 {
156+ return CARTRIDGE_NAME_PTR ;
157+ }
158+
159+ export fn boj_cartridge_version () callconv (.c ) [* :0 ]const u8 {
160+ return CARTRIDGE_VERSION_PTR ;
161+ }
162+
163+ /// Dispatch the cartridge.json MCP tools. Grade D Alpha stubs.
164+ export fn boj_cartridge_invoke (
165+ tool_name : [* c ]const u8 ,
166+ json_args : [* c ]const u8 ,
167+ out_buf : [* c ]u8 ,
168+ in_out_len : [* c ]usize ,
169+ ) callconv (.c ) i32 {
170+ _ = json_args ;
171+ if (shim .invokeArgsNull (tool_name , out_buf , in_out_len )) return shim .RC_BAD_ARGS ;
172+
173+ const body : []const u8 = if (shim .toolIs (tool_name , "cf_list_zones" ))
174+ "{\" result\" :{\" items\" :[],\" count\" :0,\" status\" :\" stub\" }}"
175+ else if (shim .toolIs (tool_name , "cf_get_zone" ))
176+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
177+ else if (shim .toolIs (tool_name , "cf_list_dns_records" ))
178+ "{\" result\" :{\" items\" :[],\" count\" :0,\" status\" :\" stub\" }}"
179+ else if (shim .toolIs (tool_name , "cf_get_dns_record" ))
180+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
181+ else if (shim .toolIs (tool_name , "cf_create_dns_record" ))
182+ "{\" result\" :{\" status\" :\" stub\" }}"
183+ else if (shim .toolIs (tool_name , "cf_update_dns_record" ))
184+ "{\" result\" :{\" status\" :\" stub\" }}"
185+ else if (shim .toolIs (tool_name , "cf_patch_dns_record" ))
186+ "{\" result\" :{\" status\" :\" stub\" }}"
187+ else if (shim .toolIs (tool_name , "cf_delete_dns_record" ))
188+ "{\" result\" :{\" status\" :\" stub\" }}"
189+ else if (shim .toolIs (tool_name , "cf_get_zone_setting" ))
190+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
191+ else if (shim .toolIs (tool_name , "cf_update_zone_setting" ))
192+ "{\" result\" :{\" status\" :\" stub\" }}"
193+ else if (shim .toolIs (tool_name , "cf_purge_cache" ))
194+ "{\" result\" :{\" status\" :\" stub\" }}"
195+ else
196+ return shim .RC_UNKNOWN_TOOL ;
197+
198+ return shim .writeResult (out_buf , in_out_len , body );
199+ }
200+
201+ // ═══════════════════════════════════════════════════════════════════════
202+ // ADR-0006 invoke dispatch tests
203+ // ═══════════════════════════════════════════════════════════════════════
204+
205+ test "boj_cartridge_name returns cloudflare-mcp" {
206+ const n = std .mem .span (boj_cartridge_name ());
207+ try std .testing .expectEqualStrings ("cloudflare-mcp" , n );
208+ }
209+
210+ test "boj_cartridge_init returns 0" {
211+ try std .testing .expectEqual (@as (c_int , 0 ), boj_cartridge_init ());
212+ }
213+
214+ test "invoke: each declared tool succeeds" {
215+ var buf : [256 ]u8 = undefined ;
216+ const tools = [_ ][]const u8 {
217+ "cf_list_zones" ,
218+ "cf_get_zone" ,
219+ "cf_list_dns_records" ,
220+ "cf_get_dns_record" ,
221+ "cf_create_dns_record" ,
222+ "cf_update_dns_record" ,
223+ "cf_patch_dns_record" ,
224+ "cf_delete_dns_record" ,
225+ "cf_get_zone_setting" ,
226+ "cf_update_zone_setting" ,
227+ "cf_purge_cache" ,
228+ };
229+ for (tools ) | t | {
230+ var len : usize = buf .len ;
231+ const rc = boj_cartridge_invoke (t .ptr , "{}" , & buf , & len );
232+ try std .testing .expectEqual (@as (i32 , 0 ), rc );
233+ try std .testing .expect (std .mem .indexOf (u8 , buf [0.. len ], "result" ) != null );
234+ }
235+ }
236+
237+ test "invoke: unknown tool returns -1" {
238+ var buf : [64 ]u8 = undefined ;
239+ var len : usize = buf .len ;
240+ const rc = boj_cartridge_invoke ("nope" , "{}" , & buf , & len );
241+ try std .testing .expectEqual (@as (i32 , -1 ), rc );
242+ }
243+
244+ test "invoke: buffer too small returns -3" {
245+ var buf : [4 ]u8 = undefined ;
246+ var len : usize = buf .len ;
247+ const rc = boj_cartridge_invoke ("cf_list_zones" , "{}" , & buf , & len );
248+ try std .testing .expectEqual (@as (i32 , -3 ), rc );
249+ try std .testing .expect (len > 4 );
250+ }
0 commit comments