Skip to content
Back to skills

Daf Jira Mcp

ASecurity

Using MCP JIRA tools with DevAIFlow validation logic and field intelligence

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 29, 2026
developmentpythongobashapibackendperformance

Works with

  • api
  • mcp

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add itdove/devaiflow --skill daf-jira-mcp --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Daf Jira Mcp?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Daf Jira Mcp
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/itdove-daf-jira-mcp/badge)](https://www.skillsdirectory.com/skills/itdove-daf-jira-mcp)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: daf-jira-mcp
description: Using MCP JIRA tools with DevAIFlow validation logic and field intelligence
user-invocable: false
---

# MCP JIRA Integration with DevAIFlow Intelligence

When using MCP JIRA tools (e.g., `mcp__mcp-atlassian__jira_*`), you can leverage DevAIFlow's configuration intelligence to build validated, compliant JIRA operations.

## Core Concept

**CRITICAL: When using MCP JIRA tools, you MUST read DevAIFlow configuration first.**

Unlike `daf jira create` commands (which are self-contained), MCP tools require you to manually:
1. **Read configuration** via `daf config show --json`
2. **Apply validation** logic yourself
3. **Map field names** to JIRA field IDs
4. **Format values** based on field types

**DevAIFlow configuration provides JIRA field metadata that MCP tools need:**
- Field IDs (customfield_12345) mapped to friendly names
- Required fields per issue type
- Allowed values for select/option fields
- Field availability per issue type
- Team/organization defaults

## Step-by-Step: Using MCP with daf Intelligence

### Step 1: Get Configuration Metadata

```bash
# Get complete JIRA configuration
daf config show --json > /tmp/daf-config.json
```

**Key sections in the output:**
```json
{
  "jira": {
    "project": "AAP",
    "custom_field_defaults": {
      "workstream": "SaaS"
    },
    "system_field_defaults": {
      "components": ["ansible-saas"],
      "labels": ["backend"]
    },
    "field_mappings": {
      "acceptance_criteria": {
        "id": "customfield_10718",
        "name": "Acceptance Criteria",
        "type": "string",
        "required_for": ["Bug", "Story", "Task", "Epic"],
        "available_for": ["Bug", "Story", "Task", "Epic"],
        "allowed_values": []
      },
      "workstream": {
        "id": "customfield_12345",
        "name": "Workstream",
        "type": "option",
        "required_for": ["Story", "Task"],
        "available_for": ["Story", "Task", "Epic"],
        "allowed_values": ["Platform", "SaaS", "Services"]
      }
    }
  }
}
```

### Step 2: Apply Validation Logic

**Before calling MCP, validate:**

1. **Field Availability Check**
   ```python
   issue_type = "Story"
   field_name = "workstream"
   
   # Check if field is available for this issue type
   if issue_type not in field_mappings[field_name]["available_for"]:
       raise Error(f"{field_name} not available for {issue_type}")
   ```

2. **Required Fields Check**
   ```python
   # Get all required fields for issue type
   required_fields = [
       field_name 
       for field_name, config in field_mappings.items()
       if issue_type in config.get("required_for", [])
   ]
   
   # Verify all required fields are provided
   missing = [f for f in required_fields if f not in provided_fields]
   if missing:
       raise Error(f"Missing required fields: {missing}")
   ```

3. **Allowed Values Check**
   ```python
   # For select/option fields, validate value
   allowed = field_mappings["workstream"]["allowed_values"]
   if value not in allowed:
       raise Error(f"Invalid value '{value}'. Allowed: {allowed}")
   ```

### Step 3: Apply Defaults

```python
# Apply custom field defaults (ONLY for required fields)
for field_name, default_value in custom_field_defaults.items():
    if field_name not in provided_fields:
        field_config = field_mappings.get(field_name, {})
        if issue_type in field_config.get("required_for", []):
            # Apply default only for required fields
            provided_fields[field_name] = default_value

# Apply system field defaults (components, labels)
if "components" not in provided_fields:
    provided_fields["components"] = system_field_defaults.get("components", [])
```

### Step 4: Map to JIRA Field IDs

```python
# Convert friendly names to JIRA field IDs
additional_fields = {}

for field_name, value in provided_fields.items():
    field_config = field_mappings.get(field_name)
    if field_config:
        field_id = field_config["id"]
        field_type = field_config["type"]
        
        # Format value based on field type
        if field_type == "option":
            additional_fields[field_id] = {"value": value}
        elif field_type == "array":
            additional_fields[field_id] = [{"name": v} for v in value]
        elif field_type == "user":
            additional_fields[field_id] = {"name": value}
        else:
            additional_fields[field_id] = value
```

### Step 5: Build MCP Call

```python
import json

# Build additional_fields JSON for MCP
additional_fields_json = json.dumps(additional_fields)

# Call MCP with validated, formatted fields
mcp__mcp-atlassian__jira_create_issue(
    project_key="AAP",
    summary="Add caching layer",
    issue_type="Story",
    description="Implementation details...",
    additional_fields=additional_fields_json
)
```

## Complete Example: Create Story with Validation

```python
# Step 1: Load config
import json
with open('/tmp/daf-config.json') as f:
    config = json.load(f)

field_mappings = config["jira"]["field_mappings"]
custom_defaults = config["jira"]["custom_field_defaults"]
system_defaults = config["jira"]["system_field_defaults"]

# Step 2: Define issue
issue_type = "Story"
provided = {
    "summary": "Add Redis caching",
    "description": "h3. Overview\n\nImplement caching...",
    "workstream": "Platform",  # Will validate against allowed_values
    "acceptance_criteria": "- [] Tests pass\n- [] Performance targets met"
}

# Step 3: Validate required fields
required = [
    name for name, cfg in field_mappings.items()
    if issue_type in cfg.get("required_for", [])
]

missing = [f for f in required if f not in provided]
if missing:
    print(f"ERROR: Missing required fields: {missing}")
    # Should include: components (from required_for)

# Step 4: Apply defaults for missing required fields
for field_name in required:
    if field_name not in provided:
        # Check custom defaults first
        if field_name in custom_defaults:
            provided[field_name] = custom_defaults[field_name]
        # Check system defaults
        elif field_name in system_defaults:
            provided[field_name] = system_defaults[field_name]

# Step 5: Validate allowed values
for field_name, value in provided.items():
    cfg = field_mappings.get(field_name, {})
    allowed = cfg.get("allowed_values", [])
    if allowed and value not in allowed:
        print(f"ERROR: Invalid value '{value}' for {field_name}")
        print(f"Allowed: {allowed}")

# Step 6: Map to JIRA IDs and format
additional_fields = {}

for field_name, value in provided.items():
    if field_name in ["summary", "description", "issue_type"]:
        continue  # These are direct parameters
    
    cfg = field_mappings[field_name]
    field_id = cfg["id"]
    field_type = cfg["type"]
    
    # Format based on type
    if field_type == "option":
        additional_fields[field_id] = {"value": value}
    elif field_type == "array":
        if isinstance(value, list):
            additional_fields[field_id] = [{"name": v} for v in value]
        else:
            additional_fields[field_id] = [{"name": value}]
    elif field_type == "string":
        additional_fields[field_id] = value
    else:
        additional_fields[field_id] = value

# Step 7: Call MCP
additional_fields_json = json.dumps(additional_fields)

mcp__mcp-atlassian__jira_create_issue(
    project_key="AAP",
    summary=provided["summary"],
    issue_type="Story",
    description=provided["description"],
    additional_fields=additional_fields_json
)
```

## Quick Reference: Field Type Formatting

| Type | Config | MCP Format |
|------|--------|------------|
| **string** | `"type": "string"` | `"customfield_123": "value"` |
| **option** | `"type": "option"` | `"customfield_123": {"value": "Option1"}` |
| **array** | `"type": "array"` | `"customfield_123": [{"name": "Item1"}, {"name": "Item2"}]` |
| **user** | `"type": "user"` | `"customfield_123": {"name": "username"}` |
| **version** | `"type": "version"` | `"customfield_123": [{"name": "1.0.0"}]` |
| **number** | `"type": "number"` | `"customfield_123": 42` |

## Validation Checklist

Before calling MCP JIRA tools, verify:

- [ ] **Field availability**: All fields in `available_for` for issue type
- [ ] **Required fields**: All fields in `required_for` are provided or have defaults
- [ ] **Allowed values**: Values match `allowed_values` (case-sensitive)
- [ ] **Field IDs**: Using JIRA field IDs (customfield_*), not friendly names
- [ ] **Field types**: Values formatted correctly for field type
- [ ] **Defaults applied**: Custom/system defaults applied to required fields only

## Error Messages to Watch For

**From MCP (indicates validation was missed):**
```
Field 'customfield_12345' is not on the appropriate screen, or unknown
→ Field not available_for this issue type

Field 'customfield_12345' is required
→ Missing required field

Invalid value 'High' for field 'customfield_12345'
→ Value not in allowed_values
```

**Better approach:** Validate BEFORE calling MCP using daf config intelligence.

## Field Format Requirements: ADF vs Wiki Markup

**CRITICAL: Field format requirements differ between daf commands and MCP tools.**

### With daf Commands (Recommended)
- ✅ **Use JIRA Wiki markup** for all text fields
- ✅ **Automatic conversion** - JIRA API converts Wiki markup to ADF for Cloud instances
- ✅ **No format issues** - daf handles the complexity

### With MCP Tools (Advanced)
- ⚠️ **Format varies by field and JIRA instance**
- **Description field**: May auto-convert Wiki markup to ADF (inconsistent)
- **Custom rich text fields**: May require explicit **Atlassian Document Format (ADF)**
- **Plain text fields**: Use plain strings

**Example ADF format** (for custom fields that require it):
```json
{
  "type": "doc",
  "version": 1,
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Your text content here"
        }
      ]
    }
  ]
}
```

**Known issues with MCP:**
- `acceptance_criteria` custom field may fail with: "Operation value must be an Atlassian Document Format"
- Auto-conversion behavior is inconsistent across JIRA field types
- No reliable way to predict which fields need ADF vs plain text

**Recommendation**: Use `daf jira create/update` for creating/updating tickets with rich text fields. MCP tools are best for reading data, searching, and advanced operations like sprint management.

## When to Use daf Commands Instead

**Use `daf jira create/update` when:**
- ✅ You want automatic validation (no manual checking)
- ✅ You want friendly field names (no field ID mapping)
- ✅ You want session integration (links issue to current session)
- ✅ You want automatic field format handling (Wiki markup → ADF conversion)
- ✅ You're creating issues frequently (daf handles all complexity automatically)
- ✅ **You're working with rich text custom fields** (avoids ADF format complexity)

**Use MCP with daf intelligence when:**
- ✅ You need advanced JIRA operations not in daf (e.g., sprint management)
- ✅ You want direct API access for reading data
- ✅ You're exploring JIRA data (searches, complex queries)
- ✅ You understand field mapping, validation, AND format requirements (ADF vs Wiki markup)
- ⚠️ **Avoid MCP for creating/updating** if you have rich text custom fields (use daf commands instead)

## See Also

- **daf-jira skill** - daf commands for validated JIRA operations
- **daf-jira-fields skill** - Field mapping reference and validation rules
- **daf-config skill** - How to view and manage daf configuration

## Issue Type Templates

DevAIFlow supports issue type templates that provide standardized descriptions for different issue types.

**Get templates from config:**

```bash
daf config show --json | jq '.organization.jira_issue_templates'
```

**Example templates in config:**
```json
{
  "organization": {
    "jira_issue_templates": {
      "Bug": "h3. Problem\n\n[Describe the bug]\n\nh3. Expected Behavior\n\n[What should happen]\n\nh3. Actual Behavior\n\n[What actually happens]\n\nh3. Reproduction Steps\n\n# Step 1\n# Step 2\n\nh3. Environment\n\n[Version, OS, browser, etc.]",
      "Story": "h3. User Story\n\nAs a [user type]\nI want [goal]\nSo that [benefit]\n\nh3. Acceptance Criteria\n\n- [] Criterion 1\n- [] Criterion 2\n\nh3. Technical Notes\n\n[Implementation details]",
      "Task": "h3. Objective\n\n[What needs to be done]\n\nh3. Tasks\n\n# Task 1\n# Task 2\n\nh3. Dependencies\n\n[Related tickets or blockers]",
      "Epic": "h3. Epic Goal\n\n[High-level objective]\n\nh3. Success Criteria\n\n- [] Outcome 1\n- [] Outcome 2\n\nh3. Scope\n\n*In Scope:*\n* Item 1\n\n*Out of Scope:*\n* Item 1"
    }
  }
}
```

### Using Templates with MCP

```python
# Load templates
templates = config["organization"]["jira_issue_templates"]

# Get template for issue type
issue_type = "Story"
description_template = templates.get(issue_type, "")

# Customize description
description = description_template.replace("[goal]", "cache API responses")
description = description.replace("[benefit]", "improve performance by 50%")

# Use in MCP call
mcp__mcp-atlassian__jira_create_issue(
    project_key="AAP",
    summary="Add Redis caching",
    issue_type="Story",
    description=description,
    additional_fields=additional_fields_json
)
```

**Benefits of using templates:**
- ✅ Consistent issue format across team
- ✅ Ensures all required information is captured
- ✅ Saves time (don't write descriptions from scratch)
- ✅ Matches team/org standards

**Note:** Templates use JIRA Wiki markup syntax (see daf-jira skill for syntax reference).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.