imgx-mcp 1.1.1 → 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/CHANGELOG.md +15 -0
- package/README.md +2 -2
- package/dist/cli.bundle.js +8 -2
- package/dist/mcp.bundle.js +36 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0 (2026-03-04)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **MCP roots-based project detection** — MCP server now calls `listRoots()` after connection to get the client's workspace directory, making project-scoped history work without `.imgxrc` when used via Claude Code and other MCP clients
|
|
8
|
+
- **`setProjectRoot()` API** — allows MCP server (or other integrations) to set the project root programmatically
|
|
9
|
+
- **Project-scoped default output** — when a project root is detected, default output directory is `<project-root>/.imgx/` instead of `~/Pictures/imgx`
|
|
10
|
+
- 5 new tests for MCP root detection and project-scoped default output (total: 59 tests)
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Project root resolution priority** — `IMGX_PROJECT_ROOT` env var > MCP roots (`setProjectRoot`) > `.imgxrc` upward search (CLI fallback)
|
|
15
|
+
- **`fallbackOutputDir()`** — configured `outputDir` is now resolved via `resolveProjectPath()` for correct relative path handling
|
|
16
|
+
- **`resetProjectRootCache()`** — now also clears the MCP root value
|
|
17
|
+
|
|
3
18
|
## 1.1.1 (2026-03-04)
|
|
4
19
|
|
|
5
20
|
### Added
|
package/README.md
CHANGED
|
@@ -100,7 +100,7 @@ The skill guides Claude Code through image workflows: blog covers, iterative edi
|
|
|
100
100
|
| `set_output_dir` | Change the default output directory (optionally move existing files) |
|
|
101
101
|
| `list_providers` | List available providers and capabilities |
|
|
102
102
|
|
|
103
|
-
Images are saved to `~/Pictures/imgx/<session-id>/`
|
|
103
|
+
Images are saved to `<project-root>/.imgx/<session-id>/` when a project root is detected, or `~/Pictures/imgx/<session-id>/` otherwise. Each session gets its own directory. File paths are returned in the response. Inline image preview is included in MCP responses (base64).
|
|
104
104
|
|
|
105
105
|
### Iterative editing
|
|
106
106
|
|
|
@@ -377,7 +377,7 @@ Or create manually:
|
|
|
377
377
|
|
|
378
378
|
Project config is shared via Git. Do not put API keys in `.imgxrc`.
|
|
379
379
|
|
|
380
|
-
When `.imgxrc` is present,
|
|
380
|
+
When used via MCP (Claude Code, etc.), imgx-mcp automatically detects the project root from the client's workspace via MCP roots. When `.imgxrc` is present, that directory is used as the project root (CLI fallback). You can also set `IMGX_PROJECT_ROOT` environment variable explicitly. History is saved to `<project-root>/.imgx/output-history.json` (project-scoped, not shared with other projects). Default image output goes to `<project-root>/.imgx/<session-id>/`. Relative paths in `output` and `output_dir` are resolved against the project root instead of the MCP server's working directory.
|
|
381
381
|
|
|
382
382
|
### Settings resolution
|
|
383
383
|
|
package/dist/cli.bundle.js
CHANGED
|
@@ -22052,9 +22052,12 @@ import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from "n
|
|
|
22052
22052
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
22053
22053
|
import { homedir, platform } from "node:os";
|
|
22054
22054
|
var _cachedProjectRoot;
|
|
22055
|
+
var _mcpRoot = null;
|
|
22055
22056
|
function findProjectRoot(startDir) {
|
|
22056
22057
|
if (process.env.IMGX_PROJECT_ROOT)
|
|
22057
22058
|
return process.env.IMGX_PROJECT_ROOT;
|
|
22059
|
+
if (_mcpRoot)
|
|
22060
|
+
return _mcpRoot;
|
|
22058
22061
|
if (_cachedProjectRoot !== void 0)
|
|
22059
22062
|
return _cachedProjectRoot;
|
|
22060
22063
|
let dir = resolve(startDir ?? process.cwd());
|
|
@@ -39244,7 +39247,10 @@ function fallbackOutputDir(outputDir) {
|
|
|
39244
39247
|
return resolveProjectPath(outputDir);
|
|
39245
39248
|
const configured = resolveDefault("outputDir");
|
|
39246
39249
|
if (configured)
|
|
39247
|
-
return configured;
|
|
39250
|
+
return resolveProjectPath(configured);
|
|
39251
|
+
const projectRoot = findProjectRoot();
|
|
39252
|
+
if (projectRoot)
|
|
39253
|
+
return join2(projectRoot, ".imgx");
|
|
39248
39254
|
return join2(homedir2(), "Pictures", "imgx");
|
|
39249
39255
|
}
|
|
39250
39256
|
function saveImage(image, outputPath, outputDir, sessionId) {
|
|
@@ -40213,7 +40219,7 @@ function runRedo() {
|
|
|
40213
40219
|
}
|
|
40214
40220
|
|
|
40215
40221
|
// build/cli/index.js
|
|
40216
|
-
var VERSION2 = "1.
|
|
40222
|
+
var VERSION2 = "1.2.0";
|
|
40217
40223
|
var HELP = `imgx v${VERSION2} \u2014 AI image generation and editing for MCP-compatible AI agents
|
|
40218
40224
|
|
|
40219
40225
|
Commands:
|
package/dist/mcp.bundle.js
CHANGED
|
@@ -6819,14 +6819,21 @@ __export(config_exports, {
|
|
|
6819
6819
|
resolveApiKey: () => resolveApiKey,
|
|
6820
6820
|
resolveDefault: () => resolveDefault,
|
|
6821
6821
|
resolveProjectPath: () => resolveProjectPath,
|
|
6822
|
-
saveConfig: () => saveConfig
|
|
6822
|
+
saveConfig: () => saveConfig,
|
|
6823
|
+
setProjectRoot: () => setProjectRoot
|
|
6823
6824
|
});
|
|
6824
6825
|
import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from "node:fs";
|
|
6825
6826
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
6826
6827
|
import { homedir, platform } from "node:os";
|
|
6828
|
+
function setProjectRoot(root) {
|
|
6829
|
+
_mcpRoot = root;
|
|
6830
|
+
_cachedProjectRoot = void 0;
|
|
6831
|
+
}
|
|
6827
6832
|
function findProjectRoot(startDir) {
|
|
6828
6833
|
if (process.env.IMGX_PROJECT_ROOT)
|
|
6829
6834
|
return process.env.IMGX_PROJECT_ROOT;
|
|
6835
|
+
if (_mcpRoot)
|
|
6836
|
+
return _mcpRoot;
|
|
6830
6837
|
if (_cachedProjectRoot !== void 0)
|
|
6831
6838
|
return _cachedProjectRoot;
|
|
6832
6839
|
let dir = resolve(startDir ?? process.cwd());
|
|
@@ -6845,6 +6852,7 @@ function findProjectRoot(startDir) {
|
|
|
6845
6852
|
}
|
|
6846
6853
|
function resetProjectRootCache() {
|
|
6847
6854
|
_cachedProjectRoot = void 0;
|
|
6855
|
+
_mcpRoot = null;
|
|
6848
6856
|
}
|
|
6849
6857
|
function resolveProjectPath(relativePath) {
|
|
6850
6858
|
if (isAbsolute(relativePath))
|
|
@@ -6919,10 +6927,11 @@ function resolveDefault(key) {
|
|
|
6919
6927
|
function getConfigPath() {
|
|
6920
6928
|
return configPath();
|
|
6921
6929
|
}
|
|
6922
|
-
var _cachedProjectRoot;
|
|
6930
|
+
var _cachedProjectRoot, _mcpRoot;
|
|
6923
6931
|
var init_config = __esm({
|
|
6924
6932
|
"build/core/config.js"() {
|
|
6925
6933
|
"use strict";
|
|
6934
|
+
_mcpRoot = null;
|
|
6926
6935
|
}
|
|
6927
6936
|
});
|
|
6928
6937
|
|
|
@@ -69531,7 +69540,10 @@ function fallbackOutputDir(outputDir) {
|
|
|
69531
69540
|
return resolveProjectPath(outputDir);
|
|
69532
69541
|
const configured = resolveDefault("outputDir");
|
|
69533
69542
|
if (configured)
|
|
69534
|
-
return configured;
|
|
69543
|
+
return resolveProjectPath(configured);
|
|
69544
|
+
const projectRoot = findProjectRoot();
|
|
69545
|
+
if (projectRoot)
|
|
69546
|
+
return join2(projectRoot, ".imgx");
|
|
69535
69547
|
return join2(homedir2(), "Pictures", "imgx");
|
|
69536
69548
|
}
|
|
69537
69549
|
function saveImage(image, outputPath, outputDir, sessionId) {
|
|
@@ -69871,7 +69883,9 @@ function initOpenAI() {
|
|
|
69871
69883
|
|
|
69872
69884
|
// build/mcp/server.js
|
|
69873
69885
|
init_history();
|
|
69886
|
+
init_config();
|
|
69874
69887
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
69888
|
+
import { fileURLToPath } from "node:url";
|
|
69875
69889
|
function buildImageContent(images, paths, extra) {
|
|
69876
69890
|
const content = [];
|
|
69877
69891
|
for (const img of images) {
|
|
@@ -69882,7 +69896,7 @@ function buildImageContent(images, paths, extra) {
|
|
|
69882
69896
|
}
|
|
69883
69897
|
var server = new McpServer({
|
|
69884
69898
|
name: "imgx",
|
|
69885
|
-
version: "1.
|
|
69899
|
+
version: "1.2.0"
|
|
69886
69900
|
});
|
|
69887
69901
|
initGemini();
|
|
69888
69902
|
initOpenAI();
|
|
@@ -70174,9 +70188,27 @@ server.tool("list_providers", "List available image providers and their capabili
|
|
|
70174
70188
|
content: [{ type: "text", text: JSON.stringify({ providers: data }) }]
|
|
70175
70189
|
};
|
|
70176
70190
|
});
|
|
70191
|
+
function fileUriToPath(uri) {
|
|
70192
|
+
try {
|
|
70193
|
+
return fileURLToPath(uri);
|
|
70194
|
+
} catch {
|
|
70195
|
+
const stripped = uri.replace(/^file:\/\/\//, "");
|
|
70196
|
+
return decodeURIComponent(stripped);
|
|
70197
|
+
}
|
|
70198
|
+
}
|
|
70177
70199
|
async function main() {
|
|
70178
70200
|
const transport = new StdioServerTransport();
|
|
70179
70201
|
await server.connect(transport);
|
|
70202
|
+
try {
|
|
70203
|
+
const result = await server.server.listRoots();
|
|
70204
|
+
if (result.roots.length > 0) {
|
|
70205
|
+
const rootUri = result.roots[0].uri;
|
|
70206
|
+
if (rootUri.startsWith("file://")) {
|
|
70207
|
+
setProjectRoot(fileUriToPath(rootUri));
|
|
70208
|
+
}
|
|
70209
|
+
}
|
|
70210
|
+
} catch {
|
|
70211
|
+
}
|
|
70180
70212
|
}
|
|
70181
70213
|
main().catch((err) => {
|
|
70182
70214
|
console.error("MCP server error:", err);
|
package/package.json
CHANGED