using Microsoft.Agents.AI; using Microsoft.Extensions.AI; using OpenAI; // MCP Apps agent. // // This agent has no bespoke tools — the CopilotKit runtime is wired with // `mcpApps: { servers: [...] }` (see `src/app/api/copilotkit-mcp-apps/route.ts`) // pointing at a public MCP server (default: Excalidraw). The runtime // auto-applies the MCP Apps middleware which exposes the remote MCP // server's tools to this agent at request time and emits the activity // events that CopilotKit's built-in `MCPAppsActivityRenderer` renders in // the chat as a sandboxed iframe. // // Reference parity with: // showcase/integrations/langgraph-python/src/agents/mcp_apps_agent.py public sealed class McpAppsAgentFactory { private const int HarnessMaxContextWindowTokens = 128_000; private const int HarnessMaxOutputTokens = 8_192; private const string SystemPrompt = "You draw simple diagrams in Excalidraw via the MCP tool.\n\n" + "SPEED MATTERS. Produce a correct-enough diagram fast; do not optimize " + "for polish. Target: one tool call, done in seconds.\n\n" + "When the user asks for a diagram:\n" + "1. Call `create_view` ONCE with 3-5 elements total: shapes + arrows + " + " an optional title text.\n" + "2. Use straightforward shapes (rectangle, ellipse, diamond) with plain " + " `label` fields (`{\"text\": \"...\", \"fontSize\": 18}`) on them.\n" + "3. Connect with arrows. Endpoints can be element centers or simple " + " coordinates — you don't need edge anchors / fixedPoint bindings.\n" + "4. Include ONE `cameraUpdate` at the END of the elements array that " + " frames the whole diagram. Use an approved 4:3 size (600x450 or " + " 800x600). No opening camera needed.\n" + "5. Reply with ONE short sentence describing what you drew.\n\n" + "Every element needs a unique string `id` (e.g. \"b1\", \"a1\", \"title\"). " + "Standard sizes: rectangles 160x70, ellipses/diamonds 120x80, 40-80px " + "gap between shapes.\n\n" + "Do NOT:\n" + "- Call `read_me`. You already know the basic shape API.\n" + "- Make multiple `create_view` calls.\n" + "- Iterate or refine. Ship on the first shot.\n" + "- Add decorative colors / fills / zone backgrounds unless the user " + " explicitly asks for them.\n" + "- Add labels on arrows unless crucial.\n\n" + "If the user asks for something specific (colors, more elements, " + "particular layout), follow their lead — but still in ONE call."; private readonly OpenAIClient _openAiClient; private readonly ILogger _logger; public McpAppsAgentFactory(OpenAIClient openAiClient, ILoggerFactory loggerFactory) { ArgumentNullException.ThrowIfNull(openAiClient); ArgumentNullException.ThrowIfNull(loggerFactory); _openAiClient = openAiClient; _logger = loggerFactory.CreateLogger(); } public AIAgent CreateMcpAppsAgent() { // gpt-4o-mini for speed — Excalidraw element emission is simple JSON // and we bias hard toward sub-30s generation. var chatClient = _openAiClient.GetChatClient("gpt-4o-mini").AsIChatClient(); return chatClient.AsHarnessAgent( HarnessMaxContextWindowTokens, HarnessMaxOutputTokens, new HarnessAgentOptions { Name = "McpAppsAgent", Description = "MCP Apps demo agent — draws Excalidraw diagrams via remote MCP tools.", ChatOptions = new ChatOptions { Instructions = SystemPrompt, MaxOutputTokens = HarnessMaxOutputTokens, Tools = [], }, }); } }