mcp
28 TopicsAgents League: The Esports-Inspired Hackathon Where AI Agents Battle for Glory
Ready to put your AI skills to the ultimate test? Agents League is here, a dynamic, esports-inspired developer challenge that brings the thrill of live competition to the world of agentic AI. Whether you're a seasoned AI developer or just getting started, this is your chance to build, compete, and win. What is Agents League? Agents League is a week-long hackathon running as part of AI Skills Fest (June 4โ14, 2026). Unlike traditional hackathons, Agents League combines live AI coding battles, asynchronous project submissions, and a thriving Discord community all competing for a total prize pool of $55,000 USD. This isn't just about building it's about showcasing what's possible with agentic AI in a format that's fast, competitive, and globally accessible. Three Challenge Tracks Pick One or Compete in All 1. Creative Apps Build innovative applications using GitHub Copilot for AI-assisted development. Show off your creativity and demonstrate how AI can accelerate app creation from concept to code. 2. Reasoning Agents Create intelligent agents using Microsoft Foundry that solve complex problems through multi-step reasoning. This track is all about building agents that can think, plan, and execute. 3. Enterprise Agents Build business-ready knowledge agents integrated with Microsoft 365 Copilot, authored in Copilot Studio. Perfect for developers focused on real-world enterprise solutions. Live Microsoft Reactor EventsโDon't Miss the Battles! The heart of Agents League beats through live Microsoft Reactor events. Watch experts go head-to-head in live coding battles, learn cutting-edge techniques, and get inspired for your own submissions: Event What You'll Learn Creative Apps Battle See GitHub Copilot in action as experts build innovative apps live Reasoning Agents Battle Watch multi-step reasoning agents come to life with Microsoft Foundry Enterprise Agents Battle Learn to build M365-integrated agents with Copilot Studio ๐ View the full event series Key Dates Registration Deadline: June 12, 2026, 12:00 PM PT Hacking Period: June 4โ14, 2026 Submission Deadline: June 14, 2026, 11:59 PM PT What You Get Live coding battles with expert demonstrations Curated technical experiences and on-demand content Learning resources on Microsoft Learn and AI Skills Navigator Community support through Discord GitHub-based submissions for transparent, collaborative judging Why Participate? Agents League isn't just another hackathon. It's designed as a streamlined, competitive format that: โ Fits into your schedule with focused, time-boxed challenges โ Provides real-world product innovation experience โ Offers global accessibilityโparticipate from anywhere โ Demonstrates the latest capabilities of agentic AI, including new IQ tools โ Connects you with a passionate developer community Ready to Enter the Arena? Register Now for Agents League Before you register: Review the Hackathon Rules and Regulations for prize categories and judging criteria Join the Microsoft Reactor event series for live battles and learning Check out the Microsoft Event Code of Conduct Join the Conversation Have questions? Want to connect with fellow competitors? Join the Agents League community on Discord and start strategizing with developers from around the world. Whether you're building creative apps, reasoning agents, or enterprise solutionsโthe arena awaits. May the best agent win! ๐ Agents League hackathon is open to the public and offered at no cost. Government employees should check with their employers to ensure participation is permitted in accordance with applicable policies. Related Links: Agents League Hackathon Registration Microsoft Reactor Series AI Skills FestThe Future of Agentic AI: Inside Microsoft Agent Framework 1.0
Agentic AI is rapidly moving beyond demos and chatbots toward longโrunning, autonomous systems that reason, call tools, collaborate with other agents, and operate reliably in production. On April 3, 2026, Microsoft marked a major milestone with the General Availability (GA) release of Microsoft Agent Framework 1.0, a productionโready, openโsource framework for building agents and multiโagent workflows in.NET and Python. [techcommun...rosoft.com] In this post, weโll deepโdive into: What Microsoft Agent Framework actually is Its core architecture and design principles Whatโs new in version 1.0 How it differs from other agent frameworks When and how to use itโwith real code examples What Is Microsoft Agent Framework? According to the official announcement, Microsoft Agent Framework is an openโsource SDK and runtime for building AI agents and multiโagent workflows with strong enterprise foundations. Agent Framework provides two primary capability categories: 1. Agents Agents are longโlived runtime components that: Use LLMs to interpret inputs Call tools and MCP servers Maintain session state Generate responses They are not just prompt wrappers, but stateful execution units. 2. Workflows Workflows are graphโbased orchestration engines that: Connect agents and functions Enforce execution order Support checkpointing and humanโinโtheโloop scenarios This leads to a clean separation of responsibilities: Concern Handled By Reasoning & interpretation Agent Execution policy & control flow Workflow This separation is a foundational design decision. HighโLevel Architecture From the official overview, Agent Framework is composed of several core building blocks: Model clients (chat completions & responses) Agent sessions (state & conversation management) Context providers (memory and retrieval) Middleware pipeline (interception, filtering, telemetry) MCP clients (tool discovery and invocation) Workflow engine (graphโbased orchestration) Conceptual Flow ๐ Whatโs New in Version 1.0 Version 1.0 marks the transition from "Release Candidate" to "General Availability" (GA). Production-Ready Stability: Unlike the earlier experimental packages, 1.0 offers stable APIs, versioned releases, and a commitment to long-term support (LTS). A2A Protocol (Agent-to-Agent): A new structured messaging protocol that allows agents to communicate across different runtimes. For example, an agent built in Python can seamlessly coordinate with an agent running in a .NET environment. MCP (Model Context Protocol) Support: Full integration with the Model Context Protocol, enabling agents to dynamically discover and invoke external tools and data sources without manual integration code. Multi-Agent Orchestration Patterns: Stable implementations of complex patterns, including: Sequential: Linear handoffs between specialized agents. Group Chat: Collaborative reasoning where agents discuss and solve problems. Magentic-One: A sophisticated pattern for task-oriented reasoning and planning. Middleware Pipeline: The new middleware architecture lets you inject logic into the agent's execution loop without modifying the core prompts. This is essential for Responsible AI (RAI), allowing you to add content safety filters, logging, and compliance checks globally. DevUI Debugger: A browser-based local debugger that provides a real-time visual representation of agent message flows, tool calls, and state changes. Code Examples Creating a Simple Agent (C#) From Microsoft Learn : using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; AIAgent agent = new AIProjectClient( new Uri("https://your-foundry-service.services.ai.azure.com/api/projects/your-project"), new AzureCliCredential()) .AsAIAgent( model: "gpt-5.4-mini", instructions: "You are a friendly assistant. Keep your answers brief."); Console.WriteLine(await agent.RunAsync("What is the largest city in France?")); This shows: Providerโagnostic model access Sessionโaware agent execution Minimal setup for production agents Creating a Simple Agent (Python) from agent_framework.foundry import FoundryChatClient from azure.identity import AzureCliCredential client = FoundryChatClient( project_endpoint="https://your-foundry-service.services.ai.azure.com/api/projects/your-project", model="gpt-5.4-mini", credential=AzureCliCredential(), ) agent = client.as_agent( name="HelloAgent", instructions="You are a friendly assistant. Keep your answers brief.", ) result = await agent.run("What is the largest city in France?") print(result) The same agent abstraction applies across languages. When to Use Agents vs Workflows Microsoft provides clear guidance: Use an Agent whenโฆ Use a Workflow whenโฆ Task is openโended Steps are wellโdefined Autonomous tool use is needed Execution order matters Single decision point Multiple agents/functions collaborate Key principle: If you can solve the task with deterministic code, do that instead of using an AI agent. ๐ How It Differs from Other Frameworks Microsoft Agent Framework 1.0 distinguishes itself by focusing on "Enterprise Readiness" and "Interoperability." Feature Microsoft Agent Framework 1.0 Semantic Kernel / AutoGen LangChain / CrewAI Philosophy Unified, production-ready SDK. Research-focused or tool-specific. High-level, developer-friendly abstractions. Integration Deeply integrated with Microsoft Foundry and Azure. Varied; often requires more glue code. Generally cloud-agnostic. Interoperability Native A2A and MCP for cross-framework tasks. Limited to internal ecosystem. Uses proprietary connectors. Runtime Identical API parity for .NET and Python. Primarily Python-first (SK has C#). Primarily Python. Control Graph-based deterministic workflows. More non-deterministic/experimental. Mixture of role-based and agentic. ๐ ๏ธ Key Technical Components Agent Harness: The execution layer that provides agents with controlled access to the shell, file system, and messaging loops. Agent Skills: A portable, file-based or code-defined format for packaging domain expertise. Implementation Tip: If you are coming from Semantic Kernel, Microsoft provides migration assistants that analyze your existing code and generate step-by-step plans to upgrade to the new Agent Framework 1.0 standards. Microsoft Agent Framework Version 1.0 | Microsoft Agent Framework Agent Framework documentation ๐ฏ Summary Microsoft Agent Framework 1.0 is the "grown-up" version of AI orchestration. By standardizing the way agents talk to each other (A2A), discover tools (MCP), and process information (Middleware), Microsoft has provided a clear path for taking AI experiments into production. For more detailed guides, check out the official Microsoft Agent Framework DocumentationMicrosoft Agent Framework - .NET AI Community StandupIf You're Building AI on Azure, ECS 2026 is Where You Need to Be
Let me be direct: there's a lot of noise in the conference calendar. Generic cloud events. Vendor showcases dressed up as technical content. Sessions that look great on paper but leave you with nothing you can actually ship on Monday. ECS 2026 isn't that. As someone who will be on stage at Cologne this May, I can tell you the European Collaboration Summit combined with the European AI & Cloud Summit and European Biz Apps Summit is one of the few events I've seen where engineers leave with real, production-applicable knowledge. Three days. Three summits. 3,000+ attendees. One of the largest Microsoft-focused events in Europe, and it keeps getting better. If you're building AI systems on Azure, designing cloud-native architectures, or trying to figure out how to take your AI experiments to production โ this is where the conversation is happening. What ECS 2026 Actually Is ECS 2026 runs May 5โ7 at Confex in Cologne, Germany. It brings together three co-located summits under one roof: European Collaboration Summit โ Microsoft 365, Teams, Copilot, and governance European AI & Cloud Summit โ Azure architecture, AI agents, cloud security, responsible AI European BizApps Summit โ Power Platform, Microsoft Fabric, Dynamics For Azure engineers and AI developers, the European AI & Cloud Summit is your primary destination. But don't ignore the overlap, some of the most interesting AI conversations happen at the intersection of collaboration tooling and cloud infrastructure. The scale matters here: 3,000+ attendees, 100+ sessions, multiple deep-dive tracks, and a speaker lineup that includes Microsoft executives, Regional Directors, and MVPs who have built, broken, and rebuilt production systems. The Azure + AI Track - What's Actually On the Agenda The AI & Cloud Summit agenda is built around real technical depth. Not "intro to AI" content, actual architecture decisions, patterns that work, and lessons from things that didn't. Here's what you can expect: AI Agents and Agentic Systems This is where the energy is right now, and ECS is leaning in. Expect sessions covering how to design agent workflows, chain reasoning steps, handle memory and state, and integrate with Azure AI services. Marco Casalaina, VP of Products for Azure AI at Microsoft, is speaking if you want to understand the direction of the Azure AI platform from the people building it, this is a direct line. Azure Architecture at Scale Cloud-native patterns, microservices, containers, and the architectural decisions that determine whether your system holds up under real load. These sessions go beyond theory you'll hear from engineers who've shipped these designs at enterprise scale. Observability, DevOps, and Production AI Getting AI to production is harder than the demos suggest. Sessions here cover monitoring AI systems, integrating LLMs into CI/CD pipelines, and building the operational practices that keep AI in production reliable and governable. Cloud Security and Compliance Security isn't optional when you're putting AI in front of users or connecting it to enterprise data. Tracks cover identity, access patterns, responsible AI governance, and how to design systems that satisfy compliance requirements without becoming unmaintainable. Pre-Conference Deep Dives One underrated part of ECS: the pre-conference workshops. These are extended, hands-on sessions typically 3โ6 hours that let you go deep on a single topic with an expert. Think of them as intensive short courses where you can actually work through the material, not just watch slides. If you're newer to a particular area of Azure AI, or you want to build fluency in a specific pattern before the main conference sessions, these are worth the early travel. The Speaker Quality Is Different Here The ECS speaker roster includes Microsoft executives, Microsoft MVPs, and Regional Directors, people who have real accountability for the products and patterns they're presenting. You'll hear from over 20 Microsoft speakers: Marco Casalaina โ VP of Products, Azure AI at Microsoft Adam Harmetz โ VP of Product at Microsoft, Enterprise Agent And dozens of MVPs and Regional Directors who are in the field every day, solving the same problems you are. These aren't keynote-only speakers โ they're in the session rooms, at the hallway track, available for real conversations. The Hallway Track Is Not a Clichรฉ I know "networking" sounds like a corporate afterthought. At ECS it genuinely isn't. When you put 3,000 practitioners, engineers, architects, DevOps leads, security specialists in one venue for three days, the conversations between sessions are often more valuable than the sessions themselves. You get candid answers to "how are you actually handling X in production?" that you won't find in documentation. The European Microsoft community is tight-knit and collaborative. ECS is where that community concentrates. Why This Matters Right Now We're in a period where AI development is moving fast but the engineering discipline around it is still maturing. Most teams are figuring out: How to move from AI prototype to production system How to instrument and observe AI behaviour reliably How to design agent systems that don't become unmaintainable How to satisfy security and compliance requirements in AI-integrated architectures ECS 2026 is one of the few places where you can get direct answers to these questions from people who've solved them โ not theoretically, but in production, on Azure, in the last 12 months. If you go, you'll come back with practical patterns you can apply immediately. That's the bar I hold events to. ECS consistently clears it. Register and Explore the Agenda Register for ECS 2026: ecs.events Explore the AI & Cloud Summit agenda: cloudsummit.eu/en/agenda Dates: May 5โ7, 2026 | Location: Confex, Cologne, Germany Early registration is worth it the pre-conference workshops fill up. And if you're coming, find me, I'll be the one talking too much about AI agents and Azure deployments. See you in Cologne.MCP Demystified: Tools vs Resources vs Prompts Explained Simply
Introduction When developers start working with Model Context Protocol (MCP), one of the most confusing parts is understanding the difference between MCP Tools, Resources, and Prompts. All three are important components in modern AI application development, but they serve completely different purposes. In real-world AI systems like chatbots, AI agents, and copilots, using these components correctly can make your application scalable, clean, and easy to maintain. If used incorrectly, it can lead to confusion, bugs, and poor system design. In this article, we will clearly explain the difference between MCP Tools, Resources, and Prompts in simple words, using real-world examples and practical explanations. This guide is helpful for both beginner and intermediate developers working with AI and MCP. What Are MCP Tools? MCP Tools are functions or services that an AI model can use to perform real-world actions. These actions usually involve doing something outside the AI system, such as calling an API, updating a database, or sending a message. In simple terms, Tools represent what the AI can do. Real-World Analogy Think of MCP Tools like service workers in a company. For example, a delivery person delivers packages, a support agent updates tickets, and a payment system processes transactions. Similarly, MCP Tools perform specific tasks when requested by the AI. Examples of MCP Tools A tool that fetches user details from a database A tool that sends emails or notifications A tool that creates or updates support tickets A tool that calls third-party APIs like payment gateways A tool that triggers workflows in enterprise systems Key Understanding Tools are action-based. They execute operations and return results. Whenever your AI needs to "do something," you should use a Tool. What Are MCP Resources? MCP Resources are data sources that the AI model can access to read information. These are typically read-only and provide context or knowledge to the AI. In simple terms, Resources represent what the AI can read or see. Real-World Analogy Think of MCP Resources like books in a library or documents in a company. You can read and learn from them, but you cannot directly change their content. Examples of MCP Resources A database table containing customer information A knowledge base with FAQs and documentation System logs that track user activity Configuration files or static datasets Company policy documents or guidelines Key Understanding Resources are data-based. They provide information but do not perform any action. Whenever your AI needs information to make a decision, you should use a Resource. What Are MCP Prompts? MCP Prompts are structured instructions or templates that guide how the AI model should think, behave, and respond. In simple terms, Prompts represent how you instruct the AI. Real-World Analogy Think of Prompts like instructions given to an employee. For example, โWrite a professional email,โ โSummarize this report,โ or โAnswer politely to the customer.โ These instructions shape how the output is generated. Examples of MCP Prompts A prompt to summarize customer feedback A prompt to generate a support response in a polite tone A prompt to analyze data and provide insights A prompt to translate text into another language A prompt to generate code based on requirements Key Understanding Prompts are instruction-based. They define how the AI should process input and generate output. Key Differences Between MCP Tools, Resources, and Prompts Understanding the difference between MCP Tools, Resources, and Prompts is important for building scalable AI systems. Tools vs Resources vs Prompts Tools are used for performing actions Resources are used for reading data Prompts are used for guiding AI behavior Detailed Comparison Tools interact with external systems and can change data or trigger operations Resources only provide data and do not modify anything Prompts control how the AI thinks, responds, and formats its output Comparison Table Aspect MCP Tools MCP Resources MCP Prompts Purpose Perform actions Provide data Guide behavior Nature Active Passive Instructional Usage API calls, updates Data reading AI response generation Output Action result Data Generated content How MCP Tools, Resources, and Prompts Work Together In real-world AI systems, these three components are used together to create powerful workflows. Step-by-Step Flow The user sends a request to the AI system The Prompt defines how the AI should understand and respond The AI fetches required information from Resources If an action is required, the AI uses a Tool The AI combines everything and generates a final response Practical Example Consider an AI customer support system: The Prompt ensures the response is polite and helpful The Resource provides customer history and previous tickets The Tool updates the ticket status or sends an email notification This combination helps build intelligent, real-world AI applications. Advantages of Understanding MCP Concepts Helps developers design clean and scalable AI architecture Improves clarity in system design and reduces confusion Enhances performance by separating responsibilities Makes debugging and maintenance easier Supports faster development of AI-powered applications Common Mistakes Developers Make Using Tools when only data retrieval is needed Treating Resources as editable systems Writing vague or unclear Prompts Mixing responsibilities between Tools, Resources, and Prompts Not structuring MCP components properly in applications Best Practices for Using MCP Tools, Resources, and Prompts Clearly define the role of each component before implementation Use Tools only for actions that change system state or trigger operations Use Resources strictly for reading and retrieving data Write clear, specific, and well-structured Prompts Test Tools, Resources, and Prompts independently before integration Keep your architecture modular and easy to scale Summary Understanding the difference between MCP Tools, Resources, and Prompts is essential for modern AI application development using Model Context Protocol. Tools allow AI systems to perform actions, Resources provide the necessary data, and Prompts guide how the AI behaves and generates responses. When these components are used correctly, developers can build scalable, efficient, and intelligent AI systems. Mastering these MCP concepts will help you design better architectures and create powerful AI-driven applications in todayโs evolving technology landscape.Building MCP servers with Entra ID and pre-authorized clients
The Model Context Protocol (MCP) gives AI agents a standard way to call external tools, but things get more complicated when those tools need to know who the user is. In this post, Iโll show how to build an MCP server with the Python FastMCP package that authenticates users with Microsoft Entra ID when they connect from a pre-authorized client such as VS Code. If you need to build a server that works with any MCP clients, read my previous blog post. With Microsoft Entra as the authorization server, supporting arbitrary clients currently requires adding an OAuth proxy in front, which increases security risk. This post focuses on the simpler pre-authorized-client path instead. MCP auth Letโs start by digging into the MCP auth spec, since that explains both the shape of the flow and the constraints we run into with Entra. The MCP specification includes an authorization protocol based on OAuth 2.1, so an MCP client can send a request that includes a Bearer token from an authorization server, and the MCP server can validate that token. In OAuth 2.1 terms, the MCP client is acting as the OAuth client, the MCP server is the resource server, the signed-in user is the resource owner, and the authorization server issues an access token. In this case, Entra will be our authorization server. We can't necessarily use any OAuth-compatible authorization servers, as MCP auth requires more than just the core OAuth 2.1 functionality. In OAuth, the authorization server needs a relationship with the client. MCP auth describes three options: Pre-registration: the auth server has a pre-existing relationship and has the client ID in its database already CIMD (Client Identity Metadata Document): the MCP client sends the URL of its CIMD, a JSON document that describes its attributes, and the auth server bases its interactions on that information. DCR (Dynamic Client Registration): when the auth server sees a new client, it explicitly registers it and stores the client information in its own data. DCR is now considered a "legacy" path, as the hope is for CIMD to be the supported path in the future. For each MCP scenario - each combination of MCP server, MCP client, and authorization server - we need to determine which of those options are viable and optimal. Here's one way of thinking through it: VS Code supports all of MCP auth, so its MCP client includes both CIMD and DCR support. However, the Microsoft Entra authorization server does not support CIMD or DCR. That leaves us with only one official option: pre-registration. If we desperately need support for arbitrary clients, it is possible to put a CIMD/DCR proxy in front of Entra, as discussed in my previous blog post, but the Entra team discourages that approach due to increased security risks. When using pre-registration, the auth flow is relatively simple (but still complex, because hey, this is OAuth!): User asks to use auth-restricted MCP server MCP client makes a request to MCP server without a bearer token MCP server responds with an HTTP 401 and a pointer to its PRM (Protected Resource Metadata) document MCP client reads PRM to discover the authorization server and options MCP client redirects to authorization server, including its client ID User signs into authorization server Authorization server returns authorization code MCP client exchanges authorization code for access token Authorization server returns access token MCP client re-tries original request, but now with bearer token included MCP server validates bearer token and returns successfully Here's what that looks like: Now let's dig into the code for implementing MCP auth with the pre-registered VS Code client. Registering the MCP server with Entra Before the server can use Entra to authorize users, we need to register the server with Entra via an app registration. We can do registration using the Azure Portal, Azure CLI, Microsoft Graph SDK, or even Bicep. In this case, I use the Python MS Graph SDK as it allows me to specify everything programmatically. First, I create the Entra app registration, specifying the sign-in audience (single-tenant) and configuring the MCP server as a protected resource: scope_id = str(uuid.uuid4()) Application( display_name="Entra App for MCP server", sign_in_audience="AzureADMyOrg", api=ApiApplication( requested_access_token_version=2, oauth2_permission_scopes=[ PermissionScope( admin_consent_description="Allows access to the MCP server as the signed-in user.", admin_consent_display_name="Access MCP Server", id=scope_id, is_enabled=True, type="User", user_consent_description="Allow access to the MCP server on your behalf.", user_consent_display_name="Access MCP Server", value="user_impersonation") ], pre_authorized_applications=[ PreAuthorizedApplication( app_id=VSCODE_CLIENT_ID, delegated_permission_ids=[scope_id], )])) The api parameter is doing the heavy lifting, ensuring that other applications (like VS Code) can request permission to access the server on behalf of a user. Here's what each parameter does: requested_access_token_version=2: Entra ID has two token formats (v1.0 and v2.0). We need v2.0 because that's what FastMCP's token validator expects. oauth2_permission_scopes: This defines a permission called user_impersonation that MCP clients can request when connecting to your server. It's the server saying: "I accept tokens that let an MCP client act on behalf of a signed-in user." Without at least one scope defined, no MCP client can obtain a token for your server โ Entra wouldn't know what permission to grant. The name user_impersonation is a convention (we could call it anything), but it clearly signals that the MCP client is accessing your server as the user, not as itself. pre_authorized_applications: This list tells Entra which client applications are pre-approved to request tokens for this serverโs API without showing an extra consent prompt to the user. In this case, I list VS Codeโs application ID and tie it to the user_impersonation scope, so VS Code can request a token for the MCP server as the signed-in user. Thanks to that configuration, when VS Code requests a token, it will request a token with the scope "api://{app_id}/user_impersonation" , and the FastMCP server will validate that incoming tokens contain that scope. Next, I create a Service Principal for that Entra app registration, which represents the Entra app in my tenant request_principal = ServicePrincipal(app_id=app.app_id, display_name=app.display_name) await graph_client.service_principals.post(request_principal) Securing credentials for Entra app registrations I also need a way for the server to prove that it can use that Entra app registration. There are three options: Client secret: Easiest to set up, but since it's a secret, it must be stored securely, protected carefully, and rotated regularly. Certificate: Stronger than a client secret and generally better suited for production, but it still requires certificate storage, renewal, and lifecycle management. Managed identity as Federated Identity Credential (MI-as-FIC): No stored secret, no certificate to manage, and usually the best choice when your app is hosted on Azure. No support for local development however. I wanted the best of both worlds: easy local development on my machine, but the most secure production story for deployment on Azure Container Apps. So I actually created two Entra app registrations, one for local with client secret, and one for production with managed identity. Here's how I set up the password for the local Entra app: password_credential = await graph_client.applications.by_application_id(app.id).add_password.post( AddPasswordPostRequestBody( password_credential=PasswordCredential(display_name="FastMCPSecret"))) It's a bit trickier to set up the MI-as-FIC, since we first need to provision the managed identity and associate that with our Azure Container Apps resource. I set all of that up in Bicep, and then after provisioning completes, I run this code to configure a FIC using the managed identity: fic = FederatedIdentityCredential( name="miAsFic", issuer=f"https://login.microsoftonline.com/{tenant_id}/v2.0", subject=managed_identity_principal_id, audiences=["api://AzureADTokenExchange"], ) await graph_client.applications.by_application_id( prod_app_id ).federated_identity_credentials.post(fic) Since I now have two Entra app registrations, I make sure that the environment variables in my local .env point to the secret-secured local Entra app registration, and the environment variables on my Azure Container App point to the FIC-secured prod Entra app registration. Granting admin consent This next step is only necessary if the MCP server uses the on-behalf-of (OBO) flow to exchange the incoming access token for a token to a downstream API, such as Microsoft Graph. In this case, my demo server uses OBO so it can query Microsoft Graph to check the signed-in user's group membership. The earlier code added VS Code as a pre-authorized application, but that only allows VS Code to obtain a token for the MCP server itself; it does not grant the MCP server permission to call Microsoft Graph on the user's behalf. Because the MCP sign-in flow in VS Code does not include a separate consent step for those downstream Graph scopes, I grant admin consent up front so the OBO exchange can succeed. This code grants the admin consent to the associated service principal for the Graph API resource and scopes: server_principal = await graph_client.service_principals_with_app_id(app.app_id).get() graph_principal = await graph_client.service_principals_with_app_id( "00000003-0000-0000-c000-000000000000" # Graph API ).get() await graph_client.oauth2_permission_grants.post( OAuth2PermissionGrant( client_id=server_principal.id, consent_type="AllPrincipals", resource_id=graph_principal.id, scope="User.Read email offline_access openid profile", ) ) If our MCP server needed to use an OBO flow with another resource server, we could request additional grants for those resources and scopes. Our Entra app registration is now ready for the MCP server, so let's move on to see the server code. Using FastMCP servers with Entra In our MCP server code, we configure FastMCP's RemoteAuthProvider based on the details from the Entra app registration process: from fastmcp.server.auth import RemoteAuthProvider from fastmcp.server.auth.providers.azure import AzureJWTVerifier verifier = AzureJWTVerifier( client_id=ENTRA_CLIENT_ID, tenant_id=AZURE_TENANT_ID, required_scopes=["user_impersonation"], ) auth = RemoteAuthProvider( token_verifier=verifier, authorization_servers=[f"https://login.microsoftonline.com/{AZURE_TENANT_ID}/v2.0"], base_url=base_url, ) Notice that we do not need to pass in a client secret at this point, even when using the local Entra app registration. FastMCP validates the tokens using Entra's public keys - no Entra app credentials needed. To make it easy for our MCP tools to access an identifier for the currently logged in user, we define a middleware that inspects the claims of the current token using FastMCP's get_access_token() and sets the "oid" (Entra object identifier) in the state: class UserAuthMiddleware(Middleware): def _get_user_id(self): token = get_access_token() if not (token and hasattr(token, "claims")): return None return token.claims.get("oid") async def on_call_tool(self, context: MiddlewareContext, call_next): user_id = self._get_user_id() if context.fastmcp_context is not None: await context.fastmcp_context.set_state("user_id", user_id) return await call_next(context) async def on_read_resource(self, context: MiddlewareContext, call_next): user_id = self._get_user_id() if context.fastmcp_context is not None: await context.fastmcp_context.set_state("user_id", user_id) return await call_next(context) When we initialize the FastMCP server, we set the auth provider and include that middleware: mcp = FastMCP("Expenses Tracker", auth=auth, middleware=[UserAuthMiddleware()]) Now, every request made to the MCP server will require authentication. The server will return a 401 if a valid token isn't provided, and that 401 will prompt the VS Code MCP client to kick off the MCP authorization flow. Inside each tool, we can grab the user id from the state, and use that to customize the response for the user, like to store or query items in a database. MCP.tool async def add_user_expense( date: Annotated[date, "Date of the expense in YYYY-MM-DD format"], amount: Annotated[float, "Positive numeric amount of the expense"], description: Annotated[str, "Human-readable description of the expense"], ctx: Context, ): """Add a new expense to Cosmos DB.""" user_id = await ctx.get_state("user_id") if not user_id: return "Error: Authentication required (no user_id present)" expense_item = { "id": str(uuid.uuid4()), "user_id": user_id, "date": date.isoformat(), "amount": amount, "description": description } await cosmos_container.create_item(body=expense_item) Using OBO flow in FastMCP server Remember when we granted admin consent for the Entra app registration earlier? That means we can use an OBO flow inside the MCP server, to make calls to the Graph API on behalf of the signed-in user. To make it easier to exchange and validate tokens, we use the Python MSAL SDK and configure a ConfidentialClientApplication . When using the local secret-secured Entra app registration, this is all we need to set it up: from msal import ConfidentialClientApplication confidential_client = ConfidentialClientApplication( client_id=entra_client_id, client_credential=os.environ["ENTRA_DEV_CLIENT_SECRET"], authority=f"https://login.microsoftonline.com/{os.environ['AZURE_TENANT_ID']}", token_cache=TokenCache(), ) When using the production FIC-secured Entra app registration, we need a function that returns tokens for the managed identity: from msal import ManagedIdentityClient, TokenCache, UserAssignedManagedIdentity mi_client = ManagedIdentityClient( UserAssignedManagedIdentity(client_id=os.environ["AZURE_CLIENT_ID"]), http_client=requests.Session(), token_cache=TokenCache()) def _get_mi_assertion(): result = mi_client.acquire_token_for_client(resource="api://AzureADTokenExchange") if "access_token" not in result: raise RuntimeError(f"Failed to get MI assertion: {result.get('error_description', 'unknown error')}") return result["access_token"] confidential_client = ConfidentialClientApplication( client_id=entra_client_id, client_credential={"client_assertion": _get_mi_assertion}, authority=f"https://login.microsoftonline.com/{os.environ['AZURE_TENANT_ID']}", token_cache=TokenCache()) Inside any code that requires OBO, we ask MSAL to exchange the MCP access token for a Graph API access token: graph_resource_access_token = confidential_client.acquire_token_on_behalf_of( user_assertion=access_token.token, scopes=["https://graph.microsoft.com/.default"] ) graph_token = graph_resource_access_token["access_token"] Once we successfully acquire the token, we can use that token with the Graph API, for any operations permitted by the scopes in the admin consent granted earlier. For this example, we call the Graph API to check whether the logged in user is a member of a particular Entra group: client = httpx.AsyncClient() url = ("https://graph.microsoft.com/v1.0/me/transitiveMemberOf/microsoft.graph.group" f"?$filter=id eq '{group_id}'&$count=true") response = await client.get( url, headers={ "Authorization": f"Bearer {graph_token}", "ConsistencyLevel": "eventual", }) data = response.json() membership_count = data.get("@odata.count", 0) is_admin = membership_count > 0 FastMCP 3.0 now provides a way to restrict tool visibility based on authorization checks, so I wrapped the above code in a function and set it as the auth constraint for the admin tool: async def require_admin_group(ctx: AuthContext) -> bool: graph_token = exchange_for_graph_token(ctx.token.token) return await check_user_in_group(graph_token, admin_group_id) @mcp.tool(auth=require_admin_group) async def get_expense_stats(ctx: Context): """Get expense statistics. Only accessible to admins.""" ... FastMCP will run that function both when an MCP client requests the list of tools, to determine which tools can be seen by the current user, and again when a user tries to use that tool, for an added just-in-time security check. This is just one way to use an OBO flow however. You can use it directly inside tools, like to query for more details from the Graph API, upload documents to OneDrive/SharePoint/Notes, send emails, etc. All together now For the full code, check out the open source azure-cosmosdb-identity-aware-mcp-server repository. The most relevant files for the Entra authentication setup are: auth_init.py: Creates the Entra app registrations for production and local development, defines the delegated user_impersonation scope, pre-authorizes VS Code, creates the service principal, and grants admin consent for the Microsoft Graph scopes used in the OBO flow. auth_postprovision.py: Adds the federated identity credential (FIC) after deployment so the container app's managed identity can act as the production Entra app without storing a client secret. main.py: Implements the MCP server using FastMCP's RemoteAuthProvider and AzureJWTVerifier for direct Entra authentication, plus OBO-based Microsoft Graph calls for admin group membership checks. As always, please let me know if you have further questions or ideas for other Entra integrations. Acknowledgements: Thank you to Matt Gotteiner for his guidance in implementing the OBO flow and review of the blog post.Agents League: Meet the Winners
Agents League brought together developers from around the world to build AI agents using Microsoft's developer tools. With 100+ submissions across three tracks, choosing winners was genuinely difficult. Today, we're proud to announce the category champions. ๐จ Creative Apps Winner: CodeSonify View project CodeSonify turns source code into music. As a genuinely thoughtful system, its functions become ascending melodies, loops create rhythmic patterns, conditionals trigger chord changes, and bugs produce dissonant sounds. It supports 7 programming languages and 5 musical styles, with each language mapped to its own key signature and code complexity directly driving the tempo. What makes CodeSonify stand out is the depth of execution. CodeSonify team delivered three integrated experiences: a web app with real-time visualization and one-click MIDI export, an MCP server exposing 5 tools inside GitHub Copilot in VS Code Agent Mode, and a diff sonification engine that lets you hear a code review. A clean refactor sounds harmonious. A messy one sounds chaotic. The team even built the MIDI generator from scratch in pure TypeScript with zero external dependencies. Built entirely with GitHub Copilot assistance, this is one of those projects that makes you think about code differently. ๐ง Reasoning Agents Winner: CertPrep Multi-Agent System View project CertPrep Multi-Agent System team built a production-grade 8-agent system for personalized Microsoft certification exam preparation, supporting 9 exam families including AI-102, AZ-204, AZ-305, and more. Each agent has a distinct responsibility: profiling the learner, generating a week-by-week study schedule, curating learning paths, tracking readiness, running mock assessments, and issuing a GO / CONDITIONAL GO / NOT YET booking recommendation. The engineering behind the scene here is impressive. A 3-tier LLM fallback chain ensures the system runs reliably even without Azure credentials, with the full pipeline completing in under 1 second in mock mode. A 17-rule guardrail pipeline validates every agent boundary. Study time allocation uses the Largest Remainder algorithm to guarantee no domain is silently zeroed out. 342 automated tests back it all up. This is what thoughtful multi-agent architecture looks like in practice. ๐ผ Enterprise Agents Winner: Whatever AI Assistant (WAIA) View project WAIA is a production-ready multi-agent system for Microsoft 365 Copilot Chat and Microsoft Teams. A workflow agent routes queries to specialized HR, IT, or Fallback agents, transparently to the user, handling both RAG-pattern Q&A and action automation โ including IT ticket submission via a SharePoint list. Technically, it's a showcase of what serious enterprise agent development looks like: a custom MCP server secured with OAuth Identity Passthrough, streaming responses via the OpenAI Responses API, Adaptive Cards for human-in-the-loop approval flows, a debug mode accessible directly from Teams or Copilot, and full OpenTelemetry integration visible in the Foundry portal. Franck also shipped end-to-end automated Bicep deployment so the solution can land in any Azure environment. It's polished, thoroughly documented, and built to be replicated. Thank you To every developer who submitted and shipped projects during Agents League: thank you ๐ Your creativity and innovation brought Agents League to life! ๐ Browse all submissions on GitHubBuilding a Smart Building HVAC Digital Twin with AI Copilot Using Foundry Local
Introduction Building operations teams face a constant challenge: optimizing HVAC systems for energy efficiency while maintaining occupant comfort and air quality. Traditional building management systems display raw sensor data, temperatures, pressures, COโ levelsโbut translating this into actionable insights requires deep HVAC expertise. What if operators could simply ask "Why is the third floor so warm?" and get an intelligent answer grounded in real building state? This article demonstrates building a sample smart building digital twin with an AI-powered operations copilot, implemented using DigitalTwin, React, Three.js, and Microsoft Foundry Local. You'll learn how to architect physics-based simulators that model thermal dynamics, implement 3D visualizations of building systems, integrate natural language AI control, and design fault injection systems for testing and training. Whether you're building IoT platforms for commercial real estate, designing energy management systems, or implementing predictive maintenance for building automation, this sample provides proven patterns for intelligent facility operations. Why Digital Twins Matter for Building Operations Physical buildings generate enormous operational data but lack intelligent interpretation layers. A 50,000 square foot office building might have 500+ sensors streaming metrics every minute, zone temperatures, humidity levels, equipment runtimes, energy consumption. Traditional BMS (Building Management Systems) visualize this data as charts and gauges, but operators must manually correlate patterns, diagnose issues, and predict failures. Digital twins solve this through physics-based simulation coupled with AI interpretation. Instead of just displaying current temperature readings, a digital twin models thermal dynamics, heat transfer rates, HVAC response characteristics, occupancy impacts. When conditions deviate from expectations, the twin compares observed versus predicted states, identifying root causes. Layer AI on top, and operators get natural language explanations: "The conference room is 3 degrees too warm because the VAV damper is stuck at 40% open, reducing airflow by 60%." This application focuses on HVAC, the largest building energy consumer, typically 40-50% of total usage. Optimizing HVAC by just 10% through better controls can save thousands of dollars monthly while improving occupant satisfaction. The digital twin enables "what-if" scenarios before making changes: "What happens to energy consumption and comfort if we raise the cooling setpoint by 2 degrees during peak demand response events?" Architecture: Three-Tier Digital Twin System The application implements a clean three-tier architecture separating visualization, simulation, and state management: The frontend uses React with Three.js for 3D visualization. Users see an interactive 3D model of the three-floor building with color-coded zones indicating temperature and COโ levels. Click any equipment, AHUs, VAVs, chillers, to see detailed telemetry. The control panel enables adjusting setpoints, running simulation steps, and activating demand response scenarios. Real-time charts display KPIs: energy consumption, comfort compliance, air quality levels. The backend Node.js/Express server orchestrates simulation and state management. It maintains the digital twin state as JSON, the single source of truth for all equipment, zones, and telemetry. REST API endpoints handle control requests, simulation steps, and AI copilot queries. WebSocket connections push real-time updates to the frontend for live monitoring. The HVAC simulator implements physics-based models: 1R1C thermal models for zones, affinity laws for fan power, chiller COP calculations, COโ mass balance equations. Foundry Local provides AI copilot capabilities. The backend uses foundry-local-sdk to query locally running models. Natural language queries ("How's the lobby temperature?") get answered with building state context. The copilot can explain anomalies, suggest optimizations, and even execute commands when explicitly requested. Implementing Physics-Based HVAC Simulation Accurate simulation requires modeling actual HVAC physics. The simulator implements several established building energy models: // backend/src/simulator/thermal-model.js class ZoneThermalModel { // 1R1C (one resistance, one capacitance) thermal model static calculateTemperatureChange(zone, delta_t_seconds) { const C_thermal = zone.volume * 1.2 * 1000; // Heat capacity (J/K) const R_thermal = zone.r_value * zone.envelope_area; // Thermal resistance // Internal heat gains (occupancy, equipment, lighting) const Q_internal = zone.occupancy * 100 + // 100W per person zone.equipment_load + zone.lighting_load; // Cooling/heating from HVAC const airflow_kg_s = zone.vav.airflow_cfm * 0.0004719; // CFM to kg/s const c_p_air = 1006; // Specific heat of air (J/kgยทK) const Q_hvac = airflow_kg_s * c_p_air * (zone.vav.supply_temp - zone.temperature); // Envelope losses const Q_envelope = (zone.outdoor_temp - zone.temperature) / R_thermal; // Net energy balance const Q_net = Q_internal + Q_hvac + Q_envelope; // Temperature change: Q = C * dT/dt const dT = (Q_net / C_thermal) * delta_t_seconds; return zone.temperature + dT; } } This model captures essential thermal dynamics while remaining computationally fast enough for real-time simulation. It accounts for internal heat generation from occupants and equipment, HVAC cooling/heating contributions, and heat loss through the building envelope. The COโ model uses mass balance equations: class AirQualityModel { static calculateCO2Change(zone, delta_t_seconds) { // COโ generation from occupants const G_co2 = zone.occupancy * 0.0052; // L/s per person at rest // Outdoor air ventilation rate const V_oa = zone.vav.outdoor_air_cfm * 0.000471947; // CFM to mยณ/s // COโ concentration difference (indoor - outdoor) const delta_CO2 = zone.co2_ppm - 400; // Outdoor ~400ppm // Mass balance: dC/dt = (G - V*ฮC) / Volume const dCO2_dt = (G_co2 - V_oa * delta_CO2) / zone.volume; return zone.co2_ppm + (dCO2_dt * delta_t_seconds); } } These models execute every simulation step, updating the entire building state: async function simulateStep(twin, timestep_minutes) { const delta_t = timestep_minutes * 60; // Convert to seconds // Update each zone for (const zone of twin.zones) { zone.temperature = ZoneThermalModel.calculateTemperatureChange(zone, delta_t); zone.co2_ppm = AirQualityModel.calculateCO2Change(zone, delta_t); } // Update equipment based on zone demands for (const vav of twin.vavs) { updateVAVOperation(vav, twin.zones); } for (const ahu of twin.ahus) { updateAHUOperation(ahu, twin.vavs); } updateChillerOperation(twin.chiller, twin.ahus); updateBoilerOperation(twin.boiler, twin.ahus); // Calculate system KPIs twin.kpis = calculateSystemKPIs(twin); // Detect alerts twin.alerts = detectAnomalies(twin); // Persist updated state await saveTwinState(twin); return twin; } 3D Visualization with React and Three.js The frontend renders an interactive 3D building view that updates in real-time as conditions change. Using React Three Fiber simplifies Three.js integration with React's component model: // frontend/src/components/BuildingView3D.jsx import { Canvas } from '@react-three/fiber'; import { OrbitControls } from '@react-three/drei'; export function BuildingView3D({ twinState }) { return ( {/* Render building floors */} {twinState.zones.map(zone => ( selectZone(zone.id)} /> ))} {/* Render equipment */} {twinState.ahus.map(ahu => ( ))} ); } function ZoneMesh({ zone, onClick }) { const color = getTemperatureColor(zone.temperature, zone.setpoint); return ( ); } function getTemperatureColor(current, setpoint) { const deviation = current - setpoint; if (Math.abs(deviation) < 1) return '#00ff00'; // Green: comfortable if (Math.abs(deviation) < 3) return '#ffff00'; // Yellow: acceptable return '#ff0000'; // Red: uncomfortable } This visualization immediately shows building state at a glance, operators see "hot spots" in red, comfortable zones in green, and can click any area for detailed metrics. Integrating AI Copilot for Natural Language Control The AI copilot transforms building data into conversational insights. Instead of navigating multiple screens, operators simply ask questions: // backend/src/routes/copilot.js import { FoundryLocalClient } from 'foundry-local-sdk'; const foundry = new FoundryLocalClient({ endpoint: process.env.FOUNDRY_LOCAL_ENDPOINT }); router.post('/api/copilot/chat', async (req, res) => { const { message } = req.body; // Load current building state const twin = await loadTwinState(); // Build context for AI const context = buildBuildingContext(twin); const completion = await foundry.chat.completions.create({ model: 'phi-4', messages: [ { role: 'system', content: `You are an HVAC operations assistant for a 3-floor office building. Current Building State: ${context} Answer questions about equipment status, comfort conditions, and energy usage. Provide specific, actionable information based on the current data. Do not speculate beyond provided information.` }, { role: 'user', content: message } ], temperature: 0.3, max_tokens: 300 }); res.json({ response: completion.choices[0].message.content, model: 'phi-4', timestamp: new Date().toISOString() }); }); function buildBuildingContext(twin) { const alerts = twin.alerts.filter(a => a.active); const zoneStatus = twin.zones.map(z => `${z.name}: ${z.temperature.toFixed(1)}ยฐF (setpoint: ${z.setpoint}ยฐF), COโ: ${z.co2_ppm}ppm, ${z.occupancy} people` ); return ` Zones: ${zoneStatus.join('\n')} Active Alerts: ${alerts.length} ${alerts.map(a => `- ${a.severity}: ${a.message}`).join('\n')} Energy: ${twin.kpis.total_power_kw.toFixed(1)} kW Chiller: ${twin.chiller.percent_load}% load, ${twin.chiller.cop.toFixed(2)} COP `.trim(); } Example interactions: User: "Why is the third floor conference room warm?" AI: "The Executive Suite on Floor 3 is currently 75.2ยฐF, 3 degrees above the 72ยฐF setpoint. This is due to high occupancy (8 people) and VAV-F3-EXEC operating at reduced airflow (285 CFM vs 450 CFM capacity). AHU-2 is supplying adequate cool air at 55ยฐF. Recommend checking VAV damper positionโit may be partially stuck." User: "What's our current energy usage?" AI: "Total building power consumption is 47.3 kW. Breakdown: Chiller (24.1 kW, 51%), AHU fans (12.8 kW, 27%), Pumps (7.2 kW, 15%), Other (3.2 kW, 7%). Chiller is operating at 62% load with a COP of 4.8, which is efficient for current conditions." User: "Activate demand response level 2" AI: "I cannot directly control building systems for safety reasons. To activate DR Level 2, use the Control Panel and click 'Demand Response' โ 'Level 2'. This will raise cooling setpoints by 3ยฐF and reduce auxiliary loads, targeting 15% energy reduction." The AI provides grounded, specific answers citing actual equipment IDs and metrics. It refuses to directly execute control commands, instead guiding operators to explicit control interfaces, a critical safety pattern for building systems. Fault Injection for Testing and Training Real building operations experience equipment failures, stuck dampers, sensor drift, communication losses. The digital twin includes comprehensive fault injection capabilities to train operators and test control logic: // backend/src/simulator/fault-injector.js const FAULT_CATALOG = { chillerFailure: { description: 'Chiller compressor failure', apply: (twin) => { twin.chiller.status = 'FAULT'; twin.chiller.cooling_output = 0; twin.alerts.push({ id: 'chiller-fault', severity: 'CRITICAL', message: 'Chiller compressor failure - no cooling available', equipment: 'CHILLER-01' }); } }, stuckVAVDamper: { description: 'VAV damper stuck at current position', apply: (twin, vavId) => { const vav = twin.vavs.find(v => v.id === vavId); vav.damper_stuck = true; vav.damper_position_fixed = vav.damper_position; twin.alerts.push({ id: `vav-stuck-${vavId}`, severity: 'HIGH', message: `VAV ${vavId} damper stuck at ${vav.damper_position}%`, equipment: vavId }); } }, sensorDrift: { description: 'Temperature sensor reading 5ยฐF high', apply: (twin, zoneId) => { const zone = twin.zones.find(z => z.id === zoneId); zone.sensor_drift = 5.0; zone.temperature_measured = zone.temperature_actual + 5.0; } }, communicationLoss: { description: 'Equipment communication timeout', apply: (twin, equipmentId) => { const equipment = findEquipmentById(twin, equipmentId); equipment.comm_status = 'OFFLINE'; equipment.stale_data = true; twin.alerts.push({ id: `comm-loss-${equipmentId}`, severity: 'MEDIUM', message: `Lost communication with ${equipmentId}`, equipment: equipmentId }); } } }; router.post('/api/twin/fault', async (req, res) => { const { faultType, targetEquipment } = req.body; const twin = await loadTwinState(); const fault = FAULT_CATALOG[faultType]; if (!fault) { return res.status(400).json({ error: 'Unknown fault type' }); } fault.apply(twin, targetEquipment); await saveTwinState(twin); res.json({ message: `Applied fault: ${fault.description}`, affectedEquipment: targetEquipment, timestamp: new Date().toISOString() }); }); Operators can inject faults to practice diagnosis and response. Training scenarios might include: "The chiller just failed during a heat wave, how do you maintain comfort?" or "Multiple VAV dampers are stuck, which zones need immediate attention?" Key Takeaways and Production Deployment Building a physics-based digital twin with AI capabilities requires balancing simulation accuracy with computational performance, providing intuitive visualization while maintaining technical depth, and enabling AI assistance without compromising safety. Key architectural lessons: Physics models enable prediction: Comparing predicted vs observed behavior identifies anomalies that simple thresholds miss 3D visualization improves spatial understanding: Operators immediately see which floors or zones need attention AI copilots accelerate diagnosis: Natural language queries get answers in seconds vs. minutes of manual data examination Fault injection validates readiness: Testing failure scenarios prepares operators for real incidents JSON state enables integration: Simple file-based state makes connecting to real BMS systems straightforward For production deployment, connect the twin to actual building systems via BACnet, Modbus, or MQTT integrations. Replace simulated telemetry with real sensor streams. Calibrate model parameters against historical building performance. Implement continuous learning where the twin's predictions improve as it observes actual building behavior. The complete implementation with simulation engine, 3D visualization, AI copilot, and fault injection system is available at github.com/leestott/DigitalTwin. Clone the repository and run the startup scripts to explore the digital twin, no building hardware required. Resources and Further Reading Smart Building HVAC Digital Twin Repository - Complete source code and simulation engine Setup and Quick Start Guide - Installation instructions and usage examples Microsoft Foundry Local Documentation - AI integration reference HVAC Simulation Documentation - Physics model details and calibration Three.js Documentation - 3D visualization framework ASHRAE Standards - Building energy modeling standardsMicrosoft Agent Framework, Microsoft Foundry, MCP, Aspire๋ฅผ ํ์ฉํ ์ค์ ์์ ๋ง๋ค๊ธฐ
AI ์์ด์ ํธ๋ฅผ ๊ฐ๋ฐํ๋ ๊ฒ์ ์ ์ ์ฌ์์ง๊ณ ์์ต๋๋ค. ํ์ง๋ง ์ฌ๋ฌ ์๋น์ค, ์ํ ๊ด๋ฆฌ, ํ๋ก๋์ ์ธํ๋ผ๋ฅผ ๊ฐ์ถ ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ผ๋ถ๋ก ๋ฐฐํฌํ๋ ๊ฒ์ ์ฌ์ ํ ๋ณต์กํฉ๋๋ค. ์ค์ ๋ก .NET ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ์์๋ ๋ก์ปฌ ๋จธ์ ๊ณผ ํด๋ผ์ฐ๋ ๋ค์ดํฐ๋ธ ๋ฐฉ์์ ํด๋ผ์ฐ๋ ํ๊ฒฝ ๋ชจ๋์์ ์ค์ ๋ก ๋์ํ๋ ์ค์ ์์ ์ ๋ํ ์๊ตฌ๊ฐ ๋ง์์ต๋๋ค. ๊ทธ๋์ ์ค๋นํ์ต๋๋ค! Microsoft Agent Framework๊ณผ Microsoft Foundry, MCP(Model Context Protocol), Aspire๋ฑ์ ์ด๋ป๊ฒ ํ๋ก๋์ ์ํฉ์์ ์กฐํฉํ ์ ์๋์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ์คํ์์ค Interview Coach ์ํ์ ๋๋ค. AI ์ฝ์น๊ฐ ์ธ์ฑ ๋ฉด์ ์ง๋ฌธ๊ณผ ๊ธฐ์ ๋ฉด์ ์ง๋ฌธ์ ์๋ดํ ํ, ์์ฝ์ ์ ๊ณตํ๋ ํจ์จ์ ์ธ ๋ฉด์ ์๋ฎฌ๋ ์ดํฐ์ ๋๋ค. ์ด ํฌ์คํธ์์๋ ์ด๋ค ํจํด์ ์ฌ์ฉํ๊ณ ํด๋น ํจํด์ด ํด๊ฒฐํ ์ ์๋ ๋ฌธ์ ๋ฅผ ๋ค๋ฃน๋๋ค. Interview Coach ๋ฐ๋ชจ ์ฑ์ ๋ฐฉ๋ฌธํด ๋ณด์ธ์. ์ Microsoft Agent Framework์ ์จ์ผ ํ๋์? .NET์ผ๋ก AI ์์ด์ ํธ๋ฅผ ๊ตฌ์ถํด ๋ณธ ์ ์ด ์๋ค๋ฉด, Semantic Kernel์ด๋ AutoGen, ๋๋ ๋ ๊ฐ์ง ๋ชจ๋๋ฅผ ์ฌ์ฉํด ๋ณธ ์ ์ด ์์ ๊ฒ๋๋ค. Microsoft Agent Framework๋ ๊ทธ ๋ค์ ๋จ๊ณ๋ก์, ๊ฐ๊ฐ์ ํ๋ก์ ํธ์์ ํจ๊ณผ์ ์ด์๋ ๋ถ๋ถ์ ํ๋์ ํ๋ ์์ํฌ๋ก ํตํฉํ์ต๋๋ค. AutoGen์ ์์ด์ ํธ ์ถ์ํ์ Semantic Kernel์ ์ํฐํ๋ผ์ด์ฆ ๊ธฐ๋ฅ(์ํ ๊ด๋ฆฌ, ํ์ ์์ ์ฑ, ๋ฏธ๋ค์จ์ด, ํ ๋ ๋ฉํธ๋ฆฌ ๋ฑ)์ ํ๋๋ก ํตํฉํ์ต๋๋ค. ๋ํ ๋ฉํฐ ์์ด์ ํธ ์ค์ผ์คํธ๋ ์ด์ ์ ์ํ ๊ทธ๋ํ ๊ธฐ๋ฐ ์ํฌํ๋ก์ฐ๋ ์ถ๊ฐํ์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด .NET ๊ฐ๋ฐ์์๊ฒ ์ด๊ฒ์ด ์ด๋ค ์๋ฏธ๋ก ๋ค๊ฐ์ฌ๊น์? ํ๋์ ํ๋ ์์ํฌ. Semantic Kernel๊ณผ AutoGen ์ฌ์ด์์ ๋ ์ด์ ๊ณ ๋ฏผํ ํ์๊ฐ ์์ต๋๋ค. ์ต์ํ ํจํด. ์์ด์ ํธ๋ ์์กด์ฑ ์ฃผ์ , IChatClient , ๊ทธ๋ฆฌ๊ณ ASP.NET ์ฑ๊ณผ ๋์ผํ ํธ์คํ ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค. ํ๋ก๋์ ์ ์ํ ์ค๊ณ. OpenTelemetry, ๋ฏธ๋ค์จ์ด ํ์ดํ๋ผ์ธ, Aspire ํตํฉ์ด ํฌํจ๋์ด ์์ต๋๋ค. ๋ฉํฐ ์์ด์ ํธ ์ค์ผ์คํธ๋ ์ด์ . ์์ฐจ ์คํ, ๋์ ์คํ, ํธ๋์คํ ํจํด, ๊ทธ๋ฃน ์ฑํ ๋ฑ ๋ค์ํ ๋ฉํฐ ์์ด์ ํธ ์ค์ผ์คํธ๋ ์ด์ ํจํด์ ์ง์ํฉ๋๋ค. Interview Coach๋ ์ด ๋ชจ๋ ๊ฒ์ Hello World๊ฐ ์๋ ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉํฉ๋๋ค. ์ Microsoft Foundry๋ฅผ ์จ์ผ ํ๋์? AI ์์ด์ ํธ์๋ ๋ชจ๋ธ ๋ง๊ณ ๋ ๋ ๋ง์ ๋ฌด์ธ๊ฐ๊ฐ ํ์ํฉ๋๋ค. ์ฐ์ ์ธํ๋ผ๊ฐ ํ์ํ๊ฒ ์ฃ . Microsoft Foundry๋ AI ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํ Azure ํ๋ซํผ์ด๋ฉฐ, Microsoft Agent Framework์ ๊ถ์ฅ ๋ฐฑ์๋์ ๋๋ค. Foundry๋ ์์ฒด ํฌํธ์์ ์๋์ ๊ฐ์ ๋ด์ฉ์ ์ ๊ณตํฉ๋๋ค: ๋ชจ๋ธ ์ก์ธ์ค. OpenAI, Meta, Mistral ๋ฑ์ ๋ชจ๋ธ ์นดํ๋ก๊ทธ๋ฅผ ํ๋์ ์๋ํฌ์ธํธ๋ก ์ ๊ณตํฉ๋๋ค. ์ฝํ ์ธ ์ธ์ดํํฐ. ์์ด์ ํธ๊ฐ ๋ฒ์ด๋์ง ์๋๋ก ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ์ฝํ ์ธ ์กฐ์ ๋ฐ PII ๊ฐ์ง ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ๋น์ฉ ์ต์ ํ ๋ผ์ฐํ . ์์ด์ ํธ์ ์์ฒญ์ ์๋์ผ๋ก ์ต์ ์ ๋ชจ๋ธ๋ก ๋ผ์ฐํ ํฉ๋๋ค. ํ๊ฐ ๋ฐ ํ์ธํ๋. ์์ด์ ํธ ํ์ง์ ์ธก์ ํ๊ณ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ฐ์ ํ ์ ์์ต๋๋ค. ์ํฐํ๋ผ์ด์ฆ ๊ฑฐ๋ฒ๋์ค. Entra ID์ Microsoft Defender๋ฅผ ํตํ ID, ์ก์ธ์ค ์ ์ด, ๊ท์ ์ค์๋ฅผ ์ง์ํฉ๋๋ค. Interview Coach์์ Foundry๋ ์์ด์ ํธ๋ฅผ ๊ตฌ๋ํ๋ ๋ชจ๋ธ ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์์ด์ ํธ ์ฝ๋๊ฐ IChatClient ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, Foundry๋ LLM ์ ํ์ ์ํ ์ค์ ์ ๋ถ๊ณผํ ์๋ ์๊ฒ ์ง๋ง, ์์ด์ ํธ๊ฐ ํ์๋ก ํ๋ ๊ฐ์ฅ ๋ง์ ๋๊ตฌ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ์ ํ์ง์ ๋๋ค. Interview Coach๋ ๋ฌด์์ ํ๋์? Interview Coach๋ ๋ชจ์ ๋ฉด์ ์ ์งํํ๋ ๋ํํ AI์ ๋๋ค. ์ด๋ ฅ์์ ์ฑ์ฉ ๊ณต๊ณ ๋ฅผ ์ ๊ณตํ๋ฉด, ์์ด์ ํธ๊ฐ ๋๋จธ์ง๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค: ์ ์. ์ด๋ ฅ์์ ๋ชฉํ ์ง๋ฌด ์ค๋ช ์ ์์งํฉ๋๋ค. ํ๋ ๋ฉด์ . ๊ฒฝํ์ ๋ง์ถ STAR ๊ธฐ๋ฒ ์ง๋ฌธ์ ํฉ๋๋ค. ๊ธฐ์ ๋ฉด์ . ์ง๋ฌด๋ณ ๊ธฐ์ ์ง๋ฌธ์ ํฉ๋๋ค. ์์ฝ. ๊ตฌ์ฒด์ ์ธ ํผ๋๋ฐฑ๊ณผ ํจ๊ป ์ฑ๊ณผ ๋ฆฌ๋ทฐ๋ฅผ ์์ฑํฉ๋๋ค. Blazor ์น UI๋ฅผ ํตํด ์ค์๊ฐ์ผ๋ก ์๋ต ์คํธ๋ฆฌ๋ฐ์ ์ ๊ณตํ๋ฉฐ ์ฌ์ฉ์์ ์์ด์ ํธ๊ฐ ์ํธ์์ฉํฉ๋๋ค. ์ํคํ ์ฒ ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ Aspire๋ฅผ ํตํด ๋ค์ํ ์๋น์ค๋ฅผ ์ค์ผ์คํธ๋ ์ด์ ํฉ๋๋ค: LLM ์ ๊ณต์. ๋ค์ํ ๋ชจ๋ธ ์ก์ธ์ค๋ฅผ ์ํ Microsoft Foundry (๊ถ์ฅ). WebUI. ๋ฉด์ ๋ํ๋ฅผ ์ํ Blazor ์ฑํ ์ธํฐํ์ด์ค. ์์ด์ ํธ. Microsoft Agent Framework๋ก ๊ตฌ์ถ๋ ๋ฉด์ ๋ก์ง. MarkItDown MCP ์๋ฒ. Microsoft์ MarkItDown์ ํตํด ์ด๋ ฅ์(PDF, DOCX)๋ฅผ ๋งํฌ๋ค์ด์ผ๋ก ๋ณํํฉ๋๋ค. InterviewData MCP ์๋ฒ. SQLite์ ์ธ์ ์ ์ ์ฅํ๋ .NET MCP ์๋ฒ. Aspire๊ฐ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ, ์ํ ํ์ธ, ํ ๋ ๋ฉํธ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ๊ฐ ์ปดํฌ๋ํธ๋ ๋ณ๋์ ํ๋ก์ธ์ค๋ก ์คํ์ํค๋ฉฐ, ํ๋์ ์ปค๋งจ๋ ๋ง์ผ๋ก ์ ์ฒด๋ฅผ ์์ํ ์ ์์ต๋๋ค. ํจํด 1: ๋ฉํฐ ์์ด์ ํธ ํธ๋์คํ ์ด ์ํ์์ ๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๋ถ๋ถ์ด๊ธฐ๋ ํ ํธ๋์คํ ํจํด์ผ๋ก ๋ฉํฐ ์์ด์ ํธ ์๋๋ฆฌ์ค๋ฅผ ๊ตฌ์ฑํ์ต๋๋ค. ํ๋์ ์์ด์ ํธ๊ฐ ๋ชจ๋ ๊ฒ์ ์ฒ๋ฆฌํ๋ ๋์ , ๋ฉด์ ์ ๋ค์ฏ ๊ฐ์ ์ ๋ฌธ ์์ด์ ํธ๋ก ๋๋ฉ๋๋ค: ์์ด์ ํธ ์ญํ ๋๊ตฌ Triage ๋ฉ์์ง๋ฅผ ์ ์ ํ ์ ๋ฌธ๊ฐ์๊ฒ ๋ผ์ฐํ ์์ (์์ ๋ผ์ฐํ ) Receptionist ์ธ์ ์์ฑ, ์ด๋ ฅ์ ๋ฐ ์ฑ์ฉ ๊ณต๊ณ ์์ง MarkItDown + InterviewData Behavioral Interviewer STAR ๊ธฐ๋ฒ์ ํ์ฉํ ํ๋ ๋ฉด์ ์ง๋ฌธ ์งํ InterviewData Technical Interviewer ์ง๋ฌด๋ณ ๊ธฐ์ ์ง๋ฌธ ์งํ InterviewData Summarizer ์ต์ข ๋ฉด์ ์์ฝ ์์ฑ InterviewData ํธ๋์คํ ํจํด์์๋ ํ๋์ ์์ด์ ํธ๊ฐ ๋ํ์ ์ ์ฒด ์ ์ด๊ถ์ ๋ค์ ์์ด์ ํธ์๊ฒ ๋๊น๋๋ค. ๊ทธ๋ฌ๋ฉด ๋๊ฒจ ๋ฐ๋ ์์ด์ ํธ๊ฐ ๋ชจ๋ ์ ์ด๊ถ์ ์ธ์ํฉ๋๋ค. ์ด๋ ์ฃผ ์์ด์ ํธ๊ฐ ๋ค๋ฅธ ์์ด์ ํธ๋ฅผ ๋์ฐ๋ฏธ๋ก ํธ์ถํ๋ฉด์๋ ์ ์ด๊ถ์ ์ ์งํ๋ "agent-as-tools(๋๊ตฌ๋ก์์ ์์ด์ ํธ)" ๋ฐฉ์๊ณผ๋ ๋ค๋ฆ ๋๋ค. ํธ๋์คํ ์ํฌํ๋ก์ฐ๋ฅผ ์ด๋ป๊ฒ ๊ตฌ์ฑํ๋์ง ์ดํด๋ณด์์ฃ : var workflow = AgentWorkflowBuilder .CreateHandoffBuilderWith(triageAgent) .WithHandoffs(triageAgent, [receptionistAgent, behaviouralAgent, technicalAgent, summariserAgent]) .WithHandoffs(receptionistAgent, [behaviouralAgent, triageAgent]) .WithHandoffs(behaviouralAgent, [technicalAgent, triageAgent]) .WithHandoffs(technicalAgent, [summariserAgent, triageAgent]) .WithHandoff(summariserAgent, triageAgent) .Build(); ๋ฉด์ ์ํฉ์ ์์ํด ๋ณธ๋ค๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฐจ์ ์ธ ๋ฐฉ์์ผ๋ก ์งํํฉ๋๋ค: Receptionist โ Behavioral โ Technical โ Summarizer. ๊ฐ ์ ๋ฌธ๊ฐ๊ฐ ์ง์ ๋ค์์ผ๋ก ํธ๋์คํํฉ๋๋ค. ์์์น ๋ชปํ ์ํฉ์ด ๋ฐ์ํ๋ฉด, ์์ด์ ํธ๋ ์ฌ๋ผ์ฐํ ์ ์ํด Triage๋ก ๋์๊ฐ๋๋ค. ์ด ์ํ์๋ ๋ ๊ฐ๋จํ ๋ฐฐํฌ๋ฅผ ์ํ ๋จ์ผ ์์ด์ ํธ ๋ชจ๋๋ ํฌํจํ๊ณ ์์ด, ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ ๋๋ํ ๋น๊ตํ ์ ์์ต๋๋ค. ํจํด 2: ๋๊ตฌ ํตํฉ์ ์ํ MCP ์ด ํ๋ก์ ํธ์์ ๋๊ตฌ๋ ์์ด์ ํธ ๋ด๋ถ์ ๊ตฌํํ๋ ๋์ MCP(Model Context Protocol) ์๋ฒ๋ฅผ ํตํด ํตํฉํฉ๋๋ค. ๋์ผํ MarkItDown ์๋ฒ๊ฐ ์์ ํ ๋ค๋ฅธ ์์ด์ ํธ ํ๋ก์ ํธ์์๋ ์ฐ์ผ ์ ์์ผ๋ฉฐ, ๋๊ตฌ ๊ฐ๋ฐํ์ ์์ด์ ํธ ๊ฐ๋ฐํ๊ณผ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฐฐํฌํ ์ ์์ต๋๋ค. MCP๋ ๋ํ ์ธ์ด์ ๊ตฌ์ ๋ฐ์ง ์์ผ๋ฏ๋ก, ์ด ์ํ ์ฑ์์ ์ฐ์ธ MarkItDown์ Python ๊ธฐ๋ฐ์ ์๋ฒ์ด๊ณ , ์์ด์ ํธ๋ .NET ๊ธฐ๋ฐ์ผ๋ก ๋์ํฉ๋๋ค. ์์ด์ ํธ๋ ์์ ์ MCP ํด๋ผ์ด์ธํธ๋ฅผ ํตํด ๋๊ตฌ๋ฅผ ๋ฐ๊ฒฌํ๊ณ , ์ ์ ํ ์์ด์ ํธ์๊ฒ ์ ๋ฌํฉ๋๋ค: var receptionistAgent = new ChatClientAgent( chatClient: chatClient, name: "receptionist", instructions: "You are the Receptionist. Set up sessions and collect documents...", tools: [.. markitdownTools, .. interviewDataTools]); ๊ฐ ์์ด์ ํธ๋ ํ์ํ ๋๊ตฌ๋ง ๋ฐ์ต๋๋ค. Triage๋ ๋๊ตฌ๋ฅผ ๋ฐ์ง ์๊ณ (๋ผ์ฐํ ๋ง ์ํ), ๋ฉด์ ๊ด์ ์ธ์ ์ก์ธ์ค๋ฅผ, Receptionist๋ ๋ฌธ์ ํ์ฑ๊ณผ ์ธ์ ์ก์ธ์ค๋ฅผ ๋ฐ์ต๋๋ค. ์ด๋ ์ต์ ๊ถํ ์์น์ ๋ฐ๋ฆ ๋๋ค. ํจํด 3: Aspire ์ค์ผ์คํธ๋ ์ด์ Aspire๊ฐ ๋ชจ๋ ๊ฒ์ ํ๋๋ก ์ฐ๊ฒฐํฉ๋๋ค. ์ฑ ํธ์คํธ๋ ์๋น์ค ํ ํด๋ก์ง๋ฅผ ์ ์ํฉ๋๋ค: ์ด๋ค ์๋น์ค๊ฐ ์กด์ฌํ๋์ง, ์๋ก ์ด๋ป๊ฒ ์์กดํ๋์ง, ์ด๋ค ๊ตฌ์ฑ์ ๋ฐ๋์ง. ๋ค์์ ์ ๊ณตํฉ๋๋ค: ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ. ์๋น์ค๊ฐ ํ๋์ฝ๋ฉ๋ URL์ด ์๋ ์ด๋ฆ์ผ๋ก ์๋ก๋ฅผ ์ฐพ์ต๋๋ค. ์ํ ํ์ธ. Aspire ๋์๋ณด๋์์ ๋ชจ๋ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ๋ณด์ฌ์ค๋๋ค. ๋ถ์ฐ ์ถ์ . ๊ณต์ ์๋น์ค ๊ธฐ๋ณธ๊ฐ์ ํตํด OpenTelemetry๊ฐ ์ฐ๊ฒฐ๋ฉ๋๋ค. ๋จ์ผ ์ปค๋งจ๋ ์์. aspire run --file ./apphost.cs ๋ก ๋ชจ๋ ๊ฒ์ ์์ํฉ๋๋ค. ๋ฐฐํฌ ์, azd up ์ผ๋ก ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ Azure Container Apps์ ํธ์ํฉ๋๋ค. ์์ํ๊ธฐ ์ฌ์ ์๊ตฌ ์ฌํญ .NET 10 SDK ์ด์ Azure ๊ตฌ๋ Microsoft Foundry ํ๋ก์ ํธ Docker Desktop ๋๋ ๊ธฐํ ์ปจํ ์ด๋ ๋ฐํ์ ๋ก์ปฌ์์ ์คํํ๊ธฐ git clone https://github.com/Azure-Samples/interview-coach-agent-framework.git cd interview-coach-agent-framework # ์๊ฒฉ ์ฆ๋ช ๊ตฌ์ฑ dotnet user-secrets --file ./apphost.cs set MicrosoftFoundry:Project:Endpoint "<your-endpoint>" dotnet user-secrets --file ./apphost.cs set MicrosoftFoundry:Project:ApiKey "<your-key>" # ๋ชจ๋ ์๋น์ค ์์ aspire run --file ./apphost.cs Aspire ๋์๋ณด๋๋ฅผ ์ด๊ณ , ๋ชจ๋ ์๋น์ค๊ฐ Running์ผ๋ก ํ์๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ, WebUI ์๋ํฌ์ธํธ๋ฅผ ํด๋ฆญํ์ฌ ๋ชจ์ ๋ฉด์ ์ ์์ํ์ธ์. ํธ๋์คํ ํจํด์ด ์ด๋ป๊ฒ ๋์ํ๋์ง DevUI์์ ์๊ฐํํ ๋ชจ์ต์ ๋๋ค. ์ด ์ฑํ UI๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉด์ ํ๋ณด์๋ก์ ์์ด์ ํธ์ ์ํธ์์ฉํ ์ ์์ต๋๋ค. Azure์ ๋ฐฐํฌํ๊ธฐ azd auth login azd up ๋ฐฐํฌ๋ฅผ ์ํด์๋ ์ด๊ฒ ์ฌ์ค์ ์ ๋ถ์ ๋๋ค! Aspire์ azd ๊ฐ ๋๋จธ์ง๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ๋ฐฐํฌ์ ํ ์คํธ๋ฅผ ์๋ฃํ ํ, ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ฌ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ์์ ํ๊ฒ ์ญ์ ํ ์ ์์ต๋๋ค: azd down --force --purge ์ด ์ํ์์ ๋ฐฐ์ธ ์ ์๋ ๊ฒ Interview Coach๋ฅผ ํตํด ๋ค์์ ๊ฒฝํํ๊ฒ ๋ฉ๋๋ค: Microsoft Foundry๋ฅผ ๋ชจ๋ธ ๋ฐฑ์๋๋ก ์ฌ์ฉํ๊ธฐ Microsoft Agent Framework๋ก ๋จ์ผ ์์ด์ ํธ ๋ฐ ๋ฉํฐ ์์ด์ ํธ ์์คํ ๊ตฌ์ถํ๊ธฐ ํธ๋์คํ ์ค์ผ์คํธ๋ ์ด์ ์ผ๋ก ์ ๋ฌธ ์์ด์ ํธ ๊ฐ ์ํฌํ๋ก์ฐ ๋ถํ ํ๊ธฐ ์์ด์ ํธ ์ฝ๋์ ๋ ๋ฆฝ์ ์ผ๋ก MCP ๋๊ตฌ ์๋ฒ ์์ฑ ๋ฐ ์ฌ์ฉํ๊ธฐ Aspire๋ก ๋ฉํฐ ์๋น์ค ์ ํ๋ฆฌ์ผ์ด์ ์ค์ผ์คํธ๋ ์ด์ ํ๊ธฐ ์ผ๊ด๋๊ณ ๊ตฌ์กฐํ๋ ๋์์ ์์ฑํ๋ ํ๋กฌํํธ ์์ฑํ๊ธฐ azd up ์ผ๋ก ๋ชจ๋ ๊ฒ ๋ฐฐํฌํ๊ธฐ ์ฌ์ฉํด ๋ณด์ธ์ ์ ์ฒด ์์ค ์ฝ๋๋ GitHub์ ์์ต๋๋ค: Azure-Samples/interview-coach-agent-framework Microsoft Agent Framework๊ฐ ์ฒ์์ด๋ผ๋ฉด, ํ๋ ์์ํฌ ๋ฌธ์์ Hello World ์ํ๋ถํฐ ์์ํ์ธ์. ๊ทธ๋ฐ ๋ค์ ์ฌ๊ธฐ๋ก ๋์์์ ๋ ํฐ ํ๋ก์ ํธ์์ ๊ฐ ๋ถ๋ถ์ด ์ด๋ป๊ฒ ๊ฒฐํฉ๋๋์ง ํ์ธํ์ธ์. ์ด๋ฌํ ํจํด์ผ๋ก ๋ฌด์ธ๊ฐ๋ฅผ ๋ง๋ค์๋ค๋ฉด, ์ด์๋ฅผ ์ด์ด ์๋ ค์ฃผ์ธ์. ๋ค์ ๊ณํ ๋ค์๊ณผ ๊ฐ์ ํตํฉ ์๋๋ฆฌ์ค๋ฅผ ํ์ฌ ์์ ์ค์ ๋๋ค. ์์ ์ด ๋๋๋ ๋๋ก ์ด ์ํ ์ฑ์ ์ ๋ฐ์ดํธ ํ๋๋ก ํ๊ฒ ์ต๋๋ค. Microsoft Foundry Agent Service GitHub Copilot A2A ์ฐธ๊ณ ์๋ฃ Microsoft Agent Framework ๋ฌธ์ Microsoft Agent Framework ํ๋ฆฌ๋ทฐ ์๊ฐ Microsoft Agent Framework, ๋ฆด๋ฆฌ์ค ํ๋ณด ๋๋ฌ Microsoft Foundry ๋ฌธ์ Microsoft Foundry Agent Service Microsoft Foundry ํฌํธ Microsoft.Extensions.AI Model Context Protocol ์ฌ์ Aspire ๋ฌธ์ ASP.NET BlazorMCP vs mcp-cli: Dynamic Tool Discovery for Token-Efficient AI Agents
Introduction The AI agent ecosystem is evolving rapidly, and with it comes a scaling challenge that many developers are hitting context window bloat. When building systems that integrate with multiple MCP (Model Context Protocol) servers, you're forced to load all tool definitions upfrontโconsuming thousands of tokens just to describe what tools could be available. mcp-cli: a lightweight tool that changes how we interact with MCP servers. But before diving into mcp-cli, it's essential to understand the foundational protocol itself, the design trade-offs between static and dynamic approaches, and how they differ fundamentally. Part 1: Understanding MCP (Model Context Protocol) What is MCP? The Model Context Protocol (MCP) is an open standard for connecting AI agents and applications to external tools, APIs, and data sources. Think of it as a universal interface that allows: AI Agents (Claude, Gemini, etc.) to discover and call tools Tool Providers to expose capabilities in a standardized way Seamless Integration between diverse systems without custom adapters New to MCP see https://aka.ms/mcp-for-beginners How MCP Works MCP operates on a simple premise: define tools with clear schemas and let clients discover and invoke them. Basic MCP Flow: Tool Provider (MCP Server) โ [Tool Definitions + Schemas] โ AI Agent / Client โ [Discover Tools] โ [Invoke Tools] โ [Get Results] Example: A GitHub MCP server exposes tools like: search_repositories - Search GitHub repos create_issue - Create a GitHub issue list_pull_requests - List open PRs Each tool comes with a JSON schema describing its parameters, types, and requirements. The Static Integration Problem Traditionally, MCP integration works like this: Startup: Load ALL tool definitions from all servers Context Window: Send every tool schema to the AI model Invocation: Model chooses which tool to call Execution: Tool is invoked and result returned The Problem: When you have multiple MCP servers, the token cost becomes substantial: Scenario Token Count 6 MCP Servers, 60 tools (static loading) ~47,000 tokens After dynamic discovery ~400 tokens Token Reduction 99% ๐ For a production system with 10+ servers exposing 100+ tools, you're burning through thousands of tokens just describing capabilities, leaving less context for actual reasoning and problem-solving. Key Issues: โ Reduced effective context length for actual work โ More frequent context compactions โ Hard limits on simultaneous MCP servers โ Higher API costs Part 2: Enter mcp-cli โ Dynamic Context Discovery What is mcp-cli? mcp-cli is a lightweight CLI tool (written in Bun, compiled to a single binary) that implements dynamic context discovery for MCP servers. Instead of loading everything upfront, it pulls in information only when needed. Static vs. Dynamic: The Paradigm Shift Traditional MCP (Static Context): AI Agent Says: "Load all tool definitions from all servers" โ Context Window Bloat โ โ Limited space for reasoning mcp-cli (Dynamic Discovery): AI Agent Says: "What servers exist?" โ mcp-cli responds AI Agent Says: "What are the params for tool X?" โ mcp-cli responds AI Agent Says: "Execute tool X" mcp-cli executes and responds Result: You only pay for information you actually use. โ Core Capabilities mcp-cli provides three primary commands: 1. Discover - What servers and tools exist? mcp-cli Lists all configured MCP servers and their tools. 2. Inspect - What does a specific tool do? mcp-cli info <server> <tool> Returns the full JSON schema for a tool (parameters, descriptions, types). 3. Execute - Run a tool mcp-cli call <server> <tool> '{"arg": "value"}' Executes the tool and returns results. Key Features of mcp-cli Feature Benefit Stdio & HTTP Support Works with both local and remote MCP servers Connection Pooling Lazy-spawn daemon avoids repeated startup overhead Tool Filtering Control which tools are available via allowedTools/disabledTools Glob Searching Find tools matching patterns: mcp-cli grep "*mail*" AI Agent Ready Designed for use in system instructions and agent skills Lightweight Single binary, minimal dependencies Part 3: Detailed Comparison Table Aspect Traditional MCP mcp-cli Protocol HTTP/REST or Stdio Stdio/HTTP (via CLI) Context Loading Static (upfront) Dynamic (on-demand) Tool Discovery All at once Lazy enumeration Schema Inspection Pre-loaded On-request Token Usage High (~47k for 60 tools) Low (~400 for 60 tools) Best For Direct server integration AI agent tool use Implementation Server-side focus CLI-side focus Complexity Medium Low (CLI handles it) Startup Time One call Multiple calls (optimized) Scaling Limited by context Unlimited (pay per use) Integration Custom implementation Pre-built mcp-cli Part 4: When to Use Each Approach Use Traditional MCP (HTTP Endpoints) when: โ Building a direct server integration โ You have few tools (< 10) and don't care about context waste โ You need full control over HTTP requests/responses โ You're building a specialized integration (not AI agents) โ Real-time synchronous calls are required Use mcp-cli when: โ Integrating with AI agents (Claude, Gemini, etc.) โ You have multiple MCP servers (> 2-3) โ Token efficiency is critical โ You want a standardized, battle-tested tool โ You prefer CLI-based automation โ Connection pooling and lazy loading are beneficial โ You're building agent skills or system instructions Conclusion MCP (Model Context Protocol) defines the standard for tool sharing and discovery. mcp-cli is the practical tool that makes MCP efficient for AI agents by implementing dynamic context discovery. The fundamental difference: MCP mcp-cli What The protocol standard The CLI tool Where Both server and client Client-side CLI Problem Solved Tool standardization Context bloat Architecture Protocol Implementation Think of it this way: MCP is the language, mcp-cli is the interpreter that speaks fluently. For AI agent systems, dynamic discovery via mcp-cli is becoming the standard. For direct integrations, traditional MCP HTTP endpoints work fine. The choice depends on your use case, but increasingly, the industry is trending toward mcp-cli for its efficiency and scalability. Resources MCP Specification mcp-cli GitHub New to MCP see https://aka.ms/mcp-for-beginners Practical demo: AnveshMS/mcp-cli-example1.5KViews0likes0CommentsGiving Your AI Agents Reliable Skills with the Agent Skills SDK
AI agents are becoming increasingly capable, but they often do not have the context they need to do real work reliably. Your agent can reason well, but it does not actually know how to do the specific things your team needs it to do. For example, it cannot follow your company's incident response playbook, it does not know your escalation policy, and it has no idea how to page the on-call engineer at 3 AM. There are many ways to close this gap, from RAG to custom tool implementations. Agent Skills is one approach that stands out because it is designed around portability and progressive disclosure, keeping context window usage minimal while giving agents access to deep expertise on demand. What is Agent Skills? Agent Skills is an open format for giving agents new capabilities and expertise. The format was originally developed by Anthropic and released as an open standard. It is now supported by a growing list of agent products including Claude Code, VS Code, GitHub, OpenAI Codex, Cursor, Gemini CLI, and many others. As defined in the spec, a skill is a folder on disk containing a SKILL.md file with metadata and instructions, plus optional scripts, references, and assets: incident-response/ SKILL.md # Required: instructions + metadata references/ # Optional: additional documentation severity-levels.md escalation-policy.md scripts/ # Optional: executable code page-oncall.sh assets/ # Optional: templates, diagrams, data files The SKILL.md file has YAML frontmatter with a name and description (so agents know when the skill is relevant), followed by markdown instructions that tell the agent how to perform the task. The format is intentionally simple: self-documenting, extensible, and portable. What makes this design practical is progressive disclosure. The spec is built around the idea that agents should not load everything at once. It works in three stages: Discovery: At startup, agents load only the name and description of each available skill, just enough to know when it might be relevant. Activation: When a task matches a skill's description, the agent reads the full SKILL.md instructions into context. Execution: The agent follows the instructions, optionally loading referenced files or executing bundled scripts as needed. This keeps agents fast while giving them access to deep context on demand. The format is well-designed and widely adopted, but if you want to use skills from your own agents, there is a gap between the spec and a working implementation. The Agent Skills SDK Conceptually, a skill is more than a folder. It is a unit of expertise: a name, a description, a body of instructions, and a set of supporting resources. The file layout is one way to represent that, but there is nothing about the concept that requires a filesystem. The Agent Skills SDK is an open-source Python library built around that idea, treating skills as abstract units of expertise that can be stored anywhere and consumed by any agent framework. It does this by addressing two challenges that come up when you try to use the format from your own agents. The first is where skills live. The spec defines skills as folders on disk, and the tools that support the format today all assume skills are local files. Files are inherently portable, and that is one of the format's strengths. But in the real world, not every team can or wants to serve skills from the filesystem. Maybe your team keeps them in an S3 bucket. Maybe they are in Azure Blob Storage behind your CDN. Maybe they live in a database alongside the rest of your application data. At the moment, if your skills are not on the local filesystem, you are on your own. The SDK changes where skills are served from, not how they are authored. The content and format stay the same regardless of the storage backend, so skills remain portable across providers. The second is how agents consume them. The spec defines the progressive disclosure pattern but actually implementing it in your agent requires real work. You need to figure out how to validate skills against the spec, generate a catalog for the system prompt, expose the right tools for on-demand content retrieval, and handle the back-and-forth of the agent requesting metadata, then the body, then individual references or scripts. That is a lot of plumbing regardless of where the skills are stored, and the work multiplies if you want to support more than one agent framework. The SDK solves both by separating where skills come from (providers) from how agents use them (integrations), so you can mix and match freely. Load skills from the filesystem today, move them to an HTTP server tomorrow, swap in a custom database provider next month, and your agent code does not change at all. How the SDK works The SDK is a set of Python packages organized around two ideas: storage-agnostic providers and progressive disclosure. The provider abstraction means your skills can live anywhere. The SDK ships with providers for the local filesystem and static HTTP servers, but the SkillProvider interface is simple enough that you can write your own in a few methods. A Cosmos DB provider, a Git provider, a SharePoint provider, whatever makes sense for your team. The rest of the SDK does not care where the data comes from. On top of that, the SDK implements the progressive disclosure pattern from the spec as a set of tools that any LLM agent can use. At startup, the SDK generates a skills catalog containing each skill's name and description. Your agent injects this catalog into its system prompt so it knows what is available. Then, during a conversation, the agent calls tools to retrieve content on demand, following the same discovery-activation-execution flow the spec describes. Here is the flow in practice: You register skills from any source (local files, an HTTP server, your own database). The SDK generates a catalog and tool usage instructions, which you inject into the system prompt. The agent calls tools to retrieve content on demand. This matters because context windows are finite. An incident response skill might have a main body, three reference documents, two scripts, and a flowchart. The agent should not load all of that upfront. It should read the body first, then pull the escalation policy only when the conversation actually gets to escalation. A quick example Here is what it looks like in practice. Start by loading a skill from the filesystem: from pathlib import Path from agentskills_core import SkillRegistry from agentskills_fs import LocalFileSystemSkillProvider provider = LocalFileSystemSkillProvider(Path("my-skills")) registry = SkillRegistry() await registry.register("incident-response", provider) Now wire it into a LangChain agent: from langchain.agents import create_agent from agentskills_langchain import get_tools, get_tools_usage_instructions tools = get_tools(registry) skills_catalog = await registry.get_skills_catalog(format="xml") tool_usage_instructions = get_tools_usage_instructions() system_prompt = ( "You are an SRE assistant. Use the available skill tools to look up " "incident response procedures, severity definitions, and escalation " "policies. Always cite which reference document you used.\n\n" f"{skills_catalog}\n\n" f"{tool_usage_instructions}" ) agent = create_agent( llm, tools, system_prompt=system_prompt, ) That is it. The agent now knows what skills are available and has tools to fetch their content. When a user asks "How do I handle a SEV1 incident?", the agent will call get_skill_body to read the instructions, then get_skill_reference to pull the severity levels document, all without you writing any of that retrieval logic. The same pattern works with Microsoft Agent Framework: from agentskills_agentframework import get_tools, get_tools_usage_instructions tools = get_tools(registry) skills_catalog = await registry.get_skills_catalog(format="xml") tool_usage_instructions = get_tools_usage_instructions() system_prompt = ( "You are an SRE assistant. Use the available skill tools to look up " "incident response procedures, severity definitions, and escalation " "policies. Always cite which reference document you used.\n\n" f"{skills_catalog}\n\n" f"{tool_usage_instructions}" ) agent = Agent( client=client, instructions=system_prompt, tools=tools, ) What is in the SDK The SDK is split into small, composable packages so you only install what you need: agentskills-core handles registration, validation, the skills catalog, and the progressive disclosure API. It also defines the SkillProvider interface that all providers implement. agentskills-fs and agentskills-http are the two built-in providers. The filesystem provider loads skills from local directories. The HTTP provider loads them from any static file host: S3, Azure Blob Storage, GitHub Pages, a CDN, or anything that serves files over HTTP. agentskills-langchain and agentskills-agentframework generate framework-native tools and tool usage instructions from a skill registry. agentskills-mcp-server spins up an MCP server that exposes skill tool access and usage as tools and resources, so any MCP-compatible client can use them. Because providers and integrations are separate packages, you can combine them however you want. Use the filesystem provider during development, switch to the HTTP provider in production, or write a custom provider that reads skills from your own database. The integration layer does not need to know or care. Where to go from here The full source, working examples, and detailed API docs are on GitHub: github.com/pratikxpanda/agentskills-sdk The repo includes end-to-end examples for both LangChain and Microsoft Agent Framework, covering filesystem providers, HTTP providers, and MCP. There is also a sample incident-response skill you can use to try things out. A proposal to contribute this SDK to the official agentskills repository has been submitted. If you find it useful, feel free to show your support on the GitHub issue. To learn more about the Agent Skills format itself: What are skills? covers the format and why it matters. Specification is the complete format reference for SKILL.md files. Integrate skills explains how to add skills support to your agent. Example skills on GitHub are a good starting point for writing your own. The SDK is MIT licensed and contributions are welcome. If you have questions or ideas, post a question here or open an issue on the repo.