Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,103 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container
}
}

var containerAppMcpResourceName = 'ca-mcp-${solutionPrefix}'
module containerAppMcp 'br/public:avm/res/app/container-app:0.18.1' = if (containerAppEnabled) {
name: take('avm.res.app.container-app.${containerAppMcpResourceName}', 64)
params: {
name: containerAppMcpResourceName
tags: containerAppConfiguration.?tags ?? tags
location: containerAppConfiguration.?location ?? solutionLocation
enableTelemetry: enableTelemetry
environmentResourceId: containerAppConfiguration.?environmentResourceId ?? containerAppEnvironment.outputs.resourceId
managedIdentities: {
systemAssigned: true
userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId]
}
ingressTargetPort: containerAppConfiguration.?ingressTargetPort ?? 8000
ingressExternal: true
activeRevisionsMode: 'Single'
corsPolicy: {
allowedOrigins: [
'https://${webSiteName}.azurewebsites.net'
'http://${webSiteName}.azurewebsites.net'
]
}
// WAF aligned configuration for Scalability
scaleSettings: {
maxReplicas: containerAppConfiguration.?maxReplicas ?? 1
minReplicas: containerAppConfiguration.?minReplicas ?? 1
rules: [
{
name: 'http-scaler'
http: {
metadata: {
concurrentRequests: containerAppConfiguration.?concurrentRequests ?? '100'
}
}
}
]
}
containers: [
{
name: 'mcp'
image: 'macaemcpacrdk.azurecr.io/macae-mac-app:t7' //'${containerAppConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${containerAppConfiguration.?containerImageName ?? 'macaebackend'}:${containerAppConfiguration.?containerImageTag ?? 'latest'}'
resources: {
//TODO: Make cpu and memory parameterized
cpu: containerAppConfiguration.?containerCpu ?? '2.0'
memory: containerAppConfiguration.?containerMemory ?? '4.0Gi'
}
env: [
{
name: 'MCP_HOST'
value: '0.0.0.0'
}
{
name: 'MCP_PORT'
value: '9000'
}
{
name: 'MCP_DEBUG'
value: 'false'
}
{
name: 'MCP_SERVER_NAME'
value: 'MACAE MCP Server'
}
{
name: 'MCP_ENABLE_AUTH'
value: 'true'
}
{
name: 'AZURE_TENANT_ID'
value: tenant().tenantId
}
{
name: 'AZURE_CLIENT_ID'
value: userAssignedIdentity!.outputs.clientId
}
{
name: 'AZURE_JWKS_URI'
value: 'https://login.microsoftonline.com/${tenant().tenantId}/discovery/v2.0/keys'
}
{
name: 'AZURE_ISSUER'
value: 'https://sts.windows.net/${tenant().tenantId}/'
}
{
name: 'AZURE_AUDIENCE'
value: 'api://${userAssignedIdentity!.outputs.clientId}'
}
{
name: 'DATASET_PATH'
value: './datasets'
}
]
}
]
}
}

var webServerFarmEnabled = webServerFarmConfiguration.?enabled ?? true
var webServerFarmResourceName = webServerFarmConfiguration.?name ?? 'asp-${solutionPrefix}'

Expand Down
43 changes: 27 additions & 16 deletions src/mcp_server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
FROM python:3.11-slim

# Set working directory
FROM mcr.microsoft.com/devcontainers/python:3.11-bullseye AS base
WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
FROM base AS builder

# Copy uv binaries from astral-sh image
COPY --from=ghcr.io/astral-sh/uv:0.6.3 /uv /uvx /bin/
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy

# Copy lock and project files first for caching
COPY uv.lock pyproject.toml /app/

# Install dependencies (frozen, no dev) using uv
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev

# Copy requirements first for better caching
COPY requirements.txt .
# Copy application code and install project dependencies
COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv uv sync --frozen --no-dev

# Final stage
FROM base

WORKDIR /app
COPY --from=builder /app /app
COPY --from=builder /bin/uv /bin/uv

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
####
# Copy the application
COPY . .
# Set PATH to use venv created by uv
ENV PATH="/app/.venv/bin:$PATH"

# Create non-root user
RUN useradd --create-home --shell /bin/bash app && chown -R app:app /app
Expand All @@ -28,5 +39,5 @@ EXPOSE 9000
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:9000/health || exit 1

# Default command
CMD ["python", "mcp_server.py"]
# Run your main script
CMD ["uv", "run", "python", "mcp_server.py", "--transport", "http", "--host", "0.0.0.0", "--port", "9000"]
7 changes: 6 additions & 1 deletion src/mcp_server/services/data_tool_service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import logging
from typing import List
from ..core.factory import MCPToolBase, Domain
from core.factory import MCPToolBase, Domain

ALLOWED_FILES = [
"competitor_Pricing_Analysis.csv",
Expand Down Expand Up @@ -88,3 +88,8 @@ def show_tables() -> List[str]:
"No allowed CSV tables found in '%s' directory.", self.dataset_path
)
return found_tables

@property
def tool_count(self) -> int:
"""Return the number of tools provided by this service."""
return 2 # data_provider and show_tables
Loading