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/common/common.c | 117 ++++++++++++++++++++++++++++++++++++++++ src/mcp/tools/common/common.h | 19 +++++++ src/mcp/tools/common/context.c | 88 ++++++++++++++++++++++++++++++ src/mcp/tools/common/context.h | 20 +++++++ src/mcp/tools/common/registry.c | 11 ++++ src/mcp/tools/common/registry.h | 13 +++++ src/mcp/tools/common/tools.h | 10 ++++ 7 files changed, 278 insertions(+) create mode 100644 src/mcp/tools/common/common.c create mode 100644 src/mcp/tools/common/common.h create mode 100644 src/mcp/tools/common/context.c create mode 100644 src/mcp/tools/common/context.h create mode 100644 src/mcp/tools/common/registry.c create mode 100644 src/mcp/tools/common/registry.h create mode 100644 src/mcp/tools/common/tools.h (limited to 'src/mcp/tools/common') diff --git a/src/mcp/tools/common/common.c b/src/mcp/tools/common/common.c new file mode 100644 index 0000000..71b6f68 --- /dev/null +++ b/src/mcp/tools/common/common.c @@ -0,0 +1,117 @@ +#include "mcp/tools/common/common.h" + +#include + +#include "base/allocator.h" + +void +tiny_mcp_tool_add_error(mcpc_ucbr_t *result, const char *code, const char *message) +{ + tiny_json_buffer_t json; + tiny_json_init(&json); + tiny_json_raw(&json, "{\"status\":\"ERROR\",\"error\":{\"code\":"); + tiny_json_string(&json, code); + tiny_json_raw(&json, ",\"message\":"); + tiny_json_string(&json, message); + tiny_json_raw(&json, "}}"); + mcpc_toolcall_result_add_errmsg_printf8( + result, (const char8_t *)"%s", json.data ? json.data : "{}"); + tiny_json_free(&json); +} + +void +tiny_mcp_tool_add_json(mcpc_ucbr_t *result, tiny_json_buffer_t *json) +{ + if (json->failed) + { + tiny_mcp_tool_add_error(result, "INTERNAL_ERROR", "response allocation failed"); + return; + } + mcpc_toolcall_result_add_text_printf8( + result, (const char8_t *)"%s", json->data ? json->data : "{}"); +} + +char * +tiny_mcp_tool_get_string(const mcpc_tool_t *tool, const char *name, size_t maximum) +{ + char *value = malloc(maximum + 1); + size_t length = 0; + if (!value + || mcpc_tool_get_tpropval_u8str( + tool, (const char8_t *)name, (char8_t *)value, maximum + 1, &length) + != MCPC_EC_0 + || length > maximum) + { + free(value); + return NULL; + } + value[length] = '\0'; + if (!tiny_utf8_valid(value, length)) + { + free(value); + return NULL; + } + return value; +} + +void +tiny_mcp_tool_append_message(tiny_json_buffer_t *json, const tiny_message_t *message) +{ + size_t index; + tiny_json_raw(json, "{\"message_id\":"); + tiny_json_string(json, message->message_id); + tiny_json_raw(json, ",\"session_id\":"); + tiny_json_string(json, message->session_id); + tiny_json_raw(json, ",\"timestamp\":"); + tiny_json_i64(json, message->timestamp_ms); + tiny_json_raw(json, ",\"role\":"); + tiny_json_string(json, tiny_role_name(message->role)); + tiny_json_raw(json, ",\"content\":"); + tiny_json_string(json, message->content); + tiny_json_raw(json, ",\"metadata\":{"); + if (message->metadata.tool_call_id) + { + tiny_json_raw(json, "\"tool_call_id\":"); + tiny_json_string(json, message->metadata.tool_call_id); + tiny_json_raw(json, ","); + } + tiny_json_raw(json, "\"tags\":["); + for (index = 0; index < message->metadata.tag_count; ++index) + { + if (index) + { + tiny_json_raw(json, ","); + } + tiny_json_string(json, message->metadata.tags[index]); + } + tiny_json_raw(json, "],\"memory_tier\":"); + tiny_json_string(json, tiny_tier_name(message->metadata.memory_tier)); + tiny_json_raw(json, "}}"); +} + +mcpc_tool_t * +tiny_mcp_tool_new(const char *name, const char *description, mcpc_tcallcb_t callback) +{ + mcpc_tool_t *tool = mcpc_tool_new2((const char8_t *)name, (const char8_t *)description); + if (!tool || mcpc_tool_set_call_cb(tool, callback) != MCPC_EC_0) + { + return NULL; + } + return tool; +} + +bool +tiny_mcp_tool_add_property(mcpc_tool_t *tool, + const char *name, + const char *description, + mcpc_anytype_t type) +{ + mcpc_toolprop_t *property + = mcpc_toolprop_new2((const char8_t *)name, (const char8_t *)description, type); + if (!property) + { + return false; + } + mcpc_tool_add_toolprop(tool, property); + return true; +} diff --git a/src/mcp/tools/common/common.h b/src/mcp/tools/common/common.h new file mode 100644 index 0000000..6b1cc96 --- /dev/null +++ b/src/mcp/tools/common/common.h @@ -0,0 +1,19 @@ +#ifndef TINY_CONVMEM_MCP_TOOLS_COMMON_H +#define TINY_CONVMEM_MCP_TOOLS_COMMON_H + +#include "domain/message.h" +#include "mcp/json.h" +#include + +void tiny_mcp_tool_add_error(mcpc_ucbr_t *result, const char *code, const char *message); +void tiny_mcp_tool_add_json(mcpc_ucbr_t *result, tiny_json_buffer_t *json); +char *tiny_mcp_tool_get_string(const mcpc_tool_t *tool, const char *name, size_t maximum); +void tiny_mcp_tool_append_message(tiny_json_buffer_t *json, const tiny_message_t *message); + +mcpc_tool_t *tiny_mcp_tool_new(const char *name, const char *description, mcpc_tcallcb_t callback); +bool tiny_mcp_tool_add_property(mcpc_tool_t *tool, + const char *name, + const char *description, + mcpc_anytype_t type); + +#endif diff --git a/src/mcp/tools/common/context.c b/src/mcp/tools/common/context.c new file mode 100644 index 0000000..1a469e0 --- /dev/null +++ b/src/mcp/tools/common/context.c @@ -0,0 +1,88 @@ +#include "mcp/tools/common/context.h" + +#include + +#include "base/allocator.h" + +/* mcpc's callback API has no user-data parameter. The stdio server is single-instance. */ +static tiny_mcp_tools_context_t *active_context; + +tiny_search_index_t * +tiny_mcp_tools_build_search_index(const tiny_store_t *store) +{ + tiny_search_index_t *index = tiny_search_index_create(); + size_t position; + if (!index) + { + return NULL; + } + for (position = 0; position < tiny_store_entry_count(store); ++position) + { + if (!tiny_search_index_add(index, &tiny_store_entry(store, position)->message, position)) + { + tiny_search_index_free(index); + return NULL; + } + } + return index; +} + +tiny_mcp_tools_context_t * +tiny_mcp_tools_context_new(tiny_store_t *store) +{ + tiny_mcp_tools_context_t *context; + if (!store) + { + return NULL; + } + context = malloc(sizeof(*context)); + if (!context) + { + return NULL; + } + context->store = store; + context->search_index = tiny_mcp_tools_build_search_index(store); + if (!context->search_index) + { + free(context); + return NULL; + } + return context; +} + +void +tiny_mcp_tools_context_free(tiny_mcp_tools_context_t *context) +{ + if (!context) + { + return; + } + tiny_search_index_free(context->search_index); + free(context); +} + +bool +tiny_mcp_tools_context_activate(tiny_mcp_tools_context_t *context) +{ + if (!context || active_context) + { + return false; + } + active_context = context; + return true; +} + +void +tiny_mcp_tools_context_deactivate(tiny_mcp_tools_context_t *context) +{ + if (active_context == context) + { + active_context = NULL; + } +} + +tiny_mcp_tools_context_t * +tiny_mcp_tools_context_current(void) +{ + return active_context; +} diff --git a/src/mcp/tools/common/context.h b/src/mcp/tools/common/context.h new file mode 100644 index 0000000..0847d4b --- /dev/null +++ b/src/mcp/tools/common/context.h @@ -0,0 +1,20 @@ +#ifndef TINY_CONVMEM_MCP_TOOLS_CONTEXT_H +#define TINY_CONVMEM_MCP_TOOLS_CONTEXT_H + +#include "domain/search.h" +#include "storage/store.h" + +typedef struct tiny_mcp_tools_context +{ + tiny_store_t *store; + tiny_search_index_t *search_index; +} tiny_mcp_tools_context_t; + +tiny_mcp_tools_context_t *tiny_mcp_tools_context_new(tiny_store_t *store); +void tiny_mcp_tools_context_free(tiny_mcp_tools_context_t *context); +bool tiny_mcp_tools_context_activate(tiny_mcp_tools_context_t *context); +void tiny_mcp_tools_context_deactivate(tiny_mcp_tools_context_t *context); +tiny_mcp_tools_context_t *tiny_mcp_tools_context_current(void); +tiny_search_index_t *tiny_mcp_tools_build_search_index(const tiny_store_t *store); + +#endif diff --git a/src/mcp/tools/common/registry.c b/src/mcp/tools/common/registry.c new file mode 100644 index 0000000..9aa1dff --- /dev/null +++ b/src/mcp/tools/common/registry.c @@ -0,0 +1,11 @@ +#include "mcp/tools/common/tools.h" + +#include "mcp/tools/common/registry.h" + +bool +tiny_mcp_tools_register(mcpc_server_t *server) +{ + return tiny_mcp_register_write_message(server) && tiny_mcp_register_read_messages(server) + && tiny_mcp_register_search_messages(server) && tiny_mcp_register_delete_message(server) + && tiny_mcp_register_rebuild_index(server) && tiny_mcp_register_get_system_health(server); +} diff --git a/src/mcp/tools/common/registry.h b/src/mcp/tools/common/registry.h new file mode 100644 index 0000000..bbc68d0 --- /dev/null +++ b/src/mcp/tools/common/registry.h @@ -0,0 +1,13 @@ +#ifndef TINY_CONVMEM_MCP_TOOLS_REGISTRY_H +#define TINY_CONVMEM_MCP_TOOLS_REGISTRY_H + +#include + +bool tiny_mcp_register_write_message(mcpc_server_t *server); +bool tiny_mcp_register_read_messages(mcpc_server_t *server); +bool tiny_mcp_register_search_messages(mcpc_server_t *server); +bool tiny_mcp_register_delete_message(mcpc_server_t *server); +bool tiny_mcp_register_rebuild_index(mcpc_server_t *server); +bool tiny_mcp_register_get_system_health(mcpc_server_t *server); + +#endif diff --git a/src/mcp/tools/common/tools.h b/src/mcp/tools/common/tools.h new file mode 100644 index 0000000..b06321c --- /dev/null +++ b/src/mcp/tools/common/tools.h @@ -0,0 +1,10 @@ +#ifndef TINY_CONVMEM_MCP_TOOLS_H +#define TINY_CONVMEM_MCP_TOOLS_H + +#include "mcp/tools/common/context.h" +#define MCPC_C23PTCH_UCHAR2 1 +#include + +bool tiny_mcp_tools_register(mcpc_server_t *server); + +#endif -- cgit v1.2.3