@@ -879,6 +879,7 @@ typedef struct {
879879 bool destructive;
880880 bool idempotent;
881881 bool open_world;
882+ bool load_upfront;
882883} tool_annotation_def_t;
883884
884885/* Tool annotations are deliberately explicit. All tools operate on the local
@@ -894,25 +895,32 @@ typedef struct {
894895 * Only handlers that write user-visible state -- index_repository, manage_adr,
895896 * delete_project, ingest_traces -- may clear readOnlyHint. Trace ingestion
896897 * accumulates observation counts on retries and can evict old runs, so it is
897- * neither read-only nor idempotent and must advertise destructive effects. */
898+ * neither read-only nor idempotent and must advertise destructive effects.
899+ *
900+ * load_upfront marks the structural discovery path (search_graph ->
901+ * trace_path -> get_code_snippet). Claude Code defers every MCP tool behind
902+ * ToolSearch by default, so an agent deciding how to answer sees Grep and Read
903+ * but not the graph; `_meta["anthropic/alwaysLoad"]` asks it to load these
904+ * three schemas upfront (about 4.6K characters) while the rest stay deferred.
905+ * Clients that do not know the key ignore it, as MCP reserves `_meta`. */
898906static const tool_annotation_def_t TOOL_ANNOTATIONS[] = {
899- {"index_repository", false, false, true, false},
900- {"search_graph", true, false, true, false},
901- {"query_graph", true, false, true, false},
902- {"trace_path", true, false, true, false},
903- {"get_code_snippet", true, false, true, false},
904- {"get_file_outline", true, false, true, false},
905- {"get_graph_schema", true, false, true, false},
906- {"compare_graphs", true, false, true, false},
907- {"get_architecture", true, false, true, false},
908- {"search_code", true, false, true, false},
909- {"list_projects", true, false, true, false},
910- {"delete_project", false, true, true, false},
911- {"index_status", true, false, true, false},
912- {"check_index_coverage", true, false, true, false},
913- {"detect_changes", true, false, true, false},
914- {"manage_adr", false, true, false, false},
915- {"ingest_traces", false, true, false, false},
907+ {"index_repository", false, false, true, false, false },
908+ {"search_graph", true, false, true, false, true },
909+ {"query_graph", true, false, true, false, false },
910+ {"trace_path", true, false, true, false, true },
911+ {"get_code_snippet", true, false, true, false, true },
912+ {"get_file_outline", true, false, true, false, false },
913+ {"get_graph_schema", true, false, true, false, false },
914+ {"compare_graphs", true, false, true, false, false },
915+ {"get_architecture", true, false, true, false, false },
916+ {"search_code", true, false, true, false, false },
917+ {"list_projects", true, false, true, false, false },
918+ {"delete_project", false, true, true, false, false },
919+ {"index_status", true, false, true, false, false },
920+ {"check_index_coverage", true, false, true, false, false },
921+ {"detect_changes", true, false, true, false, false },
922+ {"manage_adr", false, true, false, false, false },
923+ {"ingest_traces", false, true, false, false, false },
916924};
917925
918926static const tool_annotation_def_t *mcp_tool_annotations(const char *name) {
@@ -962,6 +970,12 @@ static void mcp_add_tool_def(yyjson_mut_doc *doc, yyjson_mut_val *tools, int i)
962970 yyjson_mut_obj_add_bool(doc, annotations, "openWorldHint", def ? def->open_world : true);
963971 yyjson_mut_obj_add_val(doc, tool, "annotations", annotations);
964972
973+ if (def && def->load_upfront) {
974+ yyjson_mut_val *meta = yyjson_mut_obj(doc);
975+ yyjson_mut_obj_add_bool(doc, meta, "anthropic/alwaysLoad", true);
976+ yyjson_mut_obj_add_val(doc, tool, "_meta", meta);
977+ }
978+
965979 yyjson_mut_arr_add_val(tools, tool);
966980}
967981
@@ -1439,21 +1453,42 @@ static const char *SUPPORTED_PROTOCOL_VERSIONS[] = {
14391453static const int SUPPORTED_VERSION_COUNT =
14401454 (int)(sizeof(SUPPORTED_PROTOCOL_VERSIONS) / sizeof(SUPPORTED_PROTOCOL_VERSIONS[0]));
14411455
1456+ /* With tool search (Claude Code's default, Codex's too) the model sees only tool
1457+ * names plus these instructions until it searches, and Codex shows them as the
1458+ * server's namespace description. So they state, keywords first, which
1459+ * questions the graph answers; facts, not commands. Claude Code cuts them at
1460+ * 4,096 characters. */
14421461static const char MCP_SERVER_INSTRUCTIONS[] =
1443- "Graph first: search_graph for symbols, trace_path for relationships, get_code_snippet for "
1444- "source, query_graph for multi-hop, and get_architecture for overview. Use search_code/grep "
1445- "for literals or coverage gaps. The session project's index auto-refreshes; re-index others. "
1446- "Check cited-path coverage; paginate.";
1462+ "codebase-memory-mcp is a code knowledge graph of the indexed repository: functions, "
1463+ "classes, methods, routes, calls, imports, inheritance and cross-service links. It answers "
1464+ "structural code questions: where a symbol is defined, who calls a function, what a function "
1465+ "calls, call chains and data flow, which code a change affects, which handler serves a route, "
1466+ "and how modules fit together. search_graph finds symbols by name or pattern; trace_path "
1467+ "follows callers, callees and data flow; get_code_snippet returns a symbol's exact source; "
1468+ "query_graph runs multi-hop Cypher queries; get_architecture summarizes structure; "
1469+ "detect_changes maps the current diff to affected symbols. Grep and file reads fit literal "
1470+ "text, config values, comments and non-code files better; search_code combines text search "
1471+ "with graph context. The session project's index refreshes automatically; other projects "
1472+ "need index_repository. check_index_coverage tells whether a cited file was fully indexed. "
1473+ "Results are paginated.";
14471474
14481475static const char MCP_ANALYSIS_SERVER_INSTRUCTIONS[] =
1449- "analysis tool profile: read-only graph work via search_graph, trace_path, "
1450- "get_code_snippet, query_graph, get_architecture, or search_code. Use check_index_coverage "
1451- "for cited paths; paginate.";
1476+ "analysis tool profile (read-only): a code knowledge graph of the indexed repository for "
1477+ "structural questions: where a symbol is defined, who calls a function, what it calls, call "
1478+ "chains and data flow, which code a change affects, how modules fit together. search_graph "
1479+ "finds symbols; trace_path follows callers, callees and data flow; get_code_snippet returns "
1480+ "exact source; query_graph runs multi-hop Cypher; get_architecture summarizes structure; "
1481+ "search_code combines text search with graph context; detect_changes maps the current diff "
1482+ "to affected symbols. check_index_coverage tells whether a cited file was fully indexed. "
1483+ "Results are paginated.";
14521484
14531485static const char MCP_SCOUT_SERVER_INSTRUCTIONS[] =
1454- "scout tool profile: fast positive discovery via search_graph, trace_path, "
1455- "get_code_snippet, or get_architecture with narrow limits. Use check_index_coverage for "
1456- "cited paths. Findings are provisional.";
1486+ "scout tool profile (fast, provisional): quick structural lookups in the indexed "
1487+ "repository: where a symbol is defined, who calls a function, what it calls. search_graph "
1488+ "finds symbols; trace_path follows callers and callees; get_code_snippet returns exact "
1489+ "source; get_architecture summarizes structure; narrow limits keep answers fast. "
1490+ "check_index_coverage tells whether a cited file was fully indexed. Findings are "
1491+ "provisional.";
14571492
14581493static char *cbm_mcp_initialize_response_for_profile(const char *params_json,
14591494 cbm_mcp_tool_profile_t profile) {
0 commit comments