Editor/McpServerExtension.cs
#nullable enable
using System;
using System.Linq;
using Sandbox;
using Editor.Mcp;

namespace Editor.Mcp
{
	/// <summary>
	/// S&amp;box MCP Assistant - Advanced AI integration tools for s&amp;box.
	/// </summary>
	[McpToolset( "pocketknife_editor", "Verified s&box editor complement tools for session state, package/cloud provenance, document adapters, navigation, and workflow diagnostics; use official s&box MCP for generic scene, asset, play, compile, and log operations." )]
	public static partial class SboxMcpAssistant
	{
		// Tool categories are split into partial class files in the Tools/ directory.

		[McpTool("pocketknife_find_capability")]
		public static string FindCapability(string query, int limit = 5, int offset = 0)
		{
			var normalized = (query ?? "").Trim();
			if (string.IsNullOrWhiteSpace(normalized))
				return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "capability.query_required", "A non-empty task query is required."));
			if (normalized.Length > 200)
				return McpJson.Write(ToolOutcome<object>.Failure(new { QueryLength = normalized.Length, MaximumQueryLength = 200 }, ToolStatus.Failed, "capability.query_too_long", "Capability query must be 200 characters or fewer."));

			var boundedLimit = Math.Clamp(limit, 1, 20);
			var boundedOffset = Math.Max(offset, 0);
			var results = SboxCapabilityCatalog.Search(normalized, boundedLimit, boundedOffset, out var total)
				.Select(capability => capability.ToPayload()).ToArray();
			var nextOffset = boundedOffset + results.Length < total ? boundedOffset + results.Length : (int?)null;
			return McpJson.Write(ToolOutcome<object>.Ready(new
			{
				Query = normalized,
				Offset = boundedOffset,
				Limit = boundedLimit,
				Total = total,
				Results = results,
				Next = nextOffset ?? -1
			}));
		}
	}
}