Spensara Spensara Knowledge Base & Documentation Repository

Repository Docs & Knowledge Base

Consolidated Spensara documentation repository (722 Markdown & architecture documents in ../repository)
Built Word Documents (.docx): Spensara Overview (.docx) Capability Assessment (.docx) Brink POS Ingestion Analysis (.docx) The Borg Ingestion Architecture (.docx)

Implementation Specs (157)

Detailed engineering and feature implementation specifications.
implementation-specs/specs/AnomalyDetection/TASK1.4.md 6,723 bytes · Updated Oct 23, 2026 10:44 AM EDT
Raw File

TASK 1.4: Configure MCP Client for MySQL Data Access

Summary

Set up the Model Context Protocol (MCP) client using the official MCP C# SDK to connect to the benborla/mcp-server-mysql server. The MCP tools will be retrieved and passed directly to the agent as AITool objects, following the Microsoft Agent Framework integration pattern.

Dependencies

  • None (can be done in parallel with TASK 1.1-1.3)

Architecture

The Microsoft Agent Framework integrates with MCP via the official MCP C# SDK. The pattern is:

  1. Create an McpClient via McpClientFactory.CreateAsync() with a StdioClientTransport
  2. Call mcpClient.ListToolsAsync() to get available tools
  3. Cast tools to AITool and pass them to the agent

No custom IMcpClient wrapper is needed - the SDK provides everything.

Files to Modify

1. backend/Directory.Packages.props

Add the MCP C# SDK package:

xml
<PackageVersion Include="ModelContextProtocol" Version="0.2.0-preview.1" />
Note: Check for the latest version at https://www.nuget.org/packages/ModelContextProtocol

2. backend/Kds.Ai.AnomalyDetector/Kds.Ai.AnomalyDetector.csproj

Add package reference:

xml
<ItemGroup>
  <PackageReference Include="ModelContextProtocol" />
</ItemGroup>

Files to Create

3. backend/Kds.Ai.AnomalyDetector/Settings/McpMySqlSettings.cs

csharp
using System.ComponentModel.DataAnnotations;

namespace Kds.Ai.AnomalyDetector.Settings;

public sealed class McpMySqlSettings
{
    /// <summary>
    /// Command to run the MCP server (e.g., "npx")
    /// </summary>
    [Required]
    public required string Command { get; init; }
    
    /// <summary>
    /// Arguments for the MCP server command (e.g., ["-y", "benborla-mcp-server-mysql"])
    /// </summary>
    [Required]
    public required string[] Arguments { get; init; }
    
    /// <summary>
    /// Environment variables to pass to the MCP server process
    /// (MySQL connection details: MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASS, MYSQL_DB)
    /// </summary>
    public Dictionary<string, string> EnvironmentVariables { get; init; } = new();
}

4. backend/Kds.Ai.AnomalyDetector/Mcp/McpToolProvider.cs

Factory that creates an MCP client and retrieves tools:

csharp
using Kds.Ai.AnomalyDetector.Settings;
using Microsoft.Extensions.AI;
using ModelContextProtocol.Client;

namespace Kds.Ai.AnomalyDetector.Mcp;

/// <summary>
/// Manages the MCP client lifecycle and provides tools from the MySQL MCP server.
/// </summary>
public sealed class McpToolProvider(McpMySqlSettings settings) : IAsyncDisposable
{
    private McpClient? _client;

    /// <summary>
    /// Creates the MCP client and connects to the MySQL MCP server.
    /// </summary>
    public async Task<McpClient> GetClientAsync(CancellationToken ct = default)
    {
        if (_client is not null)
        {
            return _client;
        }

        var transport = new StdioClientTransport(new StdioClientTransportOptions
        {
            Name = "mysql-mcp-server",
            Command = settings.Command,
            Arguments = settings.Arguments,
            EnvironmentVariables = settings.EnvironmentVariables
        });

        _client = await McpClient.CreateAsync(transport, cancellationToken: ct);
        return _client;
    }

    /// <summary>
    /// Retrieves available tools from the MCP server as AITool objects
    /// that can be passed directly to an agent.
    /// </summary>
    public async Task<IList<AITool>> GetToolsAsync(CancellationToken ct = default)
    {
        var client = await GetClientAsync(ct);
        var tools = await client.ListToolsAsync(cancellationToken: ct);
        return [.. tools.Cast<AITool>()];
    }

    public async ValueTask DisposeAsync()
    {
        if (_client is not null)
        {
            await _client.DisposeAsync();
            _client = null;
        }
    }
}
Note: In TASK 6.1, McpToolProvider will be refactored to internal sealed and an IMcpToolProvider interface will be extracted for testability.

5. backend/Kds.Ai.AnomalyDetector/DependencyInjectionExtensions.cs

csharp
using Kds.Ai.AnomalyDetector.Mcp;
using Kds.Ai.AnomalyDetector.Settings;
using Kds.Ai.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;

namespace Kds.Ai.AnomalyDetector;

public static class DependencyInjectionExtensions
{
    public static IHostApplicationBuilder AddAnomalyDetectorModule(this IHostApplicationBuilder builder)
    {
        builder.AddOptions<McpMySqlSettings>();

        builder.Services.AddSingleton<McpToolProvider>(provider =>
        {
            var settings = provider.GetRequiredService<IOptions<McpMySqlSettings>>();
            return new McpToolProvider(settings.Value);
        });

        return builder;
    }
}
Note: In TASK 6.1, this registration will change to AddSingleton<IMcpToolProvider, McpToolProvider> when the interface is extracted.

Configuration Example

In appsettings.json or environment configuration:

json
{
  "McpMySqlSettings": {
    "Command": "npx",
    "Arguments": ["-y", "benborla-mcp-server-mysql"],
    "EnvironmentVariables": {
      "MYSQL_HOST": "localhost",
      "MYSQL_PORT": "3306",
      "MYSQL_USER": "root",
      "MYSQL_PASS": "password",
      "MYSQL_DB": "kdsdev"
    }
  }
}

Usage Pattern (Preview)

When building the agent (in later tasks), the MCP tools will be passed directly:

csharp
var mcpToolProvider = serviceProvider.GetRequiredService<McpToolProvider>();
var mcpTools = await mcpToolProvider.GetToolsAsync(ct);

// Pass MCP tools to the agent - the agent can call mysql_query via function calling
AIAgent agent = chatClient.AsAIAgent(
    instructions: systemPrompt,
    tools: [.. mcpTools]);

Acceptance Criteria

  • [ ] ModelContextProtocol package added to Directory.Packages.props
  • [ ] Package reference added to Kds.Ai.AnomalyDetector.csproj
  • [ ] McpMySqlSettings settings class created
  • [ ] McpToolProvider created using official MCP C# SDK patterns
  • [ ] DI extensions created with provider registration
  • [ ] Solution builds without errors

Notes

  • The benborla/mcp-server-mysql server exposes a mysql_query tool that accepts SQL queries
  • MCP tools are automatically converted to AITool objects compatible with Microsoft Agent Framework
  • The MCP client connects via stdio transport (launches server as subprocess)
  • McpToolProvider manages the client lifecycle and should be disposed properly
  • No custom MCP client wrapper is needed - use the official SDK directly