Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Evaluating Agents: Trajectory, Tool Call Accuracy, Task Adherence and Production Monitoring
To evaluate an agent you measure the outcome, the path it took (trajectory) and the cost separately, and report a success rate by running the same scenario N times with fake tools; LLM-as-judge comes only after code checks, with its reasoning read. We look at our own trajectory recording, deterministic scenarios, real results of Microsoft.Extensions.AI.Evaluation's agent evaluators with local models, and the path from OpenTelemetry spans to a regression set.
MCP and Agent Security: Tool Poisoning, Confused Deputy, Least Privilege and Sandboxing
MCP and agent security rests not on the model behaving well but on controls independent of it: pinning untrusted tool definitions, accepting tokens only for your own server and never forwarding them, binding destructive tools to a separate scope and approval, and restricting network egress. With real output we cover the spec's security guidance, per-tool authorization with [Authorize], an audit log that also captures denied attempts, and a stdio server running in a container without a network.
Writing an MCP Client: McpClient, Connecting Tools to IChatClient and Agents, Elicitation
In C# you create an MCP client with McpClient.CreateAsync over a stdio or HTTP transport; since the McpClientTool returned by ListToolsAsync is an AIFunction, it can go straight into IChatClient and a MAF agent. We separate same-named tools from two servers with prefixes, pin tool definitions with fingerprints, and see real tool calls with a local qwen3:4b and how the SDK handles the server's confirmation request through MRTR rounds.
Building an MCP Server in TypeScript: Zod Schemas, Tool/Resource Registration and Node.js
For an MCP server in TypeScript you pick the v2 SDK (@modelcontextprotocol/server 2.4.0), which supports 2026-07-28, register tools with Zod 4 schemas and serve them over stdio and Streamable HTTP with serveStdio and createMcpHandler. Comparing the same Bookstore server with its C# version, we see with real output how schemas give different answers to the same input, the Zod 3 incompatibility, distribution with npx and the supply chain risk.
Remote MCP Servers in ASP.NET Core: Streamable HTTP, Stateless Mode, State Handles and Authorization
In ASP.NET Core you build a remote MCP server with WithHttpTransport and MapMcp, run it in stateless mode and protect it as an OAuth resource server: tokens must be issued for this server, and state handles must be bound to the user. With curl output we look at protected resource metadata, the audience error, the cost of statelessness with two instances, asking for confirmation via MRTR with a signed requestState, and Mcp-Method/Mcp-Name header validation.
Building an MCP Server in C#: ModelContextProtocol SDK 2.x, [McpServerTool] and stdio
You build an MCP server in C# with the ModelContextProtocol 2.x package, the Generic Host and the [McpServerTool] attributes; on the stdio transport, logs must go to stderr. We build the Bookstore tools with services from DI, structured output, resources and prompts, test them with MCP Inspector, and see with real output how polluting stdout turns into a one-minute timeout and how culture settings corrupt tool output.
What Is the Model Context Protocol? Hosts, Clients, Servers and the 2026-07-28 Spec
MCP is a JSON-RPC based protocol that lets you write tools and data sources once as a server and connect them to any AI application through a standard client. We watch the wire with hand-written JSON messages to see the host, client and server roles, the tools/resources/prompts primitives, the stdio and Streamable HTTP transports, and the 2026-07-28 revision that removed the handshake.
Human-in-the-Loop: Tool Approval, Checkpoints and Long-Running Agents
We put write tools behind approval with ApprovalRequiredAIFunction and, when approval takes hours, write the agent session to JSON and resume in another process. Reasoned rejections, an attempt to change the argument in the approval response (approval-response binding) and resuming a workflow from a checkpoint with RequestPort, all with real runs.
Multi-Agent Systems: Handoff, Group Chat, Orchestration and A2A
Several agents bring specialization, isolation and parallelism, paid for with a token multiplier and coordination errors. We run MAF's sequential, concurrent, handoff, group chat and Magentic orchestrations on Bookstore, see a handoff where the specialist hands back without calling its tool and a group chat that won't end, with real output, and hand work to an agent in another service over A2A.
Agent Workflow Patterns: Prompt Chaining, Routing, Parallelization, Orchestrator-Workers and Evaluator-Optimizer
We run five workflow patterns on Bookstore: prompt chaining and orchestrator-workers in plain C#, routing, fan-out/fan-in and a writer-critic loop with MAF WorkflowBuilder. Real runs where a small model approves "must read" and the orchestrator blows the budget, code gates, and exposing a workflow as an agent with AsAIAgent.
Context Engineering: Managing an Agent's Context, Compaction and Memory
Context is a budget, and when it fills up it can be truncated without an error: qwen3:4b loaded with 4,096 tokens loses the budget stated at the start of a long session and makes up a number. Compacting old tool output with MAF's CompactionProvider, cross-session preference memory with an AIContextProvider and taking only a summary back from a sub-agent, with real token counts.
Designing Tools for Agents: Names, Descriptions, Schemas, Error Messages and Tool Count
We compare twelve CRUD tools that mirror the API with two task-focused tools on the same requests with qwen3:4b: thirteen times the tokens, a book that can't be found and an agent that adds the wrong book and says "added". Why a schema isn't validation, human-readable output, messages that explain empty results, name collisions and side-effecting tools.