emdash-emit 0.1.8 → 0.1.10

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.
Files changed (148) hide show
  1. package/README.md +132 -28
  2. package/dist/bin/emit.d.ts.map +1 -1
  3. package/dist/bin/emit.js +6 -0
  4. package/dist/bin/emit.js.map +1 -1
  5. package/dist/cli/commands/conflicts.d.ts +4 -0
  6. package/dist/cli/commands/conflicts.d.ts.map +1 -0
  7. package/dist/cli/commands/conflicts.js +153 -0
  8. package/dist/cli/commands/conflicts.js.map +1 -0
  9. package/dist/cli/commands/delete.d.ts +4 -0
  10. package/dist/cli/commands/delete.d.ts.map +1 -0
  11. package/dist/cli/commands/delete.js +89 -0
  12. package/dist/cli/commands/delete.js.map +1 -0
  13. package/dist/cli/commands/doctor.d.ts +4 -0
  14. package/dist/cli/commands/doctor.d.ts.map +1 -0
  15. package/dist/cli/commands/doctor.js +82 -0
  16. package/dist/cli/commands/doctor.js.map +1 -0
  17. package/dist/cli/commands/new.d.ts.map +1 -1
  18. package/dist/cli/commands/new.js +52 -22
  19. package/dist/cli/commands/new.js.map +1 -1
  20. package/dist/cli/commands/profile.d.ts.map +1 -1
  21. package/dist/cli/commands/profile.js +67 -13
  22. package/dist/cli/commands/profile.js.map +1 -1
  23. package/dist/cli/commands/pull.d.ts +5 -0
  24. package/dist/cli/commands/pull.d.ts.map +1 -1
  25. package/dist/cli/commands/pull.js +119 -39
  26. package/dist/cli/commands/pull.js.map +1 -1
  27. package/dist/cli/commands/push.d.ts.map +1 -1
  28. package/dist/cli/commands/push.js +38 -1
  29. package/dist/cli/commands/push.js.map +1 -1
  30. package/dist/cli/commands/status.d.ts +19 -0
  31. package/dist/cli/commands/status.d.ts.map +1 -1
  32. package/dist/cli/commands/status.js +87 -5
  33. package/dist/cli/commands/status.js.map +1 -1
  34. package/dist/cli/context.d.ts +38 -1
  35. package/dist/cli/context.d.ts.map +1 -1
  36. package/dist/cli/context.js +129 -16
  37. package/dist/cli/context.js.map +1 -1
  38. package/dist/client/auth.d.ts +1 -0
  39. package/dist/client/auth.d.ts.map +1 -1
  40. package/dist/client/auth.js +1 -0
  41. package/dist/client/auth.js.map +1 -1
  42. package/dist/client/http.d.ts.map +1 -1
  43. package/dist/client/http.js +27 -10
  44. package/dist/client/http.js.map +1 -1
  45. package/dist/db/cache.d.ts +3 -0
  46. package/dist/db/cache.d.ts.map +1 -1
  47. package/dist/db/cache.js +39 -0
  48. package/dist/db/cache.js.map +1 -1
  49. package/dist/mcp/context.d.ts +8 -0
  50. package/dist/mcp/context.d.ts.map +1 -1
  51. package/dist/mcp/server.d.ts +8 -0
  52. package/dist/mcp/server.d.ts.map +1 -1
  53. package/dist/mcp/server.js +91 -15
  54. package/dist/mcp/server.js.map +1 -1
  55. package/dist/mcp/tool-errors.d.ts +16 -0
  56. package/dist/mcp/tool-errors.d.ts.map +1 -0
  57. package/dist/mcp/tool-errors.js +137 -0
  58. package/dist/mcp/tool-errors.js.map +1 -0
  59. package/dist/mcp/tools/profile.d.ts +9 -2
  60. package/dist/mcp/tools/profile.d.ts.map +1 -1
  61. package/dist/mcp/tools/profile.js +53 -36
  62. package/dist/mcp/tools/profile.js.map +1 -1
  63. package/dist/mcp/tools/sync-conflicts.d.ts +4 -0
  64. package/dist/mcp/tools/sync-conflicts.d.ts.map +1 -0
  65. package/dist/mcp/tools/sync-conflicts.js +100 -0
  66. package/dist/mcp/tools/sync-conflicts.js.map +1 -0
  67. package/dist/mcp/tools/sync-delete.d.ts +4 -0
  68. package/dist/mcp/tools/sync-delete.d.ts.map +1 -0
  69. package/dist/mcp/tools/sync-delete.js +77 -0
  70. package/dist/mcp/tools/sync-delete.js.map +1 -0
  71. package/dist/mcp/tools/sync-diff.d.ts.map +1 -1
  72. package/dist/mcp/tools/sync-diff.js +22 -8
  73. package/dist/mcp/tools/sync-diff.js.map +1 -1
  74. package/dist/mcp/tools/sync-doctor.d.ts +4 -0
  75. package/dist/mcp/tools/sync-doctor.d.ts.map +1 -0
  76. package/dist/mcp/tools/sync-doctor.js +57 -0
  77. package/dist/mcp/tools/sync-doctor.js.map +1 -0
  78. package/dist/mcp/tools/sync-new.d.ts.map +1 -1
  79. package/dist/mcp/tools/sync-new.js +49 -23
  80. package/dist/mcp/tools/sync-new.js.map +1 -1
  81. package/dist/mcp/tools/sync-pull.d.ts.map +1 -1
  82. package/dist/mcp/tools/sync-pull.js +132 -73
  83. package/dist/mcp/tools/sync-pull.js.map +1 -1
  84. package/dist/mcp/tools/sync-push.d.ts.map +1 -1
  85. package/dist/mcp/tools/sync-push.js +39 -33
  86. package/dist/mcp/tools/sync-push.js.map +1 -1
  87. package/dist/mcp/tools/sync-status.d.ts.map +1 -1
  88. package/dist/mcp/tools/sync-status.js +103 -11
  89. package/dist/mcp/tools/sync-status.js.map +1 -1
  90. package/dist/sync/conflicts.d.ts +89 -0
  91. package/dist/sync/conflicts.d.ts.map +1 -0
  92. package/dist/sync/conflicts.js +374 -0
  93. package/dist/sync/conflicts.js.map +1 -0
  94. package/dist/sync/delete.d.ts +58 -0
  95. package/dist/sync/delete.d.ts.map +1 -0
  96. package/dist/sync/delete.js +221 -0
  97. package/dist/sync/delete.js.map +1 -0
  98. package/dist/sync/diff.d.ts.map +1 -1
  99. package/dist/sync/diff.js +6 -3
  100. package/dist/sync/diff.js.map +1 -1
  101. package/dist/sync/doctor.d.ts +31 -0
  102. package/dist/sync/doctor.d.ts.map +1 -0
  103. package/dist/sync/doctor.js +224 -0
  104. package/dist/sync/doctor.js.map +1 -0
  105. package/dist/sync/media.d.ts +22 -0
  106. package/dist/sync/media.d.ts.map +1 -1
  107. package/dist/sync/media.js +342 -94
  108. package/dist/sync/media.js.map +1 -1
  109. package/dist/sync/new.d.ts +31 -0
  110. package/dist/sync/new.d.ts.map +1 -1
  111. package/dist/sync/new.js +139 -2
  112. package/dist/sync/new.js.map +1 -1
  113. package/dist/sync/orchestrator.d.ts +6 -0
  114. package/dist/sync/orchestrator.d.ts.map +1 -1
  115. package/dist/sync/orchestrator.js +54 -27
  116. package/dist/sync/orchestrator.js.map +1 -1
  117. package/dist/sync/preflight.d.ts.map +1 -1
  118. package/dist/sync/preflight.js +29 -3
  119. package/dist/sync/preflight.js.map +1 -1
  120. package/dist/sync/pull.d.ts +51 -0
  121. package/dist/sync/pull.d.ts.map +1 -1
  122. package/dist/sync/pull.js +289 -58
  123. package/dist/sync/pull.js.map +1 -1
  124. package/dist/sync/push.d.ts +12 -0
  125. package/dist/sync/push.d.ts.map +1 -1
  126. package/dist/sync/push.js +69 -24
  127. package/dist/sync/push.js.map +1 -1
  128. package/dist/sync/status.d.ts +21 -1
  129. package/dist/sync/status.d.ts.map +1 -1
  130. package/dist/sync/status.js +66 -6
  131. package/dist/sync/status.js.map +1 -1
  132. package/dist/sync/taxonomies.d.ts +14 -5
  133. package/dist/sync/taxonomies.d.ts.map +1 -1
  134. package/dist/sync/taxonomies.js +142 -9
  135. package/dist/sync/taxonomies.js.map +1 -1
  136. package/dist/utils/config.d.ts +23 -0
  137. package/dist/utils/config.d.ts.map +1 -1
  138. package/dist/utils/config.js +41 -4
  139. package/dist/utils/config.js.map +1 -1
  140. package/dist/utils/frontmatter.d.ts +51 -2
  141. package/dist/utils/frontmatter.d.ts.map +1 -1
  142. package/dist/utils/frontmatter.js +234 -9
  143. package/dist/utils/frontmatter.js.map +1 -1
  144. package/dist/utils/profile.d.ts +3 -3
  145. package/dist/utils/profile.d.ts.map +1 -1
  146. package/dist/utils/profile.js +105 -8
  147. package/dist/utils/profile.js.map +1 -1
  148. package/package.json +1 -1
@@ -23,15 +23,19 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
23
23
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
24
24
  import { resolveAuth } from '../client/auth.js';
25
25
  import { CacheDatabase } from '../db/cache.js';
26
- import { loadConfig } from '../utils/config.js';
27
- import { getWorkspacePaths, requireWorkspaceRoot } from '../utils/workspace.js';
28
- import { loadProfilesFile, AmbiguousProfileError } from '../utils/profile.js';
26
+ import { resolveOriginPriority } from '../cli/context.js';
27
+ import { DEFAULT_ORIGIN, getEnvOrigin, loadConfig } from '../utils/config.js';
28
+ import { findWorkspaceRoot, getWorkspacePaths, requireWorkspaceRoot } from '../utils/workspace.js';
29
+ import { findProfileByDirectory, loadProfilesFile, AmbiguousProfileError, } from '../utils/profile.js';
29
30
  import { registerProfileTools } from './tools/profile.js';
30
31
  import { registerSyncNewTool } from './tools/sync-new.js';
31
32
  import { registerSyncPullTools } from './tools/sync-pull.js';
32
33
  import { registerSyncPushTool } from './tools/sync-push.js';
33
34
  import { registerSyncStatusTool } from './tools/sync-status.js';
34
35
  import { registerSyncDiffTool } from './tools/sync-diff.js';
36
+ import { registerSyncDeleteTool } from './tools/sync-delete.js';
37
+ import { registerSyncConflictsTool } from './tools/sync-conflicts.js';
38
+ import { registerSyncDoctorTool } from './tools/sync-doctor.js';
35
39
  import { getPackageVersion } from '../utils/version.js';
36
40
  export const EMIT_MCP_INSTRUCTIONS = `
37
41
  # Emit - AI-First Local Workspace & Sync Engine for EmDash
@@ -41,31 +45,63 @@ Emit manages articles, taxonomies, and media as plain files on your local filesy
41
45
  ## Local Directory Structure
42
46
  - posts/published/YYYYMMDD_<ulid>-<title>.md : Published articles in Markdown
43
47
  - posts/draft/YYYYMMDD_<ulid>-<title>.md : Draft articles in Markdown
48
+ - posts/conflicts/<name>.conflict.md : Preserved divergent local copies (read-only rescue content; never an article)
44
49
  - categories/<id>-<name>.yaml : Category definitions
45
50
  - tags/<id>-<name>.yaml : Tag definitions
46
51
  - media/<yyyyMMdd>_<id>-<name>.<ext> & .yaml : Media assets & companion metadata
47
52
  - media/drafts/<filename> : Staging folder for offline draft images (auto-uploaded on sync_push)
48
53
 
54
+ ## Rescue Copy Rule (posts/conflicts/)
55
+ - sync_pull moves a local file whose content diverged from the remote into posts/conflicts/ before overwriting it, so unpushed writing is never discarded.
56
+ - Read rescue copies and merge any valuable content into the canonical article, then delete the copy.
57
+ - Never pass a posts/conflicts/ path to sync_push: it is refused with QUARANTINED_COPY_NOT_PUSHABLE because it would overwrite the canonical article with stale content.
58
+
49
59
  ## Media & Image Rules (Two Distinct ID Spaces)
50
60
  - Frontmatter featuredImage uses the 26-character media record id (e.g. "01M67P0MBMJQQXH2K95HHCYRYB") or null.
51
61
  - Markdown body images use the storageKey-based URL: ![alt](/_emdash/api/media/file/<storageKey>). Never put a media record id in /_emdash/api/media/file/.
52
62
  - For new local images, place the file in media/drafts/<filename> and reference it on a standalone line: ![alt](../../media/drafts/<filename>). sync_push will automatically upload it, rewrite the Markdown URL, and promote the file into media/.
53
63
 
54
64
  ## AI Workflow (The Golden Path)
55
- 1. [CHECK]: Use sync_status to list locally tracked articles and their file paths (returned newest-first, descending by date). If articles are already present locally, do NOT query remote CMS APIs (e.g. emdash MCP tools like content_list).
65
+ 1. [CHECK]: Use sync_status to inspect locally tracked articles. Returns a summary-first payload (actionRequired capped at 30 items, recentArticles 5 items). To locate specific articles across the full workspace, use search (title/slug/id/filePath) or slugFilter. If articles are already present locally, do NOT query remote CMS APIs (e.g. emdash MCP tools like content_list).
56
66
  2. [PULL]: Use sync_pull to sync articles AND taxonomies (categories/tags) from EmDash remote. Batch mode automatically pulls both and returns available taxonomy hints (also returned with postsOnly:true). Use postsOnly:true to skip taxonomies. Use includeMedia:true to also pull media assets.
57
67
  3. [READ & EDIT]: Read and edit the local Markdown files directly using your standard filesystem tools. Full article content and metadata (title, slug, status, bylines, taxonomies) are stored in the Markdown files.
58
68
  4. [PUSH]: Use sync_push with filePath to sync your changes to the remote EmDash CMS. If transitioning status from draft to published, pass allowPublish: true.
59
- 5. [NEW]: Use sync_new to scaffold a new draft file in posts/draft/ (it returns available categories/tags hints), edit it locally, and push when ready.
69
+ 5. [NEW]: Use sync_new to scaffold a new draft file in posts/draft/ (it returns available categories/tags hints). Rejects duplicates if slug already exists locally or in cache.
70
+ 6. [DELETE]: Use sync_delete to permanently delete an article from both local workspace and remote CMS. Strictly refuses deletion if unpushed local modifications exist. Requires allowDeletePublished: true for published articles. Automatically saves a rescue copy in posts/conflicts/<file>.deleted.md and preserves referenced media files in media/.
71
+ 7. [CONFLICTS]: Use sync_conflicts to inspect quarantined sync conflict copies (.conflict.md) and deletion rescue backups (.deleted.md) in posts/conflicts/ (action: 'list' | 'diff' | 'resolve', strategy: 'accept-local' | 'accept-canonical'). Overwriting canonical files with unpushed edits requires force: true (G13).
72
+ 8. [DOCTOR]: Use sync_doctor to diagnose workspace health (version compatibility, origin consistency, frontmatter integrity, conflicts/quarantine, and media references).
73
+ 9. [MEDIA]: Use sync_pull_media to download media assets and companion YAML metadata into media/. Pass article: <ULID> to pull only media referenced by that specific article without downloading the whole media library.
74
+ All tool responses include "_meta" context describing profile, workspace directory, origin, and resolution mechanism.
60
75
  `.trim();
61
76
  export function createMcpServer(options) {
62
77
  let activeProfileOverride;
63
78
  // Helper to resolve workspace context based on optional profile
64
79
  const resolveContext = (targetProfile) => {
65
80
  const profileToUse = targetProfile || activeProfileOverride;
81
+ const profilesData = loadProfilesFile(options?.profilesPath);
82
+ const explicitProf = profileToUse ? profilesData.profiles[profileToUse] : undefined;
83
+ const cwdProf = !profileToUse
84
+ ? findProfileByDirectory(process.cwd(), options?.profilesPath)
85
+ : null;
86
+ const nearestEmitRoot = !profileToUse ? findWorkspaceRoot(process.cwd()) : null;
87
+ const envOrigin = getEnvOrigin();
88
+ const preResolvedWorkspace = options?.workspaceRoot ||
89
+ explicitProf?.workspace ||
90
+ cwdProf?.config.workspace ||
91
+ nearestEmitRoot ||
92
+ process.env.EMDASH_WORKSPACE;
93
+ const preConfig = preResolvedWorkspace ? loadConfig(preResolvedWorkspace) : undefined;
94
+ const preConfiguredOrigin = preConfig && preConfig.origin !== DEFAULT_ORIGIN ? preConfig.origin : undefined;
95
+ // An explicit EMDASH_ORIGIN is also a valid disambiguation hint for multi-profile setups.
96
+ const preOriginHint = preConfiguredOrigin || envOrigin;
66
97
  let auth;
67
98
  try {
68
- auth = resolveAuth({ profile: profileToUse });
99
+ auth = resolveAuth({
100
+ profile: profileToUse,
101
+ cwd: preResolvedWorkspace || process.cwd(),
102
+ origin: preOriginHint,
103
+ customProfilesPath: options?.profilesPath,
104
+ });
69
105
  if (!auth) {
70
106
  throw new Error('No authentication token found. Please run emit profile add or set EMDASH_TOKEN.');
71
107
  }
@@ -76,23 +112,59 @@ export function createMcpServer(options) {
76
112
  }
77
113
  throw err;
78
114
  }
79
- const profilesData = loadProfilesFile();
80
- const activeProf = profileToUse ? profilesData.profiles[profileToUse] : undefined;
81
- const origin = activeProf?.origin || auth.origin || 'https://example.com';
82
- const workspaceRoot = options?.workspaceRoot ||
83
- activeProf?.workspace ||
84
- process.env.EMDASH_WORKSPACE ||
85
- requireWorkspaceRoot();
115
+ const resolvedProf = explicitProf ||
116
+ (auth.profileName ? profilesData.profiles[auth.profileName] : undefined) ||
117
+ cwdProf?.config;
118
+ // An auto-resolved profile may only override the workspace config when none was requested.
119
+ const autoProf = profileToUse ? undefined : resolvedProf;
120
+ const workspaceRoot = preResolvedWorkspace || resolvedProf?.workspace || auth.workspace || requireWorkspaceRoot();
86
121
  const paths = getWorkspacePaths(workspaceRoot);
87
122
  const cache = options?.cache || new CacheDatabase(paths.dbPath);
88
- const config = loadConfig(paths.configPath);
123
+ const config = preConfig && preResolvedWorkspace === workspaceRoot ? preConfig : loadConfig(workspaceRoot);
124
+ const configuredOrigin = config.origin !== DEFAULT_ORIGIN ? config.origin : undefined;
125
+ const resolution = resolveOriginPriority({
126
+ explicitProfileName: profileToUse,
127
+ explicitProfileOrigin: explicitProf?.origin,
128
+ envOrigin,
129
+ configuredOrigin,
130
+ autoProfileOrigin: autoProf?.origin,
131
+ autoProfileName: auth.profileName || cwdProf?.name,
132
+ authOrigin: auth.origin,
133
+ });
134
+ let resolvedBy = 'default';
135
+ if (auth.source === 'env') {
136
+ resolvedBy = 'env';
137
+ }
138
+ else if (profileToUse) {
139
+ resolvedBy = 'explicit-profile-argument';
140
+ }
141
+ else if (cwdProf) {
142
+ resolvedBy = 'workspace-directory-match';
143
+ }
144
+ else if (auth.workspace) {
145
+ resolvedBy = 'workspace-origin-match';
146
+ }
147
+ else if (auth.source === 'profile') {
148
+ resolvedBy = 'single-profile-fallback';
149
+ }
150
+ else {
151
+ resolvedBy = auth.source;
152
+ }
153
+ const meta = {
154
+ profile: auth.profileName || activeProfileOverride || 'default',
155
+ workspace: workspaceRoot,
156
+ origin: resolution.origin,
157
+ resolvedBy,
158
+ };
89
159
  return {
90
160
  root: workspaceRoot,
91
161
  paths,
92
162
  cache,
93
163
  config,
94
164
  auth,
95
- origin,
165
+ origin: resolution.origin,
166
+ originWarning: resolution.warning || undefined,
167
+ meta,
96
168
  };
97
169
  };
98
170
  const server = new McpServer({
@@ -107,12 +179,16 @@ export function createMcpServer(options) {
107
179
  setActiveOverride: (name) => {
108
180
  activeProfileOverride = name;
109
181
  },
182
+ profilesPath: options?.profilesPath,
110
183
  });
111
184
  registerSyncNewTool(server, resolveContext);
112
185
  registerSyncPullTools(server, resolveContext);
113
186
  registerSyncPushTool(server, resolveContext);
114
187
  registerSyncStatusTool(server, resolveContext);
115
188
  registerSyncDiffTool(server, resolveContext);
189
+ registerSyncDeleteTool(server, resolveContext);
190
+ registerSyncConflictsTool(server, resolveContext);
191
+ registerSyncDoctorTool(server, resolveContext);
116
192
  return server;
117
193
  }
118
194
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import type { McpMeta } from './context.js';
3
+ /**
4
+ * Formats a successful MCP response as formatted JSON with optional _meta context.
5
+ */
6
+ export declare function formatToolSuccess(data: Record<string, unknown>, meta?: McpMeta): CallToolResult;
7
+ /**
8
+ * Formats a known Emit error into a structured MCP tool result with optional _meta context.
9
+ *
10
+ * Without this, the MCP SDK converts a thrown error into `createToolError(String(error))`,
11
+ * which keeps only `error.message` and silently drops the structured diagnostics
12
+ * (`[CODE]`, HTTP status, endpoint, suggestion) that CLI users receive through
13
+ * `ApiError.toActionableString()`. AI agents need the same actionable detail.
14
+ */
15
+ export declare function formatToolError(error: unknown, meta?: McpMeta): CallToolResult;
16
+ //# sourceMappingURL=tool-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-errors.d.ts","sourceRoot":"","sources":["../../src/mcp/tool-errors.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAyB5C;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,cAAc,CAU/F;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,cAAc,CAwH9E"}
@@ -0,0 +1,137 @@
1
+ /*
2
+ * Copyright (C) 2026 SPORT-SERVICE RS★R
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { ApiError } from '../client/error.js';
23
+ import { SyncPruneConflictError } from '../sync/orchestrator.js';
24
+ import { PushValidationError } from '../sync/push.js';
25
+ import { AmbiguousProfileError } from '../utils/profile.js';
26
+ import { FrontmatterParseError } from '../utils/frontmatter.js';
27
+ import { DuplicateSlugError } from '../sync/new.js';
28
+ import { UnpushedModificationsError, PublishedArticleDeletionForbiddenError, } from '../sync/delete.js';
29
+ import { CanonicalHasUnpushedEditsError, QuarantinedPathRequiredError } from '../sync/conflicts.js';
30
+ function toolError(text) {
31
+ return {
32
+ isError: true,
33
+ content: [
34
+ {
35
+ type: 'text',
36
+ text,
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ /**
42
+ * Formats a successful MCP response as formatted JSON with optional _meta context.
43
+ */
44
+ export function formatToolSuccess(data, meta) {
45
+ const payload = meta ? { ...data, _meta: meta } : data;
46
+ return {
47
+ content: [
48
+ {
49
+ type: 'text',
50
+ text: JSON.stringify(payload, null, 2),
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ /**
56
+ * Formats a known Emit error into a structured MCP tool result with optional _meta context.
57
+ *
58
+ * Without this, the MCP SDK converts a thrown error into `createToolError(String(error))`,
59
+ * which keeps only `error.message` and silently drops the structured diagnostics
60
+ * (`[CODE]`, HTTP status, endpoint, suggestion) that CLI users receive through
61
+ * `ApiError.toActionableString()`. AI agents need the same actionable detail.
62
+ */
63
+ export function formatToolError(error, meta) {
64
+ const metaSuffix = meta ? `\n\n_meta: ${JSON.stringify(meta)}` : '';
65
+ if (error instanceof ApiError) {
66
+ return toolError(error.toActionableString() + metaSuffix);
67
+ }
68
+ if (error instanceof PushValidationError) {
69
+ return toolError(JSON.stringify({
70
+ error: 'PREFLIGHT_VALIDATION_FAILED',
71
+ message: error.message,
72
+ errors: error.errors,
73
+ ...(meta ? { _meta: meta } : {}),
74
+ }, null, 2));
75
+ }
76
+ if (error instanceof FrontmatterParseError) {
77
+ return toolError(JSON.stringify({
78
+ error: error.code,
79
+ message: error.message,
80
+ filePath: error.filePath,
81
+ line: error.line,
82
+ reason: error.reason,
83
+ suggestion: error.suggestion,
84
+ ...(meta ? { _meta: meta } : {}),
85
+ }, null, 2));
86
+ }
87
+ if (error instanceof DuplicateSlugError) {
88
+ return toolError(JSON.stringify({
89
+ error: error.code,
90
+ message: error.message,
91
+ slug: error.slug,
92
+ existingId: error.existingId,
93
+ existingFilePath: error.existingFilePath,
94
+ existingStatus: error.existingStatus,
95
+ suggestion: error.suggestion,
96
+ ...(meta ? { _meta: meta } : {}),
97
+ }, null, 2));
98
+ }
99
+ if (error instanceof UnpushedModificationsError ||
100
+ error instanceof PublishedArticleDeletionForbiddenError) {
101
+ return toolError(JSON.stringify({
102
+ error: error.code,
103
+ message: error.message,
104
+ filePath: error.filePath,
105
+ id: error.id,
106
+ suggestion: error.suggestion,
107
+ ...(meta ? { _meta: meta } : {}),
108
+ }, null, 2));
109
+ }
110
+ if (error instanceof CanonicalHasUnpushedEditsError) {
111
+ return toolError(JSON.stringify({
112
+ error: error.code,
113
+ message: error.message,
114
+ canonicalFilePath: error.canonicalFilePath,
115
+ conflictFilePath: error.conflictFilePath,
116
+ id: error.id,
117
+ suggestion: error.suggestion,
118
+ ...(meta ? { _meta: meta } : {}),
119
+ }, null, 2));
120
+ }
121
+ if (error instanceof QuarantinedPathRequiredError) {
122
+ return toolError(JSON.stringify({
123
+ error: error.code,
124
+ message: error.message,
125
+ filePath: error.filePath,
126
+ collection: error.collection,
127
+ suggestion: error.suggestion,
128
+ ...(meta ? { _meta: meta } : {}),
129
+ }, null, 2));
130
+ }
131
+ if (error instanceof SyncPruneConflictError || error instanceof AmbiguousProfileError) {
132
+ return toolError(`❌ ${error.message}${metaSuffix}`);
133
+ }
134
+ const message = error instanceof Error ? error.message : String(error);
135
+ return toolError(`❌ ${message}${metaSuffix}`);
136
+ }
137
+ //# sourceMappingURL=tool-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-errors.js","sourceRoot":"","sources":["../../src/mcp/tool-errors.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,13 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- export declare function registerProfileTools(server: McpServer, options: {
2
+ export interface ProfileToolOptions {
3
3
  getActiveOverride: () => string | undefined;
4
4
  setActiveOverride: (name: string | undefined) => void;
5
- }): void;
5
+ /**
6
+ * Custom profiles.yaml path forwarded from createMcpServer. When set, profile tools read and
7
+ * write exactly the same file the sync tools resolve against, so an embedded server never
8
+ * reports profiles it cannot actually use.
9
+ */
10
+ profilesPath?: string;
11
+ }
12
+ export declare function registerProfileTools(server: McpServer, options: ProfileToolOptions): void;
6
13
  //# sourceMappingURL=profile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE;IACP,iBAAiB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC5C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACvD,GACA,IAAI,CA0EN"}
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC5C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACtD;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAwFzF"}
@@ -21,28 +21,38 @@
21
21
  */
22
22
  import { z } from 'zod';
23
23
  import { loadProfilesFile, setActiveProfile } from '../../utils/profile.js';
24
+ import { formatToolError } from '../tool-errors.js';
24
25
  export function registerProfileTools(server, options) {
25
26
  // profile_list: List available profiles and indicate active one
26
- server.tool('profile_list', 'List configured site profiles from ~/.config/emit/profiles.yaml, showing their origin URLs, workspace roots, and active selection.', {}, async () => {
27
- const data = loadProfilesFile();
28
- const currentActive = options.getActiveOverride() || data.active;
29
- const profiles = Object.entries(data.profiles).map(([name, p]) => ({
30
- name,
31
- origin: p.origin,
32
- workspace: p.workspace,
33
- active: name === currentActive,
34
- }));
35
- return {
36
- content: [
37
- {
38
- type: 'text',
39
- text: JSON.stringify({
40
- activeProfile: currentActive,
41
- profiles,
42
- }, null, 2),
43
- },
44
- ],
45
- };
27
+ server.tool('profile_list', 'List configured site profiles from the Emit profiles file (~/.config/emit/profiles.yaml by default), showing their origin URLs, workspace roots, and active selection.', {}, async () => {
28
+ try {
29
+ const data = loadProfilesFile(options.profilesPath);
30
+ const currentActive = options.getActiveOverride() || data.active;
31
+ const profiles = Object.entries(data.profiles).map(([name, p]) => ({
32
+ name,
33
+ origin: p.origin,
34
+ workspace: p.workspace,
35
+ active: name === currentActive,
36
+ }));
37
+ return {
38
+ content: [
39
+ {
40
+ type: 'text',
41
+ text: JSON.stringify({
42
+ activeProfile: currentActive,
43
+ profiles,
44
+ _meta: {
45
+ activeProfile: currentActive,
46
+ profilesPath: options.profilesPath || '~/.config/emit/profiles.yaml',
47
+ },
48
+ }, null, 2),
49
+ },
50
+ ],
51
+ };
52
+ }
53
+ catch (error) {
54
+ return formatToolError(error);
55
+ }
46
56
  });
47
57
  // profile_switch: Switch active profile for this session or globally
48
58
  server.tool('profile_switch', 'Switch the active site profile for the current MCP session (or globally with persist: true) when managing multiple EmDash instances.', {
@@ -50,32 +60,39 @@ export function registerProfileTools(server, options) {
50
60
  persist: z
51
61
  .boolean()
52
62
  .optional()
53
- .describe('If true, updates active profile in ~/.config/emit/profiles.yaml permanently'),
63
+ .describe('If true, updates active profile in profiles.yaml permanently'),
54
64
  }, async (args) => {
55
- const data = loadProfilesFile();
56
- if (!data.profiles[args.name]) {
65
+ try {
66
+ const data = loadProfilesFile(options.profilesPath);
67
+ if (!data.profiles[args.name]) {
68
+ // Marked as a tool error so clients/agents can branch on isError instead of scraping text.
69
+ return {
70
+ isError: true,
71
+ content: [
72
+ {
73
+ type: 'text',
74
+ text: `❌ Profile "${args.name}" not found. Available profiles: ${Object.keys(data.profiles).join(', ') || 'none'}.`,
75
+ },
76
+ ],
77
+ };
78
+ }
79
+ if (args.persist) {
80
+ setActiveProfile(args.name, options.profilesPath);
81
+ }
82
+ options.setActiveOverride(args.name);
83
+ const p = data.profiles[args.name];
57
84
  return {
58
85
  content: [
59
86
  {
60
87
  type: 'text',
61
- text: `❌ Profile "${args.name}" not found. Available profiles: ${Object.keys(data.profiles).join(', ') || 'none'}.`,
88
+ text: `✅ Switched active profile to "${args.name}" (origin: ${p.origin}, workspace: ${p.workspace}${args.persist ? ', persisted to profiles.yaml' : ''}).`,
62
89
  },
63
90
  ],
64
91
  };
65
92
  }
66
- if (args.persist) {
67
- setActiveProfile(args.name);
93
+ catch (error) {
94
+ return formatToolError(error);
68
95
  }
69
- options.setActiveOverride(args.name);
70
- const p = data.profiles[args.name];
71
- return {
72
- content: [
73
- {
74
- type: 'text',
75
- text: `✅ Switched active profile to "${args.name}" (origin: ${p.origin}, workspace: ${p.workspace}${args.persist ? ', persisted to profiles.yaml' : ''}).`,
76
- },
77
- ],
78
- };
79
96
  });
80
97
  }
81
98
  //# sourceMappingURL=profile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,MAAM,UAAU,oBAAoB,CAClC,MAAiB,EACjB,OAGC;IAED,gEAAgE;IAChE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,oIAAoI,EACpI,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,MAAM,aAAa,GAAG,OAAO,CAAC,iBAAiB,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC;QACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjE,IAAI;YACJ,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,MAAM,EAAE,IAAI,KAAK,aAAa;SAC/B,CAAC,CAAC,CAAC;QAEJ,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;wBACE,aAAa,EAAE,aAAa;wBAC5B,QAAQ;qBACT,EACD,IAAI,EACJ,CAAC,CACF;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,sIAAsI,EACtI;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACtD,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,6EAA6E,CAAC;KAC3F,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,cAAc,IAAI,CAAC,IAAI,oCAAoC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG;qBACpH;iBACF;aACF,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iCAAiC,IAAI,CAAC,IAAI,cAAc,CAAC,CAAC,MAAM,gBAAgB,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,EAAE,IAAI;iBAC3J;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/mcp/tools/profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ContextResolver } from '../context.js';
3
+ export declare function registerSyncConflictsTool(server: McpServer, resolveContext: ContextResolver): void;
4
+ //# sourceMappingURL=sync-conflicts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-conflicts.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/sync-conflicts.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAIpE,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,EACjB,cAAc,EAAE,eAAe,GAC9B,IAAI,CAwGN"}
@@ -0,0 +1,100 @@
1
+ /*
2
+ * Copyright (C) 2026 SPORT-SERVICE RS★R
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { z } from 'zod';
23
+ import { listConflicts, diffConflict, resolveConflict } from '../../sync/conflicts.js';
24
+ import { formatToolError, formatToolSuccess } from '../tool-errors.js';
25
+ export function registerSyncConflictsTool(server, resolveContext) {
26
+ server.tool('sync_conflicts', 'Manage quarantined sync conflict copies (.conflict.md) and deletion rescue backups (.deleted.md) in posts/conflicts/. Actions: "list" (view quarantined files and types), "diff" (inspect line-by-line differences against canonical live article), and "resolve" (strategy "accept-local" to restore/replace canonical article, or "accept-canonical" to discard quarantined copy).', {
27
+ action: z
28
+ .enum(['list', 'diff', 'resolve'])
29
+ .describe('Operation to perform: "list", "diff", or "resolve"'),
30
+ filePath: z
31
+ .string()
32
+ .optional()
33
+ .describe('Target conflict file path or filename in posts/conflicts/ (required for diff and resolve)'),
34
+ strategy: z
35
+ .enum(['accept-local', 'accept-canonical'])
36
+ .optional()
37
+ .describe('Resolution strategy for action="resolve": "accept-local" (restore/apply quarantined copy) or "accept-canonical" (discard quarantined copy)'),
38
+ force: z
39
+ .boolean()
40
+ .optional()
41
+ .describe('Force overwrite canonical article even if it has unpushed local modifications'),
42
+ collection: z
43
+ .string()
44
+ .optional()
45
+ .describe('Collection containing conflicts (defaults to "posts")'),
46
+ profile: z.string().optional().describe('Target profile name for multi-site setups'),
47
+ }, async (args) => {
48
+ let ctx;
49
+ try {
50
+ ctx = resolveContext(args.profile);
51
+ }
52
+ catch (error) {
53
+ return formatToolError(error);
54
+ }
55
+ const collection = args.collection || ctx.config.defaultCollection || 'posts';
56
+ try {
57
+ if (args.action === 'list') {
58
+ const items = listConflicts(ctx.root, collection);
59
+ return formatToolSuccess({
60
+ conflicts: items,
61
+ count: items.length,
62
+ collection,
63
+ }, ctx.meta);
64
+ }
65
+ if (args.action === 'diff') {
66
+ if (!args.filePath) {
67
+ return formatToolError(new Error('action="diff" requires "filePath" parameter.'), ctx.meta);
68
+ }
69
+ const diffResult = diffConflict({
70
+ workspaceRoot: ctx.root,
71
+ filePath: args.filePath,
72
+ collection,
73
+ });
74
+ return formatToolSuccess(diffResult, ctx.meta);
75
+ }
76
+ if (args.action === 'resolve') {
77
+ if (!args.filePath) {
78
+ return formatToolError(new Error('action="resolve" requires "filePath" parameter.'), ctx.meta);
79
+ }
80
+ if (!args.strategy) {
81
+ return formatToolError(new Error('action="resolve" requires "strategy" parameter ("accept-local" or "accept-canonical").'), ctx.meta);
82
+ }
83
+ const res = resolveConflict({
84
+ workspaceRoot: ctx.root,
85
+ cache: ctx.cache,
86
+ filePath: args.filePath,
87
+ strategy: args.strategy,
88
+ force: args.force,
89
+ collection,
90
+ });
91
+ return formatToolSuccess(res, ctx.meta);
92
+ }
93
+ return formatToolError(new Error(`Unknown action "${args.action}". Must be "list", "diff", or "resolve".`), ctx.meta);
94
+ }
95
+ catch (err) {
96
+ return formatToolError(err, ctx.meta);
97
+ }
98
+ });
99
+ }
100
+ //# sourceMappingURL=sync-conflicts.js.map