@@ -278,6 +278,65 @@ pub export fn google_docs_mcp_reset() void {
278278}
279279
280280// ---------------------------------------------------------------------------
281+ // ═══════════════════════════════════════════════════════════════════════
282+ // Standard ABI (ADR-0005 four symbols + ADR-0006 invoke)
283+ // ═══════════════════════════════════════════════════════════════════════
284+
285+ const shim = @import ("cartridge_shim" );
286+
287+ const CARTRIDGE_NAME_PTR : [* :0 ]const u8 = "google-docs-mcp" ;
288+ const CARTRIDGE_VERSION_PTR : [* :0 ]const u8 = "0.1.0" ;
289+
290+ export fn boj_cartridge_init () callconv (.c ) c_int {
291+ return 0 ;
292+ }
293+
294+ export fn boj_cartridge_deinit () callconv (.c ) void {}
295+
296+ export fn boj_cartridge_name () callconv (.c ) [* :0 ]const u8 {
297+ return CARTRIDGE_NAME_PTR ;
298+ }
299+
300+ export fn boj_cartridge_version () callconv (.c ) [* :0 ]const u8 {
301+ return CARTRIDGE_VERSION_PTR ;
302+ }
303+
304+ /// Dispatch the cartridge.json MCP tools. Grade D Alpha stubs.
305+ export fn boj_cartridge_invoke (
306+ tool_name : [* c ]const u8 ,
307+ json_args : [* c ]const u8 ,
308+ out_buf : [* c ]u8 ,
309+ in_out_len : [* c ]usize ,
310+ ) callconv (.c ) i32 {
311+ _ = json_args ;
312+ if (shim .invokeArgsNull (tool_name , out_buf , in_out_len )) return shim .RC_BAD_ARGS ;
313+
314+ const body : []const u8 = if (shim .toolIs (tool_name , "gdocs_get_document" ))
315+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
316+ else if (shim .toolIs (tool_name , "gdocs_get_content" ))
317+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
318+ else if (shim .toolIs (tool_name , "gdocs_get_headings" ))
319+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
320+ else if (shim .toolIs (tool_name , "gdocs_search_content" ))
321+ "{\" result\" :{\" matches\" :[],\" status\" :\" stub\" }}"
322+ else if (shim .toolIs (tool_name , "gdocs_list_comments" ))
323+ "{\" result\" :{\" items\" :[],\" count\" :0,\" status\" :\" stub\" }}"
324+ else if (shim .toolIs (tool_name , "gdocs_list_suggestions" ))
325+ "{\" result\" :{\" items\" :[],\" count\" :0,\" status\" :\" stub\" }}"
326+ else if (shim .toolIs (tool_name , "gdocs_get_revisions" ))
327+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
328+ else if (shim .toolIs (tool_name , "gdocs_get_named_ranges" ))
329+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
330+ else if (shim .toolIs (tool_name , "gdocs_create_document" ))
331+ "{\" result\" :{\" status\" :\" stub\" }}"
332+ else if (shim .toolIs (tool_name , "gdocs_insert_text" ))
333+ "{\" result\" :{\" status\" :\" stub\" }}"
334+ else
335+ return shim .RC_UNKNOWN_TOOL ;
336+
337+ return shim .writeResult (out_buf , in_out_len , body );
338+ }
339+
281340// Tests
282341// ---------------------------------------------------------------------------
283342
@@ -352,3 +411,53 @@ test "slot exhaustion" {
352411 const new_slot = google_docs_mcp_connect (0 );
353412 try std .testing .expect (new_slot >= 0 );
354413}
414+
415+ // ═══════════════════════════════════════════════════════════════════════
416+ // ADR-0006 invoke dispatch tests
417+ // ═══════════════════════════════════════════════════════════════════════
418+
419+ test "boj_cartridge_name returns google-docs-mcp" {
420+ const n = std .mem .span (boj_cartridge_name ());
421+ try std .testing .expectEqualStrings ("google-docs-mcp" , n );
422+ }
423+
424+ test "boj_cartridge_init returns 0" {
425+ try std .testing .expectEqual (@as (c_int , 0 ), boj_cartridge_init ());
426+ }
427+
428+ test "invoke: each declared tool succeeds" {
429+ var buf : [256 ]u8 = undefined ;
430+ const tools = [_ ][]const u8 {
431+ "gdocs_get_document" ,
432+ "gdocs_get_content" ,
433+ "gdocs_get_headings" ,
434+ "gdocs_search_content" ,
435+ "gdocs_list_comments" ,
436+ "gdocs_list_suggestions" ,
437+ "gdocs_get_revisions" ,
438+ "gdocs_get_named_ranges" ,
439+ "gdocs_create_document" ,
440+ "gdocs_insert_text" ,
441+ };
442+ for (tools ) | t | {
443+ var len : usize = buf .len ;
444+ const rc = boj_cartridge_invoke (t .ptr , "{}" , & buf , & len );
445+ try std .testing .expectEqual (@as (i32 , 0 ), rc );
446+ try std .testing .expect (std .mem .indexOf (u8 , buf [0.. len ], "result" ) != null );
447+ }
448+ }
449+
450+ test "invoke: unknown tool returns -1" {
451+ var buf : [64 ]u8 = undefined ;
452+ var len : usize = buf .len ;
453+ const rc = boj_cartridge_invoke ("nope" , "{}" , & buf , & len );
454+ try std .testing .expectEqual (@as (i32 , -1 ), rc );
455+ }
456+
457+ test "invoke: buffer too small returns -3" {
458+ var buf : [4 ]u8 = undefined ;
459+ var len : usize = buf .len ;
460+ const rc = boj_cartridge_invoke ("gdocs_get_document" , "{}" , & buf , & len );
461+ try std .testing .expectEqual (@as (i32 , -3 ), rc );
462+ try std .testing .expect (len > 4 );
463+ }
0 commit comments