This project is to create .NET9/MCP SDK/SK project MCP server for Atera API ticket management.
See also C:\Work\Projects\Fiverr\AteraMcpServer\Clients-project-overview-and-acceptance-criteria.md and C:\Work\Projects\Fiverr\AteraMcpServer\Python-Reference-Code-Analysis.md
Client provided a Python project for the same purpose and it can found and used for reference here: C:\Work\Projects\Fiverr\Python-reference-atera-mcp-server\
Based on analysis of the Python reference code at C:\Work\Projects\Fiverr\Python-reference-atera-mcp-server\:
- Base URL:
https://app.atera.com - Endpoint:
/api/v3/agents - Method: GET
- Authentication: API Key in
X-API-KEYheader
- Optional query params:
page: Page number for pagination (default: 1)itemsInPage: Items per page (default: 100)
{
"items": [
{
"agentID": "integer",
"customerID": "integer",
"customerName": "string",
"machineID": "string",
"machineName": "string",
"deviceType": "string",
"domain": "string",
"onlineStatus": "boolean",
"lastRebootTime": "datetime",
"lastSeenDateTime": "datetime",
"operatingSystem": "string",
"ipAddress": "string",
"externalIP": "string",
"snmpEnabled": "boolean",
"monitoringThreshold": "integer"
}
],
"itemsCount": "integer",
"totalItems": "integer"
}Essential fields to map in our C# domain model:
agentID: Unique identifier for the agentcustomerID: Associated customer IDcustomerName: Customer business namemachineName: Name of the monitored machineonlineStatus: Current connection statuslastRebootTime: Last system restartoperatingSystem: OS detailsipAddress: Internal IPexternalIP: Public IP
This analysis will inform our C# domain model design and API integration layer implementation.C:\Work\Projects\Fiverr\Python-reference-atera-mcp-server. But we should not copy any code or structures from that Python project blindly, as we will follow Clean Architecture, Rich Domain Model, SOLID, and TDD/ATDD.
This offer covers the Pro Tier deliverables for your Atera MCP Server, with a clear division of responsibilities:
My Deliverables (Pro Tier): Delivery of a complete C# MCP Server, including: • 19 fully tested C# MCP Tools (11 GET, 8 mutation) for the Atera API. • 8 MindsDB Skills configured for your database queries. • A comprehensive test suite (benchmarked against the complexity of the original 268 paths) to ensure high reliability. • A CI/CD pipeline for deploying to two local environments.
Steps:
- Create C# solution with Clean Architecture (Domain, API, Data Access layers)
- Integrate Semantic Kernel and Atera API client with secure credential storage
- Implement
GetAgentListMCP tool with unit tests - Configure CI/CD pipeline (GitHub Actions) for local Docker deployment
Acceptance Criteria:
✅ C# solution builds successfully with 100% test pass rate for initial tool
✅ GetAgentList returns valid data via MCP client (Claude Desktop test)
✅ CI/CD pipeline automatically deploys to your local environment on main branch push
Implemented:
✅ C# solution structure appears created with: Domain layer (AteraMcp) Data Access layer (AteraApi.DataAccess) Test projects (*.UnitTests, *.IntegrationTests) ✅ GetAgentList tool implementation started: Core tool class exists (AgentListTool.cs) Unit tests exist (AgentListToolFacts.cs) Integration tests exist (AteraMcpServerFacts.cs) ✅ API client integration: AteraApiGateway class exists with tests Authentication likely implemented (based on test files) Not Yet Implemented:
❌ CI/CD pipeline configuration (no GitHub Actions/Docker files visible) ❌ Complete test coverage (need to verify 100% pass rate) ❌ Final deployment verification (needs Claude Desktop test) The core foundation is in place with the solution structure and initial tool implementation. The remaining work focuses on pipeline setup and validation.
- Start server with
dotnet run --no-buildin test fixture. - Use JsonRpc.Client to send requests and assert responses.
- Tests run sequentially to avoid port conflicts.
Semantic Kernel (SK):
https://github.com/microsoft/semantic-kernel
MS MCP SDK:
https://github.com/modelcontextprotocol/csharp-sdk
Note: --no-build flag is required, otherwise connection errors may occur.
"AteraMcp": {
"command": "C:\\Users\\Grand\\.dotnet\\dotnet.exe",
"args": [
"run",
"--project",
"C:\\Work\\Projects\\Fiverr\\AteraMcpServer\\AteraMcp\\AteraMcp.csproj",
"--no-build"
],
"timeout": 60,
"transportType": "stdio",
"env": {
"DOTNET_ENVIRONMENT": "Development",
"Atera__ApiKey": "6a..."
},
"disabled": false
}- Create a
.envfile for local testing:
DOCKER_USERNAME=your_dockerhub_username
DOCKER_PASSWORD=your_dockerhub_password- For GitHub Actions, add repository secrets:
DOCKER_USERNAME: Your Docker Hub usernameDOCKER_PASSWORD: Your Docker Hub password/access token
To build and push Docker images from GitHub Actions, you need to set up secrets for your Docker Hub credentials:
- Navigate to your GitHub repository.
- Click on Settings.
- In the left sidebar, click on Secrets and variables > Actions.
- Click New repository secret.
- Create the following secrets:
DOCKER_USERNAME: Your Docker Hub usernameDOCKER_PASSWORD: Your Docker Hub password or access token
These secrets will be used by the GitHub Actions workflow to authenticate with Docker Hub.
The CI/CD test scripts (test-ci-cd.sh and test-ci-cd.ps1) generate detailed logs in the Logs/ directory. Here’s how to effectively read them using PowerShell.
Basic Command:
The standard command to view a file's content is Get-Content:
Get-Content .\Logs\test-ci-cd-YYYYMMDD-HHMMSS.logGotchas and Best Practices:
-
Slow on Large Files: The test scripts can generate very large log files. Running
Get-Contenton a large file can be slow and make it seem like the command is stuck. To quickly check the most recent activity, use the-Tailparameter to view the last N lines.# Shows the last 50 lines of the log, which is much faster Get-Content .\Logs\<log-file-name>.log -Tail 50
-
Real-time Feedback: The PowerShell script now uses
Tee-Objectto show command output in the console in real-time while also writing it to the log file. This is crucial for monitoring the progress of long-running commands (likedotnet testordocker build) and confirming they aren’t stuck. -
.gitignoreand Tooling: The project's.gitignorefile contains the rule*.log. This is a best practice, but it can prevent some IDE tools or automated agents from accessing log files. If a tool reports that it cannot access a log file, the workaround is to use a directGet-Contentcommand from a standard PowerShell terminal, as this is not subject to the same restrictions.
The AteraMcp server has been dockerized for easy deployment and CI/CD integration.
- Multi-stage build for optimal image size
- .NET 9 runtime optimized for console apps
- Proper layer caching for fast rebuilds
- Stdio communication for MCP protocol
docker build -t atera-mcp .# Basic run (stdio mode)
docker run -it atera-mcp
# With environment variables
docker run -it -e ATERA_API_KEY=your_key atera-mcp# Send JSON-RPC 2.0 command
echo '{"jsonrpc":"2.0","method":"mcp-version","id":1}' | docker run -i atera-mcpExample GitHub Actions workflow:
steps:
- name: Build Docker image
run: docker build -t atera-mcp .
- name: Run tests
run: |
echo '{"jsonrpc":"2.0","method":"echo","params":{"message":"test"},"id":1}' \
| docker run -i -e ATERA_API_KEY=${{ secrets.ATERA_API_KEY }} atera-mcp- Uses JSON-RPC 2.0 over stdio
- Environment variables for configuration
.dockerignoreoptimizes build context
Use the helper scripts to execute the full cross-environment test plan locally.
Run from Windows Terminal using the built-in wsl command (no need to open a separate WSL window):
# Windows PowerShell / CMD
wsl bash -c "cd /mnt/c/Work/Projects/Fiverr/AteraMcpServer && chmod +x scripts/test-ci-cd.sh && ./scripts/test-ci-cd.sh"Or, if you are already inside a WSL shell:
cd /mnt/c/Work/Projects/Fiverr/AteraMcpServer
chmod +x scripts/test-ci-cd.sh # first time only
./scripts/test-ci-cd.sh# From a Developer PowerShell prompt
# -ApiKey parameter is optional if the variable or .atera_apikey exists
.\scripts\test-ci-cd.ps1 -ApiKey 'your_api_key_here'The scripts perform:
- Debug & Release builds/tests via
build.sh/build.ps1. - CI pipeline emulation with
act. - Docker image build and in-container integration tests.
- (PowerShell) Native Windows Debug/Release test runs.
The project looks for the Atera API key in this order:
- Environment variable
Atera__ApiKey(preferred). .atera_apikeyplaintext file in the repository root (convenience only—git-ignored by default).
If neither is provided, integration tests that reach the Atera API will be skipped/fail gracefully.
The test script will automatically:
- Check for a locally cached
actin.bin/directory - Use system-wide
actif available - Install and cache
actlocally if missing
No manual installation is required - the script handles everything.
- .NET 9 SDK (version 9.0.301 or later)
- Docker Desktop with WSL 2 integration enabled
- Go to Settings -> Resources -> WSL Integration and enable for your distro
- GitHub CLI (optional, for CI simulation)
- PowerShell 7+ (for Windows scripts)
- Bash (for Linux/WSL scripts)
- MCP .NET SDK
-
Navigate to the project directory:
cd C:\Work\Projects\Fiverr\AteraMcpServer
-
Build the solution using .NET 9:
C:\Users\Grand\.dotnet\dotnet.exe build -
Run tests:
C:\Users\Grand\.dotnet\dotnet.exe test
- The project targets
net9.0and uses modern .NET features - The MCP SDK works perfectly with .NET 9 - all warnings about .NET 9 compatibility can be safely ignored
- Verified working with .NET 9.0.301 SDK
If you encounter build issues:
-
Clear NuGet caches:
dotnet nuget locals all --clear -
Restore packages:
dotnet restore
-
Rebuild completely:
dotnet clean dotnet build
-
API Key Configuration:
- For development, use user secrets:
dotnet user-secrets init dotnet user-secrets set "Atera:ApiKey" "your_api_key_here"
- For production, set environment variable:
Atera__ApiKey=your_api_key_here
- For development, use user secrets:
-
Configuration Files:
appsettings.json: Template configuration (checked into source control)appsettings.Development.json: Local overrides (gitignored)
API keys should be stored in user secrets (shared with AteraApi.DataAccess project):
{
"Atera": {
"ApiKey": "your_api_key_here"
}
}