TeamCity
About
MCP server for TeamCity, integrates with Claude Desktop and Cursor.
Details
- Author
- itcaat
- Categories
- Developer Tools, Community, Other
Jump to
Setup
Install TeamCity in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/itcaat/teamcity-mcp
Follow the installation instructions in the repository README, then restart your MCP client.
A comprehensive Model Context Protocol (MCP) server that exposes JetBrains TeamCity as structured AI-ready resources and tools for LLM agents and IDE plugins.
The TeamCity MCP server is designed to work seamlessly with AI-powered IDEs like Cursor. Here's how to configure it:
{ "mcpServers": { "teamcity": { "command": "docker", "args": [ "run", "--rm", "-i", "-e", "TC_URL", "-e", "TC_TOKEN", "itcaat/teamcity-mcp:latest", "--transport", "stdio" ], "env": { "TC_URL": "https://your-teamcity-server.com", "TC_TOKEN": "your-teamcity-api-token" } } } }
make build # This creates ./bin/teamcity-mcp and a symlink ./server
# Required export TC_URL="https://your-teamcity-server.com" # Optional (enables HMAC authentication) export SERVER_SECRET="your-hmac-secret-key" # Authentication export TC_TOKEN="your-teamcity-api-token"
./server # Server starts on :8123 by default
# Health check curl http://localhost:8123/healthz # MCP protocol test curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-hmac-secret-key" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{}}}'
Expected result: Health endpoint should return{"status":"ok"}and MCP endpoint should return initialization response.
- MCP Protocol Compliance: Full JSON-RPC 2.0 over HTTP/WebSocket support
- TeamCity Integration: Complete REST API integration with authentication
- Resource Access: Projects, build types, builds, agents, and artifacts
- Build Operations: Trigger, cancel, pin builds, set tags, download artifacts, search builds
- Advanced Search: Comprehensive build search with multiple filters (status, branch, user, dates, tags)
- Production Ready: Docker, Kubernetes, monitoring, caching, and comprehensive logging
- Environment-Based Configuration: No config files needed, everything via environment variables
- AI Time Awareness: Provides real current date/time to prevent AI models from using training data dates
export TC_URL=http://localhost:8111 export TC_TOKEN=dev-token-123 export SERVER_SECRET=dev-secret export LOG_LEVEL=debug export LOG_FORMAT=console ./server
export TC_URL=https://teamcity.company.com export TC_TOKEN=$TEAMCITY_API_TOKEN export SERVER_SECRET=$MCP_SERVER_SECRET export TLS_CERT=/etc/ssl/certs/teamcity-mcp.pem export TLS_KEY=/etc/ssl/private/teamcity-mcp.key export LOG_LEVEL=warn export CACHE_TTL=30s ./server
# Build Docker image make docker # Run with environment variables docker run -p 8123:8123 \ -e TC_URL=https://teamcity.company.com \ -e TC_TOKEN=your-token \ -e SERVER_SECRET=your-secret \ teamcity-mcp:latest
# Start with docker-compose docker-compose up -d # Check logs docker-compose logs -f teamcity-mcp
# Deploy with Helm helm install teamcity-mcp ./helm/teamcity-mcp \ --set teamcity.url=https://teamcity.company.com \ --set secrets.teamcityToken=your-token \ --set secrets.serverSecret=your-secret
apiVersion: v1 kind: Secret metadata: name: teamcity-mcp-secrets type: Opaque stringData: teamcity-token: "your-teamcity-token" server-secret: "your-server-secret" --- apiVersion: apps/v1 kind: Deployment metadata: name: teamcity-mcp spec: replicas: 1 selector: matchLabels: app: teamcity-mcp template: metadata: labels: app: teamcity-mcp spec: containers: - name: teamcity-mcp image: teamcity-mcp:latest ports: - containerPort: 8123 env: - name: TC_URL value: "https://teamcity.company.com" - name: TC_TOKEN valueFrom: secretKeyRef: name: teamcity-mcp-secrets key: teamcity-token - name: SERVER_SECRET valueFrom: secretKeyRef: name: teamcity-mcp-secrets key: server-secret
# Show environment variable help ./server --help # Show version ./server --version # Show command line usage ./server -h
Use the included verification script to test all functionality:
# Run all tests ./scripts/verify.sh # Available options: ./scripts/verify.sh help # Show help ./scripts/verify.sh start # Start server only ./scripts/verify.sh stop # Stop server only ./scripts/verify.sh clean # Clean up processes
# 1. Set environment variables export TC_URL=http://localhost:8111 export TC_TOKEN=test-token export SERVER_SECRET=test-secret # 2. Start server ./server & # 3. Test health curl http://localhost:8123/healthz # 4. Test MCP protocol curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer test-secret" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{}}}' # 5. Stop server pkill -f teamcity-mcp
# Install dependencies make deps # Run unit tests make test # Run integration tests make test-integration # Run load tests make test-load # Run linter make lint # Format code make format # Clean build artifacts make clean
Usemake helpto see all available commands:
# Basic commands make build # Build the binary make test # Run tests make clean # Clean build artifacts make deps # Download dependencies make lint # Run linters make format # Format code # Docker commands make docker # Build Docker image make docker-push # Push Docker image # Running commands make run # Run the application make run-stdio # Run in STDIO mode make dev # Run in development mode with hot reload # Docker Compose commands make compose-up # Start services with Docker Compose make compose-down # Stop services make compose-logs # Show logs # Testing commands make test-integration # Run integration tests with Docker make test-load # Run load tests # Development tools make install-tools # Install development tools # Release commands make release-snapshot # Build snapshot release with GoReleaser make release-check # Check GoReleaser configuration # CI commands make ci # Run CI checks (deps, lint, test, build) make check # Run all checks (lint, test, build)
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-03-26", "capabilities": {}, "clientInfo": { "name": "test-client", "version": "1.0.0" } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "resources/list", "params": {} }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 3, "method": "tools/list", "params": {} }'
The TeamCity MCP server provides 10 powerful tools for managing builds:
- buildTypeId(required): Build configuration ID
- branchName(optional): Branch name to build
- properties(optional): Build properties object
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "trigger_build", "arguments": { "buildTypeId": "YourProject_BuildConfiguration", "branchName": "main", "properties": { "env.DEPLOY_ENV": "staging" } } } }'
- buildId(required): Build ID to cancel
- comment(optional): Cancellation comment
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": { "name": "cancel_build", "arguments": { "buildId": "12345", "comment": "Cancelled due to urgent hotfix" } } }'
Pin or unpin a build to prevent it from being cleaned up.
- buildId(required): Build ID to pin/unpin
- pin(required): true to pin, false to unpin
- comment(optional): Pin comment
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 6, "method": "tools/call", "params": { "name": "pin_build", "arguments": { "buildId": "12345", "pin": true, "comment": "Release candidate build" } } }'
- buildId(required): Build ID
- tags(optional): Array of tags to add
- removeTags(optional): Array of tags to remove
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 7, "method": "tools/call", "params": { "name": "set_build_tag", "arguments": { "buildId": "12345", "tags": ["release", "v1.2.3"], "removeTags": ["beta"] } } }'
- buildId(required): Build ID
- artifactPath(required): Path to the artifact
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 8, "method": "tools/call", "params": { "name": "download_artifact", "arguments": { "buildId": "12345", "artifactPath": "dist/app.zip" } } }'
Search for builds with comprehensive filtering options.
- buildTypeId: Filter by build configuration ID
- status: Filter by build status (SUCCESS, FAILURE, ERROR, UNKNOWN)
- state: Filter by build state (queued, running, finished)
- branch: Filter by branch name
- agent: Filter by agent name
- user: Filter by user who triggered the build
- sinceBuild: Search builds since this build ID
- sinceDate: Search builds since this date (YYYYMMDDTHHMMSS+HHMM)
- untilDate: Search builds until this date (YYYYMMDDTHHMMSS+HHMM)
- tags: Array of tags to filter by
- personal: Include personal builds (boolean)
- pinned: Filter by pinned status (boolean)
- count: Maximum number of builds to return (1-1000, default: 100)
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 9, "method": "tools/call", "params": { "name": "search_builds", "arguments": { "status": "FAILURE", "count": 10 } } }'
Search for recent builds on main branch:
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 10, "method": "tools/call", "params": { "name": "search_builds", "arguments": { "branch": "main", "state": "finished", "count": 20 } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 11, "method": "tools/call", "params": { "name": "search_builds", "arguments": { "tags": ["release", "production"], "pinned": true } } }'
Fetch the build log for a specific build with filtering options to handle large logs.
- buildId(required): Build ID to fetch log for
- plain(optional): Return log as plain text (default: true)
- archived(optional): Return log as zip archive (default: false)
- dateFormat(optional): Custom timestamp format (Java SimpleDateFormat)
- maxLines(optional): Maximum number of lines to return (applied after filtering)
- filterPattern(optional): Regex pattern to filter log lines
- severity(optional): Filter by severity level: "error", "warning", or "info"
- tailLines(optional): Return only the last N lines (applied after filtering)
Fetch only errors (limited to 50 lines):
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 12, "method": "tools/call", "params": { "name": "fetch_build_log", "arguments": { "buildId": "12345", "severity": "error", "maxLines": 50 } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 13, "method": "tools/call", "params": { "name": "fetch_build_log", "arguments": { "buildId": "12345", "filterPattern": "test.*failed", "maxLines": 100 } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 14, "method": "tools/call", "params": { "name": "fetch_build_log", "arguments": { "buildId": "12345", "tailLines": 200 } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 15, "method": "tools/call", "params": { "name": "fetch_build_log", "arguments": { "buildId": "12345", "archived": true } } }'
Search for build configurations with comprehensive filtering options including basic filters, parameters, steps, and VCS roots.
- projectId: Filter by project ID
- name: Search by configuration name (partial matching)
- enabled: Filter by enabled status (boolean)
- paused: Filter by paused status (boolean)
- template: Filter templates (true) or regular configurations (false) (boolean)
- count: Maximum number of configurations to return (1-1000, default: 100)
- parameterName: Search by parameter name (partial matching)
- parameterValue: Search by parameter value (partial matching)
- stepType: Search by build step type (e.g., 'gradle', 'docker', 'powershell')
- stepName: Search by build step name (partial matching)
- vcsType: Search by VCS type (e.g., 'git', 'subversion')
- includeDetails: Include detailed information (parameters, steps, VCS) in results (boolean, default: false)
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 15, "method": "tools/call", "params": { "name": "search_build_configurations", "arguments": { "name": "Test", "enabled": true } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 16, "method": "tools/call", "params": { "name": "search_build_configurations", "arguments": { "parameterName": "env.DEPLOY_TARGET", "parameterValue": "production", "includeDetails": true } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 17, "method": "tools/call", "params": { "name": "search_build_configurations", "arguments": { "stepType": "gradle", "projectId": "MyProject", "includeDetails": true } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 18, "method": "tools/call", "params": { "name": "search_build_configurations", "arguments": { "vcsType": "git", "stepName": "Deploy" } } }'
Get the current server date and time to ensure AI models use real current time instead of training data dates.
- format(optional): Date format (rfc3339, date, timestamp, or custom Go format)
- timezone(optional): Timezone (e.g., 'UTC', 'Local', 'America/New_York')
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 19, "method": "tools/call", "params": { "name": "get_current_time", "arguments": { "format": "rfc3339", "timezone": "UTC" } } }'
Get test results for a specific build with optional filtering by test status.
- buildId(required): Build ID to get test results for
- status(optional): Filter by test status: SUCCESS, FAILURE, UNKNOWN, IGNORED
- includeDetails(optional): Include test details like stack traces (default: false)
- count(optional): Maximum number of tests to return (default: 100, max: 1000)
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 20, "method": "tools/call", "params": { "name": "get_test_results", "arguments": { "buildId": "12345" } } }'
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 21, "method": "tools/call", "params": { "name": "get_test_results", "arguments": { "buildId": "12345", "status": "FAILURE", "includeDetails": true } } }'
Get successful tests with limited count:
curl -X POST http://localhost:8123/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-secret" \ -d '{ "jsonrpc": "2.0", "id": 22, "method": "tools/call", "params": { "name": "get_test_results", "arguments": { "buildId": "12345", "status": "SUCCESS", "count": 50 } } }'
If you prefer to use the local binary instead of Docker:
{ "teamcity": { "command": "/path/to/teamcity-mcp", "args": ["--transport", "stdio"], "env": { "TC_URL": "https://your-teamcity-server.com", "TC_TOKEN": "your-teamcity-api-token" } } }
Once configured, you can use natural language commands like:
- "Search for failed builds in the last week"
- "Trigger a build for the main branch"
- "Show me recent builds for project X"
- "Pin the latest successful build"
- "Cancel the running build 12345"
- "Add a release tag to build 12345"
- "Fetch the build log for build 12345"
- "Get the archived log for the latest build"
- "Find all build configurations with 'Test' in the name"
- "Search for enabled configurations in MyProject"
- "Show me all build configuration templates"
- "Find configurations that use Gradle build steps"
- "Search for configurations with DEPLOY_TARGET parameter set to production"
- "Show me all configurations using Git VCS"
- "Find Docker-based build configurations"
- "Search for configurations with specific parameter names"
- "What's the current date and time?"
- "Get current time in UTC"
- "Show me today's date"
- "Get test results for build 12345"
- "Show me failed tests for the latest build"
- "Get test results with details for build 12345"
- "Show me all passing tests for this build"
- "What tests failed in build 12345?"
The AI will automatically use the appropriate TeamCity tools to fulfill your requests.
The server exposes TeamCity data as MCP resources:
- teamcity://projects- List all projects
- teamcity://buildTypes- List all build configurations
- teamcity://builds- List recent builds
- teamcity://agents- List build agents
- teamcity://runtime- Current server date, time, and runtime information
Error: TC_URL environment variable is required
Solution: Set all required environment variables
Error: TC_TOKEN environment variable is required
Solution: SetTC_TOKENwith your TeamCity API token
Solution: Use valid duration format like30s,1m,2h
Error: listen tcp :8123: bind: address already in use
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





