Octopus — MCP
Packaging and Publishing
Package your MCP tool server as a Docker image for reproducible deployment. This page covers the Dockerfile, Kubernetes health probes, versioning strategy, and how to submit your server to the BizFirstAI community registry.
Dockerfile
# ── Build stage ────────────────────────────────────────────────
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY *.csproj ./
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish --no-restore
# ── Runtime stage ───────────────────────────────────────────────
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
# Non-root user for security
RUN addgroup --system mcp && adduser --system --ingroup mcp mcp
USER mcp
COPY --from=build /app/publish .
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Production
ENTRYPOINT ["dotnet", "MyCompany.Octopus.ZendeskMcpServer.dll"]
# Build and tag
docker build -t mycompany/zendesk-mcp-server:1.2.0 .
docker build -t mycompany/zendesk-mcp-server:latest .
# Run locally for testing
docker run -p 8080:8080 \
-e Zendesk__Subdomain=mycompany \
-e Zendesk__AdminEmail=admin@mycompany.com \
-e Zendesk__CredentialId=50 \
-e Auth__Authority=https://... \
-e Auth__Audience=api://... \
mycompany/zendesk-mcp-server:1.2.0
Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: zendesk-mcp-server
namespace: octopus-tools
spec:
replicas: 2
selector:
matchLabels:
app: zendesk-mcp-server
template:
metadata:
labels:
app: zendesk-mcp-server
spec:
containers:
- name: server
image: mycompany/zendesk-mcp-server:1.2.0
ports:
- containerPort: 8080
env:
- name: Zendesk__Subdomain
value: "mycompany"
- name: Zendesk__AdminEmail
value: "admin@mycompany.com"
- name: Zendesk__ApiKey
valueFrom:
secretKeyRef:
name: zendesk-mcp-secrets
key: api-key
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: zendesk-mcp-server
namespace: octopus-tools
spec:
selector:
app: zendesk-mcp-server
ports:
- port: 443
targetPort: 8080
type: ClusterIP
Versioning Strategy
| Change Type | Version Bump | Examples |
|---|---|---|
| New tool added | Minor (1.x.0) | Add zendesk_get_user tool |
| Tool description improved | Patch (1.x.y) | Better wording in a description field |
| New optional parameter added | Minor (1.x.0) | Add optional max_results to search tool |
| Required parameter added | Major (x.0.0) | Existing callers will fail — breaking change |
| Tool renamed or removed | Major (x.0.0) | Octopus cached the old name; agents break |
| Response shape changed | Major (x.0.0) | LLM-parsed fields disappear or change type |
Tool renames break agents. If you rename a tool between deployments, any Octopus agent that cached the old name will send calls to a non-existent endpoint until the agent config is refreshed. Use additive changes (new tools, new optional params) to avoid breaking existing agents.
Health Check Implementation
// Add deep health check — verify external connectivity
app.MapGet("/health", async (IZendeskClient zendesk) =>
{
try
{
// Cheap connectivity check — e.g. list 1 ticket
var healthy = await zendesk.PingAsync();
return healthy
? Results.Ok(new { status = "ok", version = "1.2.0" })
: Results.Json(new { status = "degraded",
reason = "Zendesk API unreachable" },
statusCode: 503);
}
catch (Exception ex)
{
return Results.Json(new { status = "unhealthy", error = ex.Message },
statusCode: 503);
}
});
Publishing to the Community Registry
- Tag your Docker image with a stable, versioned tag (e.g.
mycompany/zendesk-mcp-server:1.2.0) - Push to Docker Hub or a public container registry
- Publish a GitHub repository with:
README.md— tools list, configuration reference, getting startedSECURITY.md— credential handling, tenant isolation descriptiondocker-compose.yml— local test setup
- Open a Community MCP Server Submission thread on community.bizfirstai.com with:
- Server name and purpose
- Tool list (names and one-line descriptions)
- Docker image reference
- Link to source repository
- The community team verifies the MCP contract and SECURITY.md, then adds your server to the registry listing.
Production Deployment Checklist
| # | Item |
|---|---|
| 1 | HTTPS enforced — no plain HTTP accepted |
| 2 | Bearer token validated on every request (no public endpoints except /health) |
| 3 | Secrets loaded from environment variables or secret manager — not baked into image |
| 4 | Non-root container user |
| 5 | Liveness and readiness probes configured |
| 6 | Resource limits set (memory + CPU) |
| 7 | Structured JSON logging enabled |
| 8 | All tool handlers return structured error JSON — no unhandled exceptions |
| 9 | Tenant ID read from X-Octopus-Tenant-Id header and applied to all data access |
| 10 | Integration tests pass against the staging external service |