@aot-tech/clockify-mcp-server
Version:
MCP Server for Clockify time tracking integration with AI tools
558 lines (429 loc) โข 13.8 kB
Markdown
# Clockify MCP Server
A Model Context Protocol (MCP) server implementation for Clockify time tracking integration. This server enables AI assistants to interact with Clockify's time tracking features through natural language commands.
## ๐ Features
- **Time Entry Management**: Create, list, and manage time entries
- **Project Integration**: Access and manage Clockify projects
- **User Management**: Retrieve user information and groups
- **Workspace Support**: Multi-workspace functionality
- **Task Tracking**: Integrate with project tasks
- **Reports**: Generate detailed time tracking reports
- **Stateless Architecture**: Pure stateless design with AsyncLocalStorage
- **Authentication**: Bearer token authentication support
- **Debug Logging**: Conditional debug logging for local development
## ๐ ๏ธ Tech Stack
- **Runtime**: Node.js (v20+)
- **Language**: TypeScript
- **Framework**: Express.js with MCP SDK
- **API Client**: Axios for Clockify API integration
- **Validation**: Zod schemas
- **Testing**: Node.js built-in test runner
## ๐ฆ Installation
### Prerequisites
- Node.js v20.0.0 or higher
- npm v10.0.0 or higher
- Clockify account with API access
### Setup
1. **Install dependencies:**
```bash
npm install
```
2. **Build the project:**
```bash
npm run build
```
3. **Environment Configuration:**
Create a `.env` file:
```env
# Clockify API Configuration
CLOCKIFY_API_URL=https://api.clockify.me/api/v1
CLOCKIFY_API_TOKEN=your_clockify_api_token_here
# Server Configuration
PORT=3000
NODE_ENV=development
IS_LOCAL=true
TZ=UTC
```
## ๐โโ๏ธ Running the Server
### Development Mode
```bash
npm run dev
```
Server runs with auto-restart on file changes at `http://localhost:3000`.
### Production Mode
```bash
npm start
```
### Testing
```bash
npm test
```
### Debug Logging
Debug logging is automatically enabled in development mode and disabled in production. For manual control:
```bash
# Enable debug logging
NODE_ENV=development npm start
# OR
DEBUG_MODE=true npm start
# Disable debug logging (production)
NODE_ENV=production npm start
```
Debug logs are written to:
- Console with `[CLOCKIFY-MCP-DEBUG]` prefix and timestamps
- No file storage (npm package friendly)
See [DEBUG_SETUP.md](./DEBUG_SETUP.md) for detailed configuration.
## ๐ง Configuration
### Clockify API Token
To get your Clockify API token:
1. Log in to your Clockify account
2. Go to **Profile Settings** โ **API**
3. Generate a new API key
4. Copy the token to your `.env` file
### Smithery Configuration
For use with AI assistants like Claude Desktop, create a `smithery.yaml` configuration:
```yaml
startCommand:
type: stdio
configSchema:
type: object
required:
- clockifyApiToken
properties:
clockifyApiUrl:
type: string
default: https://api.clockify.me/api/v1
description: Base URL for Clockify API
clockifyApiToken:
type: string
default: YOUR_CLOCKIFY_API_TOKEN_HERE
description: Clockify API token for authentication
commandFunction: |
(config) => ({
command: 'node',
args: ['build/src/index.js'],
env: {
CLOCKIFY_API_URL: config.clockifyApiUrl,
CLOCKIFY_API_TOKEN: config.clockifyApiToken
}
})
```
## ๐ Integration with AI Assistants
### Claude Desktop
#### Via Smithery (Recommended)
```bash
npx -y @smithery/cli install clockify-mcp-server --client claude
```
#### Manual Installation
1. Install TypeScript globally:
```bash
npm i -g ts-node
```
2. Add to your Claude Desktop configuration (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"clockify": {
"command": "node",
"args": ["/absolute/path/to/clockify-mcp-server/build/src/index.js"],
"env": {
"CLOCKIFY_API_TOKEN": "your_clockify_api_token_here"
}
}
}
}
```
### MCP Dashboard Integration
The server integrates seamlessly with the MCP Dashboard backend:
```javascript
// Backend configuration
const mcpServers = {
clockify: {
url: 'http://localhost:3000',
name: 'Clockify Time Tracking'
}
};
```
## ๐ ๏ธ Available Tools
### Time Entries
#### `create_entry`
Create a new time entry in Clockify.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
- `description` (string, required): Time entry description
- `start` (date, required): Start time
- `end` (date, required): End time
- `projectId` (string, optional): Project ID
- `billable` (boolean, optional): Whether entry is billable (default: true)
**Example Usage:**
```
"Create a time entry for 'Website development' from 9 AM to 5 PM today in project XYZ"
```
#### `list_entries`
List time entries for a user within a date range.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
- `userId` (string, required): User ID
- `start` (date, required): Start date for search
- `end` (date, required): End date for search
**Example Usage:**
```
"Show me my time entries for this week"
```
### Projects
#### `find_project`
Search for projects in a workspace.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
- `name` (string, optional): Project name filter
**Example Usage:**
```
"Find all projects containing 'website' in the name"
```
### Users & Groups
#### `get_current_user`
Get information about the current authenticated user.
**Example Usage:**
```
"What's my user information?"
```
#### `get_all_users`
Get all users in a workspace.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
**Example Usage:**
```
"Show me all users in the workspace"
```
#### `get_all_groups`
Get all user groups in a workspace.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
**Example Usage:**
```
"List all user groups"
```
### Workspaces
#### `find_workspaces`
List all accessible workspaces for the authenticated user.
**Example Usage:**
```
"What workspaces do I have access to?"
```
### Tasks
#### `find_tasks`
Find tasks within a project.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
- `projectId` (string, required): Project ID
**Example Usage:**
```
"Show me all tasks in the current project"
```
### Reports
#### `get_detailed_report`
Generate detailed time tracking reports.
**Parameters:**
- `workspaceId` (string, required): Workspace ID
- `dateRangeStart` (date, required): Report start date
- `dateRangeEnd` (date, required): Report end date
- `users` (array, optional): User IDs to include
- `projects` (array, optional): Project IDs to include
**Example Usage:**
```
"Generate a detailed report for last month"
```
## ๐๏ธ Project Structure
```
src/
โโโ index.ts # Main server entry point
โโโ config/
โ โโโ api.ts # API configuration and client setup
โโโ tools/ # MCP tool implementations
โ โโโ entries.ts # Time entry management tools
โ โโโ projects.ts # Project management tools
โ โโโ users.ts # User management tools
โ โโโ workspaces.ts # Workspace tools
โ โโโ tasks.ts # Task management tools
โ โโโ reports.ts # Reporting tools
โโโ clockify-sdk/ # Clockify API SDK
โ โโโ entries.ts # Time entries API client
โ โโโ projects.ts # Projects API client
โ โโโ users.ts # Users API client
โ โโโ workspaces.ts # Workspaces API client
โ โโโ tasks.ts # Tasks API client
โ โโโ reports.ts # Reports API client
โโโ validation/ # Zod validation schemas
โ โโโ entries/ # Entry validation schemas
โ โโโ projects/ # Project validation schemas
โ โโโ reports/ # Report validation schemas
โโโ types/
โโโ index.ts # TypeScript type definitions
```
## ๐ Authentication
The server uses stateless bearer token authentication:
1. **Token Extraction**: Extracts bearer tokens from Authorization headers
2. **Validation**: Validates tokens against Clockify API
3. **Context Isolation**: Uses AsyncLocalStorage for request isolation
4. **Security**: No session storage, completely stateless
### Authentication Flow
```typescript
// Request with Bearer token
Authorization: Bearer your_clockify_api_token
// Server validates token with Clockify API
fetch('https://api.clockify.me/api/v1/workspaces', {
headers: { 'X-Api-Key': token }
});
// If valid, request proceeds with token context
```
## ๐ Monitoring & Health Checks
### Health Endpoint
```http
GET /health
```
**Response:**
```json
{
"status": "healthy",
"service": "Clockify MCP Server",
"version": "1.0.0",
"timestamp": "2024-01-01T00:00:00.000Z",
"clockify_api_url": "https://api.clockify.me/api/v1",
"stateless": true
}
```
### Error Handling
The server provides comprehensive error handling:
- **Authentication Errors**: Invalid or missing API tokens
- **API Errors**: Clockify API communication issues
- **Validation Errors**: Invalid request parameters
- **Network Errors**: Connection timeouts and failures
Error responses follow MCP protocol standards:
```json
{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "Authentication required: Valid Bearer token required"
},
"id": null
}
```
## ๐ Deployment
### Docker Deployment
```dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
```
### Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `CLOCKIFY_API_URL` | No | https://api.clockify.me/api/v1 | Clockify API base URL |
| `CLOCKIFY_API_TOKEN` | Yes | - | Clockify API token |
| `PORT` | No | 3000 | Server port |
| `NODE_ENV` | No | development | Environment mode |
| `IS_LOCAL` | No | false | Local development flag |
| `TZ` | No | UTC | Timezone setting |
### Elastic Beanstalk
The server includes Elastic Beanstalk deployment configuration:
```bash
# Deploy to AWS Elastic Beanstalk
eb init
eb create clockify-mcp-server
eb deploy
```
## ๐งช Testing
### Running Tests
```bash
npm test
```
### Test Coverage
Tests cover:
- Tool functionality
- API client operations
- Authentication flow
- Error handling scenarios
- Input validation
### Manual Testing
Test individual tools using the MCP protocol:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_entries",
"arguments": {
"workspaceId": "workspace-id",
"userId": "user-id",
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
}
}
}
```
## ๐ก Usage Examples
### Natural Language Commands
The MCP server enables natural language interaction:
```
User: "Start tracking time for website development"
AI: Creates time entry with current timestamp
User: "How much time did I spend on project X last week?"
AI: Generates report for specified project and date range
User: "Stop my current timer and log 8 hours for database work"
AI: Updates time entry with specified duration and description
```
### Integration with Workflows
```javascript
// Automated time tracking workflow
const workflow = {
morning: () => ai.chat("Start tracking time for daily standup"),
coding: () => ai.chat("Switch time tracking to development work"),
evening: () => ai.chat("Stop timer and show today's summary")
};
```
## ๐ค Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
### Development Guidelines
- Follow TypeScript best practices
- Add tests for new functionality
- Update documentation for new tools
- Maintain stateless architecture
- Use Zod for input validation
## ๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
## ๐ Acknowledgments
- [Clockify API](https://clockify.me/developers-api) for the comprehensive time tracking API
- [Model Context Protocol](https://modelcontextprotocol.io/) for the integration standard
- [TypeScript](https://www.typescriptlang.org/) for type safety
- [Zod](https://zod.dev/) for schema validation
```bash
npx -y @smithery/cli install @https-eduardo/clockify-mcp-server --client claude
```
### Installing Manually
First, install ts-node globally
`npm i -g ts-node`
Then insert the MCP server in `claude_desktop_config`
```json
{
"mcpServers": {
"clockify-time-entries": {
"command": "ts-node",
"args": ["ABSOLUTE_PATH/src/index.ts"],
"env": {
"CLOCKIFY_API_URL": "https://api.clockify.me/api/v1",
"CLOCKIFY_API_TOKEN": "YOUR_CLOCKIFY_API_TOKEN_HERE"
}
}
}
}
```
You can also compile the Typescript code using `tsc` and then change the config to use default `node` command and point to the `js` file.