sozsoft-platform/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopTools.cs
2026-09-18 16:47:23 +03:00

125 lines
8.6 KiB
C#

using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using ModelContextProtocol.Server;
using Sozsoft.Mcp.Dtos;
using Sozsoft.Platform.DeveloperKit;
using Sozsoft.Platform.ListForms;
namespace Sozsoft.Mcp.Tools;
/// <summary>
/// Ekran (wizard) ve custom component gelistirme araclari. Uretim uygulamadaki Wizard ve
/// Custom Components servislerinden gecer; menu, yetki, dil anahtari ve seed dosyasi ekrandaki
/// yolla ayni sekilde olusur.
/// </summary>
[McpServerToolType]
public sealed class McpDevelopTools(IMcpDevelopAppService developAppService)
{
[McpServerTool(Name = McpToolNames.GetDevGuide, ReadOnly = true)]
[Description("Ekran ve bilesen uretim sozlesmesini okur: wizard alanlari, enum degerleri, editor/lookup/script sozlesmesi, custom component kurallari. section bos ise baslik listesi doner; once listeyi al, sonra ihtiyac duydugun bolumu numarasiyla iste (ornegin 4.2). Rehberde dosya yazmak anlatilan yerlerde dosya yerine bu sunucunun araclarini kullan.")]
public async Task<McpDevGuideDto> GetDevGuideAsync(
[Description("'lowcode' (uretim protokolu ve artefakt semalari, varsayilan) ya da 'reference' (JSON kolon sozlesmeleri, tasarimci envanteri).")]
string? document = null,
[Description("Bolum numarasi (4.2) ya da baslik metninin bir parcasi. Bos birakilirsa baslik listesi doner.")]
string? section = null)
=> await developAppService.GetDevGuideAsync(document, section);
[McpServerTool(Name = McpToolNames.CreateTable, Destructive = false, Idempotent = false)]
[Description("Ekranin baglanacagi yeni tabloyu SQL Query Manager tablo tasarimcisiyla ayni bicimde olusturur ve script'i seed dosyasina (sql/object) yazar. Id (uniqueidentifier, PK), TenantId ve tam audit kolonlari (CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeletionTime, DeleterId) otomatik eklenir; columns icine yalnizca is kolonlarini yaz. Yalnizca yeni tablo olusturur: tablo varsa reddeder, kolon ekleme/degistirme tablo tasarimcisindan yapilir. SQL Server veri kaynaginda calisir. Ardindan deploy_wizard ile ekrani kur.")]
public async Task<McpCreateTableResultDto> CreateTableAsync(
[Description("Tablo adi; harf/rakam/alt cizgi. Adlandirma icin get_dev_guide'daki tablo onek kuralina uy (ornegin Adm_T_...).")]
string tableName,
[Description("Is kolonlari. type: nvarchar, nvarchar(MAX), int, bigint, decimal (18,4), float, bit, datetime, datetime2, date, uniqueidentifier, money. maxLength yalnizca nvarchar icin (varsayilan 100). defaultValue: sayi, 'metin' ya da NEWID()/GETDATE()/GETUTCDATE()/SYSUTCDATETIME().")]
List<McpTableColumnDto> columns,
[Description("Tam audit kolonlari eklensin mi. Kullanici acikca istemedikce true birak.")]
bool fullAudited = true,
[Description("TenantId kolonu eklensin mi. Kullanici acikca istemedikce true birak.")]
bool multiTenant = true)
=> await developAppService.CreateTableAsync(new McpCreateTableRequestDto
{
TableName = tableName,
Columns = columns,
FullAudited = fullAudited,
MultiTenant = multiTenant
});
[McpServerTool(Name = McpToolNames.ListWizards, ReadOnly = true)]
[Description("Wizard File Manager'daki wizard dosyalarini listeler: dosya adi, ekran kodu, yol (List/Custom), menu yolu ve bagimli wizard'lar.")]
public async Task<List<WizardFileInfoDto>> ListWizardsAsync(
[Description("Dosya adi, wizard adi, ekran kodu ya da bilesen adi icinde aranacak metin. Bos birakilabilir.")]
string? search = null)
=> await developAppService.GetWizardsAsync(search);
[McpServerTool(Name = McpToolNames.GetWizard, ReadOnly = true)]
[Description("Bir wizard seed dosyasini diskteki bicimiyle dondurur (Wizard / ListForm / Fields bolumleri). Var olan bir ekrani degistirmeden once oku.")]
public async Task<McpWizardFileDto> GetWizardAsync(
[Description("list_wizards cikisindaki fileName degeri, ornegin 'Tags.json'.")]
string fileName)
=> await developAppService.GetWizardAsync(fileName);
[McpServerTool(Name = McpToolNames.DeployWizard, Destructive = true, Idempotent = false)]
[Description("Wizard'i deploy eder: ListForm ekrani (ComponentKind 0) ya da bir custom component'i menuye baglayan kayit (ComponentKind 1), yetkileri, dil anahtarlari, menusu ve seed dosyasi birlikte uretilir. Hedef tablo onceden var olmalidir; yoksa once create_table ile olustur. replaceFileName verilirse o wizard ve urettigi kayitlar silinip yeniden uretilir; ekran wizard cevaplarindan yeniden turetildigi icin tasarimcida yapilmis ve wizard'da karsiligi olmayan ayarlar kaybolur. Ne yazacagini get_dev_guide 4. bolumunden ogren.")]
public async Task<WizardFileInfoDto?> DeployWizardAsync(
[Description("Wizard JSON'u: seed dosyasi bicimi ({\"Wizard\": {...}}, get_wizard cikisi gibi) ya da duz wizard cevaplari. Enum alanlari sayi olarak yazilir.")]
string wizard,
[Description("Guncellemede yerine gecilecek dosyanin adi (list_wizards cikisindaki fileName). Yeni wizard icin bos birak.")]
string? replaceFileName = null)
=> await developAppService.DeployWizardAsync(new McpWizardDeployRequestDto { Wizard = wizard, ReplaceFileName = replaceFileName });
[McpServerTool(Name = McpToolNames.DeleteWizard, Destructive = true, Idempotent = true)]
[Description("Bir wizard'i ve yalnizca onun urettigi kayitlari siler; baska yerde kullanilan kayitlar korunur ve raporda gosterilir. Bagimli wizard'i olan bir wizard silinemez, once bagimlilar silinir.")]
public async Task<WizardDeleteResultDto> DeleteWizardAsync(
[Description("Silinecek wizard dosyasinin adi (list_wizards cikisindaki fileName).")]
string fileName)
=> await developAppService.DeleteWizardAsync(fileName);
[McpServerTool(Name = McpToolNames.ListComponents, ReadOnly = true)]
[Description("Custom component'leri ad, rota ve aciklamasiyla listeler; kod dondurmez. isVisualDesigner true olanlarin kodu tasarimci belgesinden uretilir ve MCP ile degistirilemez.")]
public async Task<List<McpComponentSummaryDto>> ListComponentsAsync(
[Description("Ad, rota ya da aciklama icinde aranacak metin. Bos birakilabilir.")]
string? search = null)
=> await developAppService.GetComponentsAsync(search);
[McpServerTool(Name = McpToolNames.GetComponent, ReadOnly = true)]
[Description("Bir custom component'in kodunu, props'unu ve bagimliliklarini dondurur. Degistirmeden once oku.")]
public async Task<CustomComponentDto?> GetComponentAsync(
[Description("Bilesenin adi.")]
string name)
=> await developAppService.GetComponentAsync(name);
[McpServerTool(Name = McpToolNames.SaveComponent, Destructive = true, Idempotent = true)]
[Description("Custom component'i ada gore kaydeder: yoksa ekler, varsa gunceller. Guncellemede verilmeyen alanlar korunur. Kod kurallari ve kullanilabilir kutuphaneler icin get_dev_guide 7. bolumu. Bilesen menude gorunecekse ardindan ComponentKind 1 ile deploy_wizard cagir.")]
public async Task<CustomComponentDto> SaveComponentAsync(
[Description("Bilesenin adi; kimligidir.")]
string name,
[Description("Bilesenin React kodu. Yeni bilesende zorunlu, guncellemede bos birakilirsa mevcut kod korunur.")]
string? code = null,
[Description("'/' ile baslayan rota. '/admin/' ile baslamayan rota public sayfa olur. Bos dize rotayi kaldirir, verilmezse mevcut rota korunur.")]
string? routePath = null,
[Description("Aciklama.")]
string? description = null,
[Description("Props JSON metni. Tasarimci belgesi (visualDesigner) iceremez.")]
string? props = null,
[Description("Bagimli bilesen adlarinin JSON dizisi, ornegin [\"PublicHeader\"].")]
string? dependencies = null,
[Description("Bilesen etkin mi. Yeni bilesende varsayilan true.")]
bool? isActive = null)
=> await developAppService.SaveComponentAsync(new McpComponentSaveRequestDto
{
Name = name,
Code = code,
RoutePath = routePath,
Description = description,
Props = props,
Dependencies = dependencies,
IsActive = isActive
});
[McpServerTool(Name = McpToolNames.DeleteComponent, Destructive = true, Idempotent = false)]
[Description("Custom component'i siler. Bilesene bagli bir Custom wizard varsa once delete_wizard ile o silinir.")]
public async Task DeleteComponentAsync(
[Description("Bilesenin adi.")]
string name)
=> await developAppService.DeleteComponentAsync(name);
}