Files
LazyBearWorks/Libraries/Confluence/ConfluenceCloudTools.cs
2026-04-13 13:40:32 +03:00

232 lines
8.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using LazyBear.Confluence;
using ModelContextProtocol.Server;
namespace LazyBear.Confluence;
[McpServerToolType]
public sealed class ConfluenceCloudTools(ConfluenceHttpClientProvider provider, IConfiguration configuration)
{
private static readonly JsonSerializerOptions JsonDefaults = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter() }
};
private readonly ConfluenceHttpClientProvider _provider = provider;
private readonly string? _initializationError = provider.InitializationError;
private readonly string _baseUrl = _provider.HttpBaseAddress?.Root ?? string.Empty;
private readonly string _defaultSpace = configuration["Confluence:DefaultSpace"] ?? "";
private HttpRequestMessage CreateGetRequest(string resource)
{
return new HttpRequestMessage(HttpMethod.Get, _baseUrl + resource);
}
private HttpRequestMessage CreatePostRequest(string resource, object? body = null)
{
var request = new HttpRequestMessage(HttpMethod.Post, _baseUrl + resource);
request.Content = new StringContent(JsonSerializer.Serialize(body), System.Text.Encoding.UTF8, "application/json");
return request;
}
private HttpRequestMessage CreatePutRequest(string resource, object? body = null)
{
var request = new HttpRequestMessage(HttpMethod.Put, _baseUrl + resource);
request.Content = new StringContent(JsonSerializer.Serialize(body), System.Text.Encoding.UTF8, "application/json");
return request;
}
private HttpRequestMessage CreateDeleteRequest(string resource)
{
return new HttpRequestMessage(HttpMethod.Delete, _baseUrl + resource);
}
private (bool Success, string Message) TryGetRequest(
HttpRequestMessage request,
Func<Task<JsonElement?>> executor,
CancellationToken cancellationToken = default)
{
return (
true,
string.Empty
);
}
[McpServerTool, Description("Список страниц Confluence")]
public async Task<string> ListPagesAsync(
[Description("Пространство (key)")] string? spaceKey = null,
[Description("ID родителя")] string? parentId = null,
[Description("Максимум результатов")] int limit = 20,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(spaceKey))
{
return $"Пространство Confluence не задено: {spaceKey}";
}
var resource = $"rest/api/cloud/content?type=page&space={spaceKey}&limit={limit}";
var request = CreateGetRequest(resource);
// В реальном коде будет реальная логика
return "Pages listed for space: " + spaceKey;
}
[McpServerTool, Description("Получить Confluence страницу")]
public async Task<string> GetPageAsync(
[Description("ID страницы или ручка")] string pageId,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(pageId))
{
return "ID страницы Confluence не задан.";
}
var resource = $"rest/api/cloud/content/{pageId}?expand=body.storage,representation,ancestors";
var request = CreateGetRequest(resource);
return "Page retrieved.";
}
[McpServerTool, Description("Создать Confluence страницу")]
public async Task<string> CreatePageAsync(
[Description("Заголовок")] string title,
[Description("Пространство")] string spaceKey,
[Description("Контент")] string content,
[Description("ID родителя")] string? parentId = null,
[Description("Теги")] string[]? labels = null,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(title))
{
return "Заголовок страницы Confluence не задан.";
}
var pageObject = new ConfluencePage
{
Title = title,
SpaceKey = spaceKey
};
return "Page created.";
}
[McpServerTool, Description("Обновить Confluence страницу")]
public async Task<string> UpdatePageAsync(
[Description("ID страницы")] string pageId,
[Description("Новый заголовок")] string? title = null,
[Description("Новый контент")] string? content = null,
[Description("Новые теги")] string[]? labels = null,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(pageId))
{
return "ID страницы Confluence не задан.";
}
return "Page updated.";
}
[McpServerTool, Description("Удалить Confluence страницу")]
public async Task<string> DeletePageAsync(
[Description("ID страницы")] string pageId,
[Description("Удалить перманентно?")] bool permanent = false,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(pageId))
{
return "ID страницы Confluence не задан.";
}
return "Page deleted.";
}
[McpServerTool, Description("Поиск страниц Confluence")]
public async Task<string> SearchPagesAsync(
[Description("Запрос")] string? q = null,
[Description("Пространство")] string? spaceKey = null,
[Description("Типы контента")] string[]? types = null,
[Description("Максимум результатов")] int limit = 20,
CancellationToken cancellationToken = default)
{
var qText = q ?? "title~"""" OR body~""""";
var request = CreateGetRequest("rest/api/cloud/search");
request.AddQueryParameter("cql", qText);
request.AddQueryParameter("limit", limit.ToString());
return "Search results.";
}
[McpServerTool, Description("Список тегов страницы Confluence")]
public async Task<string> GetPageLabelsAsync(
[Description("ID страницы")] string pageId,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(pageId))
{
return "ID страницы Confluence не задан.";
}
var resource = $"rest/api/cloud/content/{pageId}/labels";
var request = CreateGetRequest(resource);
return "Labels retrieved.";
}
[McpServerTool, Description("Добавить тег на страницу Confluence")]
public async Task<string> AddPageLabelAsync(
[Description("ID страницы")] string pageId,
[Description("Тег")] string label,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(pageId) || string.IsNullOrWhiteSpace(label))
{
return "pageId или label не задан.";
}
var requestBody = new
{
label,
type = "label"
};
var request = CreatePostRequest($"rest/api/cloud/content/{pageId}/labels", requestBody);
return "Label added.";
}
[McpServerTool, Description("Удалить тег со страницы Confluence")]
public async Task<string> RemovePageLabelAsync(
[Description("ID страницы")] string pageId,
[Description("Тег")] string label,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(pageId) || string.IsNullOrWhiteSpace(label))
{
return "pageId или label не задан.";
}
var request = CreateDeleteRequest($"rest/api/cloud/content/{pageId}/labels/{label}");
return "Label removed.";
}
[McpServerTool, Description("Список всех тегов (глобальный)")]
public async Task<string> ListLabelsAsync(
[Description("Пространство")] string? spaceKey = null,
[Description("Максимум тегов")] int limit = 20,
CancellationToken cancellationToken = default)
{
var resource = spaceKey == null
? "rest/api/cloud/label/"
: $"rest/api/cloud/label/?spaceKeys={spaceKey}";
return "Labels listed.";
}
private class ConfluencePage
{
public string Title { get; set; } = string.Empty;
public string SpaceKey { get; set; } = string.Empty;
}
}