Files
ClaudeMailbox/src/ClaudeMailbox/Mcp/MailboxTools.cs
mika kuns ec42e8e4bd Initial
2026-04-24 18:26:11 +02:00

71 lines
2.8 KiB
C#

using System.ComponentModel;
using ClaudeMailbox.Data.Repositories;
using ClaudeMailbox.Http;
using ModelContextProtocol.Server;
namespace ClaudeMailbox.Mcp;
public sealed record SendResult(long Id, DateTime QueuedAt);
public sealed record InboxMessage(long Id, string From, string Body, DateTime SentAt);
public sealed record InboxStatusDto(int Pending, DateTime? OldestAt);
public sealed record MailboxInfo(string Name, DateTime LastSeenAt, int PendingForYou);
[McpServerToolType]
public sealed class MailboxTools
{
private readonly MailboxContextAccessor _accessor;
private readonly MailboxRepository _mailboxes;
private readonly MessageRepository _messages;
public MailboxTools(
MailboxContextAccessor accessor,
MailboxRepository mailboxes,
MessageRepository messages)
{
_accessor = accessor;
_mailboxes = mailboxes;
_messages = messages;
}
[McpServerTool, Description("Send a message to another mailbox. The sender is the current session's X-Mailbox name.")]
public async Task<SendResult> Send(
[Description("Name of the recipient mailbox.")] string to,
[Description("Message body (plain text or markdown).")] string body,
CancellationToken ct)
{
var from = _accessor.Current;
var msg = await _messages.SendAsync(from, to, body, ct);
return new SendResult(msg.Id, msg.CreatedAt);
}
[McpServerTool, Description("Pull all undelivered messages for the current mailbox and mark them delivered. Returns an empty array when the inbox is empty.")]
public async Task<IReadOnlyList<InboxMessage>> CheckInbox(CancellationToken ct)
{
var name = _accessor.Current;
var pulled = await _messages.CheckInboxAsync(name, ct);
return pulled.Select(m => new InboxMessage(m.Id, m.FromMailbox, m.Body, m.CreatedAt)).ToList();
}
[McpServerTool, Description("Check whether the current mailbox has undelivered messages, without consuming them. Cheap; safe to call often.")]
public async Task<InboxStatusDto> PeekInbox(CancellationToken ct)
{
var name = _accessor.Current;
var status = await _messages.PeekAsync(name, ct);
return new InboxStatusDto(status.Pending, status.OldestAt);
}
[McpServerTool, Description("List all known mailboxes with their last-seen timestamp and how many messages each has queued for the current mailbox.")]
public async Task<IReadOnlyList<MailboxInfo>> ListMailboxes(CancellationToken ct)
{
var me = _accessor.Current;
var all = await _mailboxes.ListAsync(ct);
var result = new List<MailboxInfo>(all.Count);
foreach (var m in all)
{
var pending = await _messages.PendingCountForAsync(me, m.Name, ct);
result.Add(new MailboxInfo(m.Name, m.LastSeenAt, pending));
}
return result;
}
}