Skip to main content
Glama

Yandex Tracker MCP Server

Test Workflow

A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with Yandex Tracker APIs. This server provides secure, authenticated access to Yandex Tracker issues, queues, comments, worklogs, and search functionality with optional Redis caching for improved performance.

Documentation in Russian is available here / Документация на русском языке доступна здесь.

Features

  • Complete Queue Management: List and access all available Yandex Tracker queues with pagination support, tag retrieval, and detailed metadata

  • Projects, Portfolios and Goals: Dedicated read and write tools with explicit schemas for each entity type in the Tracker "entities" API (opt-in via TRACKER_ENTITIES_ENABLED)

  • User Management: Retrieve user account information, including login details, email addresses, license status, and organizational data

  • Full Issue Lifecycle: Create, read, update, and manage issues with support for custom fields, attachments, and workflow transitions

  • Status Workflow Management: Execute status transitions, close issues with resolutions, and navigate complex workflows

  • Workflow Configuration: Read workflows with their statuses, transitions and transition screens, and change them (writes opt-in via TRACKER_WORKFLOWS_WRITE_ENABLED)

  • Administration (opt-in via TRACKER_ADMIN_ENABLED): queue permissions, triggers, autoactions and macros, components, boards and columns, absences and templates - kept out of the default tool list to keep it small

  • Field Management: Access global fields, queue-specific local fields, statuses, issue types, priorities, and resolutions

  • Boards and Sprints: List agile boards and their sprints to find sprint IDs for issue planning

  • Advanced Query Language: Full Yandex Tracker Query Language support with complex filtering, sorting, and date functions

  • Performance Caching: Optional Redis caching layer for improved response times

  • Security Controls: Configurable queue access restrictions and secure token handling

  • Multiple Transport Options: Support for stdio, SSE (deprecated), and HTTP transports for flexible integration

  • OAuth 2.0 Authentication: Dynamic token-based authentication with automatic refresh support as an alternative to static API tokens

  • Organization Support: Compatible with both standard and cloud organization IDs

Organization ID Configuration

Choose one of the following based on your Yandex organization type:

  • Yandex Cloud Organization: Use TRACKER_CLOUD_ORG_ID env var later for Yandex Cloud-managed organizations

  • Yandex 360 Organization: Use TRACKER_ORG_ID env var later for Yandex 360 organizations

You can find your organization ID in the Yandex Tracker URL or organization settings.

Related MCP server: yandex-tracker-mcp

MCP Client Configuration

Installing extension in Claude Desktop

Yandex Tracker MCP Server can be one-click installed in Claude Desktop as and extension.

Installation

  1. Download the *.mcpb file from GitHub Releases, or build it from a clone with npx @anthropic-ai/mcpb pack ..

  2. Double-click the downloaded file to install it in Claude Desktop. img.png

  3. Provide your Yandex Tracker OAuth token when prompted. img.png

  4. Make sure extension is enabled - now you may use this MCP Server.

Manual installation

Prerequisites

  • uv installed globally

  • Valid Yandex Tracker API token with appropriate permissions

The following sections show how to configure the MCP server for different AI clients. You can use either uvx --from git+https://github.com/Hollway/yandex-tracker-mcp yandex-tracker-mcp or a Docker image built from this repository (docker build -t yandex-tracker-mcp https://github.com/Hollway/yandex-tracker-mcp.git, see Docker Deployment). Both require these environment variables:

  • Authentication (one of the following):

    • TRACKER_TOKEN - Your Yandex Tracker OAuth token

    • TRACKER_IAM_TOKEN - Your IAM token

    • TRACKER_SA_KEY_ID, TRACKER_SA_SERVICE_ACCOUNT_ID, TRACKER_SA_PRIVATE_KEY - Service account credentials

  • Organization - exactly one of the following:

    • TRACKER_CLOUD_ORG_ID - Your Yandex Cloud organization ID

    • TRACKER_ORG_ID - Your Yandex 360 organization ID

Set one of the two. Setting both makes every Tracker call fail with Only one of org_id or cloud_org_id should be provided. The examples below use TRACKER_CLOUD_ORG_ID; on Yandex 360, replace that key with TRACKER_ORG_ID.

Configuration file path:

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

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

Using uvx:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Using Docker:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "TRACKER_TOKEN",
        "-e", "TRACKER_CLOUD_ORG_ID",
        "yandex-tracker-mcp:latest"
      ],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Using uvx:

claude mcp add yandex-tracker uvx --from git+https://github.com/Hollway/yandex-tracker-mcp yandex-tracker-mcp \
  -e TRACKER_TOKEN=your_tracker_token_here \
  -e TRACKER_CLOUD_ORG_ID=your_cloud_org_id_here \
  -e TRANSPORT=stdio

Using Docker:

claude mcp add yandex-tracker docker "run --rm -i -e TRACKER_TOKEN=your_tracker_token_here -e TRACKER_CLOUD_ORG_ID=your_cloud_org_id_here -e TRANSPORT=stdio yandex-tracker-mcp:latest"

Configuration file path:

  • Project-specific: .cursor/mcp.json in your project directory

  • Global: ~/.cursor/mcp.json

Using uvx:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Using Docker:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "TRACKER_TOKEN",
        "-e", "TRACKER_CLOUD_ORG_ID",
        "yandex-tracker-mcp:latest"
      ],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Configuration file path:

  • ~/.codeium/windsurf/mcp_config.json

Access via: Windsurf Settings → Cascade tab → Model Context Protocol (MCP) Servers → "View raw config"

Using uvx:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Using Docker:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "TRACKER_TOKEN",
        "-e", "TRACKER_CLOUD_ORG_ID",
        "yandex-tracker-mcp:latest"
      ],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Configuration file path:

  • ~/.config/zed/settings.json

Access via: Cmd+, (macOS) or Ctrl+, (Linux/Windows) or command palette: "zed: open settings"

Note: Requires Zed Preview version for MCP support.

Using uvx:

{
  "context_servers": {
    "yandex-tracker": {
      "source": "custom",
      "command": {
        "path": "uvx",
        "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
        "env": {
          "TRACKER_TOKEN": "your_tracker_token_here",
          "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
        }
      }
    }
  }
}

Using Docker:

{
  "context_servers": {
    "yandex-tracker": {
      "source": "custom",
      "command": {
        "path": "docker",
        "args": [
          "run", "--rm", "-i",
          "-e", "TRACKER_TOKEN",
          "-e", "TRACKER_CLOUD_ORG_ID",
          "yandex-tracker-mcp:latest"
        ],
        "env": {
          "TRACKER_TOKEN": "your_tracker_token_here",
          "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
        }
      }
    }
  }
}

Configuration file path:

  • Workspace: .vscode/mcp.json in your project directory

  • Global: VS Code settings.json

Option 1: Workspace Configuration (Recommended for security)

Create .vscode/mcp.json:

Using uvx:

{
  "inputs": [
    {
      "type": "promptString",
      "id": "tracker-token",
      "description": "Yandex Tracker Token",
      "password": true
    },
    {
      "type": "promptString",
      "id": "cloud-org-id",
      "description": "Yandex Cloud Organization ID"
    }
  ],
  "servers": {
    "yandex-tracker": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
      "env": {
        "TRACKER_TOKEN": "${input:tracker-token}",
        "TRACKER_CLOUD_ORG_ID": "${input:cloud-org-id}",
        "TRANSPORT": "stdio"
      }
    }
  }
}

Using Docker:

{
  "inputs": [
    {
      "type": "promptString",
      "id": "tracker-token",
      "description": "Yandex Tracker Token",
      "password": true
    },
    {
      "type": "promptString",
      "id": "cloud-org-id",
      "description": "Yandex Cloud Organization ID"
    }
  ],
  "servers": {
    "yandex-tracker": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "TRACKER_TOKEN",
        "-e", "TRACKER_CLOUD_ORG_ID",
        "yandex-tracker-mcp:latest"
      ],
      "env": {
        "TRACKER_TOKEN": "${input:tracker-token}",
        "TRACKER_CLOUD_ORG_ID": "${input:cloud-org-id}",
        "TRANSPORT": "stdio"
      }
    }
  }
}

Option 2: Global Configuration

Add to VS Code settings.json:

Using uvx:

{
  "github.copilot.chat.mcp.servers": {
    "yandex-tracker": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Using Docker:

{
  "github.copilot.chat.mcp.servers": {
    "yandex-tracker": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "TRACKER_TOKEN",
        "-e", "TRACKER_CLOUD_ORG_ID",
        "yandex-tracker-mcp:latest"
      ],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

For other MCP-compatible clients, use the standard MCP server configuration format:

Using uvx:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Hollway/yandex-tracker-mcp", "yandex-tracker-mcp"],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Using Docker:

{
  "mcpServers": {
    "yandex-tracker": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "TRACKER_TOKEN",
        "-e", "TRACKER_CLOUD_ORG_ID",
        "yandex-tracker-mcp:latest"
      ],
      "env": {
        "TRACKER_TOKEN": "your_tracker_token_here",
        "TRACKER_CLOUD_ORG_ID": "your_cloud_org_id_here"
      }
    }
  }
}

Important Notes:

  • Replace placeholder values with your actual credentials

  • Restart your AI client after configuration changes

  • Ensure uvx is installed and available in your system PATH

  • For production use, consider using environment variables instead of hardcoding tokens

Available MCP Tools

The server exposes the following tools through the MCP protocol:

queue_get_triggers, queue_delete_tag and the local field writes need TRACKER_ADMIN_ENABLED=true; queue_get_workflows comes with it or with TRACKER_WORKFLOWS_WRITE_ENABLED.

Tool

What it does

Key arguments

queues_get_all

Every queue the token may see; returns {values, hits, pages}

fields, page (omit to walk every page), per_page

queue_get_tags

The tags defined in the queue

queue_id (a key like "SOMEPROJECT")

queue_get_forms

The queue's issue-intake forms (Yandex Forms) with id, name, description and path; people fill them in, issue_create files an issue

queue_id

queue_delete_tag

Remove a tag from the queue's list; Tracker refuses a tag still set on an issue

queue_id, tag

queue_get_triggers

Automation triggers: conditions and actions, webhook credentials left out

queue_id, active_only

queue_get_versions

The queue's versions, with dates and status

queue_id

queue_get_components

The queue's components as full objects, with lead, auto-assign flag and version; queue_get_metadata with expand: ["components"] gives ids and names only

queue_id

queue_create_version

Create a version in the queue

queue_id, name, description, start_date, due_date (YYYY-MM-DD)

queue_update_version

Rename a version or change its description or dates

version_id, name, description, start_date, due_date

queue_delete_version

Delete a version - it cannot be restored

version_id

queue_get_fields

The fields configured on the queue, local ones included; schema.required marks the mandatory ones

queue_id, include_local_fields

queue_get_local_field

One local field of the queue

queue_id, field_key

queue_create_local_field

Create a field only this queue's issues have; the same settings as field_create

queue_id, field_key, name, category, type, options

queue_update_local_field

Change a local field's name, description, category, drop-down values or display flags

queue_id, field_key

queue_get_metadata

Name, description, default type and priority, plus whatever expand asks for

queue_id, expand (all, projects, components, versions, types, team, workflows, fields, issueTypesConfig)

queue_get_workflows

The workflows the queue runs, each with the issue types it applies to

queue_id

  • Read queue_get_fields before issue_create, but it is not the whole registry: system fields such as parent or estimation are settable without appearing there, and get_global_fields lists every field the organization has.

  • A local field is read and changed by its key, but an issue write names it by its id, which looks like 6adf5b36c2dc6e1bb442dffa--locTest; the key alone answers 400 "Field [locTest] was not found". A local field cannot be deleted through the API.

  • queue_get_metadata with expand: ["issueTypesConfig"] is where the resolutions valid for each issue type come from - issue_close needs one of them.

  • All of these respect TRACKER_LIMIT_QUEUES. hits / pages from queues_get_all are reported only for an explicit single page on a server without the allow-list, since the totals count queues the allow-list then hides.

Opt-in: these tools are registered only with TRACKER_ADMIN_ENABLED=true (the writes on a writable server).

Triggers react to issue events, autoactions run on a schedule over the issues a filter selects, and macros are applied by hand. Actions and conditions are passed as Tracker's own objects, keyed by type.

Tool

What it does

Key arguments

queue_get_trigger

One trigger with conditions, actions and current version

queue_id, trigger_id

queue_create_trigger

Create a trigger

queue_id, name, actions, conditions, active

queue_update_trigger

Rename, replace actions or conditions, reorder (before), or switch off with active: false

queue_id, trigger_id, version (omit to use the current one)

queue_delete_trigger

Delete a trigger for good; active: false keeps it switched off instead

queue_id, trigger_id

queue_get_trigger_logs

Runs of the trigger's HTTP request actions: issue, request sent, status code back

queue_id, trigger_id, issue_id, limit (10 by default, at most 100), created_from, created_to

queue_get_autoactions

The queue's autoactions

queue_id

queue_get_autoaction

One autoaction with filter or query, actions, interval and last launch

queue_id, autoaction_id

queue_create_autoaction

Create an autoaction

queue_id, name, actions, filter or query, interval_millis, calendar_id

queue_get_autoaction_logs

Launches of an autoaction; with run_id, the issues of one launch

queue_id, autoaction_id, run_id

queue_get_macros

The queue's macros: the comment each posts and the fields it changes

queue_id

queue_get_macro

One macro

queue_id, macro_id

queue_create_macro

Create a macro

queue_id, name, body, issue_update

queue_update_macro

Change a macro; issue_update replaces all its field changes, clear_body removes the comment

queue_id, macro_id

queue_delete_macro

Delete a macro

queue_id, macro_id

  • The API has no autoaction update or delete: an autoaction is changed in the Tracker UI. A trigger is deleted through an undocumented DELETE that needs no version.

  • Webhook credentials and headers are left out of what comes back; in a queue that forbids AI tools access, the log tools leave out the request body and the issue summaries.

  • Reads respect TRACKER_LIMIT_QUEUES, writes TRACKER_READ_ONLY_QUEUES as well.

Opt-in: these tools are registered only with TRACKER_ADMIN_ENABLED=true (the writes on a writable server).

Tool

What it does

Key arguments

queue_create

Create a queue with its owner, default type and priority, and issue types

key, name, lead, default_type, default_priority, issue_types_config ([{issue_type, workflow, resolutions}])

queue_delete

Delete a queue with its issues

queue_id

queue_restore

Restore a deleted queue (administrators only)

queue_id

queue_set_issue_type_workflow

Add an issue type to the queue, or change the workflow it follows

queue_id, issue_type, workflow_id, resolutions, make_default

queue_remove_issue_type

Remove an issue type from the queue

queue_id, issue_type, new_default_type (required for the default type)

queue_get_permissions

Who may create, read and change issues, who may change the queue's settings and who is denied: users, groups and roles for each

queue_id

queue_get_user_permissions

The permissions one user has in the queue, each with the group, role or grant it comes through

queue_id, user (login or uid)

queue_get_group_permissions

The same for a user group

queue_id, group_id (from groups_get_all)

queue_update_permissions

Grant or revoke permissions: per permission, add / remove users, groups and roles, or set the whole list

queue_id, create, read, write, grant, deny

  • queue_update_permissions can lock people out of a queue, so the user confirms the change where the client supports elicitation; a client that cannot be asked goes ahead. Roles are author, assignee, follower, access (anyone the issue was shared with) and queue-lead; an unknown user or group is refused by Tracker.

  • queue_set_issue_type_workflow moves the existing issues of the type to the new workflow; one in a status the new workflow lacks is a case the API was not tried with (the UI asks for a status mapping). Tracker refuses a resolutions list missing one the workflow's transitions set.

  • queue_create under TRACKER_LIMIT_QUEUES takes only a key on the allow-list.

Everything here but component_get needs TRACKER_ADMIN_ENABLED=true.

A component is a label grouping a queue's issues by product, process or owner. Its numeric id is what issue_create / issue_update take in components.

Tool

What it does

Key arguments

component_get

One component with queue, lead, assignAuto and version

component_id (from queue_get_components or an issue's components)

component_create

Create a component in a queue

queue_id, name, description, lead (a login or uid), assign_auto

component_update

Change name, description, lead or auto-assign flag; omitted fields keep their value, clear_lead removes the lead

component_id, name, description, lead, assign_auto, clear_lead, version

component_delete

Delete a component

component_id

component_get_user_permissions

The permissions one user has on a component

component_id, user

component_get_group_permissions

The permissions one user group has on a component

component_id, group_id

component_update_permissions

Grant or revoke a component's permissions, the way queue_update_permissions does; returns them all

component_id, create, read, write, grant, version

  • TRACKER_LIMIT_QUEUES and TRACKER_READ_ONLY_QUEUES apply through the component's queue: component_update, component_delete and component_update_permissions read the component first to learn it, and a component in a queue outside TRACKER_LIMIT_QUEUES is reported as not found.

  • A component nobody has restricted has no permissions at all; the first change restricts it, and Tracker grants create, write and grant to the queue owner role on its own. The user confirms the change where the client can ask.

Projects, portfolios and goals are separate Yandex Tracker entities (distinct from queues), exposed through the Tracker "entities" API. Custom (organization-defined) attributes are not modeled and are not returned.

These tools are opt-in. They are registered only when TRACKER_ENTITIES_ENABLED=true (default false), because they add a large tool manifest and are not covered by the queue restrictions — see Queue Access Control.

The three entity types share one tool set, so it is listed once - the row says what the tool does, the columns which name to call:

What it does

Projects

Portfolios

Goals

One entity by id or shortId

project_get

portfolio_get

goal_get

Search by name substring and/or field filters; returns {values, hits, pages}

project_find

portfolio_find

goal_find

A page of comments; returns {comments, next_cursor}

project_get_comments

portfolio_get_comments

goal_get_comments

Create, returning the entity

project_create

portfolio_create

goal_create

Change any field creation takes

project_update

portfolio_update

goal_update

Delete it, and with with_board its board too - goals have no board

project_delete

portfolio_delete

goal_delete

Add a comment

project_add_comment

portfolio_add_comment

goal_add_comment

Edit a comment

project_update_comment

portfolio_update_comment

goal_update_comment

Delete a comment

project_delete_comment

portfolio_delete_comment

goal_delete_comment

Append one checklist item

project_add_checklist_item

portfolio_add_checklist_item

-

Edit one checklist item, leaving the fields you omit as they are

project_update_checklist_item

portfolio_update_checklist_item

-

Move a checklist item before another one

project_move_checklist_item

portfolio_move_checklist_item

-

Delete one checklist item

project_delete_checklist_item

portfolio_delete_checklist_item

-

Edit several existing items by id

project_update_checklist

portfolio_update_checklist

-

Delete the whole checklist

project_delete_checklist

portfolio_delete_checklist

-

Links to other projects, portfolios and goals, with the linked entity's id and the fields asked for

project_get_links

portfolio_get_links

goal_get_links

Delete a link by the linked entity's id

project_delete_link

portfolio_delete_link

goal_delete_link

Files attached to the entity, each with the comment it came with

project_get_attachments

portfolio_get_attachments

goal_get_attachments

Delete an attached file; the comment stays

project_delete_attachment

portfolio_delete_attachment

goal_delete_attachment

Add a metric (a dashboard widget shown on the page); returns all metrics

project_add_metric

portfolio_add_metric

goal_add_metric

Change a metric's name or widget link

project_update_metric

portfolio_update_metric

goal_update_metric

Delete a metric

project_delete_metric

portfolio_delete_metric

goal_delete_metric

Who may read, change and manage access, and the parent it is inherited from

project_get_permissions

portfolio_get_permissions

goal_get_permissions

Grant or revoke read / write / grant for users, groups and roles, or switch inherit; the user confirms

project_update_permissions

portfolio_update_permissions

goal_update_permissions

Append a key result: type value (with progress) or binary (with achieved)

-

-

goal_add_key_result

Change one key result, keeping the fields you omit

-

-

goal_update_key_result

Move a key result before another one, or to the end

-

-

goal_move_key_result

Delete one key result

-

-

goal_delete_key_result

Delete all key results

-

-

goal_delete_all_key_results

  • Arguments. Reads take entity_id and fields; the *_find tools take input, filter, order_by, order_asc, root_only, page, per_page. Create and update take summary (required on create), description, lead, team_users, clients, followers, start (goals have none), end, tags, entity_status, parent_entity, team_access and links, and update also comment and version (optimistic locking). Every tool takes the same fields selector and returns the entity.

  • links on create and update are added, never replaced: *_get_links reads them and *_delete_link removes one (a link is one relationship, deleted from either end). On update Tracker applies links only when a field actually changes or a comment comes with them, so a links-only update is rejected rather than reported as a success Tracker silently ignores.

  • Not in the default field set: checklistItems (the checklist tools return the whole entity, so ask for them to see the result), metricItems, and a goal's keyResultItems. The key result tools return the goal with its keyResultItems and progressPercentage; Tracker has no per-item write for key results, so an update or a move rewrites the list and every key result gets a new id - and the same goes for *_update_metric and the metrics. Access: a right includes the ones below it (WRITE holders are not listed under READ, and no READ at all means everyone may read); while an entity inherits its access from its parent Tracker ignores changes to it, so *_update_permissions refuses them unless the same call passes inherit=false. Goals use their own entityStatus values (draft, according_to_plan, at_risk, blocked, achieved, partially_achieved, not_achieved, exceeded, cancelled). Bulk changes are not supported.

users_create_absences, users_delete_absences and groups_get_all need TRACKER_ADMIN_ENABLED=true.

Tool

What it does

Key arguments

users_get_all

A page of the organization's users; returns {values, hits, pages}

page, per_page, fields

user_get

One user by login or uid

user_id ("john.doe" or "12345")

user_get_current

The user the current token belongs to

-

users_search

Find users by login, email or real name

login_or_email_or_name

users_get_absences

Vacations, sick leave, trips and other absences overlapping a period; needs organization administrator rights

users (up to 100), date_from, date_to

users_create_absences

Record absences and get their ids; needs organization administrator rights

absences (up to 100: user, workflow, date_from, date_to, full_day, work_in_absence)

users_delete_absences

Delete absences by id; needs organization administrator rights

absence_ids (up to 100)

groups_get_all

The organization's user groups with the numeric ids queue permissions take; returns {values, hits, pages}

page, per_page

  • users_search matches login and email exactly first and falls back to fuzzy name matching (80% similarity, at most the three best matches).

  • The page from users_get_all is the last one when page equals pages.

  • An absence cannot be edited: delete it and create it again. users_delete_absences succeeds for an unknown or already deleted id too. Both write tools are not registered in read-only mode and are not covered by the queue restrictions.

Tool

What it does

Key arguments

get_global_fields

Every global field of the organization, with its schema and type

-

field_get

One field of the organization: type, category, drop-down values and its current version

field_id

fields_get_categories

The categories that group the organization's fields

-

fields_find

Find a field by the name a user says, in Russian or English, or by part of its id: the id to write, the name for an issues_find query ("Story Points", SAP."System ID") and how its values are given

query, queue (adds its local fields)

field_get_values

The values a field accepts: drop-down options, priorities, issue types, resolutions, components or versions; truncated when more match than limit

field, queue or issue_id, query

field_create

Create a field for every queue; a drop-down list is a string, integer or user field with options

field_id, name, category, type, options

field_update

Change a field's name, description, category, drop-down values or display flags; options replaces the whole list

field_id

field_create_category

Create a field category

name, order

field_update_category

Change a category's name, description or order

category_id

Queue-local fields are not here - queue_get_fields returns them together with the global ones, and fields_find with a queue searches them.

An issues query names a field by its name, not its id: storyPoints: 3 is refused, "Story Points": 3 works - take it from ql_name of fields_find. People, statuses, sprints and issues are not listed by field_get_values: its error names the tool that lists them.

The four write tools need TRACKER_WORKFLOWS_WRITE_ENABLED=true on a writable server, like the status and resolution catalogue: a field belongs to the whole organization, so an update is refused while TRACKER_LIMIT_QUEUES or TRACKER_READ_ONLY_QUEUES is set (a create is not). Neither a field nor a category can be deleted through the API.

Tool

What it does

Key arguments

get_statuses

Every issue status the organization defines

-

get_issue_types

Every issue type, for the type argument of issue_create / issue_update

-

get_priorities

Every priority, with id, key, name and order

-

get_resolutions

Every resolution, for the resolution_id of issue_close

-

These four are organization-wide. A queue may accept only some of the values they list, and Tracker answers 422 for one it does not accept - queue_get_metadata with expand: ["issueTypesConfig"] says which resolutions each issue type takes.

The reads are registered with TRACKER_ADMIN_ENABLED=true or together with the writes.

A workflow ('рабочий процесс') is the set of statuses an issue type moves through and the transitions between them; a transition may open a screen ('экран перехода') that asks for fields.

Tool

What it does

Key arguments

workflows_get_all

Every workflow as a compact row: id, name, queue, version and the number of statuses

-

workflow_get

One workflow: its statuses with their outgoing transitions, screens, conditions and post-functions - references cut down to keys unless full, one status at a time with status for a large workflow

workflow_id (from workflows_get_all or queue_get_workflows), status, full

screen_get

A transition screen with its fields and which of them are required

screen_id (a transition's screen.id from workflow_get)

workflow_create

Create a workflow from statuses and transitions, optionally bound to a queue

name, steps, initial_status, queue

workflow_delete

Delete a workflow

workflow_id

workflow_add_action

Add a transition out of a status, optionally with a screen and conditions on who may run it

workflow_id, status, name, target (status keys), screen_fields, post_functions, conditions

workflow_update_action

Change a transition; what you omit keeps its value, remove_screen drops the screen

workflow_id, status, action_id, name, target, screen_fields, remove_screen, post_functions, conditions

workflow_delete_action

Remove a transition

workflow_id, status, action_id

workflow_add_status

Add a status with at least one transition into it from a status already reachable

workflow_id, status, incoming, actions

workflow_delete_status

Remove a status and every transition into it; the initial status cannot be removed

workflow_id, status

workflow_update_status

Change a status's type or the functions Tracker runs whenever an issue enters it

workflow_id, status, status_type, on_enter_functions, remove_on_enter

workflow_update

Rename a workflow, change the status new issues start in, or set the resolutions each issue type may be closed with

workflow_id, name, initial_status, issue_type_resolutions

status_create

Create an issue status for workflows to use; type is new, inProgress, paused, done or cancelled

key, name, type

status_update

Change a status's name, description, order or type

status_id (key or id from get_statuses)

resolution_create

Create a resolution

key, name

resolution_update

Change a resolution's name, description or order

resolution_id (key or id from get_resolutions)

issue_type_create

Create an issue type

key, name

issue_type_update

Change an issue type's name or description

issue_type_id (key or id from get_issue_types)

priority_create

Create a priority; its icon cannot be set through the API

key, name, order

priority_update

Change a priority's name, description or order

priority_id (key or id from get_priorities)

  • The write tools are opt-in: registered only with TRACKER_WORKFLOWS_WRITE_ENABLED=true on a writable server. A workflow is often shared by many queues - a preset one by every queue that runs it - and a change applies to all of them at once. So does a change to a status, resolution, issue type or priority, which belong to the whole organization and cannot be deleted through the API. Names and descriptions are written in Russian, with *_en arguments for the English text (the Russian one by default); version is optional, the current one is read when it is left out.

  • Screens are re-created on every write. Tracker cannot point a transition at an existing screen, so a write sends the screen's fields and gets a new screen with a new id, deleting the old one. workflow_delete_action, workflow_add_status, workflow_delete_status and workflow_update_status rewrite the whole workflow, so they re-create every screen in it and report any other transition or status that came back different.

  • Workflows are checked through the queue they are bound to: one bound to a queue outside TRACKER_LIMIT_QUEUES is reported as not found and left out of workflows_get_all, one bound to a queue in TRACKER_READ_ONLY_QUEUES cannot be changed, and a shared workflow (bound to no queue) can be read but not changed while either restriction is set. Nor can a status, resolution, issue type or priority be updated then; creating one is allowed.

The template writes need TRACKER_ADMIN_ENABLED=true.

Tool

What it does

Key arguments

issue_templates_get_all

The issue templates, with the fieldTemplates values they prefill; returns {values, hits, pages}

queue, page (omit to walk every page), per_page

issue_template_get

One issue template by id

template_id

comment_templates_get_all

The comment templates, with the template text and its summonees / maillistSummonees

queue, page, per_page

comment_template_get

One comment template by id

template_id

issue_template_create

Create an issue template: the field values and checklist an issue starts with

name, queue, field_templates, checklist_items

issue_template_update

Change an issue template

template_id, version, name, field_templates, checklist_items

issue_template_delete

Delete an issue template

template_id, version

comment_template_create

Create a comment template

name, queue, text, summonees, maillist_summonees

comment_template_update

Change a comment template

template_id, version, and the arguments the create takes

comment_template_delete

Delete a comment template

template_id, version

  • issue_create takes template_id: the template's values fill the arguments left out (an argument passed wins) and its checklist is added to the new issue. A comment template is read and its text passed to issue_add_comment. Macros such as {{today}} arrive literally.

  • An update replaces whole sets: field_templates, checklist_items and the summonee lists replace the template's own. Without version the current one is read and used.

  • The issue body a template prefills is in fieldTemplates.description; the template's own description describes the template.

  • queue returns that queue's templates plus the ones bound to no queue, which are usable everywhere. TRACKER_LIMIT_QUEUES applies: templates of a restricted queue are omitted from the listings and rejected on direct access, while templates without a queue stay visible.

The board and column writes need TRACKER_ADMIN_ENABLED=true; the sprint writes do not.

Tool

What it does

Key arguments

boards_get_all

The organization's agile boards; returns {boards, next_cursor}

queue, fields, cursor (the previous next_cursor), per_page

board_get

One board with autoFilterSettings (what it collects), estimateBy, useRanking and its working calendar

board_id, fields

board_get_columns

The board's columns with the issue statuses that land in each

board_id

board_get_column

One column with its statuses and issue limit

board_id, column_id

board_create

Create a board, optionally with its columns and the filter that collects its issues

name, columns, auto_filter, owner, private, sprints

board_update

Rename a board, replace all of its columns, turn sprints on or off

board_id, name, columns, sprints, version

board_delete

Delete a board together with its sprints; the issues stay

board_id

board_create_column

Add a column to the right of the others

board_id, name, statuses, limit, version

board_update_column

Rename a column, change its statuses or its issue limit

board_id, column_id, name, statuses, limit, version

board_delete_column

Delete a column

board_id, column_id, version

board_get_sprints

The board's sprints with status (draft, in_progress, released, archived) and planned/actual dates

board_id, fields

board_get_sprint_issues

The issues in a sprint now, a page at a time

sprint_id, fields, include_description, page, per_page

board_create_sprint

Create a sprint; it starts as draft

board_id, name, start_date, end_date

board_update_sprint

Rename or reschedule a sprint, or change its status

sprint_id, name, start_date, end_date, status, version

board_start_sprint

Start a sprint (in_progress)

sprint_id, version

board_archive_sprint

Move a sprint to the archive

sprint_id, version

board_delete_sprint

Delete a sprint; its issues stay

sprint_id

  • A board has no queue of its own, so queue is matched against the board's own filter and misses the boards that filter by something else - a personal board filtering by assignee, for one. To catch those, read a few issues of the queue with issues_find and look at their boards field.

  • Boards belong to the organization, not to a queue, so TRACKER_LIMIT_QUEUES does not filter them: only the queue argument of boards_get_all is checked, and what these tools return can name restricted queues. The sprint write tools ignore TRACKER_READ_ONLY_QUEUES too - only TRACKER_READ_ONLY removes them; their version is optional, the current one is read when it is left out.

  • A non-scrum board has no sprints and board_get_sprints is rejected for it. The sprint id it returns is what issue_create / issue_update take.

  • The board and column writes are not covered by TRACKER_LIMIT_QUEUES / TRACKER_READ_ONLY_QUEUES either. A column has no version of its own: every column change bumps the board's version, which is what version means on all of them; leave it out to write unconditionally.

  • auto_filter can only be set when the board is created - Tracker refuses to change the filter afterwards. board_update with columns deletes every column and creates new ones with new ids. A column's limit cannot be removed once set, only changed; replacing all columns drops it.

  • board_get_sprint_issues is the sprint as it is now. What was planned when the sprint started (the burndown chart's starting set) is not in Tracker's public API. Under TRACKER_LIMIT_QUEUES only the allowed queues' issues are listed.

Tool

What it does

Key arguments

issue_get

One issue by key: the full record, the current version included

issue_id, include_description

issue_get_url

The web URL of an issue

issue_id

issue_get_comments

A page of comments, oldest first; returns {comments, next_cursor}

issue_id, cursor, per_page, fields

issue_get_comment

One comment, with its attached files

issue_id, comment_id (id or longId)

issue_add_comment

Add a comment; summonees is what notifies a user, an @login in the text notifies nobody

issue_id, text, summonees, maillist_summonees, markup_type, is_add_to_followers, attachment_ids (from attachment_create)

issue_update_comment

Edit a comment

issue_id, comment_id, text, summonees, maillist_summonees

issue_delete_comment

Delete a comment

issue_id, comment_id

issue_add_comment_reaction

Put a reaction on a comment, returning the comment with reactionsCount and ownReactions; a reaction already there is refused

issue_id, comment_id (id or longId), reaction (LIKE, DISLIKE, LAUGH, HOORAY, CONFUSED, HEART, ROCKET, EYES, FIRE, OK, FACEPALM, CHECK)

issue_delete_comment_reaction

Take your reaction off a comment

issue_id, comment_id, reaction

issue_get_links

Links to related, blocking and duplicate issues

issue_id

issue_add_link

Link two issues

issue_id, relationship, issue

issue_delete_link

Remove a link

issue_id, link_id (from issue_get_links)

issue_get_remote_links

Links to objects in other applications (pull requests, documents, ...)

issue_id

issue_add_remote_link

Link the issue to an object in another application

issue_id, origin (from applications_get_all), key, backlink

issue_delete_remote_link

Remove such a link

issue_id, link_id (from issue_get_remote_links)

applications_get_all

The applications an issue can be linked to

-

issue_get_worklogs

The time logged on one or more issues

issue_ids, fields

worklogs_find

The time one user logged across all issues over a period; Tracker filters by the day a record was entered, so start_* misses time logged in advance

author (default: you), start_from, start_to, created_from, created_to, fields

issue_add_worklog

Log spent time

issue_id, duration (ISO-8601, PT1H30M), comment, start

issue_update_worklog

Edit a worklog entry

issue_id, worklog_id, duration, comment, start

issue_delete_worklog

Delete a worklog entry

issue_id, worklog_id

issue_get_attachments

Attachment metadata

issue_id, fields

issue_download_attachment

Save an attachment to the machine the server runs on, returning its absolute path, MIME type and size; with thumbnail, Tracker's 140x140 PNG preview of an image instead

issue_id, attachment_id from issue_get_attachments, thumbnail

issue_add_attachment

Upload a file from the machine the server runs on, returning the attachment; an image shows inline in a description only when embedded as ![name](/ajax/v2/attachments/<id>?inline=true)

issue_id, file_path, filename

issue_add_attachment_from_url

Attach a file the server fetches from an https URL under TRACKER_ATTACHMENT_URL_PREFIXES, returning the attachment

issue_id, file_url, filename

issue_delete_attachment

Delete a file attached to an issue - it cannot be restored

issue_id, attachment_id

attachment_create

Upload a file from the machine the server runs on as a temporary attachment, returning the id that attachment_ids of issue_add_comment takes

file_path, filename

attachment_create_from_url

The same for a file the server fetches from an https URL under TRACKER_ATTACHMENT_URL_PREFIXES

file_url, filename

issue_get_checklist

The checklist, with the item ids the write tools need

issue_id

issue_add_checklist_items

Append items in order, creating the checklist if there is none

issue_id, items (text, checked, assignee, deadline)

issue_update_checklist_item

Change one item; the fields you omit keep their value

issue_id, checklist_item_id, text, checked, assignee, deadline, clear_assignee, clear_deadline

issue_delete_checklist_item

Delete one item

issue_id, checklist_item_id

issue_delete_checklist

Delete the whole checklist

issue_id

issue_get_transitions

The status transitions available right now, with their ids

issue_id

issue_execute_transition

Run a transition, returning the transitions available afterwards

issue_id, transition_id, comment, fields

issue_close

Find a transition to a done status and run it with a resolution

issue_id, resolution_id, comment, fields

issue_get_changelog

Field edits, status transitions, comment changes and fired triggers; returns {entries, next_cursor}

issue_id, cursor, per_page, field, type

issue_create

Create an issue, returning it, optionally from an issue template

queue, summary, type, description, markup_type, assignee, priority, parent, sprint, followers, components, tags, project, fields, template_id

issue_update

Change any of those fields; the ones you omit stay as they are

issue_id, version, and the arguments issue_create takes but template_id

issue_move

Move an issue to another queue, which changes its key (TASKS-1 → NEWQUEUE-42)

issue_id, queue, notify, notify_author, move_all_fields, initial_status

issues_bulk_update

Set the same fields on up to 10 000 issues; returns the change id

issues, values, notify

issues_bulk_transition

Run one transition on many issues

issues, transition, values (a resolution for closing), notify

issues_bulk_move

Move many issues to another queue

issues, queue, move_all_fields, initial_status, values, notify

issues_get_bulk_change

The state of a bulk change; once it is final, the issues it failed on and why

bulk_change_id

  • version goes stale on its own. Queue triggers and automation run right after issue_create and bump it, so the version it returns is routinely already old. Re-read it with issue_get immediately before issue_update, or omit it to update the latest version unconditionally; a stale one fails with an editing conflict.

  • Reference fields take the same values on create and on update: an object with id and/or key, or - for type, priority and parent - the bare key or id. components take {"id": ...} or {"name": ...}, and components / followers replace the current list rather than adding to it. Anything without a dedicated argument goes into the fields map, keyed by the field id from queue_get_fields; an entry there overrides the dedicated argument, and an explicit null clears the field.

  • Transitions are not guessed. issue_execute_transition only takes ids from issue_get_transitions, and before issue_close read the issue's type with issue_get and the resolutions valid for that type from queue_get_metadata with expand: ["issueTypesConfig"] - each type has its own set. Where the client supports elicitation, issue_move asks the user to confirm its flags first, and declining aborts the move; a client that cannot be asked (no form elicitation, or a pre-2026-07-28 client over streamable-http, which has no channel for the question) gets the flags as passed.

A queue whose setting AI tools access ('Доступ для AI инструментов') forbids them is honoured as Tracker's own MCP server honours it: issues_find returns its issues as {key, restricted: true}, the tools that read one issue refuse, worklogs_find drops the comments, and writes still work. TRACKER_AI_ACCESS_IGNORED_QUEUES lists the queues to read regardless.

Every tool here respects TRACKER_LIMIT_QUEUES and TRACKER_READ_ONLY_QUEUES; the ones that write are registered only when TRACKER_READ_ONLY is off.

The bulk tools are opt-in: registered only with TRACKER_BULK_ENABLED=true on a writable server. A bulk change cannot be undone and runs in the background - poll issues_get_bulk_change until its status is COMPLETE or FAILED. Every issue is checked against the queue restrictions before anything is sent, and where the client supports elicitation the user confirms the change first.

The attachment file tools are opt-in and local-only. issue_add_attachment and attachment_create are registered only with TRACKER_FILE_UPLOAD_ENABLED=true, because they read any file the server process can; issue_download_attachment only with TRACKER_ATTACHMENT_DOWNLOAD_ENABLED=true, read-only mode included. Both default to false, and the server refuses to start with either on a network transport or with OAUTH_ENABLED, where a client - or a prompt injected into an issue - could upload the host's secrets to an issue.

issue_add_attachment_from_url and attachment_create_from_url are registered only when TRACKER_ATTACHMENT_URL_PREFIXES lists the https URL prefixes they may fetch from, and work on any transport: the server fetches only under those prefixes, follows no redirect, sends none of the Tracker credentials and refuses a file over TRACKER_MAX_ATTACHMENT_BYTES. The fetch goes out directly, not through a proxy.

Downloads are saved under TRACKER_ATTACHMENTS_DIR (default <system temp>/yandex-tracker-mcp/attachments), one folder per issue, as <attachment id>-<name>. They are kept, so downloading the same attachment again returns the file already there; attachments over TRACKER_MAX_ATTACHMENT_BYTES (default 50 MiB) are refused before the download starts. Uploads and downloads have their own time budget, TRACKER_ATTACHMENT_TIMEOUT.

Tool

What it does

Key arguments

issues_find

Search issues with Yandex Tracker Query Language or by a saved filter; returns {values, hits, pages}

query, filter_id, fields, include_description, page, per_page

issues_count

How many issues match a query or a saved filter; returns {"count": N}

query, filter_id

issues_suggest

Quick lookup by a fragment of the summary: up to 20 issues with key, summary and status

text, queue

filter_get

A saved filter: name, conditions as query or filter, sorting, owner

filter_id

filter_create

Save a filter; it is readable by every employee by default

name, query or filter, sorts, fields (UI columns)

filter_update

Change a saved filter; new conditions replace the old ones whole

filter_id, name, query or filter, sorts, fields

filter_delete

Delete a saved filter

filter_id

  • fields uses Tracker's own spelling (storyPoints, not story_points) and accepts any field name, a queue's local and the organization's custom fields included - pass the field id from queue_get_fields. A name Tracker does not know is dropped silently.

  • include_description is ignored when description is listed in fields: naming it there is an explicit request for it.

  • per_page defaults to 100 and can be lowered when a page does not fit the context window.

  • With both query and filter_id, only issues matching both come back. The API cannot list saved filters: the id comes from filter_create or from the filter's link in Tracker. A filter takes its conditions as either query or filter, never both.

  • Saved filters belong to no queue, so TRACKER_LIMIT_QUEUES and TRACKER_READ_ONLY_QUEUES do not apply to the filter_* tools. issues_suggest drops issues of queues outside TRACKER_LIMIT_QUEUES and applies queue itself, since Tracker ignores it.

Tool

What it does

Key arguments

report_create

Export the issues a query matches to an xlsx, csv or xml file in Tracker

summary, format, fields, one of query / filter / filter_id, sorts

report_get

One report: name, status and what it exports

report_id (id or shortId)

reports_find

The organization's reports, newest first; returns {values, hits, pages}

author (login or uid), page, per_page

report_delete

Delete a report

report_id

  • The API returns no file: a report is downloaded in Tracker's web interface. To read issues through the server, use issues_find.

  • report_create is refused under TRACKER_LIMIT_QUEUES, since a query may match issues of any queue; the write tools are not registered in read-only mode.

Tool

What it does

Key arguments

dashboards_get_all

The organization's dashboards with their owners; returns {values, hits, pages}

-

dashboard_get

One dashboard with the ids and titles of its widgets

dashboard_id

dashboard_create

Create an empty dashboard

name, layout, owner

dashboard_delete

Delete a dashboard with its widgets

dashboard_id

dashboard_add_cycle_time_widget

Add a 'Cycle time' chart: how long the issues a query matches take between statuses

dashboard_id, description, one of query / filter / filter_id, from_statuses, to_statuses, bucket, lines, start, end, mode

  • 'Cycle time' is the only widget the API can create; a widget cannot be changed or removed on its own, only with its dashboard.

  • dashboard_add_cycle_time_widget is refused under TRACKER_LIMIT_QUEUES, like report_create; dashboards themselves belong to no queue and are not covered by the queue restrictions.

http Transport

The MCP server can also be run in streamable-http mode for web-based integrations or when stdio transport is not suitable.

streamable-http Mode Environment Variables

# Required - Set transport to streamable-http mode
TRANSPORT=streamable-http

# Server Configuration
HOST=0.0.0.0  # Default: 0.0.0.0 (all interfaces)
PORT=8000     # Default: 8000

Starting the streamable-http Server

# Basic streamable-http server startup
TRANSPORT=streamable-http uvx --from git+https://github.com/Hollway/yandex-tracker-mcp yandex-tracker-mcp

# With custom host and port
TRANSPORT=streamable-http \
HOST=localhost \
PORT=9000 \
uvx --from git+https://github.com/Hollway/yandex-tracker-mcp yandex-tracker-mcp

# With all environment variables
TRANSPORT=streamable-http \
HOST=0.0.0.0 \
PORT=8000 \
TRACKER_TOKEN=your_token \
TRACKER_CLOUD_ORG_ID=your_org_id \
uvx --from git+https://github.com/Hollway/yandex-tracker-mcp yandex-tracker-mcp

You may skip configuring TRACKER_CLOUD_ORG_ID or TRACKER_ORG_ID if you are using the following format when connecting to MCP Server (example for Claude Code):

claude mcp add --transport http yandex-tracker "http://localhost:8000/mcp/?cloudOrgId=your_cloud_org_id&"

or

claude mcp add --transport http yandex-tracker "http://localhost:8000/mcp/?orgId=org_id&"

The tracker-mcp://configuration resource reports the configuration the server is running with. It is a resource template (tracker-mcp://configuration{?cloudOrgId,orgId}): the optional cloudOrgId / orgId variables override the organization for that one read, the same way the query parameters above do for the whole connection, and the plain tracker-mcp://configuration URI still reads.

You may also skip configuring global TRACKER_TOKEN environment variable if you choose to use OAuth 2.0 authentication (see below).

OAuth 2.0 Authentication

The Yandex Tracker MCP Server supports OAuth 2.0 authentication as a secure alternative to static API tokens. When configured, the server acts as an OAuth provider, facilitating authentication between your MCP client and Yandex OAuth services.

How OAuth Works

The MCP server implements a standard OAuth 2.0 authorization code flow:

  1. Client Registration: Your MCP client registers with the server to obtain client credentials

  2. Authorization: Users are redirected to Yandex OAuth to authenticate

  3. Token Exchange: The server exchanges authorization codes for access tokens

  4. API Access: Clients use bearer tokens for all API requests

  5. Token Refresh: Expired tokens can be refreshed without re-authentication

MCP Client → MCP Server → Yandex OAuth → User Authentication
    ↑                                           ↓
    └────────── Access Token ←─────────────────┘

OAuth Configuration

To enable OAuth authentication, set the following environment variables:

# Enable OAuth mode
OAUTH_ENABLED=true

# Yandex OAuth Application Credentials (required for OAuth)
OAUTH_CLIENT_ID=your_yandex_oauth_app_id
OAUTH_CLIENT_SECRET=your_yandex_oauth_app_secret

# Public URL of your MCP server (required for OAuth callbacks)
MCP_SERVER_PUBLIC_URL=https://your-mcp-server.example.com

# Optional OAuth settings
OAUTH_SERVER_URL=https://oauth.yandex.ru  # Default Yandex OAuth server

# When OAuth is enabled, TRACKER_TOKEN becomes optional
OAuth Scopes

With OAUTH_USE_SCOPES=true (the default) the server requests, advertises and requires the Yandex Tracker scopes tracker:read and tracker:write - or tracker:read alone when TRACKER_READ_ONLY=true, so a read-only instance never asks the user for write access. Setting OAUTH_USE_SCOPES=false drops scopes from the flow entirely, which is what Yandex Cloud federation requires.

Setting Up Yandex OAuth Application

  1. Go to Yandex OAuth and create a new application

  2. Set the callback URL to: {MCP_SERVER_PUBLIC_URL}/oauth/yandex/callback

  3. Request the following permissions:

    • tracker:read - Read permissions for Tracker

    • tracker:write - Write permissions for Tracker

  4. Save your Client ID and Client Secret

OAuth vs Static Token Authentication

Feature

OAuth

Static Token

Security

Dynamic tokens with expiration

Long-lived static tokens

User Experience

Interactive login flow

One-time configuration

Token Management

Automatic refresh

Manual rotation

Access Control

Per-user authentication

Shared token

Setup Complexity

Requires OAuth app setup

Simple token configuration

OAuth Mode Limitations

  • Currently, the OAuth mode requires the MCP server to be publicly accessible for callback URLs

  • OAuth mode is best suited for interactive clients that support web-based authentication flows

Using OAuth with MCP Clients

When OAuth is enabled, MCP clients will need to:

  1. Support OAuth 2.0 authorization code flow

  2. Handle token refresh when access tokens expire

  3. Store refresh tokens securely for persistent authentication

Note: Not all MCP clients currently support OAuth authentication. Check your client's documentation for OAuth compatibility.

Example configuration for Claude Code:

claude mcp add --transport http yandex-tracker https://your-mcp-server.example.com/mcp/ -s user

OAuth Data Storage

The MCP server supports two different storage backends for OAuth data (client registrations, access tokens, refresh tokens, and authorization states):

InMemory Store (Default)

The in-memory store keeps all OAuth data in server memory. This is the default option and requires no additional configuration.

Characteristics:

  • Persistence: Data is lost when the server restarts

  • Performance: Very fast access since data is stored in memory

  • Scalability: Limited to single server instance

  • Setup: No additional dependencies required

  • Best for: Development, testing, or single-instance deployments where losing OAuth sessions on restart is acceptable

Configuration:

OAUTH_STORE=memory  # Default value, can be omitted
Redis Store

The Redis store provides persistent storage for OAuth data using a Redis database. This ensures OAuth sessions survive server restarts and enables multi-instance deployments.

Characteristics:

  • Persistence: Data persists across server restarts

  • Performance: Fast access with network overhead

  • Scalability: Supports multiple server instances sharing the same Redis database

  • Setup: Requires Redis server installation and configuration

  • Best for: Production deployments, high availability setups, or when OAuth sessions must persist

Configuration:

# Enable Redis store for OAuth data
OAUTH_STORE=redis

# Redis connection settings (same as used for tools caching)
REDIS_ENDPOINT=localhost                  # Default: localhost
REDIS_PORT=6379                           # Default: 6379
REDIS_DB=0                                # Default: 0
REDIS_PASSWORD=your_redis_password        # Optional: Redis password
REDIS_POOL_MAX_SIZE=10                    # Default: 10

Storage Behavior:

  • Client Information: Stored persistently

  • OAuth States: Stored with TTL (time-to-live) for security

  • Authorization Codes: Stored with TTL and automatically cleaned up after use

  • Access Tokens: Stored with automatic expiration based on token lifetime

  • Refresh Tokens: Stored persistently until revoked

  • Key Namespacing: Uses oauth:* prefixes to avoid conflicts with other Redis data

Token Encryption (Required for Redis Store)

When using Redis store, you must configure encryption to protect OAuth tokens at rest. Token values are encrypted using Fernet (AES-128) and Redis keys use SHA-256 hashes instead of raw tokens, preventing token exposure if Redis is compromised.

Generate an encryption key:

python3 -c "import base64, os; print(base64.b64encode(os.urandom(32)).decode())"

Configuration:

# Single encryption key
OAUTH_ENCRYPTION_KEYS=<base64-encoded-32-byte-key>

# Multiple keys for rotation (first encrypts, all decrypt)
OAUTH_ENCRYPTION_KEYS=<new-key>,<old-key>

Key rotation allows seamless key updates: add the new key first, wait for old tokens to expire, then remove the old key.

Important Notes:

  • Both stores use the same Redis connection settings as the tools caching system

  • When using Redis store, ensure your Redis instance is properly secured and accessible

  • The OAUTH_STORE setting only affects OAuth data storage; tools caching uses TOOLS_CACHE_ENABLED

  • Redis store uses JSON serialization for better cross-language compatibility and debugging

Authentication

Yandex Tracker MCP Server supports multiple authentication methods with a clear priority order. The server will use the first available authentication method based on this hierarchy:

Authentication Priority Order

  1. Dynamic OAuth Token (highest priority)

    • When OAuth is enabled and a user authenticates via OAuth flow

    • Tokens are dynamically obtained and refreshed per user session

    • Supports both standard Yandex OAuth and Yandex Cloud federative OAuth

    • Required env vars: OAUTH_ENABLED=true, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, MCP_SERVER_PUBLIC_URL

    • Additional vars for federative OAuth: OAUTH_SERVER_URL=https://auth.yandex.cloud/oauth, OAUTH_TOKEN_TYPE=Bearer, OAUTH_USE_SCOPES=false

  2. Passthrough Bearer OAuth Token

    • When MCP OAuth middleware does not provide a token, the server can read a Yandex OAuth token from the incoming Authorization: Bearer <token> header

    • Useful behind a trusted reverse proxy or gateway that authenticates users, resolves their stored Yandex OAuth token, and injects it per request

    • The token from MCP OAuth still has priority when OAuth mode is enabled and active

  3. Static OAuth Token

    • Traditional OAuth token provided via environment variable

    • Single token used for all requests

    • Required env var: TRACKER_TOKEN (your OAuth token)

  4. Static IAM Token

    • IAM (Identity and Access Management) token for service-to-service authentication

    • Suitable for automated systems and CI/CD pipelines

    • Required env var: TRACKER_IAM_TOKEN (your IAM token)

  5. Dynamic IAM Token (lowest priority)

    • Automatically retrieved using service account credentials

    • Token is fetched and refreshed automatically

    • Required env vars: TRACKER_SA_KEY_ID, TRACKER_SA_SERVICE_ACCOUNT_ID, TRACKER_SA_PRIVATE_KEY

Authentication Scenarios

# Enable OAuth mode
OAUTH_ENABLED=true
OAUTH_CLIENT_ID=your_oauth_app_id
OAUTH_CLIENT_SECRET=your_oauth_app_secret
MCP_SERVER_PUBLIC_URL=https://your-server.com

# Organization ID (choose one)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id  # or TRACKER_ORG_ID

Scenario 2: Static OAuth Token (Simple Setup)

# OAuth token
TRACKER_TOKEN=your_oauth_token

# Organization ID (choose one)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id  # or TRACKER_ORG_ID

Scenario 3: Passthrough Bearer Token Behind a Reverse Proxy

Use this mode when a trusted gateway handles user authentication, looks up the user's Yandex OAuth token, and forwards the request to the MCP server with that token in the request header:

Authorization: Bearer <user_yandex_oauth_token>
# Organization ID (choose one)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id  # or TRACKER_ORG_ID

This passthrough token is used only when MCP OAuth middleware has not provided an access token for the request. In OAuth-enabled deployments with an active MCP OAuth session, the MCP OAuth token takes priority.

Scenario 4: Static IAM Token

# IAM token
TRACKER_IAM_TOKEN=your_iam_token

# Organization ID (choose one)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id  # or TRACKER_ORG_ID

Scenario 5: Dynamic IAM Token with Service Account

# Service account credentials
TRACKER_SA_KEY_ID=your_key_id
TRACKER_SA_SERVICE_ACCOUNT_ID=your_service_account_id
TRACKER_SA_PRIVATE_KEY=your_private_key

# Organization ID (choose one)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id  # or TRACKER_ORG_ID

Scenario 6: Federative OAuth for OIDC Applications (Advanced)

# Enable OAuth with Yandex Cloud federation
OAUTH_ENABLED=true
OAUTH_SERVER_URL=https://auth.yandex.cloud/oauth
OAUTH_TOKEN_TYPE=Bearer
OAUTH_USE_SCOPES=false
OAUTH_CLIENT_ID=your_oidc_client_id
OAUTH_CLIENT_SECRET=your_oidc_client_secret
MCP_SERVER_PUBLIC_URL=https://your-server.com

# Organization ID (choose one)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id  # or TRACKER_ORG_ID

This configuration enables authentication through Yandex Cloud OIDC applications, which is required for federated accounts in Yandex Cloud. Federated users authenticate through their organization's identity provider (IdP) and use this OAuth flow to access Yandex Tracker APIs.

Important Notes

  • The server checks authentication methods in the order listed above

  • Only one authentication method will be used at a time

  • For production use, dynamic tokens (OAuth or IAM) are recommended for better security

  • IAM tokens have a shorter lifetime than OAuth tokens and may need more frequent renewal

  • When using service accounts, ensure the account has appropriate permissions for Yandex Tracker

Configuration

Environment Variables

# Authentication (use one of the following methods)
# Method 1: OAuth Token
TRACKER_TOKEN=your_yandex_tracker_oauth_token

# Method 2: IAM Token
TRACKER_IAM_TOKEN=your_iam_token

# Method 3: Service Account (for dynamic IAM token)
TRACKER_SA_KEY_ID=your_key_id                    # Service account key ID
TRACKER_SA_SERVICE_ACCOUNT_ID=your_sa_id        # Service account ID
TRACKER_SA_PRIVATE_KEY=your_private_key          # Service account private key

# Organization Configuration (set exactly one - setting both is an error)
TRACKER_CLOUD_ORG_ID=your_cloud_org_id    # For Yandex Cloud organizations
TRACKER_ORG_ID=your_org_id                # For Yandex 360 organizations

# API Configuration (optional)
TRACKER_API_BASE_URL=https://api.tracker.yandex.net  # Default: https://api.tracker.yandex.net
TRACKER_API_TIMEOUT=10                    # Default: 10 - Per-request timeout in seconds for Tracker API calls
TRACKER_ATTACHMENT_TIMEOUT=300            # Default: 300 - Timeout in seconds for one attachment upload or download

# Security - Restrict access to specific queues (optional)
TRACKER_LIMIT_QUEUES=PROJ1,PROJ2,DEV      # Comma-separated queue keys - allow-list of accessible queues
TRACKER_READ_ONLY_QUEUES=PROJ2            # Comma-separated queue keys - allowed for reads but reject writes (per-queue read-only)
TRACKER_ENTITIES_ENABLED=true             # Default: false - Register project/portfolio/goal tools (NOT covered by the queue restrictions above)
TRACKER_AI_ACCESS_IGNORED_QUEUES=SAP      # Queues whose 'AI tools access' setting is ignored (by default a queue that forbids AI tools gets only issue keys)
TRACKER_FILE_UPLOAD_ENABLED=true          # Default: false - Register issue_add_attachment and attachment_create, which upload local files (stdio only: refused with a network transport or OAUTH_ENABLED)
TRACKER_BULK_ENABLED=true                 # Default: false - Register the bulk-change tools (up to 10 000 issues at once, irreversible)
TRACKER_ADMIN_ENABLED=true                # Default: false - Register the tools that configure Tracker: queue administration, triggers, permissions, components, boards, absences, templates, workflow reads
TRACKER_WORKFLOWS_WRITE_ENABLED=true      # Default: false - Register the workflow write tools (a change applies to every queue sharing the workflow; screens get new ids on each write)
TRACKER_ATTACHMENT_DOWNLOAD_ENABLED=true  # Default: false - Register issue_download_attachment, which saves attachments to this machine (stdio only, like the flag above)
TRACKER_ATTACHMENTS_DIR=/path/to/dir      # Default: <system temp>/yandex-tracker-mcp/attachments - Where downloaded attachments are saved
TRACKER_MAX_ATTACHMENT_BYTES=52428800     # Default: 52428800 (50 MiB) - Larger attachments are not downloaded, nor fetched by URL
TRACKER_ATTACHMENT_URL_PREFIXES=https://files.example.com/reports/  # Default: none - https URL prefixes issue_add_attachment_from_url and attachment_create_from_url may fetch from; without it they are not registered

# Server Configuration
HOST=0.0.0.0                              # Default: 0.0.0.0
PORT=8000                                 # Default: 8000
TRANSPORT=stdio                           # Options: stdio, streamable-http, sse

# Redis connection settings (used for caching and OAuth store)
REDIS_ENDPOINT=localhost                  # Default: localhost
REDIS_PORT=6379                           # Default: 6379
REDIS_DB=0                                # Default: 0
REDIS_PASSWORD=your_redis_password        # Optional: Redis password
REDIS_POOL_MAX_SIZE=10                    # Default: 10

# Tools caching configuration (optional)
TOOLS_CACHE_ENABLED=true                  # Default: false
TOOLS_CACHE_REDIS_TTL=3600                # Default: 3600 seconds (1 hour)

# OAuth 2.0 Authentication (optional)
OAUTH_ENABLED=true                        # Default: false
OAUTH_STORE=redis                         # Options: memory, redis (default: memory)
OAUTH_SERVER_URL=https://oauth.yandex.ru  # Default: https://oauth.yandex.ru (use https://auth.yandex.cloud/oauth for federation)
OAUTH_TOKEN_TYPE=<Bearer|OAuth|<empty>>   # Default: <empty> (required to be Bearer for Yandex Cloud federation)
OAUTH_USE_SCOPES=true                     # Default: true (set to false for Yandex Cloud federation)
OAUTH_CLIENT_ID=your_oauth_client_id      # Required when OAuth enabled
OAUTH_CLIENT_SECRET=your_oauth_secret     # Required when OAuth enabled
MCP_SERVER_PUBLIC_URL=https://your.server.com  # Required when OAuth enabled
TRACKER_READ_ONLY=true                    # Default: false - Disable all write tools for the whole instance

Queue Access Control

Access to queues can be scoped at three levels, from coarse to fine-grained:

  • TRACKER_LIMIT_QUEUES — allow-list of queue keys. Queues outside the list are treated as not found / not allowed for both reads and writes. Keys are matched ignoring case, here and in TRACKER_READ_ONLY_QUEUES, so dev and DEV name the same queue. The one exception is the board tools: a board belongs to the organization rather than to a queue, so they are not filtered and can name a restricted queue in a board's settings.

  • TRACKER_READ_ONLY — when true, all write tools are unregistered, so the whole instance is read-only.

  • TRACKER_READ_ONLY_QUEUES — per-queue read-only allow-list. Write tools stay registered, but any mutating call (create/update/move/comment/worklog/link, queue version creation) targeting a listed queue is rejected, while reads keep working. Queues not listed here remain read-write.

Project/portfolio/goal tools are outside this model. A project, portfolio or goal isn't reliably mappable to a single queue, so none of the three settings above constrain them — neither the read tools (project_get, project_find, *_get_comments, …) nor the write tools (including comment and checklist tools). Enabling them grants org-wide access to those entities for anyone who can reach the server. For this reason they are opt-in: they are registered only when TRACKER_ENTITIES_ENABLED=true (default false), which also keeps the tool manifest small for deployments that don't need them. TRACKER_READ_ONLY still applies: it unregisters entity write tools along with all other write tools.

This lets a single instance be read-write on some queues and read-only on others at the same time — e.g. TRACKER_LIMIT_QUEUES=DEV,MGMT together with TRACKER_READ_ONLY_QUEUES=MGMT gives full access to DEV and read-only visibility into MGMT. This is especially useful for a shared MCP gateway where end users reach Tracker only through the server and never hold the raw token themselves.

These checks are in-process guardrails. For clients that hold the raw Tracker token directly, real limits should additionally be enforced on the token itself.

Docker Deployment

Building the Image

# From GitHub
docker build -t yandex-tracker-mcp https://github.com/Hollway/yandex-tracker-mcp.git

# From a local clone
docker build -t yandex-tracker-mcp .

Running the Image

The image defaults to TRANSPORT=stdio, which talks over the container's stdin/stdout and opens no port. Set TRANSPORT=streamable-http for the examples below, where the server is reached over HTTP; for a stdio client, run the container with -i and no -p instead (see the MCP Client Configuration examples).

# Using environment file (it must set TRANSPORT=streamable-http)
docker run --env-file .env -p 8000:8000 yandex-tracker-mcp:latest

# With inline environment variables
docker run -e TRACKER_TOKEN=your_token \
           -e TRACKER_CLOUD_ORG_ID=your_org_id \
           -e TRANSPORT=streamable-http \
           -p 8000:8000 \
           yandex-tracker-mcp:latest

Docker Compose

services:
  mcp-tracker:
    build: .
    ports:
      - "8000:8000"
    environment:
      - TRACKER_TOKEN=${TRACKER_TOKEN}
      - TRACKER_CLOUD_ORG_ID=${TRACKER_CLOUD_ORG_ID}
      - TRANSPORT=streamable-http

Development Setup

# Clone and setup
git clone https://github.com/Hollway/yandex-tracker-mcp
cd yandex-tracker-mcp

# Install development dependencies
uv sync --dev

# Formatting and static checking
task

License

This project is licensed under the terms specified in the LICENSE file.

Support

For issues and questions:

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with Yandex Tracker through its API for managing tasks, comments, and attachments. It supports issue searching, status transitions, and metadata retrieval for automated project management.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for Yandex Tracker API, enabling AI assistants to search, read, create, and edit issues, as well as manage comments, attachments, and links in Yandex Tracker.
    38 npm
    1
    MIT