Set-MCPServerConfig.ps1

[CmdletBinding()]
param(
    [string]$WorkspaceRoot = (Get-Location).Path,
    [string]$ConfigPath = (Join-Path $PSScriptRoot 'Config\config.json')
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function Test-CommandAvailable {
    param([Parameter(Mandatory = $true)][string]$Name)

    return $null -ne (Get-Command -Name $Name -ErrorAction SilentlyContinue)
}

function Ensure-RequiredTools {
    if (-not (Test-CommandAvailable -Name 'node')) {
        throw "Node.js is required but not found on PATH. Install Node LTS first: https://nodejs.org/"
    }

    if (-not (Test-CommandAvailable -Name 'npx')) {
        throw "npx is required but not found on PATH. Ensure Node.js is installed and on PATH."
    }

    if (-not (Test-CommandAvailable -Name 'uvx')) {
        throw "uvx is required but not found on PATH. Install uv: https://docs.astral.sh/uv/ or winget install --id=astral-sh.uv -e"
    }
}

function Get-ConfigObject {
    param([string]$Path)

    if (-not (Test-Path -LiteralPath $Path)) {
        return [ordered]@{
            schemaVersion = 1
            settings      = [ordered]@{
                agent = [ordered]@{
                    mcp = [ordered]@{
                        enabled = $true
                        servers = @()
                    }
                }
            }
        }
    }

    try {
        $raw = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop
        if ([string]::IsNullOrWhiteSpace($raw)) {
            return [ordered]@{
                schemaVersion = 1
                settings      = [ordered]@{
                    agent = [ordered]@{
                        mcp = [ordered]@{
                            enabled = $true
                            servers = @()
                        }
                    }
                }
            }
        }

        $obj = $raw | ConvertFrom-Json -Depth 100 -ErrorAction Stop
        return $obj
    }
    catch {
        throw "Unable to parse JSON in '$Path'. $($_.Exception.Message)"
    }
}

function Merge-Server {
    param(
        [Parameter(Mandatory = $true)]$Config,
        [Parameter(Mandatory = $true)][pscustomobject]$Server
    )

    $servers = @()
    if ($null -ne $Config.settings.agent.mcp.servers) {
        $servers = @($Config.settings.agent.mcp.servers)
    }

    $existing = @{}
    foreach ($item in $servers) {
        if ($null -eq $item) { continue }
        $name = [string]$item.name
        if (-not [string]::IsNullOrWhiteSpace($name)) {
            $existing[$name.ToLowerInvariant()] = $item
        }
    }

    $candidateName = [string]$Server.name
    $normalizedName = $candidateName.ToLowerInvariant()

    if ($existing.ContainsKey($normalizedName)) {
        $merged = $existing[$normalizedName]
        foreach ($prop in $Server.PSObject.Properties) {
            $merged | Add-Member -NotePropertyName $prop.Name -NotePropertyValue $prop.Value -Force
        }
        $servers = @(
            foreach ($item in $servers) {
                if ($null -eq $item) { continue }
                $name = [string]$item.name
                if (-not [string]::IsNullOrWhiteSpace($name) -and $name.Equals($candidateName, [System.StringComparison]::OrdinalIgnoreCase)) {
                    $merged
                }
                else {
                    $item
                }
            }
        )
    }
    else {
        $servers += $Server
    }

    $Config.settings.agent.mcp.enabled = $true
    $Config.settings.agent.mcp.servers = @($servers)
}

$WorkspaceRoot = [System.IO.Path]::GetFullPath($WorkspaceRoot)
if (-not (Test-Path -LiteralPath $WorkspaceRoot -PathType Container)) {
    throw "WorkspaceRoot '$WorkspaceRoot' does not exist."
}

Write-Host "Workspace root: $WorkspaceRoot" -ForegroundColor Cyan

Ensure-RequiredTools

$config = Get-ConfigObject -Path $ConfigPath

if (-not $config.settings) { $config.settings = [ordered]@{} }
if (-not $config.settings.agent) { $config.settings.agent = [ordered]@{} }
if (-not $config.settings.agent.mcp) { $config.settings.agent.mcp = [ordered]@{} }

$filesystemServer = [pscustomobject]@{
    name                  = 'filesystem'
    enabled               = $true
    transport             = 'Stdio'
    command               = 'npx'
    arguments             = @('-y', '@modelcontextprotocol/server-filesystem', $WorkspaceRoot)
    authMode              = 'None'
    namespacePrefix       = 'filesystem'
    allowedTools          = @(
        'read_text_file',
        'read_media_file',
        'read_multiple_files',
        'write_file',
        'edit_file',
        'create_directory',
        'list_directory',
        'list_directory_with_sizes',
        'directory_tree',
        'get_file_info',
        'list_allowed_directories',
        'delete_file',
        'search_files',
        'move_file'
    )
    requestTimeoutSeconds = 60
}

$ripgrepServer = [pscustomobject]@{
    name                  = 'ripgrep'
    enabled               = $true
    transport             = 'Stdio'
    command               = 'npx'
    arguments             = @('-y', 'ripgrep-mcp@latest')
    authMode              = 'None'
    namespacePrefix       = 'ripgrep'
    allowedTools          = @(
        'search',
        'advanced-search',
        'count-matches',
        'list-files',
        'list-file-types'
    )
    requestTimeoutSeconds = 60
}

$gitServer = [pscustomobject]@{
    name                  = 'git'
    enabled               = $true
    transport             = 'Stdio'
    command               = 'uvx'
    arguments             = @('mcp-server-git')
    authMode              = 'None'
    namespacePrefix       = 'git'
    allowedTools          = @(
        'git_init',
        'git_clone',
        'git_status',
        'git_clean',
        'git_add',
        'git_commit',
        'git_diff',
        'git_diff_unstaged',
        'git_diff_staged',
        'git_log',
        'git_show',
        'git_blame',
        'git_reflog',
        'git_branch',
        'git_checkout',
        'git_merge',
        'git_rebase',
        'git_cherry_pick',
        'git_remote',
        'git_fetch',
        'git_pull',
        'git_push',
        'git_tag',
        'git_stash',
        'git_reset',
        'git_worktree',
        'git_set_working_dir',
        'git_clear_working_dir',
        'git_wrapup_instructions'
    )
    requestTimeoutSeconds = 60
}

Merge-Server -Config $config -Server $filesystemServer
Merge-Server -Config $config -Server $ripgrepServer
Merge-Server -Config $config -Server $gitServer

$config.settings.agent.mcp.enabled = $true

$directory = Split-Path -Parent $ConfigPath
if (-not (Test-Path -LiteralPath $directory)) {
    New-Item -ItemType Directory -Path $directory -Force | Out-Null
}

$json = $config | ConvertTo-Json -Depth 100
[System.IO.File]::WriteAllText($ConfigPath, $json + [Environment]::NewLine)

Write-Host ""
Write-Host "Updated MCP config: $ConfigPath" -ForegroundColor Green
Write-Host "Servers configured:" -ForegroundColor Green
foreach ($server in @($config.settings.agent.mcp.servers)) {
    Write-Host " - $($server.name)" -ForegroundColor Green
}

Write-Host ""
Write-Host "Next step:" -ForegroundColor Yellow
Write-Host " 1) Open a fresh PowerShell session and import the module." -ForegroundColor Yellow
Write-Host " 2) Run: Test-TechAgentMcpConnection" -ForegroundColor Yellow
Write-Host " 3) If you want Tavily too, add that MCP server separately using Set-TechAgentMcpApiKey." -ForegroundColor Yellow

# SIG # Begin signature block
# MIIfAgYJKoZIhvcNAQcCoIIe8zCCHu8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCYU420BNi+ojrX
# OuENz+29/9EMTQBrcUDuWr/wqN78C6CCGEowggUMMIIC9KADAgECAhAR+U4xG7FH
# qkyqS9NIt7l5MA0GCSqGSIb3DQEBCwUAMB4xHDAaBgNVBAMME1ZBRFRFSyBDb2Rl
# IFNpZ25pbmcwHhcNMjUxMjE5MTk1NDIxWhcNMjYxMjE5MjAwNDIxWjAeMRwwGgYD
# VQQDDBNWQURURUsgQ29kZSBTaWduaW5nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
# MIICCgKCAgEA3pzzZIUEY92GDldMWuzvbLeivHOuMupgpwbezoG5v90KeuN03S5d
# nM/eom/PcIz08+fGZF04ueuCS6b48q1qFnylwg/C/TkcVRo0WFcKoFGT8yGxdfXi
# caHtapZfbSRh73r7qR7w0CioVveNBVgfMsTgE0WKcuwxemvIe/ptmkfzwAiw/IAC
# Ib0E0BjiX4PySbwWy/QKy/qMXYY19xpRItVTKNBtXzADUtzPzUcFqJU83vM2gZFs
# Or0MhPvM7xEVkOWZFBAWAubbMCJ3rmwyVv9keVDJChhCeLSz2XR11VGDOEA2OO90
# Y30WfY9aOI2sCfQcKMeJ9ypkHl0xORdhUwZ3Wz48d3yJDXGkduPm2vl05RvnA4T6
# 29HVZTmMdvP2475/8nLxCte9IB7TobAOGl6P1NuwplAMKM8qyZh62Br23vcx1fXZ
# TJlKCxBFx1nTa6VlIJk+UbM4ZPm954peB/fIqEacm8LkZ0cPwmLE5ckW7hfK4Trs
# o+RaudU1sKeA+FvpOWgsPccVRWcEYyGkwbyTB3xrIBXA+YckbANZ0XL7fv7x29hn
# gXbZipGu3DnTISiFB43V4MhNDKZYfbWdxze0SwLe8KzIaKnwlwRgvXDMwXgk99Mi
# EbYa3DvA/5ZWikLW9PxBFD7Vdr8ZiG/tRC9I2Y6fnb+PVoZKc/2xsW0CAwEAAaNG
# MEQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQW
# BBRfYLVE8caSc990rnrIHUjoB7X/KjANBgkqhkiG9w0BAQsFAAOCAgEAiGB2Wmk3
# QBtd1LcynmxHzmu+X4Y5DIpMMNC2ahsqZtPUVcGqmb5IFbVuAdQphL6PSrDjaAR8
# 1S8uTfUnMa119LmIb7di7TlH2F5K3530h5x8JMj5EErl0xmZyJtSg7BTiBA/UrMz
# 6WCf8wWIG2/4NbV6aAyFwIojfAcKoO8ng44Dal/oLGzLO3FDE5AWhcda/FbqVjSJ
# 1zMfiW8odd4LgbmoyEI024KkwOkkPyJQ2Ugn6HMqlFLazAmBBpyS7wxdaAGrl18n
# 6bS7QuAwCd9hitdMMitG8YyWL6tKeRSbuTP5E+ASbu0Ga8/fxRO5ZSQhO6/5ro1j
# PGe1/Kr49Uyuf9VSCZdNIZAyjjeVAoxmV0IfxQLKz6VOG0kGDYkFGskvllIpQbQg
# WLuPLJxoskJsoJllk7MjZJwrpr08+3FQnLkRuisjDOc3l4VxFUsUe4fnJhMUONXT
# Sk7vdspgxirNbLmXU4yYWdsizz3nMUR0zebUW29A+HYme16hzrMPOeyoQjy4I5XX
# 3wXAFdworfPEr/ozDFrdXKgbLwZopymKbBwv6wtT7+1zVhJXr+jGVQ1TWr6R+8ea
# tIOFnY7HqGaxe5XB7HzOwJKdj+bpHAfXft1vUoiKr16VajLigcYCG8MdwC3sngO3
# JDyv2V+YMfsYBmItMGBwvizlQ6557NbK95EwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqG
# SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4
# RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYg
# MjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphB
# cr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6p
# vF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHe
# HYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEd
# gkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjU
# jsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bR
# VFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeS
# LsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIV
# NSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL
# 6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2Zd
# SoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFU
# eEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/
# BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0j
# BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E
# PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEw
# DQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/
# T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQ
# E7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9r
# EVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y
# 1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gx
# dEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3t
# y9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcy
# tL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEB
# YTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud
# /v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiS
# uEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZP
# ubdcMIIG7TCCBNWgAwIBAgIQCE/cM09+RU7bww+P+ZIYNTANBgkqhkiG9w0BAQsF
# ADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV
# BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hB
# MjU2IDIwMjUgQ0ExMB4XDTI2MDgwNTAwMDAwMFoXDTM3MTEwNDIzNTk1OVowYzEL
# MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE
# aWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIwMjYg
# MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALZ7pvLJ/s1K+NSbTGWz
# /TjGMPh8CQ6RucZCLv5anHzWJjF/NWJrFIhy24fcpKXlgRiky4WAawDfU3YP0BMx
# t9l3Dm5oCG5Z69AqEN1kgHg2epx+l+lZBcmJCcN0ASURML5uFIS80sZsDwO3BSkU
# xDjLJhBI+qiZP3aixAC/qEGLjsBNlLol9VZ7pfGEXiMlneJIC5/YKuizVzNFKZZE
# eoy/0B8Zm+nzKBgSWG52lCO1w+nCg6XpCtklTJXeIg283hw7TmmsZXR+SMbjbrEO
# vZ3fP2VxIgeR28Y90ZStd3F9VuA5RVynb/whITPAo9b75Zr4Ta6Mj3URm26QZYMn
# /FnbuTegcoRcFEZ9FOqM5T6MTdtr/n74lIT/ug0eeOzmZ6QTFg33otX+bFRsIolv
# ykE1jive4PuESaT8zzVeFWDAMDtozNgLctkGD1ZjkEyZtJrLl5ya0m5doH/ScpaZ
# CZVl6pNUOCybMc/kxC6EAmSJY24L0yYKD1Nkddsnb/ItVKi/2nXpQNMu1PT5prW8
# 3vV8d67WowuUs0HdY4H8AMLGvdL/WHEj3ZnqMqAQQP9u3Ai9t+5eQ02GDwy0ODjd
# zi0xlp70W+ow63/0++YDEX1M0iwgUHwbrJvfpklkZQvw3+kv3vUPItdwroczk9ic
# flf55W1zOEKAcJVAIXpcMCU9AgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0G
# A1UdDgQWBBQUyWOKMC7USvtulPPm40B+9ezN4jAfBgNVHSMEGDAWgBTvb1NK6eQG
# fHrK4pBW9i/USezLTjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYB
# BQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
# cC5kaWdpY2VydC5jb20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2lj
# ZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEy
# NTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hB
# MjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB
# MA0GCSqGSIb3DQEBCwUAA4ICAQCNxTphHp1SCt+ZrAmAfn0oQLFr0mLywSLaDXQI
# ENoyKqxrFbJblzCVP/pkXmwXOdrOpWygLzlT12os5ipDCy35RBCg2UMeApEtrfGh
# z45F4Wt4WGdNdIbRWt3YTYJmpR+b7lr4d7Uwn+H600u4D7RnOGf8Wj4UNgAdZkfH
# hHv1mx9EVh71SJelcEN/oORSjXzdjfw1iZH9d8Nh/thn6hH23d+VsPAr6GAYyzSA
# 02nXD1nYLI7Ijmiv+xLCiYC41DSFYL3GhTiy0PxpawPtGRyaBVGzq+UiTfM8pD7K
# VyF5aQyWP4KhVGUUTnmm/RlYJoW3TiXA/+t0YcT2oRVBm3JETjajHug2AL+v5jht
# KVnd3D0rbHXEu27o+Q8p4sEWPMqKDB+qbceb6T/6WcwTwXmQ9lOCLLYcsQeSWmvK
# qzpAec9etE14jOQAzLKWdE3w/TCaKtLRaRT7LCkRYVnhA2D73FLje1O5b3HR5eHs
# 0NzU/+xX7NbEdcofy0W3Wdwd1XOqtlpg/JgwtKfZM5dqO94lbUveOiJBI+xZEbGR
# sMNbXmMREUTgu+Oca7Y73MPWcslIx2VhkSKSXjDbD6rgg39H5Mh7QfieAIjWagkJ
# Nt68Yfim6cjEzVSiLSeZfdkr5dtFPTW6jATlWJdYeeDRGCyatf8R1hSjzSvdN8yW
# QPT9gzGCBg4wggYKAgEBMDIwHjEcMBoGA1UEAwwTVkFEVEVLIENvZGUgU2lnbmlu
# ZwIQEflOMRuxR6pMqkvTSLe5eTANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3
# AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
# AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAhIBSvIVNp
# b88rdqiNKBiFLX9R5fmQy/Kf1XdAta0emDANBgkqhkiG9w0BAQEFAASCAgC6vzO4
# WwuPnlLYrscFXBiVO0rhLfpoDTuzF2hEVzW+0+rSyj4FCGYyao9x+CE5tBX9Kvrp
# +p8ok+enb3EBdni2/EQbaAY+PQTqGB7JwU3VXetlVAOKF8CWcdJ39BH5pcAOicY9
# R7LiLTl8/VHogcaCLSX5TARssbJLsnxeLNRRhhP20y/14dueNU1LTHVCXDREHTnF
# d6XKiTf2KybRuZtmG7OG+AM92ILH53YmxrLqWGqydgWWyeHiIlrXxccCJCR4v6b6
# NroGUasw99q019GbLRlPz9g5Ysiix/uCCI/nMDEsLmdBpHfGTvBoQnonmtk2dx6b
# crxfwOUUZEvkh/jaaBJf0H6RvMEoOUI8wR07tbqIjVAiHxZpzgtPgbQ9cRX0a69L
# UtoJKt7n3QsMB6ONqERlp+lNto3+XsxMF25vKhZrt3Tr/ENAWi9yqmv6aoVwYtLo
# gaZbUD1HuufJAp3AZ0nN+WSx4CINafkMFZZpt/iT69p9jQLFsFRE5HXaXA9iVWSS
# fPuKtrCwrJ4CB+U8+jTxVGZlbwRmDmFb1gXp48+YzyjUsV9FW8K8GGjEt0K3oJpv
# 4LbBk6mBFe2yRSO9NPyKgcriaMguK9L1KZzd8qRDcyXTRGRt2o52VrGFshM0eF97
# UMS/KGHtCAh9qgImc+Jwjqp+AQMQkAd3k7W2QaGCAyYwggMiBgkqhkiG9w0BCQYx
# ggMTMIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcg
# UlNBNDA5NiBTSEEyNTYgMjAyNSBDQTECEAhP3DNPfkVO28MPj/mSGDUwDQYJYIZI
# AWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ
# BTEPFw0yNjA5MTcwMzIzMzRaMC8GCSqGSIb3DQEJBDEiBCBWnAfsxDQ44ddul5RP
# H0ZNUTU7NjdAZDOTaQuK8lQiOjANBgkqhkiG9w0BAQEFAASCAgBqXfy691bIBEBs
# qKU5kW24LZBwCJDCP7n+8dcFSE6Hf+Imx12b91KyZSHFTJU1hcYThQiQLAeK6dkq
# 29aSchPkqgxkdmwe/2PkhNuc3QWewlqjSFSs4M4X2v2jIzinbQp05E8UHFeuJEMv
# TMdHxAYWmHR5KyigqP22dmhDYiPS0mRKVkNTzl5nm6QQveJnHKuwA9EAGWRyd1aX
# wiZcKNdIiy9P4CikKfTxz3p/xHwe/JmH7JkbiFMQ7bi876uEUpoK0t8hOoiEAn2N
# vdcdAvkaR69wmJYiWl1f4othBGSggutgk3lpV3Cr22BIWhcOngXy2sSTdG/LU4HZ
# opR2BoGJECYYsh4eHxILbNBbRDhuF7O5iagAcXJBQuFERpMX7JBHEFcUzPJ3+pjR
# ybfX9HP3fW2MVUrLMZxqoi+o6R8NQgasl5yvPt3Xzt3mTlmskAdrIujvP949XFOz
# P3WeIESaB+6u6TJ2UblCZoTQJ3cRmZ6UzcE2dHgo+gCrXp0wp0GlAqqjwhAT11Ez
# 7yjXyQ4A6MBTr8p3/kxxPNJ2pd1/rdDhBpOJwN/XavQyPViNs9vu0IfwCy9+uFrC
# PVbK8evXEub97jYmi5STnYCqOP1JwkJMdoeviOSisxB0tAKF6b+4+AQqc4DHHknZ
# N4XNZS0bXG6P5Li3RpGaFORFcKS4Dg==
# SIG # End signature block