
Read a Jira attachment: contentbase64, plus extractedtext for PDF, DOCX and text files (logs, stack traces); check extractionstatus. REQUIRED: attachmentId from getissueattachments(). Over 10 MB returns toolarge=true; then set returndownloadurl=true for a download link (not on API-token connections). Use getattachmentthumbnail() for an image preview.
Get the small preview Jira generates for an image attachment, as contentbase64. REQUIRED: attachmentId from getissueattachments(). Works for images over getattachmentcontent()'s 10 MB limit; use getattachmentcontent() to read a document. Non-images return not found. returndownload_url=true gives a download link instead (not on API-token connections).
Add a comment to a Jira issue. Supports plain text or ADF format. Text: {'issuekey': 'PROJ-123', 'body': 'Comment'}. ADF: {'issuekey': 'PROJ-123', 'body': {'type': 'doc', 'version': 1, 'content': [...]}}
Get comments for a Jira issue
Replace the body of an existing Jira comment. Call getcomments first to get a real commentid, which cannot be invented. comment_body accepts plain text, or an ADF dict ({'type': 'doc', 'version': 1, 'content': [...]}) for rich formatting such as bold, lists, tables, links and code blocks.
Delete a comment from a Jira issue
List visible saved Jira filters to discover IDs for createboard.filterid. Search by name or owner, or filters shared with a project or group. Returns compact IDs, names, JQL and owner details. Supports offset pagination; use nextstartat to continue.
Create a Jira issue. REQUIRED: project, issuetype, summary. ALWAYS call discoverissuerequiredfields first — its 'fields' list contains field IDs and allowedvalues needed for the payload. Map each required custom field to its ID, e.g. 'customfield_11623': {'id': '12093'}. Do NOT dump custom field data into description — use the correct field IDs.
Get Jira issue details using the issue key
Update a Jira issue. Required: issuekey. Optional: summary, description, environment, priority, issuetype, assignee, labels, components, fixVersions, duedate, custom fields (customfield*), or a nested 'fields' object. description/environment accept plain text or an ADF document. Only provided fields are updated; an explicit null clears a custom field.
Delete a Jira issue
Link two Jira issues. REQUIRED: outwardissue (FROM), inwardissue (TO), linktype. Common types: 'Duplicate' (marks FROM as duplicate of TO), 'Relates', 'Blocks'. Example: {'outwardissue': 'PROJ-1', 'inwardissue': 'PROJ-2', 'linktype': 'Duplicate'}
Transition a Jira issue to a new status. Provide either transitionid or transitionname. Example: {'issuekey': 'PROJ-123', 'transitionname': 'In Progress', 'comment': 'Starting work'}
Search Jira issues with JQL ({'jql': 'project = PROJ AND status = "Done"'}) or structured filters (project, textsearch, dates); at least one is required. Searches ALL statuses by default; add 'resolution': 'Unresolved' for open issues. description is not returned by default; pass fields with every field you need plus 'description', or use getissue. Page via nextpagetoken until is_last.
Get available transitions for a Jira issue
Discover required fields for Jira issue creation. Always call this tool ahead of create_issue.
List all workflow statuses in Jira. READ-ONLY: Creating statuses via API is NOT supported - use Jira UI to add custom statuses like 'In Review', then use this to verify.
Get workflow statuses available for a specific project. Use this to verify if custom statuses like 'In Review' are configured before using transition_issue.
List an issue's attachments: attachment ID, filename, size, MIME type, author, created date. Metadata only, never file content. Pass an attachment ID to getattachmentcontent() to read the file itself, to getattachmentthumbnail() for an image preview, or to delete_attachment() to remove it.
Delete an attachment by ID. REQUIRED: attachmentId from getissueattachments(). Requires 'Delete All Attachments' or 'Delete Own Attachments' project permission.
Add an attachment to a Jira issue. REQUIRED: issueKey, filename, contentBase64 (base64-encoded file). Optional: contentType (MIME type). Returns attachment ID and metadata.
Move issues between projects. Max 1000 issues. Returns task ID for async tracking. Requires: targetprojectkey, targetissuetypeid, issuekeys. Auto-maps fields/statuses. Call discoverissuerequired_fields first.
Check progress of bulk move operation. Requires taskid from moveissuesbetweenprojects. Returns status: RUNNING, COMPLETE, or FAILED with progress percentage and result details.
Search and filter Jira projects. Supports filtering by: query (name search), keys (project keys), id (project IDs), typeKey (software/servicedesk/business), categoryId, action (view/browse/edit permission), status (live/archived/deleted). Supports ordering via orderBy and field expansion via expand. Returns paginated results with maxresults (default 50, max 100).
Get a specific Jira project by key or ID
Get issue types for a specific project
Get all components for a Jira project. Returns component names, IDs, descriptions, lead users, and assignee info. Components organize issues (e.g., 'Frontend', 'Backend'). Example: getprojectcomponents(project_key='PROJ')
Get versions for a specific project by project key or numeric project ID
Get all available priorities. Returns list with 'id', 'name', 'description' fields. Use these values when setting priority in createissue or updateissue. Format: {"name": "High"} or {"id": "3"}.
Get template keys for project type. Returns list with 'templateKey' field (e.g., 'com.pyxis.greenhopper.jira:gh-scrum-template'). Use this templateKey value for createproject's projectTemplateKey parameter. Call this BEFORE createproject.
Create Jira project. REQUIRED: key (2-10 uppercase), name, projectTypeKey ('software'/'business'/'servicedesk'), projectTemplateKey (from getprojecttemplates), leadAccountId (from getcurrentuser/searchusers). Input at top level, NO 'fields' wrapper. Requires 'Administer Jira' permission and 'manage:jira-configuration' OAuth scope.
Update a Jira project. All parameters are optional. Only provided fields will be updated. Changing key or schemes requires 'Administer Jira' permission, otherwise 'Administer Projects' permission is sufficient. Example: {'projectIdOrKey': 'PROJ', 'name': 'New Name', 'description': 'Updated description'}.
Delete a Jira project. WARNING: This is a destructive operation. Cannot delete archived projects - restore them first via Jira UI. Requires 'Administer Jira' global permission. Example: {'projectIdOrKey': 'PROJ', 'enableUndo': false}.
Move issues to sprint. Max 50 issues. Requires sprintid and issuekeys. Optional ranking. Sprint must be active or future. Requires 'Manage Sprints' permission. Use getboardsprints to find sprint IDs.
Move issues to backlog. Max 50 issues. Removes from future/active sprints. Requires issue_keys. Use to unassign issues from sprints. Requires 'Manage Sprints' permission and valid license.
List sprints for board. Returns sprint IDs, names, states, dates. Filter by one or more comma-separated states: active, future, closed (e.g. active,future). Pagination supported. Use to find sprint IDs for move operations.
Get sprint details. Requires sprint_id. Returns state, dates, goal, board ID. Use to check sprint status before moving issues.
Create Jira board (scrum/kanban). Required: name, type (scrum/kanban), filterid. Call listfilters first to find filter_id. Filter must ORDER BY Rank for issue reordering. Returns board ID. Requires 'Create shared objects' permission for shared boards.
List all Jira boards. Filter by type (scrum/kanban), name, or project. Pagination supported. Returns board IDs, names, types. Use to discover board IDs for sprint operations.
Get Jira board details. Requires boardid. Returns name, type, location, configuration. Use getboards to find board IDs.
Get the active sprint for a Jira project by project key. Iterates boards for the project in API order (up to 20 boards) and returns the first active sprint found. Use this instead of manually calling getboards and getboard_sprints.
Search for Jira users. Requires at least one of: query (e.g., 'john'), username, or accountid. Cloud search returns active users only; inactive users are only returned by an accountid lookup.
Get a specific Jira user by accountid (find it with searchusers). Jira Cloud requires account_id: lookup by username or key is unsupported, so a call that passes only username is rejected.
Get the current authenticated user
Get user assignee suggestions. Requires projectkey (or project: a key or numeric ID) or issuekey; query alone is rejected. Use get_projects to find a project key.
Get groups that a user belongs to
Validate Jira credentials. Verifies credentials during setup.
Log work on a Jira issue. Requires issuekey and timespent (Jira duration, e.g. '1h 30m'). Optional comment supports plain text or ADF. adjustestimate controls the remaining estimate ('auto' Jira default, 'leave', 'new', 'manual'). Example: {'issuekey': 'PROJ-123', 'time_spent': '2h', 'comment': 'Investigated the bug'}
Get worklog entries for a Jira issue

In an mcp.json file, add the configuration below, and restart Cursor.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "url": "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
5 "headers": {
6 "Authorization": "Bearer yMt*****"
7 }
8 }
9 }
10}
11Open your Claude Desktop configuration file and add the server configuration below. You'll also need to restart the application for the changes to take effect.
Make sure Claude is using the Node v20+.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "mcp-remote@latest",
8 "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
9 "--header",
10 "Authorization: Bearer ${AUTH_TOKEN}"
11 ],
12 "env": {
13 "AUTH_TOKEN": "yMt*****"
14 }
15 }
16 }
17}Open your Windsurf MCP configuration file and add the server configuration below.
Click on the refresh button in the top right of the Manage MCP server page or in the top right of the chat box in the box icon.
Learn more in the official documentation ↗
1{
2 "mcpServers": {
3 "agent-handler": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "mcp-remote@latest",
8 "https://ah-api.merge.dev/api/v1/tool-packs/<tool-pack-id>/registered-users/<registered-user-id>/mcp",
9 "--header",
10 "Authorization: Bearer ${AUTH_TOKEN}"
11 ],
12 "env": {
13 "AUTH_TOKEN": "<ah-production-access-key>"
14 }
15 }
16 }
17 }In Command Palette (Cmd+Shift+P on macOS, Ctrl+Shift+P on Windows), run "MCP: Open User Configuration".
You can then add the configuration below and press "start" right under servers. Enter the auth token when prompted.
Learn more in the official documentation ↗
1{
2 "inputs": [
3 {
4 "type": "promptString",
5 "id": "agent-handler-auth",
6 "description": "Agent Handler AUTH_TOKEN", // "yMt*****" when prompt
7 "password": true
8 }
9 ],
10 "servers": {
11 "agent-handler": {
12 "type": "stdio",
13 "command": "npx",
14 "args": [
15 "-y",
16 "mcp-remote@latest",
17 "https://ah-api-develop.merge.dev/api/v1/tool-packs/{TOOL_PACK_ID}/registered-users/{REGISTERED_USER_ID}/mcp",
18 "--header",
19 "Authorization: Bearer ${input:agent-handler-auth}"
20 ]
21 }
22 }
23}Your use cases depend on the type of agent you’re building. That said, here are a few common use cases:
Here are some of the most common tools segmented by data types:
Merge Agent Handler differentiates itself by operating as a full agent–tool management platform, not just an MCP endpoint.
Yes, you can set custom security rules for any Jira tool calls to block or redact sensitive data. You can also log certain tool calls, allowing the agent to make them while providing your team with real-time visibility whenever this happens.
Here are some specific examples:
You can add or modify Jira tools using Connector Studio within Merge Agent Handler:
1. Start from a pre-built Jira connector: Log into the Agent Handler dashboard and navigate to "Connectors" in the sidebar. Select the Jira connector from the list of available connectors.
2. Enable or disable specific Jira tools in a Tool Pack: Navigate to "Tool Packs" and either create a new Tool Pack or select an existing one. Add the Jira connector to your Tool Pack, then choose which specific Jira tools you want to make available to your agent.
3. Customize/extend tools, or add tools tailored to your workflows: Within Connector Studio, you can modify existing Jira tools by editing their names, descriptions, input schemas, and implementation logic. You can also create entirely new custom tools for Jira-specific actions that aren't available by default, such as custom field updates or advanced query filters.
4. Associate the updated Tool Pack with your agent: Once you've configured your Jira tools, save your Tool Pack. Then connect it to your agent using the MCP entry URL provided in the Tool Pack settings. Your agent will now have access to exactly the Jira tools you've configured, with all authentication, security rules, and logging handled automatically by Agent Handler.
Whether you're an engineer experimenting with agents or a product manager looking to add tools, you can get started for free now