teamdynamix-mcp is a layered TypeScript MCP server. Each layer has a single responsibility; dependencies only flow downward.
┌──────────────────────────────────────────────────────────────┐
│ MCP Transport │ src/index.ts
│ (StdioServerTransport) │
├──────────────────────────────────────────────────────────────┤
│ Tool Handlers │ src/tools/*.tools.ts
│ (Gateway action validation, safety guards, routing) │
├──────────────────────────────────────────────────────────────┤
│ TeamDynamixClient (HTTP + auth) │ src/services/teamdynamix/client.service.ts
│ Core helpers (dates, patch, rate limit) │ src/services/teamdynamix/core.service.ts
└──────────────────────────────────────────────────────────────┘Directory Structure
src/
├── index.ts # MCP entry point — registers all gateway tool families
├── config.ts # TeamDynamix + MCP env var parsing
├── constants.ts # Shared constants (tool prefix, character limits)
├── types.ts # Shared TypeScript types (auth config, request options)
├── schemas/
│ └── teamdynamix/index.ts # All Zod input schemas (tickets, KB, assets, CI, projects …)
├── tools/
│ ├── teamdynamix.domain-gateways.tools.ts # Domain gateway registrations + action routing
│ ├── teamdynamix.discovery.tools.ts # Legacy direct tool module (kept for compatibility tests)
│ ├── teamdynamix.tickets.tools.ts # Legacy direct tool module
│ ├── teamdynamix.ticket-tasks.tools.ts # Legacy direct tool module
│ ├── teamdynamix.people.tools.ts # Legacy direct tool module
│ ├── teamdynamix.kb.tools.ts # Legacy direct tool module
│ ├── teamdynamix.assets.tools.ts # Legacy direct tool module
│ ├── teamdynamix.services.tools.ts # Legacy direct tool module
│ ├── teamdynamix.cmdb.tools.ts # Legacy direct tool module
│ └── teamdynamix.enumeration.tools.ts # Legacy direct tool module
├── services/
│ ├── teamdynamix/
│ │ ├── client.service.ts # TeamDynamixClient — HTTP, auth, retry, safety guards
│ │ └── core.service.ts # Date helpers, JSON Patch builder, rate limit parser, JWT decode
│ └── __tests__/ # Service unit tests
└── resources/
└── teamdynamix.resources.ts # TeamDynamix MCP resources (capabilities, config)Layer Responsibilities
Transport layer (src/index.ts)
- Creates the MCP server instance using
@modelcontextprotocol/sdk - Imports and calls
registerTeamDynamixDomainGatewayTools - Registers MCP resources
- Starts
StdioServerTransport
Tool handlers (src/tools/*.tools.ts)
- Accept domain gateway inputs (
action,payload,response_format) - Validate
payloadper action with Zod schemas - Call
assertWriteToolsEnabledorassertAdminToolsEnabledbefore mutating operations - Delegate to
TeamDynamixClientmethods - Format and return the response
- Keep behavior thin and predictable
Gateway model
The exposed MCP surface is intentionally reduced to domain gateways:
teamdynamix_discoveryteamdynamix_ticketsteamdynamix_ticket_relationshipsteamdynamix_peopleteamdynamix_knowledge_baseteamdynamix_assetsteamdynamix_cmdbteamdynamix_servicesteamdynamix_projectsteamdynamix_timeteamdynamix_reference_data
Each gateway routes named actions to the underlying client methods.
TeamDynamixClient (src/services/teamdynamix/client.service.ts)
- Manages bearer token cache (standard and admin) with expiry-aware refresh
- Retries on transient failures up to
TEAMDYNAMIX_MAX_RETRIES - Parses
X-RateLimit-Resetand waits at leastTEAMDYNAMIX_MIN_RATE_LIMIT_WAIT_MSon 429 - All HTTP methods are typed
Record<string, unknown>to stay schema-agnostic - Exports
assertWriteToolsEnabledandassertAdminToolsEnabledguards - Never imports MCP SDK types
Core helpers (src/services/teamdynamix/core.service.ts)
toTeamDynamixDateTime/toTeamDynamixDateOnly— normalises ISO 8601 to TDX wire formatbuildTeamDynamixJsonPatchDocument— converts user-facing path strings to RFC 6902op/path/valueobjectsparseRateLimit— extracts wait duration from rate limit response headersdecodeJwtExpiryEpochSeconds— readsexpclaim from TDX JWT to enable proactive token refreshredactTeamDynamixConfig— strips secrets before logging the config
Schemas
All TeamDynamix Zod schemas live in src/schemas/teamdynamix/index.ts. Each domain section is separated by comments. Schemas are imported into tool files and used as inputSchema directly.
Configuration
src/config.ts parses environment variables at startup and exports a typed TeamDynamixConfig. Tool handlers call getTeamDynamixConfig() rather than reading process.env directly. The config includes all connection, auth, and safety flag values.
Safety policy
Two safety guards gate mutating and administrative operations:
assertWriteToolsEnabled(config)— throws unlessenableWriteToolsistrue(TEAMDYNAMIX_ENABLE_WRITE_TOOLS=true)assertAdminToolsEnabled(config)— throws unlessenableAdminToolsistrue(TEAMDYNAMIX_ENABLE_ADMIN_TOOLS=true)
Destructive tools (remove asset link, remove contact, etc.) additionally include a confirm: z.literal(true) field in the input schema. The MCP SDK enforces this at the schema level before the handler is called.
Response Formatting
All tool responses support two formats:
"markdown"(default) — human-readable output"json"— a JSON object suitable for programmatic consumption
Formatting helpers are co-located with tool handlers.
Character Limit
Large outputs are truncated to CHARACTER_LIMIT (defined in src/constants.ts) to avoid overwhelming MCP clients.
Error Model
Errors should be returned as structured objects with:
- A human-readable message explaining what went wrong
- Where applicable, guidance on how to resolve the issue
No errors should be swallowed silently.
Build
pnpm build # tsup bundles src/ → dist/
pnpm start # node dist/index.js
pnpm dev # tsx watch src/index.ts (hot reload)
pnpm typecheck # tsc --noEmittsup is configured to target Node.js, produce CJS output, and emit type declarations.