From 4bc721c3bf7589b519c5730d093f704ce56e3f09 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Mon, 29 Jun 2026 21:43:54 +0900 Subject: refactor: MCP層をmcpc APIベースに刷新 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 独自JSON-RPC処理をmcpcへ置き換え - 各MCPツールを個別ソースへ分離 - 共通コンテキストと登録処理を整理 - mcpc互換修正と統合テストを更新 --- src/mcp/tools/search_messages.c | 134 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/mcp/tools/search_messages.c (limited to 'src/mcp/tools/search_messages.c') diff --git a/src/mcp/tools/search_messages.c b/src/mcp/tools/search_messages.c new file mode 100644 index 0000000..166c167 --- /dev/null +++ b/src/mcp/tools/search_messages.c @@ -0,0 +1,134 @@ +#include "mcp/tools/common/registry.h" + +#include "mcp/tools/common/common.h" +#include "mcp/tools/common/context.h" + +#include +#include +#include + +#include "base/allocator.h" + +typedef struct result_item +{ + const tiny_store_entry_t *entry; + double score; +} result_item_t; + +static int +compare_results(const void *left, const void *right) +{ + const result_item_t *a = left; + const result_item_t *b = right; + if (a->score > b->score) + { + return -1; + } + if (a->score < b->score) + { + return 1; + } + if (a->entry->message.timestamp_ms > b->entry->message.timestamp_ms) + { + return -1; + } + if (a->entry->message.timestamp_ms < b->entry->message.timestamp_ms) + { + return 1; + } + return strcmp(a->entry->message.message_id, b->entry->message.message_id); +} + +static void +call_search_messages(const mcpc_tool_t *tool, mcpc_ucbr_t *result) +{ + tiny_mcp_tools_context_t *context = tiny_mcp_tools_context_current(); + char *query = tiny_mcp_tool_get_string(tool, "query", TINY_QUERY_MAX); + char *session = tiny_mcp_tool_get_string(tool, "session_id", TINY_SESSION_ID_MAX); + int32_t requested_limit = 0; + size_t limit, index, count = 0, candidate_count = 0, *candidates = NULL; + result_item_t *items = NULL; + tiny_json_buffer_t json; + bool valid + = context && query && query[0] && session + && mcpc_tool_get_tpropval_i32(tool, (const char8_t *)"limit", &requested_limit) == MCPC_EC_0 + && requested_limit >= 1 && requested_limit <= 100; + if (!valid) + { + tiny_mcp_tool_add_error(result, "VALIDATION_ERROR", "query or limit is invalid"); + } + else + { + limit = (size_t)requested_limit; + if (!context->search_index) + { + context->search_index = tiny_mcp_tools_build_search_index(context->store); + } + if (!context->search_index + || !tiny_search_index_candidates( + context->search_index, query, &candidates, &candidate_count)) + { + tiny_mcp_tool_add_error(result, "INTERNAL_ERROR", "search index allocation failed"); + } + else + { + items = malloc((candidate_count + 1) * sizeof(*items)); + if (!items) + { + tiny_mcp_tool_add_error(result, "INTERNAL_ERROR", "out of memory"); + } + else + { + for (index = 0; index < candidate_count; ++index) + { + const tiny_store_entry_t *entry + = tiny_store_entry(context->store, candidates[index]); + double score; + if (!entry || entry->deleted + || (session[0] && strcmp(entry->message.session_id, session) != 0)) + { + continue; + } + score = tiny_search_score(query, &entry->message); + if (score > 0) + { + items[count].entry = entry; + items[count++].score = score; + } + } + qsort(items, count, sizeof(*items), compare_results); + if (count > limit) + { + count = limit; + } + tiny_json_init(&json); + tiny_json_raw(&json, "{\"results\":["); + for (index = 0; index < count; ++index) + { + if (index) + { + tiny_json_raw(&json, ","); + } + tiny_mcp_tool_append_message(&json, &items[index].entry->message); + } + tiny_json_raw(&json, "]}"); + tiny_mcp_tool_add_json(result, &json); + tiny_json_free(&json); + } + } + } + free(items); + free(candidates); + free(query); + free(session); +} + +bool +tiny_mcp_register_search_messages(mcpc_server_t *server) +{ + mcpc_tool_t *tool = tiny_mcp_tool_new("search_messages", "Search messages", call_search_messages); + return tool && tiny_mcp_tool_add_property(tool, "query", "Search text", MCPC_U8STR) + && tiny_mcp_tool_add_property(tool, "session_id", "Session ID; empty for all", MCPC_U8STR) + && tiny_mcp_tool_add_property(tool, "limit", "Result limit from 1 to 100", MCPC_I32) + && mcpc_server_add_tool(server, tool) == MCPC_EC_0; +} -- cgit v1.2.3