@@ -372,6 +372,59 @@ pub export fn linear_mcp_reset() void {
372372}
373373
374374// ---------------------------------------------------------------------------
375+ // ═══════════════════════════════════════════════════════════════════════
376+ // Standard ABI (ADR-0005 four symbols + ADR-0006 invoke)
377+ // ═══════════════════════════════════════════════════════════════════════
378+
379+ const shim = @import ("cartridge_shim" );
380+
381+ const CARTRIDGE_NAME_PTR : [* :0 ]const u8 = "linear-mcp" ;
382+ const CARTRIDGE_VERSION_PTR : [* :0 ]const u8 = "0.1.0" ;
383+
384+ export fn boj_cartridge_init () callconv (.c ) c_int {
385+ return 0 ;
386+ }
387+
388+ export fn boj_cartridge_deinit () callconv (.c ) void {}
389+
390+ export fn boj_cartridge_name () callconv (.c ) [* :0 ]const u8 {
391+ return CARTRIDGE_NAME_PTR ;
392+ }
393+
394+ export fn boj_cartridge_version () callconv (.c ) [* :0 ]const u8 {
395+ return CARTRIDGE_VERSION_PTR ;
396+ }
397+
398+ /// Dispatch the cartridge.json MCP tools. Grade D Alpha stubs.
399+ export fn boj_cartridge_invoke (
400+ tool_name : [* c ]const u8 ,
401+ json_args : [* c ]const u8 ,
402+ out_buf : [* c ]u8 ,
403+ in_out_len : [* c ]usize ,
404+ ) callconv (.c ) i32 {
405+ _ = json_args ;
406+ if (shim .invokeArgsNull (tool_name , out_buf , in_out_len )) return shim .RC_BAD_ARGS ;
407+
408+ const body : []const u8 = if (shim .toolIs (tool_name , "linear_authenticate" ))
409+ "{\" result\" :{\" status\" :\" stub\" }}"
410+ else if (shim .toolIs (tool_name , "linear_list_issues" ))
411+ "{\" result\" :{\" items\" :[],\" count\" :0,\" status\" :\" stub\" }}"
412+ else if (shim .toolIs (tool_name , "linear_get_issue" ))
413+ "{\" result\" :{\" metadata\" :{},\" status\" :\" stub\" }}"
414+ else if (shim .toolIs (tool_name , "linear_create_issue" ))
415+ "{\" result\" :{\" status\" :\" stub\" }}"
416+ else if (shim .toolIs (tool_name , "linear_update_issue" ))
417+ "{\" result\" :{\" status\" :\" stub\" }}"
418+ else if (shim .toolIs (tool_name , "linear_list_teams" ))
419+ "{\" result\" :{\" items\" :[],\" count\" :0,\" status\" :\" stub\" }}"
420+ else if (shim .toolIs (tool_name , "linear_search_issues" ))
421+ "{\" result\" :{\" matches\" :[],\" status\" :\" stub\" }}"
422+ else
423+ return shim .RC_UNKNOWN_TOOL ;
424+
425+ return shim .writeResult (out_buf , in_out_len , body );
426+ }
427+
375428// Tests
376429// ---------------------------------------------------------------------------
377430
@@ -459,3 +512,50 @@ test "slot exhaustion" {
459512 const new_slot = linear_mcp_authenticate ("lin_api_reuse_slot_token_1234567" );
460513 try std .testing .expect (new_slot >= 0 );
461514}
515+
516+ // ═══════════════════════════════════════════════════════════════════════
517+ // ADR-0006 invoke dispatch tests
518+ // ═══════════════════════════════════════════════════════════════════════
519+
520+ test "boj_cartridge_name returns linear-mcp" {
521+ const n = std .mem .span (boj_cartridge_name ());
522+ try std .testing .expectEqualStrings ("linear-mcp" , n );
523+ }
524+
525+ test "boj_cartridge_init returns 0" {
526+ try std .testing .expectEqual (@as (c_int , 0 ), boj_cartridge_init ());
527+ }
528+
529+ test "invoke: each declared tool succeeds" {
530+ var buf : [256 ]u8 = undefined ;
531+ const tools = [_ ][]const u8 {
532+ "linear_authenticate" ,
533+ "linear_list_issues" ,
534+ "linear_get_issue" ,
535+ "linear_create_issue" ,
536+ "linear_update_issue" ,
537+ "linear_list_teams" ,
538+ "linear_search_issues" ,
539+ };
540+ for (tools ) | t | {
541+ var len : usize = buf .len ;
542+ const rc = boj_cartridge_invoke (t .ptr , "{}" , & buf , & len );
543+ try std .testing .expectEqual (@as (i32 , 0 ), rc );
544+ try std .testing .expect (std .mem .indexOf (u8 , buf [0.. len ], "result" ) != null );
545+ }
546+ }
547+
548+ test "invoke: unknown tool returns -1" {
549+ var buf : [64 ]u8 = undefined ;
550+ var len : usize = buf .len ;
551+ const rc = boj_cartridge_invoke ("nope" , "{}" , & buf , & len );
552+ try std .testing .expectEqual (@as (i32 , -1 ), rc );
553+ }
554+
555+ test "invoke: buffer too small returns -3" {
556+ var buf : [4 ]u8 = undefined ;
557+ var len : usize = buf .len ;
558+ const rc = boj_cartridge_invoke ("linear_authenticate" , "{}" , & buf , & len );
559+ try std .testing .expectEqual (@as (i32 , -3 ), rc );
560+ try std .testing .expect (len > 4 );
561+ }
0 commit comments