mcpill 1.7.0 → 1.8.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/CHANGELOG.md +5 -0
- package/README.md +3 -16
- package/dist/cli.js +39 -71
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.8.0
|
|
4
|
+
|
|
5
|
+
- `mcpill run` (stdio) now auto-registers the server in Claude config on start and auto-unregisters on SIGINT, SIGTERM, and process exit — no manual step required
|
|
6
|
+
- `--register` flag and `mcpill unregister` command removed; lifecycle management is now automatic
|
|
7
|
+
|
|
3
8
|
## 1.7.0
|
|
4
9
|
|
|
5
10
|
- `mcpill run` is now side-effect-free by default — stopping the process disconnects the server; no Claude config is written
|
package/README.md
CHANGED
|
@@ -20,8 +20,7 @@ Describe your server in plain English, let Claude generate the source files.
|
|
|
20
20
|
mcpill init # scaffolds PILL.md + example source files
|
|
21
21
|
# fill PILL.md # describe your server: tools, resources, prompts
|
|
22
22
|
# tell Claude: "Build this PILL.md" # agent generates source files + runs compile
|
|
23
|
-
mcpill run # start the server
|
|
24
|
-
mcpill run --register # or: register so Claude manages it persistently
|
|
23
|
+
mcpill run # start the server — registered while running, removed on exit
|
|
25
24
|
```
|
|
26
25
|
|
|
27
26
|
`PILL.md` embeds the agent instructions — Claude knows exactly what to generate and how.
|
|
@@ -88,23 +87,11 @@ Validates all pill directories (`.<name>/`) in the project root.
|
|
|
88
87
|
Starts the MCP server from the pill artifact.
|
|
89
88
|
|
|
90
89
|
```bash
|
|
91
|
-
mcpill run # stdio (default)
|
|
90
|
+
mcpill run # stdio (default) — registered while running, removed on exit
|
|
92
91
|
mcpill run --transport http --port 3333
|
|
93
|
-
mcpill run --register # also write server entry to Claude config
|
|
94
92
|
```
|
|
95
93
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
### `mcpill unregister`
|
|
99
|
-
|
|
100
|
-
Removes the server entry from all Claude config files — the inverse of `mcpill run --register`.
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
mcpill unregister
|
|
104
|
-
mcpill unregister --dir <path>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Removes from `.claude/settings.json` (project scope), `~/.claude.json` (user scope), and the Claude Desktop config. Prints what was removed, or reports if the server was not registered.
|
|
94
|
+
For stdio transport, the server entry is automatically written to Claude's config on start and removed on exit (SIGINT, SIGTERM, or normal process exit). HTTP transport is self-hosted — Claude connects to a URL, so no registration occurs.
|
|
108
95
|
|
|
109
96
|
### `mcpill pack`
|
|
110
97
|
|
package/dist/cli.js
CHANGED
|
@@ -548,6 +548,7 @@ async function runInit(opts) {
|
|
|
548
548
|
// src/commands/run.ts
|
|
549
549
|
import path7 from "path";
|
|
550
550
|
import fs6 from "fs";
|
|
551
|
+
import os from "os";
|
|
551
552
|
import { z as z2 } from "mcpill-runtime";
|
|
552
553
|
import { createServer, applySetup } from "mcpster";
|
|
553
554
|
|
|
@@ -1106,6 +1107,32 @@ async function runValidate(baseDir) {
|
|
|
1106
1107
|
}
|
|
1107
1108
|
|
|
1108
1109
|
// src/commands/run.ts
|
|
1110
|
+
function patchJson(filePath, patcher) {
|
|
1111
|
+
if (!fs6.existsSync(filePath)) return;
|
|
1112
|
+
try {
|
|
1113
|
+
const obj = JSON.parse(fs6.readFileSync(filePath, "utf-8"));
|
|
1114
|
+
patcher(obj);
|
|
1115
|
+
fs6.writeFileSync(filePath, JSON.stringify(obj, null, 2) + "\n", "utf-8");
|
|
1116
|
+
} catch {
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
function desktopConfigPaths() {
|
|
1120
|
+
const home = os.homedir();
|
|
1121
|
+
if (process.platform === "win32") {
|
|
1122
|
+
const appData = process.env.APPDATA ?? path7.join(home, "AppData", "Roaming");
|
|
1123
|
+
return [path7.join(appData, "Claude", "claude_desktop_config.json")];
|
|
1124
|
+
}
|
|
1125
|
+
return [path7.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")];
|
|
1126
|
+
}
|
|
1127
|
+
function unregisterSync(name, baseDir) {
|
|
1128
|
+
const remove = (obj) => {
|
|
1129
|
+
const servers = obj.mcpServers;
|
|
1130
|
+
if (servers) delete servers[name];
|
|
1131
|
+
};
|
|
1132
|
+
patchJson(path7.join(baseDir, ".claude", "settings.json"), remove);
|
|
1133
|
+
patchJson(path7.join(os.homedir(), ".claude.json"), remove);
|
|
1134
|
+
for (const p of desktopConfigPaths()) patchJson(p, remove);
|
|
1135
|
+
}
|
|
1109
1136
|
async function runServer(opts) {
|
|
1110
1137
|
const baseDir = path7.resolve(opts.dir ?? process.cwd());
|
|
1111
1138
|
await runValidate(baseDir);
|
|
@@ -1157,7 +1184,7 @@ async function runServer(opts) {
|
|
|
1157
1184
|
resolver: async () => content
|
|
1158
1185
|
});
|
|
1159
1186
|
}
|
|
1160
|
-
if (
|
|
1187
|
+
if (transport === "stdio") {
|
|
1161
1188
|
applySetup(name, tools.map((t) => t.name), {
|
|
1162
1189
|
projectPath: baseDir,
|
|
1163
1190
|
permissions: "restrictive",
|
|
@@ -1167,6 +1194,16 @@ async function runServer(opts) {
|
|
|
1167
1194
|
args: ["run", "--dir", baseDir]
|
|
1168
1195
|
}
|
|
1169
1196
|
});
|
|
1197
|
+
const cleanup = () => unregisterSync(name, baseDir);
|
|
1198
|
+
process.on("exit", cleanup);
|
|
1199
|
+
process.on("SIGINT", () => {
|
|
1200
|
+
cleanup();
|
|
1201
|
+
process.exit(0);
|
|
1202
|
+
});
|
|
1203
|
+
process.on("SIGTERM", () => {
|
|
1204
|
+
cleanup();
|
|
1205
|
+
process.exit(0);
|
|
1206
|
+
});
|
|
1170
1207
|
}
|
|
1171
1208
|
try {
|
|
1172
1209
|
await server.start();
|
|
@@ -1561,72 +1598,6 @@ async function runPublish(dir, access) {
|
|
|
1561
1598
|
}
|
|
1562
1599
|
}
|
|
1563
1600
|
|
|
1564
|
-
// src/commands/unregister.ts
|
|
1565
|
-
import path10 from "path";
|
|
1566
|
-
import fs8 from "fs";
|
|
1567
|
-
import os from "os";
|
|
1568
|
-
function patchJson(filePath, patcher) {
|
|
1569
|
-
if (!fs8.existsSync(filePath)) return false;
|
|
1570
|
-
try {
|
|
1571
|
-
const obj = JSON.parse(fs8.readFileSync(filePath, "utf-8"));
|
|
1572
|
-
patcher(obj);
|
|
1573
|
-
fs8.writeFileSync(filePath, JSON.stringify(obj, null, 2) + "\n", "utf-8");
|
|
1574
|
-
return true;
|
|
1575
|
-
} catch {
|
|
1576
|
-
return false;
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
function desktopConfigPaths() {
|
|
1580
|
-
const home = os.homedir();
|
|
1581
|
-
if (process.platform === "win32") {
|
|
1582
|
-
const appData = process.env.APPDATA ?? path10.join(home, "AppData", "Roaming");
|
|
1583
|
-
return [path10.join(appData, "Claude", "claude_desktop_config.json")];
|
|
1584
|
-
}
|
|
1585
|
-
return [path10.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")];
|
|
1586
|
-
}
|
|
1587
|
-
async function runUnregister(opts) {
|
|
1588
|
-
const baseDir = path10.resolve(opts.dir ?? process.cwd());
|
|
1589
|
-
const mcpillDir = path10.join(baseDir, ".mcpill", "server");
|
|
1590
|
-
const config = await loadConfig(mcpillDir);
|
|
1591
|
-
const { name } = config;
|
|
1592
|
-
let removed = 0;
|
|
1593
|
-
const settingsPath = path10.join(baseDir, ".claude", "settings.json");
|
|
1594
|
-
const removedProject = patchJson(settingsPath, (obj) => {
|
|
1595
|
-
const servers = obj.mcpServers;
|
|
1596
|
-
if (servers && name in servers) {
|
|
1597
|
-
delete servers[name];
|
|
1598
|
-
removed++;
|
|
1599
|
-
}
|
|
1600
|
-
});
|
|
1601
|
-
if (removedProject) process.stderr.write(`removed "${name}" from .claude/settings.json
|
|
1602
|
-
`);
|
|
1603
|
-
const claudeJsonPath = path10.join(os.homedir(), ".claude.json");
|
|
1604
|
-
const removedUser = patchJson(claudeJsonPath, (obj) => {
|
|
1605
|
-
const servers = obj.mcpServers;
|
|
1606
|
-
if (servers && name in servers) {
|
|
1607
|
-
delete servers[name];
|
|
1608
|
-
removed++;
|
|
1609
|
-
}
|
|
1610
|
-
});
|
|
1611
|
-
if (removedUser) process.stderr.write(`removed "${name}" from ~/.claude.json
|
|
1612
|
-
`);
|
|
1613
|
-
for (const configPath of desktopConfigPaths()) {
|
|
1614
|
-
const removedDesktop = patchJson(configPath, (obj) => {
|
|
1615
|
-
const servers = obj.mcpServers;
|
|
1616
|
-
if (servers && name in servers) {
|
|
1617
|
-
delete servers[name];
|
|
1618
|
-
removed++;
|
|
1619
|
-
}
|
|
1620
|
-
});
|
|
1621
|
-
if (removedDesktop) process.stderr.write(`removed "${name}" from Claude Desktop config
|
|
1622
|
-
`);
|
|
1623
|
-
}
|
|
1624
|
-
if (removed === 0) {
|
|
1625
|
-
process.stderr.write(`"${name}" was not registered \u2014 nothing to remove
|
|
1626
|
-
`);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
1601
|
// src/cli.ts
|
|
1631
1602
|
var pkgDir = dirname(fileURLToPath(import.meta.url));
|
|
1632
1603
|
var pkg = JSON.parse(
|
|
@@ -1637,7 +1608,7 @@ program.name("mcpill").version(pkg.version);
|
|
|
1637
1608
|
program.command("init").description("Scaffold a new .mcpill/ directory").option("--dir <path>", "Target directory").action(async (opts) => {
|
|
1638
1609
|
await runInit(opts);
|
|
1639
1610
|
});
|
|
1640
|
-
program.command("run").description("Start the MCP server").option("--transport <type>", "Transport: stdio (default) or http").option("--port <n>", "Port number (HTTP only)", parseInt).option("--dir <path>", "Project root containing .mcpill/").
|
|
1611
|
+
program.command("run").description("Start the MCP server").option("--transport <type>", "Transport: stdio (default) or http").option("--port <n>", "Port number (HTTP only)", parseInt).option("--dir <path>", "Project root containing .mcpill/").action(
|
|
1641
1612
|
async (opts) => {
|
|
1642
1613
|
await runServer(opts);
|
|
1643
1614
|
}
|
|
@@ -1649,9 +1620,6 @@ program.command("validate").description("Validate .mcpill/ configuration").optio
|
|
|
1649
1620
|
program.command("compile").description("Compile server.md \u2194 .mcpill/ files").option("--dir <path>", "Directory containing server.md and .mcpill/").option("--to-md", "Reverse: generate server.md from .mcpill/ files").option("--strict", "Error on missing tool handlers instead of generating stubs").option("--no-hooks", "Skip writing the PreToolUse hook to .claude/settings.json").action(async (opts) => {
|
|
1650
1621
|
await runCompile({ ...opts, noHooks: opts.hooks === false });
|
|
1651
1622
|
});
|
|
1652
|
-
program.command("unregister").description("Remove server entry from Claude config (undo mcpill run --register)").option("--dir <path>", "Project root containing .mcpill/").action(async (opts) => {
|
|
1653
|
-
await runUnregister(opts);
|
|
1654
|
-
});
|
|
1655
1623
|
program.command("pack").description("Prepare pill for npm distribution").option("--dir <path>", "pill project root", ".").action(({ dir }) => runPack(dir));
|
|
1656
1624
|
program.command("publish").description("Pack and publish pill to npm").option("--dir <path>", "pill project root", ".").option("--access <level>", "npm access level", "public").action(({ dir, access }) => runPublish(dir, access));
|
|
1657
1625
|
program.parseAsync(process.argv).catch((err) => {
|