mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-10 09:13:53 +08:00
fix(mcp): return structured compact results
Tools advertise an object outputSchema, so strict MCP clients reject compact TOON responses that omit structuredContent. Signed-off-by: wargloom <wargloom@gmail.com>
This commit is contained in:
+15
-2
@@ -258,17 +258,30 @@ char *cbm_mcp_text_result(const char *text, bool is_error) {
|
||||
yyjson_mut_arr_add_val(content, item);
|
||||
yyjson_mut_obj_add_val(doc, root, "content", content);
|
||||
|
||||
if (!is_error && text) {
|
||||
bool has_structured_content = false;
|
||||
if (text) {
|
||||
yyjson_doc *structured_doc = yyjson_read(text, strlen(text), 0);
|
||||
if (structured_doc) {
|
||||
yyjson_val *structured_root = yyjson_doc_get_root(structured_doc);
|
||||
if (yyjson_is_obj(structured_root)) {
|
||||
yyjson_mut_val *structured = yyjson_val_mut_copy(doc, structured_root);
|
||||
yyjson_mut_obj_add_val(doc, root, "structuredContent", structured);
|
||||
if (structured) {
|
||||
yyjson_mut_obj_add_val(doc, root, "structuredContent", structured);
|
||||
has_structured_content = true;
|
||||
}
|
||||
}
|
||||
yyjson_doc_free(structured_doc);
|
||||
}
|
||||
}
|
||||
if (!has_structured_content) {
|
||||
/* Every advertised MCP tool has an object outputSchema, so even compact
|
||||
* TOON/plain-text and error results must carry a conforming structured
|
||||
* object. Keep the text Content block above for model visibility and
|
||||
* backwards compatibility. */
|
||||
yyjson_mut_val *structured = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_str(doc, structured, is_error ? "error" : "text", text ? text : "");
|
||||
yyjson_mut_obj_add_val(doc, root, "structuredContent", structured);
|
||||
}
|
||||
yyjson_mut_obj_add_bool(doc, root, "isError", is_error);
|
||||
|
||||
char *out = yy_doc_to_str(doc);
|
||||
|
||||
+5
-3
@@ -448,10 +448,10 @@ TEST(mcp_text_result) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(mcp_text_result_skips_structured_content_for_plain_text) {
|
||||
TEST(mcp_text_result_wraps_plain_text_as_structured_content) {
|
||||
char *json = cbm_mcp_text_result("plain text", false);
|
||||
ASSERT_NOT_NULL(json);
|
||||
ASSERT_NULL(strstr(json, "\"structuredContent\""));
|
||||
ASSERT_NOT_NULL(strstr(json, "\"structuredContent\":{\"text\":\"plain text\"}"));
|
||||
ASSERT_NOT_NULL(strstr(json, "\"isError\":false"));
|
||||
free(json);
|
||||
PASS();
|
||||
@@ -470,6 +470,7 @@ TEST(mcp_cancel_matches_request_id) {
|
||||
TEST(mcp_text_result_error) {
|
||||
char *json = cbm_mcp_text_result("something failed", true);
|
||||
ASSERT_NOT_NULL(json);
|
||||
ASSERT_NOT_NULL(strstr(json, "\"structuredContent\":{\"error\":\"something failed\"}"));
|
||||
ASSERT_NOT_NULL(strstr(json, "\"isError\":true"));
|
||||
ASSERT_NOT_NULL(strstr(json, "something failed"));
|
||||
free(json);
|
||||
@@ -756,6 +757,7 @@ TEST(tool_search_graph_includes_node_properties) {
|
||||
"\"arguments\":{\"project\":\"test-project\",\"label\":\"Function\","
|
||||
"\"name_pattern\":\"HandleRequest\",\"limit\":5}}}");
|
||||
ASSERT_NOT_NULL(resp);
|
||||
ASSERT_NOT_NULL(strstr(resp, "\"structuredContent\":{\"text\":"));
|
||||
char *inner = extract_text_content(resp);
|
||||
ASSERT_NOT_NULL(inner);
|
||||
ASSERT_NOT_NULL(strstr(inner, "results[")); /* TOON table header */
|
||||
@@ -5611,7 +5613,7 @@ SUITE(mcp) {
|
||||
RUN_TEST(mcp_ingest_traces_items_disallow_additional_properties_issue731);
|
||||
RUN_TEST(mcp_get_architecture_aspects_schema_enum_pr560);
|
||||
RUN_TEST(mcp_text_result);
|
||||
RUN_TEST(mcp_text_result_skips_structured_content_for_plain_text);
|
||||
RUN_TEST(mcp_text_result_wraps_plain_text_as_structured_content);
|
||||
RUN_TEST(mcp_cancel_matches_request_id);
|
||||
RUN_TEST(mcp_text_result_error);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user