TeamCity

by itcaat

Not rated
GitHub

About

MCP server for TeamCity, integrates with Claude Desktop and Cursor.

Details

Author
itcaat
Categories
Developer Tools, Community, Other

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
No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.