Skip to main content
Glama
expel-io

Atlassian Goals MCP Server

by expel-io

Atlassian Goals MCP Server

A Model Context Protocol (MCP) server for the Atlassian Goals API. Enables AI assistants like Claude to query, search, and update Atlassian Goals and Projects.

Features

Goals — Read

  • List, get (single or batch), and search goals via TQL (Townsquare Query Language)

Projects — Read

  • List, get (single or batch), and search projects via TQL

Goals — Write

  • Post weekly status updates (with summary, More detail, status/score, target date, and metric values)

  • Edit or delete the most recent update

  • Update goal metadata (name, description, owner, target/start date, archive flag)

  • Add or remove goal tags by name

Operational

  • Health check for API connectivity and authentication

  • Security: TQL injection prevention, input validation, request timeouts, retry with exponential backoff

  • Performance: rate limiting, automatic throttling, structured logging

  • Robustness: enhanced ADF parser supporting 15+ node types; markdown→ADF conversion for write fields

Related MCP server: MCP Jira & Confluence Server

Prerequisites

  • Node.js >= 18.0.0 (comes with Claude Desktop)

  • Atlassian Cloud account with Goals access

  • Atlassian API token

Quick Start

1. Get Your Atlassian Credentials

You'll need these four values:

  • Email: Your Atlassian account email

  • API Token: Generate at https://id.atlassian.com/manage-profile/security/api-tokens

  • Cloud ID: Visit https://your-company.atlassian.net/_edge/tenant_info (replace your-company with your subdomain) and copy the cloudId value

  • Site URL: Your Atlassian site URL (e.g., https://your-company.atlassian.net)

2. Add to Claude Desktop

Open your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add this configuration (replace the placeholder values with your credentials from step 1):

{
  "mcpServers": {
    "atlassian-goals": {
      "command": "npx",
      "args": ["-y", "github:expel-io/atlassian-goals-mcp"],
      "env": {
        "ATLASSIAN_EMAIL": "your-email@example.com",
        "ATLASSIAN_API_TOKEN": "your-api-token",
        "ATLASSIAN_CLOUD_ID": "your-cloud-id",
        "ATLASSIAN_SITE_URL": "https://your-subdomain.atlassian.net"
      }
    }
  }
}

3. Restart Claude Desktop

Restart Claude Desktop to load the MCP server.

That's it! You can now ask Claude about your Atlassian Goals.

Local Development

If you want to modify or contribute to this server:

  1. Clone and build:

git clone https://github.com/expel-io/atlassian-goals-mcp.git
cd atlassian-goals-mcp
npm install
npm run build
  1. Update your Claude Desktop config to use the local build:

{
  "mcpServers": {
    "atlassian-goals": {
      "command": "node",
      "args": ["/absolute/path/to/atlassian-goals-mcp/build/index.js"],
      "env": {
        "ATLASSIAN_EMAIL": "your-email@example.com",
        "ATLASSIAN_API_TOKEN": "your-api-token",
        "ATLASSIAN_CLOUD_ID": "your-cloud-id",
        "ATLASSIAN_SITE_URL": "https://your-subdomain.atlassian.net"
      }
    }
  }
}
  1. Optionally create a .env file for testing:

cp .env.example .env
# Edit .env with your credentials

Available Tools

Tools are grouped by surface area. All goal/update IDs are Atlassian ARIs (e.g. ari:cloud:townsquare:{cloudId}:goal/{uuid}); the formats are validated by each tool's input schema.

Goals — Read

list_goals

List goals with optional filtering by status, name, or tags. Supports cursor-based pagination.

Parameters:

  • limit (optional): 1–100, default 20

  • status (optional): one of NOT_STARTED, IN_PROGRESS, COMPLETED, CANCELLED

  • searchTerm (optional): partial-match filter on goal name

  • tags (optional): array of tag names; multiple tags AND together

  • cursor (optional): pagination cursor from a previous response

get_goal

Fetch a single goal with description, owner, metrics, parent/sub-goal relationships, tags, and recent updates.

Parameters:

  • goalId (required): goal ARI

get_goals

Batch-fetch multiple goals in one request. More efficient than calling get_goal repeatedly.

Parameters:

  • goalIds (required): array of goal ARIs (1–20)

search_goals

Search goals using TQL (Townsquare Query Language).

Operators: LIKE (partial, supports _ as a single-character wildcard), = (exact), AND, OR. Fields: name, status (pending / on_track / at_risk / off_track / done / cancelled), owner (account ID), tag.

Parameters:

  • searchString (required): a TQL query, e.g. name LIKE "Q4" AND status = on_track

  • limit (optional): 1–100, default 20

  • cursor (optional): pagination cursor

Projects — Read

list_projects

List projects with optional name filtering and cursor pagination.

Parameters:

  • limit (optional): 1–100, default 20

  • searchTerm (optional): partial-match filter on project name

  • cursor (optional): pagination cursor

get_project

Fetch a single project with description, owner, members, linked goals, and recent updates.

Parameters:

  • projectId (required): project ARI (ari:cloud:townsquare:{cloudId}:project/{uuid})

get_projects

Batch-fetch multiple projects (1–20 per call).

Parameters:

  • projectIds (required): array of project ARIs

search_projects

Search projects using TQL. Currently supports LIKE on name with OR.

Parameters:

  • searchString (required): TQL query, e.g. name LIKE "Integration"

  • limit (optional): 1–100, default 20

  • cursor (optional): pagination cursor

Goals — Write

post_goal_update

Post a weekly status update — the entry that appears in the goal's Updates tab.

Status/score model: on_track/at_risk/off_track are derived from a 1–100 integer score (the Atlassian UI labels these as decimals like "0.8", but the API stores integers). Bands: 10–30 = off_track, 40–60 = at_risk, 70–100 = on_track. Status alone fills the band midpoint; score alone infers status; combined values are validated. pending/paused/done/cancelled/archived take only status — no score.

Markdown is supported in both summary and details and is converted to ADF before send.

Parameters:

  • goalId (required): goal ARI

  • summary (required): the visible headline, max 280 chars

  • details (optional): longer-form "More detail" body (no length limit)

  • status (optional): see above

  • score (optional): integer 1–100

  • targetDate (optional): { date: "YYYY-MM-DD", confidence?: "EXACT"|"QUARTER"|"HALF"|"YEAR" }

  • metricUpdates (optional): [{ targetId, value }]targetId is the metric target ID from get_goal

  • dryRun (optional): return the resolved mutation payload without submitting

edit_goal_update

Edit a previously-posted update. Partial fields are supported; at least one editable field is required.

Both goalId and goalUpdateId are required so the tool can pre-query existing update notes and pass updateNoteId when replacing details — without it, Townsquare appends a second note that the UI doesn't render.

Note the metric-input asymmetry with post_goal_update: metricUpdates takes metricId (the metric itself), not targetId (the metric target).

Parameters:

  • goalId (required): goal ARI

  • goalUpdateId (required): update ARI (ari:cloud:townsquare:{cloudId}:goal-update/{uuid})

  • summary, details, status, score, targetDate (all optional): same as post_goal_update

  • metricUpdates (optional): [{ metricId, value }]

  • dryRun (optional)

delete_latest_goal_update

Remove the most recent update on a goal. The Townsquare API only deletes the latest update per goal; earlier updates cannot be removed this way.

Parameters:

  • goalUpdateId (required): update ARI; must be the latest on its goal

  • dryRun (optional)

update_goal

Edit a goal's metadata. Status changes are NOT done here — use post_goal_update. Tags are also separate — use add_goal_tags / remove_goal_tags.

description accepts markdown and is converted to ADF. archived: true archives the goal (destructive in effect — confirm with the user before flipping on a real goal).

Parameters:

  • goalId (required): goal ARI

  • name (optional): new goal name

  • description (optional): markdown

  • ownerId (optional): Atlassian account ID (the value get_goal returns as owner.accountId)

  • targetDate (optional): { date, confidence? }

  • startDate (optional): YYYY-MM-DD

  • archived (optional): boolean

  • dryRun (optional)

At least one editable field is required.

add_goal_tags

Attach tags to a goal by name. Tag names that don't yet exist at the workspace level are auto-created — the Townsquare API does not expose a delete-tag mutation, so prefer reusing existing names over inventing new ones.

Parameters:

  • goalId (required): goal ARI

  • tagNames (required): array of tag names (≥1)

  • dryRun (optional)

remove_goal_tags

Detach tags from a goal. Prefer tagNames — the tool looks up matching tag IDs from the goal's current tag list. tagIds is supported for callers that already have them.

Parameters:

  • goalId (required): goal ARI

  • tagNames (optional): array of tag names — looked up against the goal's current tags; errors if a name is not currently attached

  • tagIds (optional): array of tag ARIs — provide either tagNames or tagIds

  • dryRun (optional)

Operational

health_check

Verify API connectivity, authentication, and performance.

Parameters:

  • verbose (optional): include diagnostic details (default false)

Development

Build

npm run build

Watch Mode

For development with automatic rebuilding:

npm run watch

Project Structure

atlassian-goals-mcp/
├── src/
│   ├── index.ts                          # Entry point
│   ├── server.ts                         # MCP server setup
│   ├── config.ts                         # Configuration management
│   ├── atlassian/
│   │   ├── client.ts                     # GraphQL client
│   │   ├── queries.ts                    # GraphQL query + mutation definitions
│   │   ├── mutation-result.ts            # Shared payload-error unwrap for write mutations
│   │   └── types.ts                      # TypeScript interfaces
│   ├── tools/
│   │   ├── index.ts                      # Tool registry + executeTool dispatch
│   │   ├── list-goals.ts                 # Goal tools — read
│   │   ├── get-goal.ts
│   │   ├── get-goals.ts
│   │   ├── search-goals.ts
│   │   ├── list-projects.ts              # Project tools — read
│   │   ├── get-project.ts
│   │   ├── get-projects.ts
│   │   ├── search-projects.ts
│   │   ├── post-goal-update.ts           # Goal tools — write
│   │   ├── edit-goal-update.ts
│   │   ├── delete-latest-goal-update.ts
│   │   ├── update-goal.ts
│   │   ├── add-goal-tags.ts
│   │   ├── remove-goal-tags.ts
│   │   └── health-check.ts
│   └── utils/
│       ├── logger.ts                     # Logging utility
│       ├── errors.ts                     # Error handling
│       ├── adf-parser.ts                 # ADF → text
│       ├── markdown-to-adf.ts            # Markdown → ADF JSON (write fields)
│       ├── goal-update-status.ts         # Score/status resolution shared by post/edit
│       ├── tql.ts                        # TQL escaping/builders
│       ├── goal-formatter.ts             # Read-tool formatting
│       └── project-formatter.ts          # Read-tool formatting
├── tests/
│   ├── unit/                             # Unit tests
│   ├── integration/                      # Integration tests
│   └── helpers/                          # Test utilities
├── scripts/                              # Introspection + live verification scripts
├── build/                                # Compiled output
├── package.json
├── tsconfig.json
├── vitest.config.ts                      # Test configuration
└── README.md

Testing

This project uses Vitest for testing with separate unit and integration test suites.

Running Tests

# Run all tests
npm test

# Run unit tests only (fast, no credentials needed)
npm run test:unit

# Run integration tests (requires .env configuration)
npm run test:integration

# Watch mode for development
npm run test:watch

# Generate coverage report
npm run test:coverage

# Interactive UI
npm run test:ui

Unit Tests

Unit tests are located in tests/unit/ and test individual functions and modules in isolation. They don't require API credentials and should run quickly.

Coverage:

  • utils/adf-parser.test.ts — Atlassian Document Format parsing

  • utils/tql.test.ts — TQL escaping/injection prevention

  • utils/goal-update-status.test.ts — score/status resolution for the update tools

  • atlassian/client.test.ts — rate limiting and error handling

  • atlassian/mutation-result.test.ts — write-mutation payload-error unwrapping

  • tools/*.test.ts — schema validation for each tool

Integration Tests

Integration tests are located in tests/integration/ and test against the real Atlassian Goals API. They require valid credentials in your .env file.

Note: Integration tests are automatically skipped if credentials are not available. This allows unit tests to run in CI environments without requiring API access.

To run integration tests locally:

  1. Set up your .env file with valid Atlassian credentials

  2. Optionally set TEST_OWNER_ACCOUNT_ID to a valid account ID from your workspace to test owner filtering. To find your account ID, look at the owner.accountId field on any goal returned by get_goal.

  3. Run npm run test:integration

Integration test suites:

  • connection.test.ts — API connectivity and configuration

  • health-check.test.ts — health-check tool behavior

  • list-goals.test.ts — goal listing

  • get-goal.test.ts — single goal detail

  • get-goals.test.ts — batch goal fetching

  • search-goals.test.ts — TQL goal search

  • projects.test.ts — project list/get/search

  • updates.test.ts — goal update data structures

Write tools (post_goal_update, edit_goal_update, delete_latest_goal_update, update_goal, add_goal_tags, remove_goal_tags) are exercised by the scripts/test-*.js live-verification scripts rather than the integration test suite — they need a known-safe test goal to write against. See Development Scripts below.

Development Scripts

# GraphQL schema introspection (npm-aliased)
npm run introspect:goal      # Inspect TownsquareGoal type
npm run introspect:types     # Inspect available types
npm run introspect:updates   # Inspect update types
npm run introspect:metric    # Inspect metric types

# Diagnostic tools
npm run diagnose:ari         # Test ARI format variations

Several more one-off scripts live in scripts/ and are run directly with node:

# Type introspection (used when adding write tools)
node scripts/introspect-write-inputs.js
node scripts/introspect-edit-delete.js
node scripts/introspect-tag-mutations.js
node scripts/introspect-mutations.js

# Live-verification harnesses for the write tools — each one posts/edits/
# deletes test data on a "Jeffrey Test" goal and reverts when possible.
# These are NOT in the integration test suite because they need a known-safe
# test goal to write against.
node scripts/test-post-goal-update.js
node scripts/test-edit-delete-goal-update.js
node scripts/test-update-goal.js
node scripts/test-tag-tools.js
node scripts/verify-update-notes-behavior.js

These scripts are useful for:

  • Exploring available GraphQL fields

  • Verifying write-tool behavior end-to-end against the live API

  • Troubleshooting API connectivity

  • Understanding the data schema

Troubleshooting

Authentication Errors

If you see authentication errors:

  • Verify your API token is correct and hasn't expired

  • Ensure your email matches the Atlassian account

  • Check that your Cloud ID is correct

Connection Errors

If the server can't connect:

  • Verify your site URL is correct

  • Check your network connection

  • Ensure you have access to the Atlassian Goals API

Configuration Errors

If you see "Invalid configuration" errors:

  • Check all required environment variables are set

  • Verify the format of your site URL (must be a valid URL)

  • Ensure your email is in valid email format

Package Installation Errors

If npx fails to install or run the server, you may encounter authentication or network errors from your package manager:

Symptoms:

  • npm ERR! code E401 or npm ERR! 401 Unauthorized

  • ETIMEDOUT or ENOTFOUND errors

  • Proxy authentication failures

  • Certificate verification errors

Common Causes:

  • Corporate package registry proxies (Artifactory, Nexus, Verdaccio)

  • npm registry authentication required

  • Network proxy configuration

  • SSL/TLS certificate issues

Debugging Steps:

  1. Check npm registry configuration:

    npm config get registry
    # Should show https://registry.npmjs.org/ for public packages
  2. Check for authentication requirements:

    npm config get //registry.npmjs.org/:_authToken
    # If set, your npm may require authentication for public packages
  3. View all npm configuration:

    npm config list
    # Look for proxy, registry, or cert settings
  4. Test registry access:

    npm view @modelcontextprotocol/sdk version
    # Should return a version number if registry is accessible

Solutions:

  • Corporate registry: Contact your IT team about accessing public npm packages

  • Proxy settings: Configure npm proxy settings or use VPN

  • Direct registry: Temporarily use the official npm registry:

    npm config set registry https://registry.npmjs.org/
  • Local installation: Clone the repository and use the local development setup instead of npx

Logging and Performance Monitoring

The server includes structured logging and performance profiling capabilities.

Environment Variables:

# Enable debug logging (logs INFO level and above)
DEBUG=true

# Enable trace logging (very verbose, includes timing details)
TRACE=true

# Show performance metrics in tool responses
SHOW_PERFORMANCE=true

Log Levels:

  • ERROR: Errors and failures

  • WARN: Warnings and potential issues

  • INFO: Tool calls, completions, and important events

  • DEBUG: Detailed diagnostic information (requires DEBUG=true)

  • TRACE: Very detailed tracing including timers (requires DEBUG=true and TRACE=true)

Log Format:

[2025-01-06T12:34:56.789Z] [INFO] Tool called: list_goals {"tool":"list_goals","operation":"start","args":"{\"limit\":20}"}
[2025-01-06T12:34:57.123Z] [INFO] Tool completed: list_goals (334ms) {"tool":"list_goals","operation":"complete","duration":334,"resultSize":1250}

Performance Profiling:

  • Automatic timing for all tool calls

  • Duration logged in milliseconds

  • Result size tracking

  • Optional performance metrics in responses (with SHOW_PERFORMANCE=true)

Viewing Logs:

  • Logs are written to stderr (stdout is reserved for MCP JSON-RPC)

  • In Claude Desktop: View logs in developer console

  • In terminal: Redirect stderr to file: node build/index.js 2> logs.txt

Debug Mode

Enable debug logging by adding to your environment variables:

DEBUG=true

API Reference

This server uses the Atlassian Goals GraphQL API. For more information:

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Support

For issues related to:

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/expel-io/atlassian-goals-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server