@cocaxcode/devflow-mcp
Your Jira + GitHub/GitLab workflow, handled by your AI assistant.
One MCP server. 32 tools. Say what you need, it gets done.
Overview ·
Just Talk to It ·
Installation ·
Tools ·
Flows ·
Rules ·
Storage ·
Compatibility ·
Architecture
Overview
devflow-mcp is an MCP server that connects Jira (Cloud + Server) with GitHub/GitLab (cloud + self-hosted) through 32 tools your AI assistant can call directly. It auto-detects your Jira version and git provider, enforces configurable safety rules, and lets you define custom YAML flow playbooks for repeatable workflows.
No context switching. No browser tabs. Just tell your assistant what you need.
Just Talk to It
You don't memorize tool names. You talk naturally and the assistant picks the right tools.
"Let's work on PROJ-123"
> Reading PROJ-123...
Title: Add OAuth login
Status: To Do | Priority: High
> Branch feat/PROJ-123 not found. Creating...
branch: feat/PROJ-123-add-oauth-login
base: main
Confirm? (confirm: true to execute)
> Moved PROJ-123 → In Progress
> Assigned to you
"Show me my tasks for the ACME project"
ACME-45 Fix OAuth login In Progress High
ACME-52 Dashboard refactor To Do Medium
ACME-61 Update dependencies To Do Low
"Push my changes"
Preview:
branch: feat/PROJ-123-add-oauth-login
pending commits:
- a1b2c3d feat: add login component
- d4e5f6g feat: add auth service
Confirm? (confirm: true to execute)
"Merge main into my current branch"
Conflict detected:
- src/auth/login.ts
- src/config/routes.ts
Resolve the files and commit to complete the merge.
"Create a PR titled 'feat: add OAuth login'"
PR created:
url: https://github.com/org/repo/pull/42
title: feat: add OAuth login
provider: github
"Comment on PROJ-123 that the PR is ready for review"
Preview:
issue: PROJ-123
comment: "PR ready for review: https://github.com/org/repo/pull/42"
Confirm? (confirm: true to publish)
"Create a fix branch for PROJ-456 with description fix-oauth-redirect"
Preview:
branch: fix/PROJ-456-fix-oauth-redirect
base: main
actions: checkout main → pull → create branch
Confirm? (confirm: true to execute)
Installation
Claude Code (recommended)
claude mcp add --scope user devflow -- npx -y @cocaxcode/devflow-mcp
claude mcp add devflow -- npx -y @cocaxcode/devflow-mcp
Claude Desktop
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"devflow": {
"command": "npx",
"args": ["-y", "@cocaxcode/devflow-mcp"]
}
}
}
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"devflow": {
"command": "npx",
"args": ["-y", "@cocaxcode/devflow-mcp"]
}
}
}
Cursor / Windsurf
{
"mcpServers": {
"devflow": {
"command": "npx",
"args": ["-y", "@cocaxcode/devflow-mcp"]
}
}
}
VS Code / Codex / Gemini CLI
{
"mcpServers": {
"devflow": {
"command": "npx",
"args": ["-y", "@cocaxcode/devflow-mcp"]
}
}
}
Tools
32 tools organized in 5 categories.
Projects (5)
df_project_setup | Configure a new project (Jira + Git, auto-detects everything) |
df_project_update | Modify project configuration |
df_project_list | List all configured projects |
df_project_switch | Switch the active project |
df_project_delete | Delete a project |
Example: setting up a project
df_project_setup with:
name: "my-project"
jiraUrl: "https://my-company.atlassian.net"
jiraEmail: "dev@company.com"
jiraToken: "ATATT3x..."
jiraProjectKey: "PROJ"
gitToken: "ghp_..."
paths: ["C:/repos/my-project"]
Auto-detects:
- Jira Cloud (API v3)
- GitHub (org/my-project)
- Base branch: main
Jira (6)
df_issues | List my assigned issues (filters by project) | -- |
df_issue | Full issue detail | -- |
df_statuses | Available transitions for an issue | -- |
df_transition | Move issue to another status | Yes |
df_assign | Assign issue to current user | -- |
df_comment | Comment on an issue | Yes |
Git (7)
df_branch | Create branch (feat/ or fix/) from base | Yes |
df_find_branch | Search branch by issue key | -- |
df_checkout | Switch branch (with safety guard) | -- |
df_pull | Pull current branch from remote | -- |
df_push | Push current branch to remote | Yes |
df_merge | Merge a branch into the current one | Yes |
df_pr | Create PR (GitHub) or MR (GitLab) | -- |
Important: df_branch, df_checkout, and df_push verify the working directory before executing. They block if there are uncommitted files or unpushed commits, listing exactly what needs attention. This prevents accidental work loss.
Flows (5)
df_flow_create | Create a custom flow |
df_flow_list | List all flows |
df_flow_get | View flow details |
df_flow_update | Modify an existing flow |
df_flow_delete | Delete a flow (protects start-task) |
Rules (9)
df_rule_create | Create a global rule | Global |
df_rule_list | List all rules | Global |
df_rule_get | View rule details | Global |
df_rule_update | Modify a rule | Global |
df_rule_toggle | Enable/disable a rule | Global |
df_rule_delete | Delete a rule | Global |
df_rule_project_override | Enable/disable a global rule for a project | Project |
df_rule_project_add | Create a project-only rule | Project |
df_rule_project_remove | Remove a project rule or override | Project |
Flows
Flows are YAML playbooks that define step sequences. They don't run automatically -- you tell the assistant when to use them.
Default: start-task
Triggered when you say something like "let's work on PROJ-123":
name: start-task
trigger: "when the user says 'let's work on', 'start task', 'new task' + issue ID"
steps:
- tool: df_issue
note: "Read issue detail and summarize the task"
- tool: df_find_branch
note: "Check if a branch already exists for this issue"
- tool: df_branch
confirm: true
note: "Only if no existing branch was found"
- tool: df_statuses
note: "Get transitions to find the 'In Progress' transition ID"
- tool: df_transition
target: "In Progress"
confirm: true
- tool: df_assign
note: "Assign the issue if it has no assignee"
Custom flows
Create your own by asking naturally:
"Create a flow called 'finish-task' that pushes, creates a PR, and comments on Jira"
name: finish-task
trigger: "when the user says 'finish task', 'wrap up' + issue ID"
steps:
- tool: df_push
confirm: true
note: "Push pending commits"
- tool: df_pr
note: "Create PR/MR to base branch"
- tool: df_comment
confirm: true
note: "Comment on the issue with the PR link"
The start-task flow can be modified but not deleted. Use df_flow_update to change any flow's steps, trigger, or name.
Rules
Rules are configurable guards that block or warn about actions. Two levels: global and per-project.
Default rules
no-merge-to-base | git | block | Prevent direct push/merge to main/master |
no-merge-from-dev | git | block | Prevent merging dev/develop/int branches out |
no-close-issues | jira | block | Prevent closing issues (Done, Closed, Resolved...) |
only-own-issues | jira | block | Prevent modifying issues assigned to others |
Project overrides
Each project can override global rules or define its own:
# Disable a global rule for one project
df_rule_project_override: name="no-close-issues", enabled=false
# Add a project-only rule
df_rule_project_add: name="no-push-friday", scope="git", action="warn"
# Remove an override or project rule
df_rule_project_remove: name="no-close-issues"
Custom rules
df_rule_create:
name: "no-push-friday"
description: "Warn when pushing on Fridays"
scope: "git" # git | jira | all
action: "warn" # block | warn
Note: Rule resolution order: Global rules load first, then project overrides are applied (project wins), then project-specific rules are added. Rules are filtered by scope and enabled state before evaluation.
Storage
All data lives in ~/.dfm/:
~/.dfm/
├── projects/ # Project configs (.json)
│ ├── my-project.json
│ └── other-project.json
├── flows/ # Flow definitions (.yaml)
│ └── start-task.yaml
├── rules/ # Global rules (.json)
│ ├── no-merge-to-base.json
│ ├── no-merge-from-dev.json
│ ├── no-close-issues.json
│ └── only-own-issues.json
├── active-project # Current active project (plain text)
└── config.json # Server configuration
Project files are created with 600 permissions (owner-only read/write).
Tip: Project resolution: devflow-mcp matches your current working directory against each project's paths. If no match, it falls back to the project set via df_project_switch. If neither works, it prompts you to configure with df_project_setup.
Compatibility
Jira
| Jira Cloud | REST API v3 | Email + API Token (Basic) |
| Jira Server / Data Center | REST API v2 | Personal Access Token (Bearer) |
Auto-detection via /rest/api/2/serverInfo -- no manual configuration needed.
Git providers
| GitHub (cloud) | REST API v3 |
| GitHub Enterprise | REST API v3 (custom URL) |
| GitLab (cloud) | REST API v4 |
| GitLab self-hosted | REST API v4 (custom URL) |
Auto-detection by parsing the repository's remote URL.
Architecture
src/
├── index.ts # Entry point (stdio transport)
├── server.ts # Factory: createServer() + instructions
├── lib/
│ ├── types.ts # Interfaces, defaults, valid tool names
│ ├── storage.ts # CRUD: projects, flows, rules, config
│ ├── git-exec.ts # Git CLI wrapper (execFile)
│ ├── jira/
│ │ ├── client.ts # JiraClient (Cloud v3 + Server v2)
│ │ └── types.ts # Raw Jira API response shapes
│ └── git/
│ ├── detect.ts # parseRemoteUrl (SSH/HTTPS, GitHub/GitLab)
│ ├── github.ts # GitHubClient (REST API v3)
│ ├── gitlab.ts # GitLabClient (REST API v4)
│ ├── factory.ts # createGitProviderClient()
│ └── types.ts # Git provider interfaces
└── tools/
├── project.ts # 5 tools: setup, update, list, switch, delete
├── jira.ts # 6 tools: issues, issue, statuses, transition, assign, comment
├── git.ts # 7 tools: branch, find_branch, checkout, pull, push, merge, pr
├── flow.ts # 5 tools: create, list, get, update, delete
└── rule.ts # 9 tools: CRUD global + 3 project-level
Stack: TypeScript · MCP SDK · Zod · YAML · tsup
Tests: 4 suites · 51 tests (Vitest + InMemoryTransport)
MIT · Built by cocaxcode