648 lines
28 KiB
C#
648 lines
28 KiB
C#
using System.ComponentModel;
|
|
using Alchegos.Core.Services.Gitea;
|
|
using ModelContextProtocol.Server;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Linq;
|
|
using System;
|
|
|
|
namespace Alchegos.MCP.Tools;
|
|
|
|
public class GiteaApiLoggingHandler : DelegatingHandler
|
|
{
|
|
public GiteaApiLoggingHandler(HttpMessageHandler innerHandler = null)
|
|
: base(innerHandler ?? new HttpClientHandler())
|
|
{
|
|
Console.WriteLine("GiteaApiLoggingHandler constructor called");
|
|
}
|
|
|
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
Console.WriteLine("GiteaApiLoggingHandler.SendAsync called");
|
|
Console.WriteLine($"Gitea API Request: {request.Method} {request.RequestUri}");
|
|
Console.WriteLine($"Base Address: {request.RequestUri?.IsAbsoluteUri}");
|
|
Console.WriteLine($"Request Headers: {string.Join(", ", request.Headers.Select(h => $"{h.Key}: {string.Join(", ", h.Value)}"))}");
|
|
|
|
if (request.Content != null)
|
|
{
|
|
var content = await request.Content.ReadAsStringAsync();
|
|
Console.WriteLine($"Request Body: {content}");
|
|
}
|
|
|
|
var response = await base.SendAsync(request, cancellationToken);
|
|
|
|
Console.WriteLine($"Response Status: {response.StatusCode}");
|
|
var responseContent = await response.Content.ReadAsStringAsync();
|
|
Console.WriteLine($"Response Body: {responseContent}");
|
|
|
|
return response;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error in GiteaApiLoggingHandler: {ex}");
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
[McpServerToolType, Description("Tools for interacting with Gitea API, providing repository management functionalities")]
|
|
public static class GiteaTool
|
|
{
|
|
|
|
private static readonly Dictionary<string, string> _apiKeyMap = new Dictionary<string, string>
|
|
{
|
|
{ "project-manager", Environment.GetEnvironmentVariable("PM_GITEA_ACCESS_TOKEN") },
|
|
{ "developer", Environment.GetEnvironmentVariable("DEV_GITEA_ACCESS_TOKEN") },
|
|
{ "analyst", Environment.GetEnvironmentVariable("AN_GITEA_ACCESS_TOKEN") },
|
|
{ "reviewer", Environment.GetEnvironmentVariable("RE_GITEA_ACCESS_TOKEN") },
|
|
{ "tester", Environment.GetEnvironmentVariable("TE_GITEA_ACCESS_TOKEN") },
|
|
};
|
|
|
|
private static GiteaApiClient CreateClient(string role)
|
|
{
|
|
if (string.IsNullOrEmpty(role))
|
|
throw new ArgumentException("role cannot be empty", nameof(role));
|
|
|
|
if (!_apiKeyMap.TryGetValue(role, out var apiKey))
|
|
throw new ArgumentException($"Invalid role: {role}", nameof(role));
|
|
|
|
var baseUrl = Environment.GetEnvironmentVariable("GITEA_BASE_URL") ??
|
|
throw new InvalidOperationException("GITEA_BASE_URL environment variable is not set");
|
|
|
|
Console.WriteLine($"Creating Gitea client with base URL: {baseUrl}");
|
|
|
|
var client = new HttpClient(new GiteaApiLoggingHandler());
|
|
|
|
var options = new GiteaApiOptions
|
|
{
|
|
BaseUrl = baseUrl,
|
|
Token = apiKey
|
|
};
|
|
return new GiteaApiClient(client, Microsoft.Extensions.Options.Options.Create(options));
|
|
}
|
|
|
|
[McpServerTool, Description("Create a new repository in Gitea")]
|
|
public static Repository GiteaCreateRepository(
|
|
[Description("Your role")] string role,
|
|
[Description("Name of the repository")] string name,
|
|
[Description("Description of the repository")] string description = "",
|
|
[Description("Whether the repository should be private")] bool isPrivate = false)
|
|
{
|
|
if (string.IsNullOrEmpty(name))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(name));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
var body = new CreateRepoOption
|
|
{
|
|
Name = name,
|
|
Description = description,
|
|
Private = isPrivate,
|
|
Auto_init = true
|
|
};
|
|
return client.CreateCurrentUserRepoAsync(body).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to create repository '{name}' : {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("List all repositories of a Gitea organization")]
|
|
public static ICollection<Repository> GiteaListOrganizationRepositories(
|
|
[Description("Your role")] string role,
|
|
[Description("Name of the organization")] string org,
|
|
[Description("Page number, starting from 1")] int? page = null,
|
|
[Description("Number of items per page")] int? limit = null)
|
|
{
|
|
if (string.IsNullOrEmpty(org))
|
|
throw new ArgumentException("Organization name cannot be empty", nameof(org));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.OrgListReposAsync(org, page, limit).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to list repositories for organization '{org}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("List all repositories of a Gitea user")]
|
|
public static ICollection<Repository> GiteaListUserRepositories(
|
|
[Description("Your role")] string role,
|
|
[Description("Username of the repository owner")] string username,
|
|
[Description("Page number, starting from 1")] int? page = null,
|
|
[Description("Number of items per page")] int? limit = null)
|
|
{
|
|
if (string.IsNullOrEmpty(username))
|
|
throw new ArgumentException("Username cannot be empty", nameof(username));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.UserListReposAsync(username, page, limit).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to list repositories for user '{username}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Get detailed information about a Gitea repository")]
|
|
public static Repository GiteaGetRepository(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string name)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(name))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(name));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.RepoGetAsync(owner, name).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to get repository '{name}' for owner '{owner}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Delete a Gitea repository")]
|
|
public static void GiteaDeleteRepository(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string name)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(name))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(name));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
client.RepoDeleteAsync(owner, name).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to delete repository '{name}' for owner '{owner}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Create a new wiki page in a Gitea repository")]
|
|
public static WikiPage GiteaCreateWikiPage(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Title of the wiki page")] string title,
|
|
[Description("Content of the wiki page")] string content,
|
|
[Description("Commit message for the wiki change")] string message = "")
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(title))
|
|
throw new ArgumentException("Wiki page title cannot be empty", nameof(title));
|
|
if (string.IsNullOrEmpty(content))
|
|
throw new ArgumentException("Wiki page content cannot be empty", nameof(content));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
var body = new CreateWikiPageOptions
|
|
{
|
|
Title = title,
|
|
Content_base64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(content)),
|
|
Message = string.IsNullOrEmpty(message) ? $"Create wiki page: {title}" : message
|
|
};
|
|
|
|
return client.RepoCreateWikiPageAsync(owner, repo, body).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to create wiki page '{title}' in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Edit an existing wiki page in a Gitea repository")]
|
|
public static WikiPage GiteaEditWikiPage(
|
|
[Description("Your role")] string role,
|
|
[Description("Username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Title of the wiki page")] string pageName,
|
|
[Description("New content of the wiki page")] string content,
|
|
[Description("New title for the wiki page (optional)")] string newTitle = null,
|
|
[Description("Commit message for the wiki change")] string message = "")
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(pageName))
|
|
throw new ArgumentException("Wiki page name cannot be empty", nameof(pageName));
|
|
if (string.IsNullOrEmpty(content))
|
|
throw new ArgumentException("Wiki page content cannot be empty", nameof(content));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
var body = new CreateWikiPageOptions
|
|
{
|
|
Title = newTitle ?? pageName,
|
|
Content_base64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(content)),
|
|
Message = string.IsNullOrEmpty(message) ? $"Update wiki page: {pageName}" : message
|
|
};
|
|
|
|
return client.RepoEditWikiPageAsync(owner, repo, pageName, body).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to edit wiki page '{pageName}' in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("List all wiki pages in a Gitea repository")]
|
|
public static ICollection<WikiPageMetaData> GiteaListWikiPages(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Page number, starting from 1")] int? page = null,
|
|
[Description("Number of items per page")] int? limit = null)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.RepoGetWikiPagesAsync(owner, repo, page, limit).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to list wiki pages in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Get a specific wiki page from a Gitea repository")]
|
|
public static WikiPage GiteaGetWikiPage(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Title of the wiki page")] string pageName)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(pageName))
|
|
throw new ArgumentException("Wiki page name cannot be empty", nameof(pageName));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.RepoGetWikiPageAsync(owner, repo, pageName).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to get wiki page '{pageName}' from repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Get the revision history of a wiki page")]
|
|
public static WikiCommitList GiteaGetWikiPageHistory(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Title of the wiki page")] string pageName,
|
|
[Description("Page number, starting from 1")] int? page = null)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(pageName))
|
|
throw new ArgumentException("Wiki page name cannot be empty", nameof(pageName));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.RepoGetWikiPageRevisionsAsync(owner, repo, pageName, page).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to get revision history for wiki page '{pageName}' in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Delete a wiki page from a Gitea repository")]
|
|
public static void GiteaDeleteWikiPage(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Title of the wiki page")] string pageName)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(pageName))
|
|
throw new ArgumentException("Wiki page name cannot be empty", nameof(pageName));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
client.RepoDeleteWikiPageAsync(owner, repo, pageName).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to delete wiki page '{pageName}' from repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Create a new branch in a Gitea repository")]
|
|
public static Branch GiteaCreateBranch(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Name of the new branch")] string branchName,
|
|
[Description("Name of the branch or commit to branch from")] string fromBranch)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(branchName))
|
|
throw new ArgumentException("Branch name cannot be empty", nameof(branchName));
|
|
if (string.IsNullOrEmpty(fromBranch))
|
|
throw new ArgumentException("Source branch cannot be empty", nameof(fromBranch));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
var body = new CreateBranchRepoOption
|
|
{
|
|
New_branch_name = branchName,
|
|
Old_branch_name = fromBranch
|
|
};
|
|
|
|
return client.RepoCreateBranchAsync(owner, repo, body).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to create branch '{branchName}' in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Delete a branch from a Gitea repository")]
|
|
public static void GiteaDeleteBranch(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Name of the branch to delete")] string branchName)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(branchName))
|
|
throw new ArgumentException("Branch name cannot be empty", nameof(branchName));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
client.RepoDeleteBranchAsync(owner, repo, branchName).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to delete branch '{branchName}' from repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("List all branches in a Gitea repository")]
|
|
public static ICollection<Branch> GiteaListBranches(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Page number, starting from 1")] int? page = null,
|
|
[Description("Number of items per page")] int? limit = null)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.RepoListBranchesAsync(owner, repo, page, limit).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to list branches in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Get detailed information about a specific branch")]
|
|
public static Branch GiteaGetBranch(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Name of the branch")] string branchName)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(branchName))
|
|
throw new ArgumentException("Branch name cannot be empty", nameof(branchName));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.RepoGetBranchAsync(owner, repo, branchName).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to get branch '{branchName}' from repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Create a new issue in a Gitea repository")]
|
|
public static Issue GiteaCreateIssue(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Title of the issue")] string title,
|
|
[Description("Body content of the issue")] string issueBody = "",
|
|
[Description("Labels to apply to the issue (label IDs)")] ICollection<long> labels = null,
|
|
[Description("Milestone to assign the issue to")] int? milestone = null,
|
|
[Description("User to assign the issue to")] string assignee = null)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
if (string.IsNullOrEmpty(title))
|
|
throw new ArgumentException("Issue title cannot be empty", nameof(title));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
var body = new CreateIssueOption
|
|
{
|
|
Title = title,
|
|
Body = issueBody,
|
|
Labels = labels,
|
|
Milestone = milestone,
|
|
Assignee = assignee
|
|
};
|
|
|
|
return client.IssueCreateIssueAsync(owner, repo, body).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to create issue in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Update an existing issue in a Gitea repository")]
|
|
public static Issue GiteaEditIssue(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Index of the issue")] int index,
|
|
[Description("New title of the issue")] string title = null,
|
|
[Description("New body content of the issue")] string issueBody = null,
|
|
[Description("New milestone to assign the issue to")] int? milestone = null,
|
|
[Description("New user to assign the issue to")] string assignee = null,
|
|
[Description("New state of the issue (open/closed)")] string state = null)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
var body = new EditIssueOption
|
|
{
|
|
Title = title,
|
|
Body = issueBody,
|
|
Milestone = milestone,
|
|
Assignee = assignee,
|
|
State = state
|
|
};
|
|
|
|
return client.IssueEditIssueAsync(owner, repo, index, body).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to edit issue #{index} in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Delete an issue from a Gitea repository")]
|
|
public static void GiteaDeleteIssue(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Index of the issue")] int index)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
client.IssueDeleteAsync(owner, repo, index).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to delete issue #{index} from repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("List all issues in a Gitea repository")]
|
|
public static ICollection<Issue> GiteaListIssues(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Filter issues by state (open/closed/all)")] string state = "open",
|
|
[Description("Filter issues by labels (comma separated)")] string labels = null,
|
|
[Description("Search query")] string q = null,
|
|
[Description("Filter issues by type (issues/pulls)")] string type = null,
|
|
[Description("Filter issues by milestones (comma separated)")] string milestones = null,
|
|
[Description("Filter issues created by this user")] string created_by = null,
|
|
[Description("Filter issues assigned by this user")] string assigned_by = null,
|
|
[Description("Filter issues mentioning this user")] string mentioned_by = null,
|
|
[Description("Page number, starting from 1")] int? page = null,
|
|
[Description("Number of items per page")] int? limit = null)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.IssueListIssuesAsync(
|
|
owner,
|
|
repo,
|
|
state == "open" ? State3.Open : state == "closed" ? State3.Closed : State3.All,
|
|
labels,
|
|
q,
|
|
type == "pulls" ? Type3.Pulls : Type3.Issues,
|
|
milestones,
|
|
null,
|
|
null,
|
|
created_by,
|
|
assigned_by,
|
|
mentioned_by,
|
|
page,
|
|
limit).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to list issues in repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
[McpServerTool, Description("Get detailed information about a specific issue")]
|
|
public static Issue GiteaGetIssue(
|
|
[Description("Your role")] string role,
|
|
[Description("Organization or username that owns the repository")] string owner,
|
|
[Description("Name of the repository")] string repo,
|
|
[Description("Index of the issue")] int index)
|
|
{
|
|
if (string.IsNullOrEmpty(owner))
|
|
throw new ArgumentException("Owner cannot be empty", nameof(owner));
|
|
if (string.IsNullOrEmpty(repo))
|
|
throw new ArgumentException("Repository name cannot be empty", nameof(repo));
|
|
|
|
try
|
|
{
|
|
var client = CreateClient(role);
|
|
return client.IssueGetIssueAsync(owner, repo, index).GetAwaiter().GetResult();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"Failed to get issue #{index} from repository '{owner}/{repo}': {ex.Message}", ex);
|
|
}
|
|
}
|
|
} |