# Декомпозиция модулей ## 1. Цель документа Этот документ фиксирует детальную структуру проекта до начала активной разработки. Его задача - заранее ограничить ответственность каждого компонента, избежать разрастания `mcpaas-core`, не допустить появления "универсальных" структур на все случаи жизни и сохранить понятные границы между доменной логикой, runtime, адаптерами, API и UI. Основной принцип: каждый crate отвечает за один слой системы. Внутри crate модули должны быть маленькими, тематическими и с минимальным количеством публичных сущностей. ## 2. Общие архитектурные правила ### 2.1. Что считается правильной декомпозицией - `core` содержит только базовую доменную модель, идентификаторы, типы ошибок и общие контракты. - `registry` отвечает только за хранение и загрузку конфигурации операций. - `runtime` исполняет операции, но не знает о способе их хранения. - адаптеры знают только свой протокол и общий контракт runtime. - `admin-api` оркестрирует use case для UI, но не содержит протокольной логики. - `mcp-server` публикует tools и вызывает runtime, но не содержит бизнес-логики конфигурирования. - `ui` не знает внутреннюю реализацию runtime и работает только через HTTP API. ### 2.2. Что запрещено - помещать SQL, HTTP-клиенты или gRPC-клиенты в `mcpaas-core`; - хранить в `core` "общие утилиты", не относящиеся к доменной модели; - делать `runtime`, который напрямую читает БД; - писать mapping-логику внутри REST, GraphQL или gRPC адаптеров; - дублировать доменные типы в `admin-api`, `mcp-server` и адаптерах; - создавать большие структуры вида `AppState`, в которые складывается все подряд; - создавать большие enum или config-объекты, содержащие поля всех протоколов одновременно без выделенных вложенных типов. ### 2.3. Предпочтительный стиль - узкие интерфейсы; - маленькие DTO; - отдельные типы для draft, published и runtime-view сущностей; - отдельные модули для чтения, записи, валидации и исполнения; - композиция из небольших сервисов вместо одного глобального сервиса. ## 3. Workspace-структура Рекомендуемая структура: ```text mcpaas/ apps/ admin-api/ mcp-server/ ui/ crates/ mcpaas-core/ mcpaas-registry/ mcpaas-runtime/ mcpaas-adapter-rest/ mcpaas-adapter-graphql/ mcpaas-adapter-grpc/ mcpaas-mapping/ mcpaas-schema/ mcpaas-proto/ ``` Дополнительные crates `mcpaas-mapping`, `mcpaas-schema` и `mcpaas-proto` нужны затем, чтобы не перегружать `mcpaas-core`. ## 4. Детальная декомпозиция по crate ### 4.1. `mcpaas-core` Назначение: - базовые доменные типы; - идентификаторы; - метаданные операций; - общие контракты и ошибки верхнего уровня. Что должно лежать в crate: ```text mcpaas-core/ src/ lib.rs ids.rs protocol.rs operation/ mod.rs model.rs status.rs target.rs metadata.rs auth/ mod.rs profile.rs secret_ref.rs errors/ mod.rs domain.rs validation.rs runtime.rs ``` Описание модулей: - `ids.rs` - типы `OperationId`, `DescriptorId`, `ToolId` и другие идентификаторы. - `protocol.rs` - enum протоколов и общие protocol capability flags. - `operation/model.rs` - основная доменная модель операции без технических деталей хранения. - `operation/status.rs` - типы состояний операции. - `operation/target.rs` - базовые protocol-specific target structs. - `operation/metadata.rs` - описание tool, display name, version, tags. - `auth/profile.rs` - типы auth-профилей без привязки к конкретному клиенту. - `auth/secret_ref.rs` - ссылки на секреты, а не сами секреты. - `errors/*` - типизированные ошибки доменного слоя. Что не должно лежать в crate: - JSON Schema реализация; - mapping engine; - SQL-модели; - HTTP DTO; - protobuf parsing; - `reqwest`, `sqlx`, `tonic`, `axum`. Причина: `mcpaas-core` должен быть максимально стабильным и независимым. Если положить туда все подряд, он станет точкой связности всей системы. ### 4.2. `mcpaas-schema` Назначение: - внутренняя модель схем; - нормализация входа и выхода; - представление полей для UI и runtime; - преобразование схем из разных источников в единый вид. Структура: ```text mcpaas-schema/ src/ lib.rs schema/ mod.rs model.rs field.rs scalar.rs object.rs collection.rs oneof.rs enums.rs normalize/ mod.rs json.rs graphql.rs protobuf.rs validate/ mod.rs input.rs output.rs ``` Описание: - `schema/model.rs` - корневая структура схемы. - `field.rs` - описание поля, nullable, required, description. - `scalar.rs` - базовые scalar types. - `object.rs` - вложенные объекты. - `collection.rs` - массивы и map-подобные структуры. - `oneof.rs` - представление protobuf `oneof`. - `enums.rs` - enum-значения и метаданные. - `normalize/*` - преобразование GraphQL и protobuf моделей в единую схему. - `normalize/json.rs` - нормализация загруженных JSON-примеров во внутреннюю schema model. - `validate/*` - проверка JSON относительно внутренней схемы. Почему отдельный crate: Схемы будут использоваться почти везде, но это не повод тащить их в `core`. Иначе `core` станет тяжелым и начнет менять версию при каждом изменении схемной логики. ### 4.3. `mcpaas-mapping` Назначение: - описание mapping DSL; - компиляция mappings в runtime-представление; - применение mappings к входу и выходу; - автогенерация чернового mapping по загруженным примерам; - трассировка ошибок маппинга. Структура: ```text mcpaas-mapping/ src/ lib.rs model/ mod.rs mapping.rs source.rs target.rs transform.rs parser/ mod.rs jsonpath.rs compile/ mod.rs plan.rs infer/ mod.rs from_samples.rs from_schema.rs execute/ mod.rs input.rs output.rs errors.rs ``` Описание: - `model/mapping.rs` - описание одного правила mapping. - `model/source.rs` - откуда берем данные: `mcp`, `response`, `constant`. - `model/target.rs` - куда кладем данные: `request.path`, `request.query`, `request.body`, `output`. - `model/transform.rs` - ограниченный набор допустимых преобразований. - `parser/jsonpath.rs` - единый parser и validator для `JSONPath` выражений. - `compile/plan.rs` - предварительно скомпилированный план маппинга. - `infer/from_samples.rs` - генерация чернового mapping по загруженным примерам JSON. - `infer/from_schema.rs` - генерация чернового mapping по нормализованной схеме. - `execute/input.rs` - применение mappings к запросу. - `execute/output.rs` - применение mappings к ответу. Антипаттерн, которого нужно избежать: не помещать mapping-правила в строковые поля, которые потом интерпретируются каждым адаптером по-своему. Mapping должен быть единым движком. ### 4.4. `mcpaas-proto` Назначение: - работа с `.proto` и descriptor set; - извлечение services, methods и message schemas; - преобразование protobuf metadata во внутренние типы. Структура: ```text mcpaas-proto/ src/ lib.rs descriptor/ mod.rs loader.rs source.rs registry.rs reflect/ mod.rs client.rs model/ mod.rs service.rs method.rs message.rs field.rs convert/ mod.rs to_schema.rs to_json.rs from_json.rs errors.rs ``` Описание: - `descriptor/loader.rs` - загрузка descriptor set. - `descriptor/source.rs` - типы источников: upload, file, reflection. - `descriptor/registry.rs` - индексирование описаний для поиска services/methods. - `reflect/client.rs` - клиент server reflection, если будет добавлен. - `model/*` - protobuf-ориентированная промежуточная модель. - `convert/to_schema.rs` - перевод protobuf message в `mcpaas-schema`. - `convert/to_json.rs` и `from_json.rs` - преобразование runtime payload. Почему отдельный crate: protobuf-логика объемная и быстро начнет загрязнять gRPC adapter, если не отделить ее сразу. ### 4.5. `mcpaas-registry` Назначение: - хранение операций, схем, descriptor links и статусов; - выдача draft/published представлений; - поиск активных операций для runtime и MCP server. Структура: ```text mcpaas-registry/ src/ lib.rs model/ mod.rs record.rs draft.rs published.rs repo/ mod.rs operation_repo.rs descriptor_repo.rs service/ mod.rs create_operation.rs update_operation.rs publish_operation.rs list_operations.rs get_runtime_view.rs storage/ mod.rs postgres.rs cache/ mod.rs runtime_cache.rs errors.rs ``` Описание: - `model/record.rs` - DB-aligned record model. - `model/draft.rs` - модель черновика. - `model/published.rs` - модель опубликованной операции. - `repo/*` - контракты репозиториев. - `service/*` - use case операции над реестром. - `storage/*` - реализации репозиториев на `sqlx`. - `cache/runtime_cache.rs` - кэш активных операций. Правило: `registry` не выполняет операции и не знает о `reqwest`/`tonic`. Он только хранит и отдает согласованные представления. ### 4.6. `mcpaas-runtime` Назначение: - исполнение операций; - orchestration между схемой, mapping и адаптерами; - выдача нормализованного результата. Структура: ```text mcpaas-runtime/ src/ lib.rs executor/ mod.rs operation_executor.rs input_prepare.rs output_finalize.rs adapter/ mod.rs traits.rs dispatch.rs context/ mod.rs execution_context.rs model/ mod.rs runtime_operation.rs prepared_request.rs adapter_response.rs errors.rs ``` Описание: - `executor/operation_executor.rs` - основной orchestration use case. - `executor/input_prepare.rs` - валидация входа и применение input mapping. - `executor/output_finalize.rs` - обработка adapter response и output mapping. - `adapter/traits.rs` - общий контракт для протокольных адаптеров. - `adapter/dispatch.rs` - выбор адаптера по протоколу. - `context/execution_context.rs` - correlation id, deadlines, tracing data. - `model/runtime_operation.rs` - runtime-ready представление операции. Правило: `runtime` не должен знать, где хранится операция. Он получает уже готовую `runtime_operation`. ### 4.7. `mcpaas-adapter-rest` Назначение: - построение и выполнение REST-вызовов. Структура: ```text mcpaas-adapter-rest/ src/ lib.rs client.rs request/ mod.rs build.rs path.rs query.rs headers.rs body.rs response/ mod.rs decode.rs normalize.rs errors.rs ``` Правило: REST adapter не валидирует MCP input и не знает о registry. Он получает уже подготовленный request contract. ### 4.8. `mcpaas-adapter-graphql` Назначение: - построение и выполнение GraphQL-вызовов. Структура: ```text mcpaas-adapter-graphql/ src/ lib.rs client.rs request/ mod.rs build.rs variables.rs response/ mod.rs decode.rs extract.rs errors.rs ``` Правило: GraphQL adapter не занимается introspection по умолчанию и не содержит редактор схем. Он только исполняет подготовленный operation template. Дополнительное ограничение: один GraphQL tool соответствует одному заранее определенному `query` или `mutation`. Адаптер не должен принимать от LLM произвольный GraphQL-документ, потому что в MCP-модели операция должна оставаться узкой, предсказуемой и валидируемой по фиксированной схеме. ### 4.9. `mcpaas-adapter-grpc` Назначение: - выполнение unary gRPC-вызовов на основе уже выбранного метода и descriptor metadata. Структура: ```text mcpaas-adapter-grpc/ src/ lib.rs channel.rs invoke/ mod.rs unary.rs request/ mod.rs build.rs response/ mod.rs decode.rs errors.rs ``` Правило: gRPC adapter не должен сам парсить `.proto`. Этим занимается `mcpaas-proto`. Иначе в адаптере смешаются discovery и execution. Дополнительное ограничение: adapter поддерживает только unary RPC. Streaming-вызовы не реализуются, потому что целевая модель MCP tool в проекте соответствует сценарию `запрос -> ответ`, а не долгоживущей сессии обмена сообщениями. ### 4.10. `admin-api` Назначение: - HTTP API для UI; - координация use case создания, редактирования, тестирования и публикации. Структура: ```text apps/admin-api/ src/ main.rs app.rs state.rs router.rs http/ mod.rs dto/ mod.rs operation.rs mapping.rs test_run.rs handlers/ mod.rs create_operation.rs update_operation.rs publish_operation.rs list_operations.rs test_operation.rs export_operation_yaml.rs import_operation_yaml.rs upload_json_samples.rs upload_proto.rs list_grpc_services.rs response.rs services/ mod.rs operation_service.rs descriptor_service.rs config_portability_service.rs test_service.rs errors.rs ``` Правила: - HTTP DTO не должны протекать в доменный слой; - handlers должны быть тонкими; - orchestration должна жить в `services/*`; - `state.rs` не должен разрастаться в огромную структуру. Лучше использовать вложенные state-компоненты или отдельные service bundles. - import/export конфигурации в `YAML` должен быть отдельным use case, а не побочным эффектом обычного CRUD. ### 4.11. `mcp-server` Назначение: - публикация MCP tools; - вызов runtime по имени tool; - обновление активного списка tools. Структура: ```text apps/mcp-server/ src/ main.rs app.rs state.rs tools/ mod.rs list.rs call.rs cache.rs translate/ mod.rs to_mcp_tool.rs from_mcp_input.rs to_mcp_output.rs errors.rs ``` Правило: `mcp-server` не должен реализовывать business rules публикации. Он читает уже опубликованные операции и транслирует их в MCP. ### 4.12. `ui` Назначение: - интерфейс оператора. Предлагаемая frontend-структура: ```text apps/ui/ src/ main.tsx app/ router.tsx providers.tsx pages/ operation-list/ operation-create/ operation-edit/ operation-test/ grpc-browser/ features/ operation-form/ mapping-editor/ sample-upload/ grpc-method-picker/ schema-viewer/ publish-operation/ entities/ operation/ descriptor/ shared/ api/ lib/ ui/ config/ ``` Правило: UI должен декомпозироваться по пользовательским сценариям, а не по типам файлов уровня "все компоненты в одной папке". ## 5. Правила зависимостей между crate Целевой граф зависимостей: ```text mcpaas-core mcpaas-schema -> mcpaas-core mcpaas-mapping -> mcpaas-core mcpaas-proto -> mcpaas-core, mcpaas-schema mcpaas-registry -> mcpaas-core, mcpaas-schema, mcpaas-mapping mcpaas-adapter-rest -> mcpaas-core mcpaas-adapter-graphql -> mcpaas-core mcpaas-adapter-grpc -> mcpaas-core, mcpaas-proto mcpaas-runtime -> mcpaas-core, mcpaas-schema, mcpaas-mapping, adapters admin-api -> mcpaas-core, mcpaas-schema, mcpaas-mapping, mcpaas-proto, mcpaas-registry, mcpaas-runtime mcp-server -> mcpaas-core, mcpaas-registry, mcpaas-runtime ``` Критические ограничения: - `mcpaas-core` ни от кого не зависит; - адаптеры не зависят от `registry`; - `runtime` не зависит от `admin-api` и `mcp-server`; - `registry` не зависит от адаптеров; - `ui` зависит только от HTTP API. ## 6. Границы публичных API модулей Чтобы структура не разъехалась, нужно заранее ограничить публичность. Рекомендуемое правило: - наружу экспортируются только корневые доменные типы, service-интерфейсы и ошибки; - внутренние DTO, record-модели и промежуточные builder-структуры остаются `pub(crate)`; - не реэкспортировать целые деревья модулей без необходимости; - не делать `mod utils`, если можно назвать модуль по смыслу. Пример плохого решения: - `pub mod common;` - `pub mod helpers;` - `pub struct AppContext { ... 25 полей ... }` Пример правильного решения: - `pub struct OperationExecutor` - `pub trait OperationRepository` - `pub struct RuntimeOperation` ## 7. Какие большие структуры точно не нужны Ниже список сущностей, которые легко превращаются в антипаттерн: - одна гигантская `Operation`, содержащая сразу все REST, GraphQL и gRPC поля; - один `MappingConfig`, содержащий и input, и output, и transforms, и validation rules без разделения; - единый `AppState` со всеми репозиториями, клиентами, кэшами и конфигами; - один `ProtocolAdapter` с ветвлением `match protocol` внутри на сотни строк; - один `SchemaField` без выделения object/array/enum/oneof вариантов. Правильный подход: - отдельные target-типы по протоколам; - отдельные input/output mapping модели; - отдельные bounded state-наборы для каждого приложения; - отдельные adapter crates; - выделенная иерархия schema types. ## 8. Порядок реализации без архитектурного долга Рекомендуемый порядок разработки: 1. `mcpaas-core` 2. `mcpaas-schema` 3. `mcpaas-mapping` 4. `mcpaas-registry` 5. `mcpaas-adapter-rest` 6. `mcpaas-runtime` 7. `admin-api` 8. `ui` 9. `mcpaas-proto` 10. `mcpaas-adapter-grpc` 11. `mcpaas-adapter-graphql` 12. `mcp-server` Причина такого порядка: - сначала фиксируется доменная модель; - затем схема и mapping как самые чувствительные части; - затем реестр и базовое выполнение REST; - после этого можно собирать UI и только потом наращивать сложные протоколы. ## 9. Практический итог Если придерживаться этой декомпозиции, то: - `mcpaas-core` останется маленьким и стабильным; - schema и mapping не смешаются с transport-логикой; - protobuf discovery не загрязнит gRPC runtime; - `admin-api` и `mcp-server` останутся тонкими входными слоями; - добавление нового протокола не потребует переписывать половину проекта. Это и есть целевая архитектурная дисциплина проекта: отдельные слои, отдельные модели, минимально необходимая публичность и отсутствие "универсальных" структур, в которые со временем начинает стекаться вся система.