imgx-mcp 1.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
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
+
18
+ ## 1.1.1 (2026-03-04)
19
+
20
+ ### Added
21
+
22
+ - **`CLAUDE.md`** — Project instructions for Claude Code (release flow reference, dev commands, architecture overview, project config)
23
+ - **`RELEASING.md` full rewrite** — 4-step checklist expanded to 11-step mandatory release flow covering test, version update, build, publish, MCP verification, app-division-ops docs, and public distribution
24
+
25
+ ### Fixed
26
+
27
+ - **Plugin/registry version sync** — `server.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `.cursor-plugin/plugin.json` were stuck at v1.0.4; now updated to match the actual release version
28
+
3
29
  ## 1.1.0 (2026-03-04)
4
30
 
5
31
  ### 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>/` by default. Each session gets its own directory. File paths are returned in the response. Inline image preview is included in MCP responses (base64).
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, imgx-mcp treats that directory as the project root. History is saved to `<project-root>/.imgx/output-history.json` (project-scoped, not shared with other projects). Relative paths in `output` and `output_dir` are resolved against the project root instead of the MCP server's working directory.
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
 
@@ -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.1.0";
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:
@@ -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.1.0"
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imgx-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "mcpName": "io.github.somacoffeekyoto/imgx",
5
5
  "description": "AI image generation and editing for Claude Code, Codex CLI, and MCP-compatible AI agents",
6
6
  "type": "module",