MCP ERPNext
by sharat9703
README.md
# devflow-mcp
An MCP (Model Context Protocol) server that exposes engineering-workflow operations to MCP clients such as Claude Code, Claude Desktop, or any other MCP-compatible assistant. It wraps four systems behind one stdio server: **ERPNext** (timesheets, leave applications, projects, Developer Tasks, Software Release documents), **Taiga** (user stories, tasks, attachments), **Redmine** (issue read/create/update, attachments), and **GitLab** (merge request listing, analysis, and release-note generation from MRs). All 52 tools are registered in a single process; ERPNext credentials are mandatory, the other three services activate only when their credentials are present.
## Prerequisites
- **Node.js >= 18** (declared in `package.json` `engines`). No build step — the server runs plain ESM JavaScript from `src/`.
- **ERPNext account** — required. The server exits at startup without it.
- **GitLab personal access token** — optional; needed for merge-request and software-release tools.
- **Redmine API key** — optional; needed for Redmine issue and attachment tools, and for auto-fetching ticket titles during release creation.
- **Taiga credentials** (token, or user + password) — optional; needed for all Taiga tools.
## Installation
```bash
git clone https://gitlab.credenceanalytics.com/Sharat/devflow-mcp.git
cd devflow-mcp
npm install
```
There is no build step. Verify it starts:
```bash
npm start # or: node src/index.js
```
It should print `MCP ERPNext Server running` on stderr and then wait for stdio input (Ctrl+C to exit).
### Configuration
Create a `.env` file **in the repository root**. `src/index.js` loads it relative to the package root, not the working directory, so the file must sit next to `package.json`.
```env
ERPNEXT_URL=https://erp.example.com
ERPNEXT_USERNAME=you@example.com
ERPNEXT_PASSWORD=your-password
ERPNEXT_TOTP_SECRET=BASE32SECRET
GITLAB_URL=https://gitlab.example.com
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
REDMINE_URL=https://redmine.example.com
REDMINE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TAIGA_HOST=https://taiga.example.com/api/v1
TAIGA_USER=you@example.com
TAIGA_PASS=your-password
# TAIGA_TOKEN=eyJ0eXAi... # alternative to TAIGA_USER + TAIGA_PASS
```
| Variable | Required | Default | What it is / where to get it |
|----------|----------|---------|------------------------------|
| `ERPNEXT_URL` | Yes | — | Base URL of your ERPNext/Frappe instance, no trailing path. |
| `ERPNEXT_USERNAME` | Yes | — | ERPNext login, usually your email address. |
| `ERPNEXT_PASSWORD` | Yes | — | Password for that ERPNext login. |
| `ERPNEXT_TOTP_SECRET` | No | — | Base32 TOTP seed, only if your ERPNext enforces 2FA. Shown as the "manual entry" secret when you set up the authenticator app. |
| `GITLAB_URL` | No | `https://gitlab.credenceanalytics.com` | Base URL of your GitLab instance. |
| `GITLAB_TOKEN` | No | — | Personal access token with `api` (or at least `read_api`) scope: GitLab → User Settings → Access Tokens. |
| `REDMINE_URL` | No | `https://support.credenceanalytics.com` | Base URL of your Redmine instance. |
| `REDMINE_API_KEY` | No | — | Redmine REST API key: Redmine → My account → API access key → Show. Needs write permission for the issue-create/update tools. |
| `TAIGA_HOST` | No | `https://api.taiga.io/api/v1` | Taiga **API** base URL — must include the `/api/v1` suffix. |
| `TAIGA_USER` | No | — | Taiga username or email (used with `TAIGA_PASS` for password login). |
| `TAIGA_PASS` | No | — | Password for `TAIGA_USER`. |
| `TAIGA_TOKEN` | No | — | Pre-issued Taiga auth token. Use this *or* `TAIGA_USER` + `TAIGA_PASS`. |
Credentials may also be supplied through the MCP client's `env` block instead of `.env` (see below); the process environment wins where both are set.
## Client setup
Add the server to your MCP client config. Use an **absolute path** to `src/index.js`.
**Claude Desktop** — `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
```json
{
"mcpServers": {
"devflow": {
"command": "node",
"args": ["D:\\devflow-mcp\\src\\index.js"],
"env": {
"ERPNEXT_URL": "https://erp.example.com",
"ERPNEXT_USERNAME": "you@example.com",
"ERPNEXT_PASSWORD": "your-password",
"GITLAB_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
"REDMINE_API_KEY": "xxxxxxxxxxxxxxxxxxxxxxxx",
"TAIGA_HOST": "https://taiga.example.com/api/v1",
"TAIGA_USER": "you@example.com",
"TAIGA_PASS": "your-password"
}
}
}
}
```
**Claude Code** — same block inside `.mcp.json` (project scope) or `~/.claude.json` (user scope), or register it in one command:
```bash
claude mcp add devflow -- node /absolute/path/to/devflow-mcp/src/index.js
```
Windows path notes:
- In JSON, backslashes must be escaped: `"D:\\devflow-mcp\\src\\index.js"`. Forward slashes (`"D:/devflow-mcp/src/index.js"`) also work and avoid the issue.
- Keeping credentials in `.env` and omitting the `env` block entirely is simpler — the server finds `.env` from its own location regardless of where the client launches it from.
## Usage
Once the server is connected, ask the assistant in plain language:
- **"Create my weekly timesheet for project PROJ-0460."**
Calls `erpnext_create_weekly_timesheet`, which creates Mon–Fri entries of 7h Billable + 2h Non-Billable, validates that no time ranges overlap, and returns the draft timesheet name for review before you submit it.
- **"Preview a software release for https://gitlab.example.com/team/repo/-/merge_requests/412 using https://erp.example.com/app/software-release/PROD-v1.2.0 as the template."**
Calls `erpnext_preview_software_release`: pulls commits and notes from the MR, extracts Redmine ids from the description, fetches their titles from Redmine, inherits Product/Customer/Reviewer from the template release, and shows every field plus its source. Nothing is written until you follow up with `erpnext_create_software_release`.
- **"Show the tasks under this Taiga user story and the commits they reference."**
Calls `erpnext_get_user_story_tasks`, returning each task's full description along with the merge-commit SHAs and Redmine issue ids found in it — useful for assembling a cherry-pick list for a release branch.
- **"Apply for leave from 25 Dec to 27 Dec, and show my leave balance first."**
Calls `erpnext_get_leave_balance`, then `erpnext_apply_leave` to create the application as a draft; `erpnext_submit_leave_application` sends it for approval as a separate, explicit step.
See [USAGE.md](USAGE.md) for longer worked examples.
## Tool reference
52 tools, registered in `src/definitions/` and dispatched from `src/handlers/`.
### Auth
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_login` | Log in to ERPNext with the configured username/password and optional TOTP. Call before other operations. | — |
| `erpnext_get_current_employee` | Get the Employee record linked to the logged-in user. | — |
### Timesheets
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_list_activity_types` | List available activity types for timesheets. | — |
| `erpnext_create_timesheet` | Create a timesheet with an array of time logs. | `time_logs` |
| `erpnext_quick_timesheet` | Create a timesheet for today with a single entry. | `hours`, `activity_type` |
| `erpnext_create_weekly_timesheet` | Create a Mon–Fri week of 7h Billable + 2h Non-Billable per day (hours and days configurable). | — |
| `erpnext_create_custom_timesheet` | Create a timesheet from fully custom entries. | `entries` |
| `erpnext_list_timesheets` | List timesheets, filterable by employee, status and date range. | — |
| `erpnext_get_timesheet` | Get one timesheet's details. | `name` |
| `erpnext_get_my_draft_timesheets` | List all draft timesheets for the current employee. | — |
| `erpnext_add_time_log` | Append a time log to an existing draft timesheet. | `timesheet`, `activity_type`, `hours` |
| `erpnext_update_time_log` | Edit hours, times, project, activity type or description of one log in a draft. | `timesheet`, `time_log_index` |
| `erpnext_remove_time_log` | Remove one time log from a draft (cannot remove the last one). | `timesheet`, `time_log_index` |
| `erpnext_update_timesheet_note` | Update the note on a draft timesheet. | `timesheet`, `note` |
| `erpnext_delete_timesheet` | Delete a draft (unsubmitted) timesheet. | `timesheet` |
| `erpnext_submit_timesheet` | Submit a draft timesheet. | `name` |
| `erpnext_cancel_timesheet` | Cancel a submitted timesheet. | `name` |
### Leave
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_list_leave_types` | List available leave types. | — |
| `erpnext_get_leave_balance` | Get leave balance for the current employee, optionally for one leave type. | — |
| `erpnext_list_leave_applications` | List leave applications, filterable by status, type and date range. | — |
| `erpnext_get_leave_application` | Get one leave application's details. | `name` |
| `erpnext_get_my_pending_leaves` | List pending leave applications for the current employee. | — |
| `erpnext_get_my_approved_leaves` | List approved leave applications for the current employee. | — |
| `erpnext_apply_leave` | Apply for leave, single or multiple days, with half-day support. | `from_date` |
| `erpnext_submit_leave_application` | Submit a leave application for approval. | `name` |
| `erpnext_cancel_leave_application` | Cancel a leave application. | `name` |
### Tasks & Projects
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_list_projects` | List ERPNext projects, optionally filtered by status. | — |
| `erpnext_list_tasks` | List tasks for a project. | `project` |
| `erpnext_create_tasks_from_analysis` | Create ERPNext tasks from a prior merge-request analysis, marked Completed and assigned to the current employee. | `tasks` |
| `erpnext_get_developer_tasks` | Get Developer Tasks for a developer (default: logged-in user) with date/status/product/subject filters, plus a per-client breakdown. | — |
### Taiga
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_validate_user_story` | Validate a user story by URL and return its id, title and project. | `user_story_url` |
| `erpnext_create_user_story` | Create a user story in a Taiga project; returns id, ref and URL. | `project_slug`, `subject` |
| `erpnext_create_taiga_tasks` | Create one or more tasks under a user story, resolving assignees from project members and setting custom attributes (complexity, task type) where they exist. | `user_story_id`, `project_slug`, `tasks` |
| `erpnext_get_taiga_tasks` | Get tasks assigned to a user (default: authenticated user) with descriptions and attachment metadata; open tasks only by default. | — |
| `erpnext_get_user_story_tasks` | Get all tasks under a user story (any assignee) with full descriptions, plus merge-commit SHAs and Redmine ids referenced in them. | `user_story` |
| `erpnext_update_taiga_task` | Update a task's status and/or description, identified by `task_id` or by `ref` + project. | — |
| `erpnext_download_taiga_attachment` | Download a task attachment to disk by URL or attachment id; returns the saved path and a text preview where applicable. | — |
| `erpnext_export_tasks_to_erp` | Export tasks to ERPNext as Developer Task documents, resolving the employee code, mapping task type to an ERP category and normalizing complexity. | `tasks` |
### Redmine
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_get_redmine_issue` | Get an issue's title/subject from its id or URL. | `issue_id` |
| `erpnext_get_redmine_issue_details` | Get full issue content: description, status, priority, assignee, done ratio, comments, attachments, sub-tasks and relations. | `issue_id` |
| `erpnext_create_redmine_issue` | Create a new issue in a project, with optional tracker, assignee, dates, parent and custom fields. Needs create permission. | `project_id`, `subject` |
| `erpnext_update_redmine_issue` | Add a note and/or change fields (status by id or name, assignee, priority, done ratio, subject, description, dates). Needs write permission. | `issue_id` |
| `erpnext_download_redmine_attachment` | Download an issue attachment to disk by attachment id or download URL; returns the saved path, metadata and a text preview where applicable. | `attachment` |
All Redmine tools require `REDMINE_API_KEY`.
### GitLab merge requests
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_list_merge_requests` | List MRs in a project, filterable by state, author, target branch and creation date range. | `project_path` |
| `erpnext_analyze_merge_request` | Analyze one or more MRs: extract commits, group them by type (features/fixes/refactors) and identify Redmine issues, returning a suggested task breakdown for review. | — (pass `mr_url` or `mr_urls`) |
| `erpnext_get_mr_details` | Get MR details including auto-detected customer, version, Redmine ids from the description and patch/test-report URLs from the notes. | `mr_url` |
### Software releases
| Tool | Description | Required params |
|------|-------------|-----------------|
| `erpnext_preview_software_release` | Show what the release document will contain — auto-detected fields, their sources and anything still missing — without creating it. | `mr_urls` |
| `erpnext_create_software_release` | Create the Software Release document in ERPNext from GitLab MR URL(s), auto-filling Product/Customer/Reviewer from a template release and pulling Redmine ids, ticket titles, patch URLs and test-report URLs. | `mr_urls` |
| `erpnext_get_software_release` | Get an existing release by URL or name (commonly used as the template reference). | — (pass `release_url` or `release_name`) |
| `erpnext_list_software_releases` | List recent releases, filterable by product and customer. | — |
| `erpnext_list_products` | List products (Brands) available for release selection. | — |
| `erpnext_list_customers_for_release` | List customers available for release selection. | — |
### Resources
Read-only endpoints exposed alongside the tools:
| URI | Contents |
|-----|----------|
| `erpnext://timesheets/draft` | Draft timesheets for the current employee |
| `erpnext://activity-types` | Available timesheet activity types |
| `erpnext://projects` | All projects |
| `erpnext://leave-types` | Available leave types |
| `erpnext://leaves/pending` | Pending leave applications |
## Troubleshooting
**Server exits immediately with "ERPNEXT_URL, ERPNEXT_USERNAME, and ERPNEXT_PASSWORD are required".**
The `.env` file is missing or not in the repository root. It is loaded from the package root (next to `package.json`), not from the client's working directory. Either move it there or pass the values in the client's `env` block.
**ERPNext login fails / 401.**
Run `erpnext_login` explicitly and read the error. If the account has 2FA enabled, `ERPNEXT_TOTP_SECRET` must be the Base32 seed — not a 6-digit code. Check that `ERPNEXT_URL` has no trailing slash or path segment.
**Redmine tools return an error about the API key.**
`REDMINE_API_KEY` is unset or lacks permission. Creating and updating issues needs write access on the target project; a read-only key will fail only on those tools.
**Taiga tools fail to authenticate.**
Supply either `TAIGA_TOKEN` or both `TAIGA_USER` and `TAIGA_PASS`. `TAIGA_HOST` must point at the API base and include `/api/v1` — a plain site URL will 404.
**GitLab / release tools fail.**
`GITLAB_TOKEN` needs `api` scope and access to the project the MR lives in. Confirm `GITLAB_URL` matches the instance hosting that MR.
**The server does not appear in the client.**
- Restart the client fully after editing its config — MCP servers are launched at startup.
- Check the path in `args` is absolute and the file exists; in JSON, backslashes must be doubled.
- Run `node /absolute/path/to/src/index.js` in a terminal. If the process prints `MCP ERPNext Server running` and hangs, the server is fine and the problem is the client config; any other output is the actual error.
- In Claude Code, `claude mcp list` shows registered servers and their connection status.
## License
MIT — see [LICENSE](LICENSE).
## Author
**Sharat Yaragatti** — [GitHub](https://github.com/sharat9703)
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues