Templatetypescriptintermediateโœ“ Production ReadyFreeโœ… Code Verified

Linear MCP Server Template

A production-ready TypeScript MCP server using HTTP transport with API key authentication, designed to integrate with the Linear project management API. Features structured Pino logging with correlation IDs, health monitoring, Docker support, and Jest tests covering tool execution and error handling.

๐Ÿ“– 12 min readโš™๏ธ Setup: 20 minutesutilities
linearmcptypescripthttpapi-key

Files(18)

{
  "name": "linear-mcp-server",
  "version": "1.0.0",
  "description": "Production-ready MCP server for Linear project management via HTTP transport",
  "main": "dist/server.js",
  "scripts": {
    "build": "tsc --project tsconfig.json",
    "start": "node dist/server.js",
    "dev": "ts-node --project tsconfig.json src/server.ts",
    "test": "jest --forceExit",
    "test:watch": "jest --watch --forceExit",
    "test:coverage": "jest --coverage --forceExit",
    "lint": "eslint src --ext .ts",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.12.0",
    "express": "4.18.2",
    "pino": "8.17.2",
    "pino-http": "9.0.0",
    "uuid": "9.0.1",
    "zod": "^3.25.0"
  },
  "devDependencies": {
    "@types/express": "4.17.21",
    "@types/jest": "29.5.11",
    "@types/node": "20.11.0",
    "@types/supertest": "6.0.2",
    "@types/uuid": "9.0.7",
    "jest": "29.7.0",
    "supertest": "6.3.4",
    "ts-jest": "29.1.2",
    "ts-node": "10.9.2",
    "typescript": "5.3.3"
  },
  "engines": {
    "node": ">=20.0.0"
  }
}

Interactive tester

Test Your Server

Enter a deployed HTTP MCP server URL and API key to run live browser checks.

No signup

Use the public MCP endpoint, not a dashboard URL or local stdio command.

The key stays in this browser check and is sent to the endpoint you enter.

For local servers, use the local testing guide or MCP Inspector. This online tester works best with deployed HTTP MCP servers.

Linear MCP Server Template

Overview

This template provides a fully production-ready Model Context Protocol (MCP) server built in TypeScript, using HTTP transport and API key authentication. It integrates with the Linear project management platform, exposing tools that allow AI assistants like Claude to query issues, create tasks, update statuses, and search across your Linear workspace โ€” all through a secure, observable, and containerised service.

The server is designed for teams who want to give AI coding assistants real access to their project management workflow without sacrificing security or observability. Every request is authenticated via API key, traced with a correlation ID through structured JSON logs (Pino), and exposed through a health endpoint that reports upstream Linear API reachability.

This is an intermediate-level template, appropriate for developers who are comfortable with TypeScript and Node.js and want to learn how to build maintainable MCP servers that are ready to deploy to production on day one.

What You'll Learn

  • How to scaffold and register MCP tools using the official @modelcontextprotocol/sdk package
  • How to implement HTTP transport for MCP with Express, including proper SSE and POST endpoint wiring
  • How to validate and enforce API key authentication via Express middleware
  • How to use Pino for structured JSON logging with per-request correlation IDs
  • How to expose a /health endpoint that checks live connectivity to an external API (Linear)
  • How to use Zod for runtime input validation on every tool invocation
  • How to write a multi-stage Dockerfile that produces a minimal production image
  • How to configure a docker-compose environment for local development with hot reload
  • How to write Jest + Supertest integration tests that cover auth, health, and tool execution
  • How to manage all configuration through environment variables with documented defaults
  • How to handle upstream API errors gracefully and return well-structured MCP error responses
  • How to model Linear domain objects (issues, projects, teams) with full TypeScript types

Architecture

Claude Desktop / Claude Code
        โ”‚
        โ”‚  HTTP POST /mcp  (MCP JSON-RPC)
        โ–ผ
  Express HTTP Server
        โ”‚
        โ”œโ”€โ”€ API Key Middleware  (validates X-API-Key header)
        โ”œโ”€โ”€ Correlation ID Middleware  (injects req-id into Pino child logger)
        โ”‚
        โ”œโ”€โ”€ GET  /health  โ”€โ”€โ–บ HealthChecker โ”€โ”€โ–บ Linear API ping
        โ”‚
        โ””โ”€โ”€ POST /mcp  โ”€โ”€โ”€โ”€โ”€โ–บ MCP SDK Server
                                    โ”‚
                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                          โ”‚    Tool Router      โ”‚
                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                 โ–ผ                  โ–ผ                   โ–ผ
          list_issues         create_issue       update_issue_status
                 โ”‚                  โ”‚                   โ”‚
                 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                    โ”‚
                             Linear REST API
                          (api.linear.app/graphql)

Project Structure

linear-mcp-server/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ __tests__/
โ”‚   โ”‚   โ”œโ”€โ”€ setup.ts
โ”‚   โ”‚   โ”œโ”€โ”€ health.test.ts
โ”‚   โ”‚   โ””โ”€โ”€ server.test.ts
โ”‚   โ”œโ”€โ”€ tools/
โ”‚   โ”‚   โ”œโ”€โ”€ listIssues.ts
โ”‚   โ”‚   โ”œโ”€โ”€ createIssue.ts
โ”‚   โ”‚   โ””โ”€โ”€ updateIssueStatus.ts
โ”‚   โ”œโ”€โ”€ server.ts
โ”‚   โ”œโ”€โ”€ config.ts
โ”‚   โ”œโ”€โ”€ auth.ts
โ”‚   โ”œโ”€โ”€ logger.ts
โ”‚   โ””โ”€โ”€ health.ts
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ tsconfig.json
โ”œโ”€โ”€ jest.config.ts
โ”œโ”€โ”€ .env.example
โ””โ”€โ”€ .gitignore

Prerequisites

  • Node.js 20+ and npm 10+
  • A Linear account with an API key (Settings โ†’ API โ†’ Personal API keys)
  • Docker Desktop (optional, for container workflow)
  • Claude Desktop or another MCP-compatible client for end-to-end testing

Quick Start

# 1. Clone or copy this template
git clone https://github.com/your-org/linear-mcp-server.git
cd linear-mcp-server

# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env
# Edit .env โ€” set LINEAR_API_KEY and MCP_API_KEY at minimum

# 4. Run in development mode (ts-node with watch)
npm run dev

# 5. Verify the server is healthy
curl http://localhost:3000/health

# 6. Run tests
npm test

Features

  • Three production-quality Linear tools: list_issues, create_issue, update_issue_status with Zod input validation and full TypeScript types
  • API key authentication: Every MCP request requires a valid X-API-Key header; the health endpoint is publicly accessible
  • Structured Pino logging: JSON output with req_id correlation on every log line; level controlled by LOG_LEVEL env var
  • Health monitoring: /health returns { status, uptime, linear: { reachable } } and checks live Linear API connectivity
  • Multi-stage Docker build: builder stage compiles TypeScript; production stage runs only compiled JS with no dev dependencies
  • docker-compose: One-command local stack with volume mounts for hot reload via ts-node
  • Jest + Supertest tests: Auth rejection, health endpoint, and tool execution all covered
  • Zod configuration validation: Server refuses to start if required environment variables are missing or malformed
  • Graceful shutdown: SIGTERM/SIGINT handlers drain in-flight requests before exiting

Works With

  • Claude Desktop โ€” add server to claude_desktop_config.json using the HTTP transport URL
  • Claude Code โ€” reference via --mcp-server flag pointing to http://localhost:3000/mcp
  • Cursor โ€” configure in MCP settings panel with URL and API key header
  • Windsurf โ€” add as a remote MCP server in workspace settings
  • Continue โ€” add MCP server block in config.json with transport: http

Configuration

VariableDescriptionRequiredDefault
PORTHTTP port the server listens onOptional3000
MCP_API_KEYSecret key clients must send in X-API-KeyRequiredโ€”
LINEAR_API_KEYYour Linear personal API keyRequiredโ€”
LINEAR_TEAM_IDDefault Linear team ID for issue creationOptionalโ€”
LOG_LEVELPino log level: trace debug info warn errorOptionalinfo
NODE_ENVdevelopment or productionOptionaldevelopment
HEALTH_CHECK_TIMEOUT_MSTimeout for Linear connectivity check in msOptional5000

Deployment

# Build production image
docker build -t linear-mcp-server:latest .

# Run with environment file
docker run -d \
  --name linear-mcp \
  -p 3000:3000 \
  --env-file .env \
  linear-mcp-server:latest

# Check logs
docker logs -f linear-mcp

Railway

# Install Railway CLI
npm install -g @railway/cli
railway login
railway new linear-mcp-server
railway up

# Set environment variables in Railway dashboard or via CLI
railway variables set MCP_API_KEY=your-secret LINEAR_API_KEY=lin_api_xxx

Fly.io

# Install flyctl and authenticate
curl -L https://fly.io/install.sh | sh
fly auth login

# Launch app (uses existing Dockerfile)
fly launch --name linear-mcp-server --region lax

# Set secrets
fly secrets set MCP_API_KEY=your-secret LINEAR_API_KEY=lin_api_xxx

# Deploy
fly deploy

Production Checklist

  • MCP_API_KEY is a cryptographically random string (at least 32 characters)
  • LINEAR_API_KEY is stored as a secret, not committed to version control
  • NODE_ENV=production is set in your deployment environment
  • LOG_LEVEL=info or warn in production (avoid debug/trace)
  • Health endpoint is reachable by your load balancer or uptime monitor
  • Docker image is built from the production stage only
  • .env file is listed in .gitignore and never committed
  • HTTPS/TLS is terminated at the load balancer or reverse proxy in front of this server
  • Rate limiting is applied at the gateway layer before reaching this server
  • LINEAR_TEAM_ID is set to avoid requiring it on every tool call
  • Container restart policy is set to unless-stopped or equivalent
  • Logs are forwarded to a centralised log aggregator (Datadog, Logtail, etc.)
  • /health is monitored every 30 seconds with alerting on failure
  • Image is pinned to a specific tag in production, not latest
  • npm audit is run and all high/critical vulnerabilities are resolved

Testing

Automated Tests

# Run full test suite
npm test

# Watch mode during development
npm run test:watch

# With coverage report
npm run test:coverage

Manual curl Testing

# Health check (no auth required)
curl -s http://localhost:3000/health | jq .

# Rejected request โ€” missing API key
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/mcp
# Expected: 401

# List issues via MCP JSON-RPC
curl -s -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-mcp-api-key" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "list_issues",
      "arguments": { "limit": 5, "stateFilter": "started" }
    }
  }' | jq .

Claude Desktop Integration

Add this to your ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "linear": {
      "transport": "http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "X-API-Key": "your-mcp-api-key"
      }
    }
  }
}

Then restart Claude Desktop and ask: "Show me my open Linear issues" or "Create a Linear issue titled 'Fix login bug' in the backend team".

โœ… Template ready. What's next?

  1. 1.Copy or download the template above
  2. 2.Deploy your MCP server (Railway, Vercel)
  3. 3.Test your deployment
  4. 4.Verify production readiness