itemscore-helper 1.0.0 → 1.2.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 +19 -6
- package/bin/cli.js +80 -71
- package/lib/install.js +113 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
# itemscore-helper
|
|
2
2
|
|
|
3
|
-
Set up **any** AI assistant to build and edit custom Minecraft items for the [ItemsCore](https://www.coredevelopment.shop/plugins/
|
|
3
|
+
Set up **any** AI assistant to build and edit custom Minecraft items for the [ItemsCore](https://www.coredevelopment.shop/plugins/itemscore) plugin. Works with Claude, Codex, Cursor, Gemini, and anything else that supports MCP or custom instructions. You do not need to know how to code.
|
|
4
|
+
|
|
5
|
+
## Easiest: let your AI set itself up
|
|
6
|
+
|
|
7
|
+
Run this, copy what it prints, and paste it into your AI (Claude, Cursor, Gemini, Codex, anything):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx itemscore-helper prompt
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Your AI reads the prompt, sets up the ItemsCore tools itself, then asks what item you want. No config files, no terminal knowledge needed.
|
|
14
|
+
|
|
15
|
+
## Or set it up in one command
|
|
4
16
|
|
|
5
17
|
```bash
|
|
6
18
|
npx itemscore-helper
|
|
7
19
|
```
|
|
8
20
|
|
|
9
|
-
|
|
21
|
+
This auto-detects the AI tools on your machine and connects the local MCP server to each one (a backup of every file it changes is saved beside it). Then just ask your AI for an item.
|
|
10
22
|
|
|
11
23
|
## What it sets up
|
|
12
24
|
|
|
@@ -19,8 +31,9 @@ The MCP server is `npx -y itemscore-helper serve`. It speaks the standard stdio
|
|
|
19
31
|
|
|
20
32
|
| Command | What it does |
|
|
21
33
|
|---|---|
|
|
22
|
-
| `npx itemscore-helper` |
|
|
23
|
-
| `npx itemscore-helper
|
|
34
|
+
| `npx itemscore-helper` | Auto-detect your AI tools and connect the local MCP server |
|
|
35
|
+
| `npx itemscore-helper prompt` | Print a prompt to paste into your AI so it sets itself up |
|
|
36
|
+
| `npx itemscore-helper --dry-run` | Show what would change, without writing anything |
|
|
24
37
|
| `npx itemscore-helper serve` | Run the local MCP server (this is what your AI runs) |
|
|
25
38
|
| `npx itemscore-helper print` | Print the skill instructions to stdout |
|
|
26
39
|
| `npx itemscore-helper mcp` | Print the MCP server config |
|
|
@@ -76,8 +89,8 @@ To edit an existing item, run `/ic export <name>`, share the exported file with
|
|
|
76
89
|
|
|
77
90
|
## Links
|
|
78
91
|
|
|
79
|
-
- Documentation: https://www.coredevelopment.shop/docs/
|
|
80
|
-
- Plugin page: https://www.coredevelopment.shop/plugins/
|
|
92
|
+
- Documentation: https://www.coredevelopment.shop/docs/itemscore
|
|
93
|
+
- Plugin page: https://www.coredevelopment.shop/plugins/itemscore
|
|
81
94
|
|
|
82
95
|
## License
|
|
83
96
|
|
package/bin/cli.js
CHANGED
|
@@ -3,12 +3,26 @@
|
|
|
3
3
|
|
|
4
4
|
const fs = require("fs")
|
|
5
5
|
const path = require("path")
|
|
6
|
+
const { autoConfigure } = require("../lib/install.js")
|
|
6
7
|
|
|
7
8
|
const HOSTED_URL = "https://www.coredevelopment.shop/api/mcp"
|
|
8
9
|
const LLMS_URL = "https://www.coredevelopment.shop/llms.txt"
|
|
9
|
-
const DOCS_URL = "https://www.coredevelopment.shop/docs/
|
|
10
|
+
const DOCS_URL = "https://www.coredevelopment.shop/docs/itemscore"
|
|
10
11
|
const SKILL_DIR = path.join(__dirname, "..", "skill")
|
|
11
12
|
|
|
13
|
+
const SETUP_PROMPT = [
|
|
14
|
+
"Help me build a custom item for my Minecraft server with the ItemsCore plugin. Set yourself up first, then we'll build it together.",
|
|
15
|
+
"",
|
|
16
|
+
"1. Fetch and read " + LLMS_URL + " - it explains how ItemsCore items work, the item JSON format, and every method you can use.",
|
|
17
|
+
"",
|
|
18
|
+
"2. Set up the ItemsCore tools so you can look up methods and validate items for me. In my project folder, run:",
|
|
19
|
+
" npx -y itemscore-helper install",
|
|
20
|
+
' Then reload your MCP servers (or restart this app) so the "itemscore" tools appear. If you cannot run commands, add this to your MCP config instead:',
|
|
21
|
+
' {"mcpServers":{"itemscore":{"command":"npx","args":["-y","itemscore-helper","serve"]}}}',
|
|
22
|
+
"",
|
|
23
|
+
"3. Once you are set up, tell me you are ready and ask what item I want. Write a valid .item file, validate it, then tell me to drop it in plugins/ItemsCore/imports/ and run /ic import. The item stays fully editable in the in-game editor.",
|
|
24
|
+
].join("\n")
|
|
25
|
+
|
|
12
26
|
function copyDir(src, dest) {
|
|
13
27
|
fs.mkdirSync(dest, { recursive: true })
|
|
14
28
|
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
@@ -20,12 +34,11 @@ function copyDir(src, dest) {
|
|
|
20
34
|
}
|
|
21
35
|
|
|
22
36
|
function parseArgs(argv) {
|
|
23
|
-
const out = { cmd: "install",
|
|
37
|
+
const out = { cmd: "install", dryRun: false }
|
|
24
38
|
const rest = []
|
|
25
|
-
for (
|
|
26
|
-
|
|
27
|
-
if (a === "--
|
|
28
|
-
else if (a === "-h" || a === "--help") out.cmd = "help"
|
|
39
|
+
for (const a of argv) {
|
|
40
|
+
if (a === "-h" || a === "--help") out.cmd = "help"
|
|
41
|
+
else if (a === "--dry-run") out.dryRun = true
|
|
29
42
|
else rest.push(a)
|
|
30
43
|
}
|
|
31
44
|
if (rest[0]) out.cmd = rest[0]
|
|
@@ -38,16 +51,16 @@ function printHelp() {
|
|
|
38
51
|
"itemscore-helper - set up any AI to build ItemsCore items",
|
|
39
52
|
"",
|
|
40
53
|
"Usage",
|
|
41
|
-
" npx itemscore-helper
|
|
42
|
-
" npx itemscore-helper
|
|
43
|
-
" npx itemscore-helper --
|
|
54
|
+
" npx itemscore-helper Auto-detect your AI tools and connect the local MCP server",
|
|
55
|
+
" npx itemscore-helper prompt Print a prompt to paste into your AI so it sets itself up",
|
|
56
|
+
" npx itemscore-helper --dry-run Show what would be changed, without writing anything",
|
|
44
57
|
" npx itemscore-helper serve Run the local MCP server (this is what your AI runs)",
|
|
45
58
|
" npx itemscore-helper print Print the skill instructions (SKILL.md) to stdout",
|
|
46
59
|
" npx itemscore-helper mcp Print the MCP server config",
|
|
47
60
|
" npx itemscore-helper help Show this help",
|
|
48
61
|
"",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
62
|
+
"Zero terminal? Run `npx itemscore-helper prompt`, copy it, and paste it into your AI - it sets itself up.",
|
|
63
|
+
"Supports Claude (Code & Desktop), Cursor, Gemini CLI, Codex, Windsurf and any MCP client.",
|
|
51
64
|
"Docs: " + DOCS_URL,
|
|
52
65
|
"",
|
|
53
66
|
].join("\n"))
|
|
@@ -55,11 +68,7 @@ function printHelp() {
|
|
|
55
68
|
|
|
56
69
|
function printMcp() {
|
|
57
70
|
console.log(
|
|
58
|
-
JSON.stringify(
|
|
59
|
-
{ mcpServers: { itemscore: { command: "npx", args: ["-y", "itemscore-helper", "serve"] } } },
|
|
60
|
-
null,
|
|
61
|
-
2
|
|
62
|
-
)
|
|
71
|
+
JSON.stringify({ mcpServers: { itemscore: { command: "npx", args: ["-y", "itemscore-helper", "serve"] } } }, null, 2)
|
|
63
72
|
)
|
|
64
73
|
}
|
|
65
74
|
|
|
@@ -67,58 +76,59 @@ function printSkill() {
|
|
|
67
76
|
process.stdout.write(fs.readFileSync(path.join(SKILL_DIR, "SKILL.md"), "utf8"))
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
"",
|
|
82
|
-
"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
""
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
"
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
79
|
+
function printPrompt() {
|
|
80
|
+
console.log(SETUP_PROMPT)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function manualLines() {
|
|
84
|
+
return [
|
|
85
|
+
" Add this to your AI client's MCP config (same for Claude, Cursor, Gemini):",
|
|
86
|
+
' {"mcpServers":{"itemscore":{"command":"npx","args":["-y","itemscore-helper","serve"]}}}',
|
|
87
|
+
" Codex (~/.codex/config.toml):",
|
|
88
|
+
" [mcp_servers.itemscore]",
|
|
89
|
+
' command = "npx"',
|
|
90
|
+
' args = ["-y","itemscore-helper","serve"]',
|
|
91
|
+
" No MCP client? A hosted copy is at " + HOSTED_URL + " (guide: " + LLMS_URL + ").",
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function runInstall(dryRun) {
|
|
96
|
+
const targetDir = path.resolve(process.cwd(), "itemscore-helper")
|
|
97
|
+
if (!dryRun) copyDir(SKILL_DIR, targetDir)
|
|
98
|
+
|
|
99
|
+
const results = autoConfigure({ dryRun })
|
|
100
|
+
const configured = results.filter((r) => r.ok)
|
|
101
|
+
|
|
102
|
+
const out = ["", dryRun ? "ItemsCore helper - dry run (nothing was changed):" : "ItemsCore helper installed.", ""]
|
|
103
|
+
|
|
104
|
+
if (configured.length > 0) {
|
|
105
|
+
out.push(dryRun ? "Would connect the ItemsCore MCP server to:" : "Connected the ItemsCore MCP server to:")
|
|
106
|
+
for (const r of results) {
|
|
107
|
+
if (r.ok) out.push(" + " + r.name + (r.already ? " (already set)" : "") + " -> " + r.file)
|
|
108
|
+
else out.push(" ! " + r.name + " skipped: " + r.reason)
|
|
109
|
+
}
|
|
110
|
+
if (!dryRun) {
|
|
111
|
+
out.push("")
|
|
112
|
+
out.push("Restart your AI app, then just ask it to build an ItemsCore item.")
|
|
113
|
+
out.push("A backup of each changed file was saved beside it (*.itemscore-bak).")
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
out.push("No AI tool configs were detected on this machine. Two easy options:")
|
|
117
|
+
out.push("")
|
|
118
|
+
out.push(" 1. Paste this prompt into your AI and it sets itself up:")
|
|
119
|
+
out.push("")
|
|
120
|
+
out.push(SETUP_PROMPT.split("\n").map((l) => " " + l).join("\n"))
|
|
121
|
+
out.push("")
|
|
122
|
+
out.push(" 2. Or add the MCP server to your AI client's config yourself:")
|
|
123
|
+
out.push(...manualLines())
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!dryRun) {
|
|
127
|
+
out.push("")
|
|
128
|
+
out.push("Skill files written to " + targetDir + " - hand SKILL.md to your AI if it asks for guidance.")
|
|
129
|
+
}
|
|
130
|
+
out.push("")
|
|
131
|
+
console.log(out.join("\n"))
|
|
122
132
|
}
|
|
123
133
|
|
|
124
134
|
function main() {
|
|
@@ -129,15 +139,14 @@ function main() {
|
|
|
129
139
|
}
|
|
130
140
|
if (args.cmd === "help") return printHelp()
|
|
131
141
|
if (args.cmd === "mcp") return printMcp()
|
|
142
|
+
if (args.cmd === "prompt") return printPrompt()
|
|
132
143
|
if (args.cmd === "print") return printSkill()
|
|
133
144
|
if (args.cmd !== "install") {
|
|
134
145
|
console.error("Unknown command: " + args.cmd + "\nRun: npx itemscore-helper help")
|
|
135
146
|
process.exitCode = 1
|
|
136
147
|
return
|
|
137
148
|
}
|
|
138
|
-
|
|
139
|
-
copyDir(SKILL_DIR, targetDir)
|
|
140
|
-
printGuide(targetDir)
|
|
149
|
+
runInstall(args.dryRun)
|
|
141
150
|
}
|
|
142
151
|
|
|
143
152
|
main()
|
package/lib/install.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const os = require("os")
|
|
6
|
+
|
|
7
|
+
const ENTRY = { command: "npx", args: ["-y", "itemscore-helper", "serve"] }
|
|
8
|
+
const TOML_BLOCK = '\n[mcp_servers.itemscore]\ncommand = "npx"\nargs = ["-y", "itemscore-helper", "serve"]\n'
|
|
9
|
+
|
|
10
|
+
function homeDir() {
|
|
11
|
+
return process.env.ITEMSCORE_HOME_OVERRIDE || os.homedir()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function backup(file) {
|
|
15
|
+
const bak = file + ".itemscore-bak"
|
|
16
|
+
if (fs.existsSync(file) && !fs.existsSync(bak)) {
|
|
17
|
+
try {
|
|
18
|
+
fs.copyFileSync(file, bak)
|
|
19
|
+
} catch {
|
|
20
|
+
/* best effort */
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function mergeJsonMcp(file, key) {
|
|
26
|
+
let data = {}
|
|
27
|
+
if (fs.existsSync(file)) {
|
|
28
|
+
const txt = fs.readFileSync(file, "utf8").trim()
|
|
29
|
+
if (txt) {
|
|
30
|
+
try {
|
|
31
|
+
data = JSON.parse(txt)
|
|
32
|
+
} catch {
|
|
33
|
+
return { ok: false, reason: "existing config is not valid JSON; left untouched" }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
38
|
+
return { ok: false, reason: "existing config is not a JSON object; left untouched" }
|
|
39
|
+
}
|
|
40
|
+
if (!data[key] || typeof data[key] !== "object") data[key] = {}
|
|
41
|
+
const already = JSON.stringify(data[key].itemscore) === JSON.stringify(ENTRY)
|
|
42
|
+
data[key].itemscore = ENTRY
|
|
43
|
+
backup(file)
|
|
44
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
45
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n")
|
|
46
|
+
return { ok: true, already }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function appendTomlMcp(file) {
|
|
50
|
+
const txt = fs.existsSync(file) ? fs.readFileSync(file, "utf8") : ""
|
|
51
|
+
if (txt.includes("[mcp_servers.itemscore]")) return { ok: true, already: true }
|
|
52
|
+
backup(file)
|
|
53
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
54
|
+
const next = txt.trim() ? txt.trimEnd() + "\n" + TOML_BLOCK : TOML_BLOCK.replace(/^\n/, "")
|
|
55
|
+
fs.writeFileSync(file, next)
|
|
56
|
+
return { ok: true, already: false }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function globalTargets() {
|
|
60
|
+
const h = homeDir()
|
|
61
|
+
const list = [
|
|
62
|
+
{ name: "Cursor", dir: path.join(h, ".cursor"), file: path.join(h, ".cursor", "mcp.json"), kind: "json", key: "mcpServers" },
|
|
63
|
+
{ name: "Codex", dir: path.join(h, ".codex"), file: path.join(h, ".codex", "config.toml"), kind: "toml" },
|
|
64
|
+
{ name: "Gemini CLI", dir: path.join(h, ".gemini"), file: path.join(h, ".gemini", "settings.json"), kind: "json", key: "mcpServers" },
|
|
65
|
+
{ name: "Windsurf", dir: path.join(h, ".codeium", "windsurf"), file: path.join(h, ".codeium", "windsurf", "mcp_config.json"), kind: "json", key: "mcpServers" },
|
|
66
|
+
]
|
|
67
|
+
if (process.platform === "win32") {
|
|
68
|
+
const appData = process.env.APPDATA || path.join(h, "AppData", "Roaming")
|
|
69
|
+
list.push({ name: "Claude Desktop", dir: path.join(appData, "Claude"), file: path.join(appData, "Claude", "claude_desktop_config.json"), kind: "json", key: "mcpServers" })
|
|
70
|
+
} else if (process.platform === "darwin") {
|
|
71
|
+
list.push({ name: "Claude Desktop", dir: path.join(h, "Library", "Application Support", "Claude"), file: path.join(h, "Library", "Application Support", "Claude", "claude_desktop_config.json"), kind: "json", key: "mcpServers" })
|
|
72
|
+
} else {
|
|
73
|
+
list.push({ name: "Claude Desktop", dir: path.join(h, ".config", "Claude"), file: path.join(h, ".config", "Claude", "claude_desktop_config.json"), kind: "json", key: "mcpServers" })
|
|
74
|
+
}
|
|
75
|
+
return list
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function isProjectDir(cwd) {
|
|
79
|
+
return [".git", "package.json", ".cursor", ".claude", ".vscode"].some((m) => fs.existsSync(path.join(cwd, m)))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function applyTarget(t, dryRun) {
|
|
83
|
+
if (dryRun) return { name: t.name, file: t.file, ok: true, already: false, dry: true }
|
|
84
|
+
const r = t.kind === "json" ? mergeJsonMcp(t.file, t.key) : appendTomlMcp(t.file)
|
|
85
|
+
return { name: t.name, file: t.file, ...r }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Detects installed AI tools and writes the itemscore MCP server into each one's
|
|
90
|
+
* config (creating a backup first). Returns a list describing what happened.
|
|
91
|
+
*/
|
|
92
|
+
function autoConfigure(opts) {
|
|
93
|
+
opts = opts || {}
|
|
94
|
+
const dryRun = !!opts.dryRun
|
|
95
|
+
const cwd = opts.cwd || process.cwd()
|
|
96
|
+
const results = []
|
|
97
|
+
|
|
98
|
+
for (const t of globalTargets()) {
|
|
99
|
+
const present = fs.existsSync(t.dir) || fs.existsSync(t.file)
|
|
100
|
+
if (!present) continue
|
|
101
|
+
results.push({ scope: "global", ...applyTarget(t, dryRun) })
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Project-scoped .mcp.json for Claude Code, VS Code and project-level Cursor.
|
|
105
|
+
if (isProjectDir(cwd)) {
|
|
106
|
+
const file = path.join(cwd, ".mcp.json")
|
|
107
|
+
results.push({ scope: "project", name: "Project (.mcp.json)", file, ...(dryRun ? { ok: true, dry: true } : mergeJsonMcp(file, "mcpServers")) })
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return results
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = { autoConfigure, globalTargets, isProjectDir, ENTRY }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "itemscore-helper",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "One command sets up any AI (Claude, Codex, Cursor, Gemini, and others) to build and edit custom Minecraft items for the ItemsCore plugin. Auto-detects your AI tools and connects a local MCP server that runs entirely on your machine.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"itemscore-helper": "bin/cli.js",
|
|
7
7
|
"itemscore-mcp": "bin/mcp.js"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"codex",
|
|
29
29
|
"gemini"
|
|
30
30
|
],
|
|
31
|
-
"homepage": "https://www.coredevelopment.shop/docs/
|
|
31
|
+
"homepage": "https://www.coredevelopment.shop/docs/itemscore",
|
|
32
32
|
"repository": {
|
|
33
33
|
"type": "git",
|
|
34
34
|
"url": "https://github.com/Tc554/itemscore-helper.git"
|