Atlassian Goals MCP Server
Provides tools for querying, searching, and updating Atlassian Goals and Projects via the Atlassian Goals API, including reading goals and projects, posting weekly status updates, editing or deleting updates, updating goal metadata, and managing tags.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Atlassian Goals MCP Serverlist my top 10 goals with status in progress"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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(replaceyour-companywith your subdomain) and copy thecloudIdvalueSite 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.jsonWindows:
%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:
Clone and build:
git clone https://github.com/expel-io/atlassian-goals-mcp.git
cd atlassian-goals-mcp
npm install
npm run buildUpdate 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"
}
}
}
}Optionally create a
.envfile for testing:
cp .env.example .env
# Edit .env with your credentialsAvailable 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 20status(optional): one ofNOT_STARTED,IN_PROGRESS,COMPLETED,CANCELLEDsearchTerm(optional): partial-match filter on goal nametags(optional): array of tag names; multiple tags AND togethercursor(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_tracklimit(optional): 1–100, default 20cursor(optional): pagination cursor
Projects — Read
list_projects
List projects with optional name filtering and cursor pagination.
Parameters:
limit(optional): 1–100, default 20searchTerm(optional): partial-match filter on project namecursor(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 20cursor(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 ARIsummary(required): the visible headline, max 280 charsdetails(optional): longer-form "More detail" body (no length limit)status(optional): see abovescore(optional): integer 1–100targetDate(optional):{ date: "YYYY-MM-DD", confidence?: "EXACT"|"QUARTER"|"HALF"|"YEAR" }metricUpdates(optional):[{ targetId, value }]—targetIdis the metric target ID fromget_goaldryRun(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 ARIgoalUpdateId(required): update ARI (ari:cloud:townsquare:{cloudId}:goal-update/{uuid})summary,details,status,score,targetDate(all optional): same aspost_goal_updatemetricUpdates(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 goaldryRun(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 ARIname(optional): new goal namedescription(optional): markdownownerId(optional): Atlassian account ID (the valueget_goalreturns asowner.accountId)targetDate(optional):{ date, confidence? }startDate(optional):YYYY-MM-DDarchived(optional): booleandryRun(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 ARItagNames(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 ARItagNames(optional): array of tag names — looked up against the goal's current tags; errors if a name is not currently attachedtagIds(optional): array of tag ARIs — provide eithertagNamesortagIdsdryRun(optional)
Operational
health_check
Verify API connectivity, authentication, and performance.
Parameters:
verbose(optional): include diagnostic details (default false)
Development
Build
npm run buildWatch Mode
For development with automatic rebuilding:
npm run watchProject 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.mdTesting
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:uiUnit 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 parsingutils/tql.test.ts— TQL escaping/injection preventionutils/goal-update-status.test.ts— score/status resolution for the update toolsatlassian/client.test.ts— rate limiting and error handlingatlassian/mutation-result.test.ts— write-mutation payload-error unwrappingtools/*.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:
Set up your
.envfile with valid Atlassian credentialsOptionally set
TEST_OWNER_ACCOUNT_IDto a valid account ID from your workspace to test owner filtering. To find your account ID, look at theowner.accountIdfield on any goal returned byget_goal.Run
npm run test:integration
Integration test suites:
connection.test.ts— API connectivity and configurationhealth-check.test.ts— health-check tool behaviorlist-goals.test.ts— goal listingget-goal.test.ts— single goal detailget-goals.test.ts— batch goal fetchingsearch-goals.test.ts— TQL goal searchprojects.test.ts— project list/get/searchupdates.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 variationsSeveral 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.jsThese 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 E401ornpm ERR! 401 UnauthorizedETIMEDOUTorENOTFOUNDerrorsProxy 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:
Check npm registry configuration:
npm config get registry # Should show https://registry.npmjs.org/ for public packagesCheck for authentication requirements:
npm config get //registry.npmjs.org/:_authToken # If set, your npm may require authentication for public packagesView all npm configuration:
npm config list # Look for proxy, registry, or cert settingsTest 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=trueLog Levels:
ERROR: Errors and failuresWARN: Warnings and potential issuesINFO: Tool calls, completions, and important eventsDEBUG: 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=trueAPI 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:
This MCP server: Open an issue in this repository
Atlassian Goals API: Visit Atlassian Developer Community
Claude Desktop: Visit Anthropic Support
This server cannot be installed
Maintenance
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
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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