Skip to content

itcaat/teamcity-mcp

Repository files navigation

TeamCity MCP Server

A comprehensive Model Context Protocol (MCP) server that exposes JetBrains TeamCity as structured AI-ready resources and tools for LLM agents and IDE plugins.

Quick Start

IDE Integration (Cursor)

The TeamCity MCP server is designed to work seamlessly with AI-powered IDEs like Cursor. Here's how to configure it:

Cursor Configuration

Add this to your Cursor MCP settings:

{
  "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"
        }
      }
    }
}    

Local Development

1. Build the Server

make build
# This creates ./bin/teamcity-mcp and a symlink ./server

2. Set Environment Variables

# 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"

3. Run the Server

./server
# Server starts on :8123 by default

4. Test the Server

# 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.

Features

  • 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

Environment Variables Reference

Required Variables

Variable Description Example
TC_URL TeamCity server URL https://teamcity.company.com
SERVER_SECRET HMAC secret for client authentication (optional) my-secure-secret-123

Authentication Variables

Variable Description Example
TC_TOKEN TeamCity API token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

Optional Variables

Variable Default Description Example
LISTEN_ADDR :8123 Server listen address :8080 or 0.0.0.0:8123
TC_TIMEOUT 30s TeamCity API timeout 60s or 2m
TLS_CERT Path to TLS certificate /path/to/cert.pem
TLS_KEY Path to TLS private key /path/to/key.pem
LOG_LEVEL info Log level debug, info, warn, error
LOG_FORMAT json Log format json or console
CACHE_TTL 10s Cache TTL for API responses 30s or 1m

Configuration Examples

Development Environment

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

Production Environment

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

Docker Deployment

Build and Run

# 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

Docker Compose

# Start with docker-compose
docker-compose up -d

# Check logs
docker-compose logs -f teamcity-mcp

Kubernetes Deployment

Using Helm

# 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

Manual Kubernetes Deployment

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

Command Line Options

Flag Description Default
--help Show environment variable help
--version Show version information
--transport Transport mode: http or stdio http

Help and Documentation

# Show environment variable help
./server --help

# Show version
./server --version

# Show command line usage
./server -h

Testing and Verification

Automated Verification

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

Manual Testing

# 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

Development Testing

# 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

Available Make Commands

Use make help to 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)

MCP Protocol Testing

Initialize MCP Session

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"
      }
    }
  }'

List Resources

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": {}
  }'

List Tools

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": {}
  }'

Available Tools

The TeamCity MCP server provides 7 powerful tools for managing builds:

1. trigger_build

Trigger a new build in TeamCity.

Parameters:

  • buildTypeId (required): Build configuration ID
  • branchName (optional): Branch name to build
  • properties (optional): Build properties object

Example:

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"
        }
      }
    }
  }'

2. cancel_build

Cancel a running build.

Parameters:

  • buildId (required): Build ID to cancel
  • comment (optional): Cancellation comment

Example:

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"
      }
    }
  }'

3. pin_build

Pin or unpin a build to prevent it from being cleaned up.

Parameters:

  • buildId (required): Build ID to pin/unpin
  • pin (required): true to pin, false to unpin
  • comment (optional): Pin comment

Example:

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"
      }
    }
  }'

4. set_build_tag

Add or remove tags from a build.

Parameters:

  • buildId (required): Build ID
  • tags (optional): Array of tags to add
  • removeTags (optional): Array of tags to remove

Example:

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"]
      }
    }
  }'

5. download_artifact

Download build artifacts.

Parameters:

  • buildId (required): Build ID
  • artifactPath (required): Path to the artifact

Example:

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"
      }
    }
  }'

6. search_builds

Search for builds with comprehensive filtering options.

Parameters (all optional):

  • 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)

Examples:

Search for failed builds:

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
      }
    }
  }'

Search for builds with specific tags:

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
      }
    }
  }'

7. fetch_build_log

Fetch the complete build log for a specific build.

Parameters:

  • 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)

Examples:

Fetch plain text build log:

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"
      }
    }
  }'

Fetch archived build log:

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",
        "archived": true
      }
    }
  }'

Fetch log with custom timestamp format:

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",
        "dateFormat": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }'

Local Binary Configuration

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"
    }
  }
}

Usage in Cursor

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"

The AI will automatically use the appropriate TeamCity tools to fulfill your requests.

Available Resources

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

Troubleshooting

Common Issues

  1. Missing required environment variables

    Error: TC_URL environment variable is required
    

    Solution: Set all required environment variables

  2. Authentication failures

    Error: TC_TOKEN environment variable is required
    

    Solution: Set TC_TOKEN with your TeamCity API token

  3. Invalid timeout format

    Error: invalid TC_TIMEOUT format
    

    Solution: Use valid duration format like 30s, 1m, 2h

  4. Port already in use

    Error: listen tcp :8123: bind: address already in use
    

    Solution: Set LISTEN_ADDR to a different port or stop the conflicting service

Debug Mode

Enable debug logging:

export LOG_LEVEL=debug
export LOG_FORMAT=console
./server

Health Check

The server provides a health endpoint:

curl http://localhost:8123/healthz
# Expected: {"service":"teamcity-mcp","status":"ok","timestamp":"..."}

Metrics

Prometheus metrics are available:

curl http://localhost:8123/metrics

TeamCity Integration Testing

Verify TeamCity connectivity:

# Check TeamCity server accessibility
curl -H "Authorization: Bearer your-token" \
  http://your-teamcity-url/app/rest/projects

# Verify authentication
curl -H "Authorization: Bearer your-token" \
  http://your-teamcity-url/app/rest/server

Protocol Reference

See Protocol.md for detailed MCP protocol implementation and TeamCity API mapping.

License

MIT License - see LICENSE for details.

About

Teamcity MCP Server

Resources

License

Stars

Watchers

Forks

Packages

No packages published