@thammarongg/jira-mcp 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -3
- package/dist/agents.js +412 -0
- package/dist/index.js +54 -3
- package/dist/install.js +47 -381
- package/dist/prompt.js +139 -0
- package/dist/status.js +81 -0
- package/dist/uninstall.js +140 -0
- package/dist/update.js +71 -0
- package/package.json +1 -1
- package/skill/SKILL.md +23 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { AGENTS, hasAgentEntry, removeAgentConfig, resolveAgents } from "./agents.js";
|
|
2
|
+
import { makePrompter } from "./prompt.js";
|
|
3
|
+
function parseFlags(argv) {
|
|
4
|
+
const flags = {};
|
|
5
|
+
for (let i = 0; i < argv.length; i++) {
|
|
6
|
+
const arg = argv[i];
|
|
7
|
+
if (arg === "--agents") {
|
|
8
|
+
const value = argv[++i];
|
|
9
|
+
if (value === undefined)
|
|
10
|
+
throw new Error("Missing value for --agents");
|
|
11
|
+
flags.agents = value;
|
|
12
|
+
}
|
|
13
|
+
else if (arg === "--yes") {
|
|
14
|
+
flags.yes = true;
|
|
15
|
+
}
|
|
16
|
+
else if (arg === "--help" || arg === "-h") {
|
|
17
|
+
flags.help = true;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
throw new Error(`Unknown option: ${arg} (see --help)`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return flags;
|
|
24
|
+
}
|
|
25
|
+
function printUsage() {
|
|
26
|
+
console.log(`jira-mcp uninstall — remove jira MCP entries
|
|
27
|
+
|
|
28
|
+
Usage:
|
|
29
|
+
npx -y @thammarongg/jira-mcp uninstall
|
|
30
|
+
npx -y @thammarongg/jira-mcp uninstall --agents all --yes
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
--agents <list> Comma-separated agent ids or 'all'
|
|
34
|
+
--yes Skip the confirmation prompt
|
|
35
|
+
-h, --help Show this help
|
|
36
|
+
`);
|
|
37
|
+
}
|
|
38
|
+
function configuredAgents() {
|
|
39
|
+
return AGENTS.filter((agent) => hasAgentEntry(agent));
|
|
40
|
+
}
|
|
41
|
+
function resolveConfigured(spec, configured) {
|
|
42
|
+
const norm = spec.trim().toLowerCase();
|
|
43
|
+
if (norm === "all" || norm === "a")
|
|
44
|
+
return [...configured];
|
|
45
|
+
const ids = norm.split(/[,\s]+/).filter(Boolean);
|
|
46
|
+
const selected = [];
|
|
47
|
+
for (const id of ids) {
|
|
48
|
+
const agent = /^\d+$/.test(id)
|
|
49
|
+
? configured[Number(id) - 1]
|
|
50
|
+
: configured.find((candidate) => candidate.id === id);
|
|
51
|
+
if (!agent) {
|
|
52
|
+
throw new Error(`Unknown configured agent '${id}'. Valid: ${configured.map((candidate, index) => `${index + 1}/${candidate.id}`).join(", ")} or all`);
|
|
53
|
+
}
|
|
54
|
+
if (!selected.includes(agent))
|
|
55
|
+
selected.push(agent);
|
|
56
|
+
}
|
|
57
|
+
if (selected.length === 0)
|
|
58
|
+
throw new Error("No agents selected");
|
|
59
|
+
return selected;
|
|
60
|
+
}
|
|
61
|
+
async function promptSelection(p, configured) {
|
|
62
|
+
console.log("\njira-mcp uninstall — select agents to remove:\n");
|
|
63
|
+
console.log(" a) Select All");
|
|
64
|
+
configured.forEach((agent, index) => {
|
|
65
|
+
console.log(` ${index + 1}) ${agent.label.padEnd(15)} ${agent.path}`);
|
|
66
|
+
});
|
|
67
|
+
for (;;) {
|
|
68
|
+
const answer = (await p.ask("\nChoice (e.g. 1,3 or a): ")).trim().toLowerCase();
|
|
69
|
+
if (answer === "" && p.closed)
|
|
70
|
+
throw new Error("No input received (stdin closed)");
|
|
71
|
+
try {
|
|
72
|
+
return resolveConfigured(answer, configured);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
if (p.closed)
|
|
76
|
+
throw err;
|
|
77
|
+
console.log(` ${err instanceof Error ? err.message : String(err)}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function runUninstall(argv) {
|
|
82
|
+
const flags = parseFlags(argv);
|
|
83
|
+
if (flags.help) {
|
|
84
|
+
printUsage();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const configured = configuredAgents();
|
|
88
|
+
if (configured.length === 0) {
|
|
89
|
+
console.error("No jira MCP entries found. Run install to configure an agent first.");
|
|
90
|
+
process.exitCode = 1;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const p = !flags.yes ? makePrompter() : undefined;
|
|
94
|
+
try {
|
|
95
|
+
const selected = flags.agents
|
|
96
|
+
? resolveAgents(flags.agents)
|
|
97
|
+
: flags.yes
|
|
98
|
+
? [...configured]
|
|
99
|
+
: await promptSelection(p, configured);
|
|
100
|
+
console.log("\nWill remove the jira MCP server from:");
|
|
101
|
+
for (const agent of selected) {
|
|
102
|
+
if (hasAgentEntry(agent))
|
|
103
|
+
console.log(` - ${agent.label.padEnd(15)} ${agent.path}`);
|
|
104
|
+
else
|
|
105
|
+
console.log(` skip ${agent.label.padEnd(15)} ${agent.path} (no jira entry)`);
|
|
106
|
+
}
|
|
107
|
+
if (!flags.yes) {
|
|
108
|
+
const answer = (await p.ask("\nProceed? [y/N] ")).trim().toLowerCase();
|
|
109
|
+
if (answer !== "y" && answer !== "yes") {
|
|
110
|
+
console.log("Aborted.");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
let removed = 0;
|
|
115
|
+
let failed = false;
|
|
116
|
+
for (const agent of selected) {
|
|
117
|
+
try {
|
|
118
|
+
const result = removeAgentConfig(agent);
|
|
119
|
+
if (result === "removed") {
|
|
120
|
+
removed++;
|
|
121
|
+
console.log(` ok ${agent.label.padEnd(15)} ${agent.path} (removed)`);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.log(` skip ${agent.label.padEnd(15)} ${agent.path} (no jira entry)`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
failed = true;
|
|
129
|
+
console.error(` ERR ${agent.label.padEnd(15)} ${agent.path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (removed === 0 || failed)
|
|
133
|
+
process.exitCode = 1;
|
|
134
|
+
if (removed > 0)
|
|
135
|
+
console.log("\nDone. Restart each agent to pick up the change.");
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
p?.close();
|
|
139
|
+
}
|
|
140
|
+
}
|
package/dist/update.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { AGENTS, hasAgentEntry, readAgentEnv, resolveAgents, writeAgentConfig } from "./agents.js";
|
|
2
|
+
function parseFlags(argv) {
|
|
3
|
+
const flags = {};
|
|
4
|
+
for (let i = 0; i < argv.length; i++) {
|
|
5
|
+
const arg = argv[i];
|
|
6
|
+
if (arg === "--agents") {
|
|
7
|
+
const value = argv[++i];
|
|
8
|
+
if (value === undefined)
|
|
9
|
+
throw new Error("Missing value for --agents");
|
|
10
|
+
flags.agents = value;
|
|
11
|
+
}
|
|
12
|
+
else if (arg === "--yes") {
|
|
13
|
+
// Accepted for scripts that use the same non-interactive convention as install/uninstall.
|
|
14
|
+
}
|
|
15
|
+
else if (arg === "--help" || arg === "-h") {
|
|
16
|
+
flags.help = true;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
throw new Error(`Unknown option: ${arg} (see --help)`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return flags;
|
|
23
|
+
}
|
|
24
|
+
function printUsage() {
|
|
25
|
+
console.log(`jira-mcp update — refresh existing jira MCP entries
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
npx -y @thammarongg/jira-mcp update [--agents <list>]
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--agents <list> Comma-separated agent ids or 'all'
|
|
32
|
+
-h, --help Show this help
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
export async function runUpdate(argv) {
|
|
36
|
+
const flags = parseFlags(argv);
|
|
37
|
+
if (flags.help) {
|
|
38
|
+
printUsage();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const selected = flags.agents ? resolveAgents(flags.agents) : [...AGENTS];
|
|
42
|
+
let found = 0;
|
|
43
|
+
let failed = false;
|
|
44
|
+
for (const agent of selected) {
|
|
45
|
+
const env = readAgentEnv(agent);
|
|
46
|
+
if (!env) {
|
|
47
|
+
const reason = hasAgentEntry(agent) ? "no readable jira credentials" : "no jira entry";
|
|
48
|
+
console.log(` skip ${agent.label.padEnd(15)} ${agent.path} (${reason})`);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
found++;
|
|
52
|
+
try {
|
|
53
|
+
const result = writeAgentConfig(agent, env);
|
|
54
|
+
if (result === "skipped")
|
|
55
|
+
console.log(` skip ${agent.label.padEnd(15)} ${agent.path}`);
|
|
56
|
+
else
|
|
57
|
+
console.log(` ok ${agent.label.padEnd(15)} ${agent.path} (${result})`);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
failed = true;
|
|
61
|
+
console.error(` ERR ${agent.label.padEnd(15)} ${agent.path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (found === 0) {
|
|
65
|
+
console.error("No jira MCP entries with credentials were found. Run install to configure an agent first.");
|
|
66
|
+
process.exitCode = 1;
|
|
67
|
+
}
|
|
68
|
+
else if (failed) {
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -33,6 +33,29 @@ Or non-interactive: `npx -y @thammarongg/jira-mcp install --agents all
|
|
|
33
33
|
Security → API tokens)
|
|
34
34
|
- DC: `JIRA_USERNAME` + `JIRA_API_TOKEN` (PAT) or `JIRA_PASSWORD` (app password)
|
|
35
35
|
|
|
36
|
+
When a selected agent already has a `jira` entry, the interactive installer
|
|
37
|
+
offers to reuse its base URL and account; `--yes` with no credential flags
|
|
38
|
+
reuses those credentials without prompting.
|
|
39
|
+
|
|
40
|
+
The CLI also supports these maintenance commands:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx -y @thammarongg/jira-mcp update # refresh configured entries
|
|
44
|
+
npx -y @thammarongg/jira-mcp update --agents codex
|
|
45
|
+
npx -y @thammarongg/jira-mcp uninstall # choose entries to remove
|
|
46
|
+
npx -y @thammarongg/jira-mcp uninstall --agents all --yes
|
|
47
|
+
npx -y @thammarongg/jira-mcp --version
|
|
48
|
+
npx -y @thammarongg/jira-mcp --help
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`update` is non-interactive and skips agents without a `jira` entry.
|
|
52
|
+
`uninstall` preserves every other config key and confirms before removing the
|
|
53
|
+
selected entries unless `--yes` is supplied. Running the command with no
|
|
54
|
+
arguments in a terminal shows a status card; MCP clients use piped stdio, so
|
|
55
|
+
the same command starts the server and expects `JIRA_*` environment variables.
|
|
56
|
+
Without those variables, a bare server start reports a missing
|
|
57
|
+
`JIRA_BASE_URL`.
|
|
58
|
+
|
|
36
59
|
Claude Code one-liner:
|
|
37
60
|
|
|
38
61
|
```bash
|