Skip to main content
Glama
heathweaver

Asana MCP Server Extended

by heathweaver
README.md
# Asana MCP Server Extended

A Model Context Protocol (MCP) server that provides comprehensive Asana integration, enabling AI assistants like Claude to interact with Asana workspaces, projects, tasks, goals, portfolios, and more.

## Features

- **43 MCP Tools**: Full coverage of Asana's API with 29 read-only and 14 write/delete tools
- **OAuth 2.0 Authentication**: Secure PKCE-based OAuth flow with GitHub integration
- **HTTP Transport**: Streamable HTTP transport for MCP protocol
- **Type-Safe**: Built with TypeScript for reliability
- **Comprehensive Testing**: Full test suite with mocked and integration tests

## Quick Start

### Prerequisites

- Node.js 18+ 
- Asana Personal Access Token or OAuth credentials
- (Optional) GitHub OAuth credentials for user authentication

### Installation

```bash
# Clone the repository
git clone <repository-url>
cd asana-mcp-server-extended

# Install dependencies
npm install

# Build the project
npm run build
```

### Configuration

Set the following environment variables:

```bash
# Required: Asana API access token
export ASANA_ACCESS_TOKEN="your_asana_personal_access_token"

# Optional: Custom Asana API base URL (defaults to https://app.asana.com/api/1.0)
export ASANA_API_BASE_URL="https://app.asana.com/api/1.0"

# Optional: Server configuration
export PORT=8766
export HOST=0.0.0.0

# Optional: GitHub OAuth (for user authentication)
export GITHUB_OAUTH_CLIENT_ID="your_github_client_id"
export GITHUB_OAUTH_SECRET="your_github_client_secret"
export GITHUB_OAUTH_CALLBACK_URL="https://your-domain.com/auth/github/callback"

# Optional: Pre-shared tokens (comma-separated)
export MCP_ALLOWED_TOKENS="token1,token2,token3"
```

### Running the Server

```bash
# Development
npm run dev

# Production
npm run build
node dist/index.js
```

The server will start on `http://0.0.0.0:8766` by default.

### Health Check

```bash
curl http://localhost:8766/health
```

Expected response:
```json
{
  "status": "ok",
  "server": "asana-mcp-server-http"
}
```

## MCP Client Configuration

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "asana": {
      "command": "node",
      "args": ["/path/to/asana-mcp-server-extended/dist/index.js"],
      "env": {
        "ASANA_ACCESS_TOKEN": "your_token_here"
      }
    }
  }
}
```

### HTTP Transport

For HTTP-based MCP clients:

```json
{
  "mcpServers": {
    "asana": {
      "url": "https://your-domain.com/mcp",
      "headers": {
        "Authorization": "Bearer your_mcp_token"
      }
    }
  }
}
```

## Available Tools

### Read-Only Tools (29)

#### Attachments
- `asana_get_attachment` - Get a single attachment by gid
- `asana_get_attachments_for_object` - List attachments for a parent resource

#### Goals
- `asana_get_goal` - Get a single goal
- `asana_get_goals` - List goals filtered by workspace/team/portfolio/time period
- `asana_get_parent_goals_for_goal` - Get parent goals for a goal

#### Portfolios
- `asana_get_portfolio` - Get a single portfolio
- `asana_get_portfolios` - List portfolios in a workspace
- `asana_get_items_for_portfolio` - List items in a portfolio

#### Projects
- `asana_get_project` - Get a single project
- `asana_get_projects` - List projects filtered by workspace/team
- `asana_get_projects_for_team` - List projects for a team
- `asana_get_projects_for_workspace` - List projects in a workspace
- `asana_get_project_sections` - List sections in a project
- `asana_get_project_status` - Get a project status update
- `asana_get_project_statuses` - List status updates for a project
- `asana_get_project_task_counts` - Get task counts for a project

#### Tasks
- `asana_get_task` - Get a single task
- `asana_get_tasks` - List tasks filtered by workspace/project/assignee
- `asana_get_stories_for_task` - List stories (activity) for a task
- `asana_search_tasks` - Full-text search for tasks in a workspace

#### Teams & Workspaces
- `asana_get_team_users` - List users in a team
- `asana_get_teams_for_user` - List teams for a user
- `asana_get_teams_for_workspace` - List teams in a workspace
- `asana_get_workspace_users` - List users in a workspace
- `asana_list_workspaces` - List accessible workspaces

#### Time Periods
- `asana_get_time_period` - Get a time period
- `asana_get_time_periods` - List time periods in a workspace

#### Users
- `asana_get_user` - Get a user by gid

#### Search
- `asana_typeahead_search` - Typeahead search within a workspace

### Write/Delete Tools (14)

#### Tasks
- `asana_create_task` - Create a new task
- `asana_update_task` - Update task fields
- `asana_delete_task` - Delete a task
- `asana_add_task_followers` - Add followers to a task
- `asana_remove_task_followers` - Remove followers from a task
- `asana_set_parent_for_task` - Set or clear task parent
- `asana_set_task_dependencies` - Add task dependencies
- `asana_set_task_dependents` - Add task dependents
- `asana_create_task_story` - Create a story/comment on a task

#### Projects
- `asana_create_project` - Create a new project
- `asana_create_project_status` - Create a project status update

#### Goals
- `asana_create_goal` - Create a new goal
- `asana_update_goal` - Update goal fields
- `asana_update_goal_metric` - Update a goal's metric

## API Reference

All tools follow Asana's REST API conventions:

- **GIDs**: Asana uses numeric gids (globally unique identifiers) as strings
- **Data Wrapping**: Request bodies are wrapped in `{ data: {...} }`
- **Response Format**: Responses follow `{ data: {...}, next_page: {...} }` format
- **Pagination**: Use `limit`, `offset`, and `next_page` for paginated endpoints
- **Field Selection**: Use `opt_fields` parameter to request specific fields

See [Asana API Documentation](https://developers.asana.com/reference/rest-api-reference) for detailed endpoint specifications.

## Authentication

### Personal Access Token (PAT)

The simplest authentication method. Get your token from [Asana Developer Console](https://app.asana.com/0/my-apps).

```bash
export ASANA_ACCESS_TOKEN="your_pat_here"
```

### OAuth 2.0 Flow

The server supports OAuth 2.0 with PKCE for secure client authentication:

1. **Client Registration**: POST to `/oauth/register`
2. **Authorization**: GET `/oauth/authorize` (redirects to GitHub)
3. **Token Exchange**: POST to `/oauth/token` with authorization code

See `tests/pkce-handshake.test.js` for a complete OAuth flow example.

## Testing

### Run All Tests

```bash
npm test
```

### Run Specific Test Suites

```bash
# Unit tests
node --test tests/tools/task-tools.test.js

# Integration tests
node --test tests/tools/integration.test.js

# Auth tests
node --test tests/auth.test.js
```

### Test Configuration

Set environment variables for testing:

```bash
export ASANA_ACCESS_TOKEN="test_token"
export TEST_BASE_URL="http://localhost:9876"
export MCP_TEST_TARGET="local"  # or "remote"
```

## Development

### Project Structure

```
asana-mcp-server-extended/
├── src/
│   ├── index.ts          # Main server implementation
│   └── auth.ts           # Authentication helpers
├── tests/
│   ├── auth.test.js      # Authentication tests
│   ├── pkce-handshake.test.js  # OAuth PKCE flow tests
│   ├── tools/
│   │   ├── integration.test.js   # Integration tests
│   │   └── task-tools.test.js    # Unit tests
│   └── helpers/
│       └── test-server.js        # Test server utilities
├── docs/
│   └── guidelines/       # Development guidelines
└── dist/                 # Compiled output
```

### Building

```bash
npm run build
```

### Type Checking

```bash
npm run type-check
```

## Deployment

### Environment Variables

Ensure all required environment variables are set in your deployment environment.

### Docker

```dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
EXPOSE 8766
CMD ["node", "dist/index.js"]
```

### Health Monitoring

Monitor the `/health` endpoint for server status:

```bash
curl https://your-domain.com/health
```

## Troubleshooting

### Common Issues

1. **"ASANA_ACCESS_TOKEN environment variable is required"**
   - Ensure the token is set in your environment
   - Check token validity in Asana Developer Console

2. **"Asana API error (401)"**
   - Verify your access token is valid
   - Check token permissions/scopes

3. **"Invalid gid"**
   - Asana gids are numeric strings (e.g., "1234567890")
   - Ensure gids are passed as strings, not numbers

4. **OAuth flow fails**
   - Verify GitHub OAuth credentials are correct
   - Check callback URL matches registered redirect URI

## Contributing

1. Follow the coding guidelines in `docs/guidelines/`
2. Write tests for new features
3. Update documentation
4. Ensure all tests pass

## License

[Your License Here]

## Support

For issues and questions:
- GitHub Issues: [repository-url]/issues
- Asana API Docs: https://developers.asana.com/reference/rest-api-reference