@commentray/mcp-server 0.4.1

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.
@@ -0,0 +1,5 @@
1
+ export { createMcpServer } from "./mcp-server.js";
2
+ export { installMcpConfigs, type InstallMcpConfigsOptions, type HarnessConfig, } from "./mcp-install.js";
3
+ export { ALL_TOOLS, type McpToolDef } from "./mcp-tools.js";
4
+ export { repoRootFrom } from "./repo-root.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { createMcpServer } from "./mcp-server.js";
2
+ export { installMcpConfigs, } from "./mcp-install.js";
3
+ export { ALL_TOOLS } from "./mcp-tools.js";
4
+ export { repoRootFrom } from "./repo-root.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,iBAAiB,GAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAmB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface HarnessConfig {
2
+ /** Human-readable harness name */
3
+ name: string;
4
+ /** Path relative to repo root for the MCP config file */
5
+ configFileRel: string;
6
+ /** Whether this harness is always written (true) or only if its directory already exists */
7
+ alwaysWrite: boolean;
8
+ }
9
+ export interface InstallMcpConfigsOptions {
10
+ dryRun?: boolean;
11
+ force?: boolean;
12
+ }
13
+ export interface InstallResult {
14
+ harness: string;
15
+ configFile: string;
16
+ action: "created" | "updated" | "skipped" | "would_create" | "would_update";
17
+ }
18
+ /**
19
+ * Install (or update) repo-local MCP config files for all supported harnesses.
20
+ *
21
+ * Each config file references `commentray mcp serve` as the command — fully
22
+ * portable, no absolute paths. Safe to commit to a multi-contributor repo.
23
+ *
24
+ * @param repoRoot Absolute path to the repo root
25
+ * @param options dryRun (preview only), force (overwrite existing commentray entry)
26
+ * @returns Array of results describing what happened for each harness
27
+ */
28
+ export declare function installMcpConfigs(repoRoot: string, options?: InstallMcpConfigsOptions): Promise<InstallResult[]>;
29
+ //# sourceMappingURL=mcp-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-install.d.ts","sourceRoot":"","sources":["../src/mcp-install.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,cAAc,GAAG,cAAc,CAAC;CAC7E;AAyCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,aAAa,EAAE,CAAC,CA2D1B"}
@@ -0,0 +1,92 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ // ── Harness definitions ───────────────────────────────────────────────────
4
+ const HARNESSES = [
5
+ { name: "VS Code Copilot", configFileRel: ".vscode/mcp.json", alwaysWrite: true },
6
+ { name: "Claude Code", configFileRel: ".claude/mcp.json", alwaysWrite: true },
7
+ { name: "Antigravity", configFileRel: ".antigravity/mcp.json", alwaysWrite: true },
8
+ { name: "OpenCode", configFileRel: ".opencode/mcp.json", alwaysWrite: true },
9
+ ];
10
+ // ── MCP server entry (portable — no absolute paths) ───────────────────────
11
+ function makeMcpEntry() {
12
+ return {
13
+ commentray: {
14
+ type: "stdio",
15
+ command: "commentray",
16
+ args: ["mcp", "serve"],
17
+ cwd: "${workspaceFolder}",
18
+ },
19
+ };
20
+ }
21
+ async function readOrEmpty(absPath) {
22
+ try {
23
+ const raw = await fs.readFile(absPath, "utf8");
24
+ return JSON.parse(raw);
25
+ }
26
+ catch {
27
+ return {};
28
+ }
29
+ }
30
+ // ── Install function ──────────────────────────────────────────────────────
31
+ /**
32
+ * Install (or update) repo-local MCP config files for all supported harnesses.
33
+ *
34
+ * Each config file references `commentray mcp serve` as the command — fully
35
+ * portable, no absolute paths. Safe to commit to a multi-contributor repo.
36
+ *
37
+ * @param repoRoot Absolute path to the repo root
38
+ * @param options dryRun (preview only), force (overwrite existing commentray entry)
39
+ * @returns Array of results describing what happened for each harness
40
+ */
41
+ export async function installMcpConfigs(repoRoot, options = {}) {
42
+ const results = [];
43
+ for (const harness of HARNESSES) {
44
+ const configAbs = path.join(repoRoot, harness.configFileRel);
45
+ // Check if directory exists for non-always-write harnesses
46
+ if (!harness.alwaysWrite) {
47
+ try {
48
+ await fs.access(path.dirname(configAbs));
49
+ }
50
+ catch {
51
+ continue; // skip — harness not present
52
+ }
53
+ }
54
+ const existing = await readOrEmpty(configAbs);
55
+ const hasCommentray = existing.servers && "commentray" in existing.servers;
56
+ if (hasCommentray && !options.force) {
57
+ results.push({
58
+ harness: harness.name,
59
+ configFile: harness.configFileRel,
60
+ action: "skipped",
61
+ });
62
+ continue;
63
+ }
64
+ const action = hasCommentray ? "updated" : "created";
65
+ const dryAction = hasCommentray ? "would_update" : "would_create";
66
+ if (options.dryRun) {
67
+ results.push({
68
+ harness: harness.name,
69
+ configFile: harness.configFileRel,
70
+ action: dryAction,
71
+ });
72
+ continue;
73
+ }
74
+ // Merge the Commentray entry into the existing config
75
+ const merged = {
76
+ ...existing,
77
+ servers: {
78
+ ...(existing.servers ?? {}),
79
+ ...makeMcpEntry(),
80
+ },
81
+ };
82
+ await fs.mkdir(path.dirname(configAbs), { recursive: true });
83
+ await fs.writeFile(configAbs, JSON.stringify(merged, null, 2) + "\n", "utf8");
84
+ results.push({
85
+ harness: harness.name,
86
+ configFile: harness.configFileRel,
87
+ action,
88
+ });
89
+ }
90
+ return results;
91
+ }
92
+ //# sourceMappingURL=mcp-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-install.js","sourceRoot":"","sources":["../src/mcp-install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Create a configured MCP server with all Commentray tools registered.
4
+ * @param repoRoot Absolute path to the Commentray project root
5
+ */
6
+ export declare function createMcpServer(repoRoot: string): McpServer;
7
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAW3D"}
@@ -0,0 +1,24 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { ALL_TOOLS } from "./mcp-tools.js";
3
+ import serverPackage from "../package.json" with { type: "json" };
4
+ /**
5
+ * Create a configured MCP server with all Commentray tools registered.
6
+ * @param repoRoot Absolute path to the Commentray project root
7
+ */
8
+ export function createMcpServer(repoRoot) {
9
+ const server = new McpServer({
10
+ name: "commentray-mcp",
11
+ version: serverPackage.version,
12
+ });
13
+ for (const tool of ALL_TOOLS) {
14
+ registerTool(server, tool, repoRoot);
15
+ }
16
+ return server;
17
+ }
18
+ function registerTool(server, tool, repoRoot) {
19
+ // The MCP SDK infers args type from the schema; we pass through to our handler.
20
+ server.tool(tool.name, tool.description, tool.schema, async (args) => {
21
+ return tool.handler(repoRoot, args);
22
+ });
23
+ }
24
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAmB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,aAAa,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAElE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,aAAa,CAAC,OAAO;KAC/B,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,MAAiB,EAAE,IAAgB,EAAE,QAAgB;IACzE,gFAAgF;IAChF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACnE,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAA+B,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ export interface McpToolDef {
3
+ name: string;
4
+ description: string;
5
+ schema: z.ZodRawShape;
6
+ handler: (repoRoot: string, args: Record<string, unknown>) => Promise<McpToolResult>;
7
+ }
8
+ export interface McpToolResult {
9
+ content: Array<{
10
+ type: "text";
11
+ text: string;
12
+ }>;
13
+ isError?: boolean;
14
+ [x: string]: unknown;
15
+ }
16
+ export declare const ALL_TOOLS: McpToolDef[];
17
+ //# sourceMappingURL=mcp-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC;IACtB,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;CACtF;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAcD,eAAO,MAAM,SAAS,EAAE,UAAU,EA0mBjC,CAAC"}
@@ -0,0 +1,574 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { execSync } from "node:child_process";
4
+ import { applyAnglesFlatMigrationToCommentrayToml, applyPathRenamesToCommentrayIndex, collectOrphanCompanionMarkdownTargets, convertCommentraySourceMarkersToLanguage, defaultMetadataIndexPath, discoverCommentrayPairsOnDisk, discoverFlatCompanionMarkdownFiles, ensureAnglesSentinelFile, GitScmProvider, initializeCommentrayProject, loadCommentrayConfig, normalizeRepoRelativePath, planAnglesMigrationFromCompanions, pruneOrphanCompanionMarkdown, readIndex, refreshIndexMigrationsOnDisk, resolveCommentrayMarkdownPath, rewriteIndexKeysForAnglesMigration, upsertAngleDefinitionInCommentrayToml, validateProject, writeIndex, } from "@commentray/core";
5
+ import { renderSideBySideHtml } from "@commentray/render";
6
+ import { z } from "zod";
7
+ // ── Helpers ──────────────────────────────────────────────────────────────
8
+ function textResult(text) {
9
+ return { content: [{ type: "text", text }] };
10
+ }
11
+ function errorResult(message) {
12
+ return { content: [{ type: "text", text: message }], isError: true };
13
+ }
14
+ // ── Tool definitions ─────────────────────────────────────────────────────
15
+ export const ALL_TOOLS = [
16
+ // ── commentray_init ──────────────────────────────────────────────────
17
+ {
18
+ name: "commentray_init",
19
+ description: "Initialize a Commentray project in the current workspace. " +
20
+ "Creates the .commentray/ storage directory, index.json, and .commentray.toml " +
21
+ "configuration file. Idempotent — safe to run multiple times.",
22
+ schema: {},
23
+ handler: async (repoRoot) => {
24
+ const result = await initializeCommentrayProject(repoRoot);
25
+ const msgs = [];
26
+ if (result.createdToml)
27
+ msgs.push("Created .commentray.toml");
28
+ if (result.createdIndex)
29
+ msgs.push("Created index.json");
30
+ if (result.migratedIndex)
31
+ msgs.push("Migrated index to current schema");
32
+ if (result.addedSiteGitignore)
33
+ msgs.push("Added _site to .gitignore");
34
+ if (result.validationIssues.length > 0) {
35
+ for (const issue of result.validationIssues) {
36
+ msgs.push(`[${issue.level.toUpperCase()}] ${issue.message}`);
37
+ }
38
+ }
39
+ if (msgs.length === 0)
40
+ msgs.push("Project already initialized (no changes).");
41
+ return textResult(msgs.join("\n"));
42
+ },
43
+ },
44
+ // ── commentray_validate ──────────────────────────────────────────────
45
+ {
46
+ name: "commentray_validate",
47
+ description: "Validate the Commentray project metadata and configuration. " +
48
+ "Returns errors and warnings. Set staged=true to only validate index entries " +
49
+ "touched by staged Git files.",
50
+ schema: {
51
+ staged: z.boolean().optional().default(false).describe("Only validate staged Git changes"),
52
+ },
53
+ handler: async (repoRoot, args) => {
54
+ const opts = args.staged
55
+ ? { stagedRepoRelativePaths: [] }
56
+ : undefined;
57
+ const result = await validateProject(repoRoot, opts);
58
+ const errors = result.issues.filter((i) => i.level === "error").length;
59
+ const warnings = result.issues.filter((i) => i.level === "warn").length;
60
+ const lines = [];
61
+ if (result.issues.length === 0) {
62
+ lines.push("OK: no validation issues.");
63
+ }
64
+ else {
65
+ for (const issue of result.issues) {
66
+ lines.push(`[${issue.level.toUpperCase()}] ${issue.message}`);
67
+ }
68
+ lines.push("");
69
+ lines.push(`Summary: ${errors} error(s), ${warnings} warning(s)`);
70
+ }
71
+ return errors === 0 ? textResult(lines.join("\n")) : errorResult(lines.join("\n"));
72
+ },
73
+ },
74
+ // ── commentray_paths ─────────────────────────────────────────────────
75
+ {
76
+ name: "commentray_paths",
77
+ description: "Resolve and return the Commentray Markdown companion path for a source file. " +
78
+ "Given a repo-relative source file path, returns the corresponding .md path.",
79
+ schema: {
80
+ file: z.string().describe("Repo-relative path to the source file"),
81
+ },
82
+ handler: async (repoRoot, args) => {
83
+ const rel = normalizeRepoRelativePath(String(args.file));
84
+ const cfg = await loadCommentrayConfig(repoRoot);
85
+ const resolved = resolveCommentrayMarkdownPath(repoRoot, rel, cfg);
86
+ return textResult(resolved.commentrayPath);
87
+ },
88
+ },
89
+ // ── commentray_render ────────────────────────────────────────────────
90
+ {
91
+ name: "commentray_render",
92
+ description: "Render a side-by-side HTML page (source code + Commentray Markdown). " +
93
+ "Reads the source and markdown files from disk, writes HTML output.",
94
+ schema: {
95
+ source: z.string().optional().describe("Repo-relative source file path"),
96
+ markdown: z.string().optional().describe("Path to Commentray Markdown file"),
97
+ out: z.string().optional().default("_site/index.html").describe("Output HTML path"),
98
+ mermaid: z.boolean().optional().default(false).describe("Include Mermaid diagram runtime"),
99
+ },
100
+ handler: async (repoRoot, args) => {
101
+ const cfg = await loadCommentrayConfig(repoRoot);
102
+ const srcRel = args.source ?? cfg.staticSite?.sourceFile;
103
+ const mdRel = args.markdown ?? cfg.staticSite?.commentrayMarkdownFile;
104
+ const outRel = String(args.out ?? "_site/index.html");
105
+ if (!srcRel) {
106
+ return errorResult("No source file provided. Pass source or set [static_site].source_file in .commentray.toml.");
107
+ }
108
+ if (!mdRel) {
109
+ return errorResult("No markdown file provided. Pass markdown or set [static_site].commentray_markdown in .commentray.toml.");
110
+ }
111
+ const srcAbs = path.join(repoRoot, normalizeRepoRelativePath(String(srcRel)));
112
+ const mdAbs = path.join(repoRoot, normalizeRepoRelativePath(String(mdRel)));
113
+ const outAbs = path.resolve(repoRoot, outRel);
114
+ let code;
115
+ let mdText;
116
+ try {
117
+ code = await fs.readFile(srcAbs, "utf8");
118
+ mdText = await fs.readFile(mdAbs, "utf8");
119
+ }
120
+ catch (err) {
121
+ const codeErr = err.code;
122
+ if (codeErr === "ENOENT") {
123
+ return errorResult("Source or markdown file not found. Check paths.");
124
+ }
125
+ throw err;
126
+ }
127
+ const ext = path.extname(String(srcRel)).slice(1) || "txt";
128
+ const html = await renderSideBySideHtml({
129
+ code,
130
+ language: ext,
131
+ commentrayMarkdown: mdText,
132
+ hljsTheme: cfg.render.syntaxTheme,
133
+ includeMermaidRuntime: Boolean(args.mermaid),
134
+ });
135
+ await fs.mkdir(path.dirname(outAbs), { recursive: true });
136
+ await fs.writeFile(outAbs, html, "utf8");
137
+ return textResult(`Rendered HTML to ${outRel}`);
138
+ },
139
+ },
140
+ // ── commentray_doctor ────────────────────────────────────────────────
141
+ {
142
+ name: "commentray_doctor",
143
+ description: "Run validation plus environment checks. With allowDeletions=true, also " +
144
+ "removes orphan companion Markdown files (no matching primary source file).",
145
+ schema: {
146
+ allowDeletions: z
147
+ .boolean()
148
+ .optional()
149
+ .default(false)
150
+ .describe("Remove orphan companion Markdown files"),
151
+ },
152
+ handler: async (repoRoot, args) => {
153
+ const lines = [];
154
+ if (args.allowDeletions) {
155
+ const cfg = await loadCommentrayConfig(repoRoot);
156
+ const { removedAbsPaths } = await pruneOrphanCompanionMarkdown(repoRoot, cfg.storageDir);
157
+ if (removedAbsPaths.length > 0) {
158
+ lines.push(`Removed ${removedAbsPaths.length} orphan companion path(s):`);
159
+ for (const abs of removedAbsPaths) {
160
+ lines.push(` - ${path.relative(repoRoot, abs)}`);
161
+ }
162
+ }
163
+ }
164
+ const result = await validateProject(repoRoot);
165
+ const errors = result.issues.filter((i) => i.level === "error").length;
166
+ const warnings = result.issues.filter((i) => i.level === "warn").length;
167
+ if (result.issues.length === 0) {
168
+ lines.push("OK: no validation issues.");
169
+ }
170
+ else {
171
+ for (const issue of result.issues) {
172
+ lines.push(`[${issue.level.toUpperCase()}] ${issue.message}`);
173
+ }
174
+ lines.push(`Summary: ${errors} error(s), ${warnings} warning(s)`);
175
+ }
176
+ try {
177
+ await fs.access(path.join(repoRoot, ".git"));
178
+ lines.push("OK: Git checkout detected.");
179
+ }
180
+ catch {
181
+ lines.push("[WARN] No .git directory — SCM features require a Git checkout.");
182
+ }
183
+ return errors === 0 ? textResult(lines.join("\n")) : errorResult(lines.join("\n"));
184
+ },
185
+ },
186
+ // ── commentray_migrate ───────────────────────────────────────────────
187
+ {
188
+ name: "commentray_migrate",
189
+ description: "Migrate the metadata index.json to the current schema version. " +
190
+ "Safe to run multiple times — only applies pending migrations.",
191
+ schema: {},
192
+ handler: async (repoRoot) => {
193
+ const { changed } = await refreshIndexMigrationsOnDisk(repoRoot);
194
+ if (changed) {
195
+ return textResult("Index migrated to current schema.");
196
+ }
197
+ return textResult("Index already at current schema (no migration needed).");
198
+ },
199
+ },
200
+ // ── commentray_migrate_angles ────────────────────────────────────────
201
+ {
202
+ name: "commentray_migrate_angles",
203
+ description: "Convert flat .commentray/source/ companions to the Angles layout " +
204
+ "(per-source folders under angle directories). Use dryRun=true to preview.",
205
+ schema: {
206
+ angleId: z.string().optional().default("main").describe("Angle ID for migrated files"),
207
+ dryRun: z.boolean().optional().default(false).describe("Preview moves without writing files"),
208
+ },
209
+ handler: async (repoRoot, args) => {
210
+ const cfg = await loadCommentrayConfig(repoRoot);
211
+ const storageDir = cfg.storageDir;
212
+ const companions = await discoverFlatCompanionMarkdownFiles(repoRoot, storageDir);
213
+ if (companions.length === 0) {
214
+ return textResult("No files to migrate (already in Angles layout or no flat companions).");
215
+ }
216
+ const angleId = String(args.angleId ?? "main");
217
+ const plan = planAnglesMigrationFromCompanions(companions, angleId, storageDir);
218
+ if (args.dryRun) {
219
+ const lines = [`Dry run: ${plan.moves.length} file(s) would be moved:`];
220
+ for (const m of plan.moves) {
221
+ lines.push(` ${m.fromRepoRel} → ${m.toRepoRel}`);
222
+ }
223
+ return textResult(lines.join("\n"));
224
+ }
225
+ // Apply filesystem moves
226
+ for (const m of plan.moves) {
227
+ const fromAbs = path.join(repoRoot, m.fromRepoRel);
228
+ const toAbs = path.join(repoRoot, m.toRepoRel);
229
+ await fs.mkdir(path.dirname(toAbs), { recursive: true });
230
+ await fs.rename(fromAbs, toAbs);
231
+ }
232
+ // Update .commentray.toml
233
+ const firstCompanion = companions[0];
234
+ const firstTarget = plan.moves[0];
235
+ const sourceFile = firstCompanion.sourcePath;
236
+ const fromCommentray = path.posix.join(storageDir, "source", `${sourceFile}.md`);
237
+ const toCommentray = firstTarget?.toRepoRel;
238
+ await applyAnglesFlatMigrationToCommentrayToml(repoRoot, {
239
+ angleId,
240
+ staticCommentrayMarkdownFrom: fromCommentray,
241
+ staticCommentrayMarkdownTo: toCommentray,
242
+ });
243
+ // Rewrite index keys
244
+ const index = await readIndex(repoRoot);
245
+ if (index) {
246
+ const newIndex = rewriteIndexKeysForAnglesMigration(index, plan.flatToAnglePath);
247
+ await writeIndex(repoRoot, newIndex);
248
+ }
249
+ return textResult(`Migrated ${plan.moves.length} file(s) to angle "${angleId}".`);
250
+ },
251
+ },
252
+ // ── commentray_angles_add ────────────────────────────────────────────
253
+ {
254
+ name: "commentray_angles_add",
255
+ description: "Register a new angle in .commentray.toml and create the Angles sentinel. " +
256
+ "Use makeDefault=true to set it as the default angle.",
257
+ schema: {
258
+ angleId: z
259
+ .string()
260
+ .regex(/^[a-zA-Z0-9_-]+$/)
261
+ .describe("New angle ID (letters, digits, underscores, hyphens)"),
262
+ source: z.string().optional().describe("Repo-relative primary source path"),
263
+ title: z.string().optional().describe("Human-readable angle label"),
264
+ makeDefault: z.boolean().optional().default(false).describe("Set as the default angle"),
265
+ },
266
+ handler: async (repoRoot, args) => {
267
+ await upsertAngleDefinitionInCommentrayToml(repoRoot, {
268
+ id: String(args.angleId),
269
+ title: args.title ? String(args.title) : undefined,
270
+ makeDefault: Boolean(args.makeDefault),
271
+ });
272
+ const cfg = await loadCommentrayConfig(repoRoot);
273
+ await ensureAnglesSentinelFile(repoRoot, cfg.storageDir);
274
+ return textResult(`Angle "${args.angleId}" registered${args.makeDefault ? " (default)" : ""}.`);
275
+ },
276
+ },
277
+ // ── commentray_sync_moved_paths ──────────────────────────────────────
278
+ {
279
+ name: "commentray_sync_moved_paths",
280
+ description: "Rewrite index.json paths using Git rename detection between two tree-ish refs. " +
281
+ "Use dryRun=true to preview without writing.",
282
+ schema: {
283
+ from: z.string().optional().default("HEAD~1").describe("Older tree-ish ref"),
284
+ to: z.string().optional().default("HEAD").describe("Newer tree-ish ref"),
285
+ dryRun: z.boolean().optional().default(false).describe("Preview renames without writing"),
286
+ },
287
+ handler: async (repoRoot, args) => {
288
+ const scm = new GitScmProvider();
289
+ if (!scm.listPathRenamesBetweenTreeishes) {
290
+ return errorResult("SCM provider does not support rename listing.");
291
+ }
292
+ const fromRef = String(args.from ?? "HEAD~1");
293
+ const toRef = String(args.to ?? "HEAD");
294
+ const renames = await scm.listPathRenamesBetweenTreeishes(repoRoot, fromRef, toRef);
295
+ if (renames.length === 0) {
296
+ return textResult("No Git-detected renames in that range.");
297
+ }
298
+ const cfg = await loadCommentrayConfig(repoRoot);
299
+ const index = await readIndex(repoRoot);
300
+ if (!index) {
301
+ return errorResult(`No index at ${defaultMetadataIndexPath()}. Run commentray_init first.`);
302
+ }
303
+ const next = applyPathRenamesToCommentrayIndex(index, renames, repoRoot, cfg);
304
+ if (!next.changed) {
305
+ return textResult("Index paths already match those renames (nothing to update).");
306
+ }
307
+ if (args.dryRun) {
308
+ const lines = [`Dry run: would apply ${renames.length} rename(s):`];
309
+ for (const r of renames) {
310
+ lines.push(` ${r.from} → ${r.to}`);
311
+ }
312
+ return textResult(lines.join("\n"));
313
+ }
314
+ await writeIndex(repoRoot, next.index);
315
+ return textResult(`Applied ${renames.length} rename(s) to index.json.`);
316
+ },
317
+ },
318
+ // ── commentray_convert_source_markers ────────────────────────────────
319
+ {
320
+ name: "commentray_convert_source_markers",
321
+ description: "Rewrite Commentray marker pairs in a source file to the delimiter style " +
322
+ "for a given VS Code language ID. Use dryRun=true to preview.",
323
+ schema: {
324
+ file: z.string().describe("Repo-relative path to the source file"),
325
+ language: z.string().describe("VS Code language ID (e.g. typescript, rust, yaml, css)"),
326
+ dryRun: z
327
+ .boolean()
328
+ .optional()
329
+ .default(false)
330
+ .describe("Preview changes without writing the file"),
331
+ },
332
+ handler: async (repoRoot, args) => {
333
+ const rel = normalizeRepoRelativePath(String(args.file));
334
+ const abs = path.join(repoRoot, ...rel.split("/"));
335
+ let raw;
336
+ try {
337
+ raw = await fs.readFile(abs, "utf8");
338
+ }
339
+ catch (err) {
340
+ const code = err.code;
341
+ if (code === "ENOENT")
342
+ return errorResult(`File not found: ${rel}`);
343
+ throw err;
344
+ }
345
+ const { sourceText, changed, convertedPairs } = convertCommentraySourceMarkersToLanguage(raw, String(args.language));
346
+ if (!changed) {
347
+ return textResult("No changes (no marker pairs, already target style, or only line-ending normalization).");
348
+ }
349
+ if (args.dryRun) {
350
+ return textResult(`Dry run: would rewrite ${convertedPairs} marker pair(s) in ${rel}.`);
351
+ }
352
+ await fs.writeFile(abs, sourceText, "utf8");
353
+ return textResult(`Rewrote ${convertedPairs} marker pair(s) in ${rel}.`);
354
+ },
355
+ },
356
+ // ── Read-only discovery tools ────────────────────────────────────────
357
+ {
358
+ name: "commentray_list_pairs",
359
+ description: "List all source→commentary pairs in the project. " +
360
+ "Returns repo-relative paths for each source file and its companion Markdown. " +
361
+ "Use this to discover what files already have commentary.",
362
+ schema: {},
363
+ handler: async (repoRoot) => {
364
+ const cfg = await loadCommentrayConfig(repoRoot);
365
+ const pairs = await discoverCommentrayPairsOnDisk(repoRoot, cfg.storageDir);
366
+ if (pairs.length === 0) {
367
+ return textResult("No commentray pairs found. Run commentray_init first, then add commentary.");
368
+ }
369
+ const lines = [`${pairs.length} source→commentary pair(s):`];
370
+ for (const p of pairs) {
371
+ lines.push(` ${p.sourcePath} → ${p.commentrayPath}`);
372
+ }
373
+ return textResult(lines.join("\n"));
374
+ },
375
+ },
376
+ {
377
+ name: "commentray_read_commentray",
378
+ description: "Read the commentary Markdown for a given source file. " +
379
+ "Returns the full Markdown content. Use this before writing or editing commentary.",
380
+ schema: {
381
+ file: z.string().describe("Repo-relative path to the source file"),
382
+ angleId: z.string().optional().describe("Angle ID (uses default if omitted)"),
383
+ },
384
+ handler: async (repoRoot, args) => {
385
+ const rel = normalizeRepoRelativePath(String(args.file));
386
+ const cfg = await loadCommentrayConfig(repoRoot);
387
+ const resolved = resolveCommentrayMarkdownPath(repoRoot, rel, cfg, args.angleId ? String(args.angleId) : undefined);
388
+ const absPath = path.join(repoRoot, ...resolved.commentrayPath.split("/"));
389
+ try {
390
+ const content = await fs.readFile(absPath, "utf8");
391
+ return textResult(content);
392
+ }
393
+ catch (err) {
394
+ const code = err.code;
395
+ if (code === "ENOENT") {
396
+ return errorResult(`No commentary found for ${rel}. Run commentray_init and add commentary first.`);
397
+ }
398
+ throw err;
399
+ }
400
+ },
401
+ },
402
+ {
403
+ name: "commentray_read_source",
404
+ description: "Read a source file's content. Returns the full file text. " +
405
+ "Use this to understand the code before writing commentary for it.",
406
+ schema: {
407
+ file: z.string().describe("Repo-relative path to the source file"),
408
+ },
409
+ handler: async (repoRoot, args) => {
410
+ const rel = normalizeRepoRelativePath(String(args.file));
411
+ const abs = path.join(repoRoot, ...rel.split("/"));
412
+ try {
413
+ const content = await fs.readFile(abs, "utf8");
414
+ const lines = content.split("\n");
415
+ const header = `// ${rel} (${lines.length} lines, ${content.length} bytes)\n`;
416
+ return textResult(header + content);
417
+ }
418
+ catch (err) {
419
+ const code = err.code;
420
+ if (code === "ENOENT")
421
+ return errorResult(`File not found: ${rel}`);
422
+ throw err;
423
+ }
424
+ },
425
+ },
426
+ {
427
+ name: "commentray_list_orphans",
428
+ description: "List orphan companion Markdown files — commentary without a matching " +
429
+ "primary source file. Use commentray_doctor with allowDeletions=true to remove them.",
430
+ schema: {},
431
+ handler: async (repoRoot) => {
432
+ const cfg = await loadCommentrayConfig(repoRoot);
433
+ const orphans = await collectOrphanCompanionMarkdownTargets(repoRoot, cfg.storageDir);
434
+ if (orphans.length === 0) {
435
+ return textResult("No orphan companions found. All commentary files have matching source files.");
436
+ }
437
+ const lines = [`${orphans.length} orphan companion(s) found:`];
438
+ for (const o of orphans) {
439
+ const kind = o.cleanupIsDirectory ? "dir" : "file";
440
+ lines.push(` [${kind}] ${o.commentrayPath} (missing source: ${o.sourcePath})`);
441
+ }
442
+ lines.push("");
443
+ lines.push("To remove them: use commentray_doctor with allowDeletions=true, or run `commentray doctor --allow-deletions` from the CLI.");
444
+ return textResult(lines.join("\n"));
445
+ },
446
+ },
447
+ {
448
+ name: "commentray_find_uncommented",
449
+ description: "Find source files in the repo that could have commentary but don't. " +
450
+ "Scans Git-tracked files, filters by common source extensions, and " +
451
+ "compares against the index. Use this to discover documentation opportunities.",
452
+ schema: {
453
+ maxFiles: z
454
+ .number()
455
+ .optional()
456
+ .default(100)
457
+ .describe("Maximum files to return (prevents overwhelming output)"),
458
+ },
459
+ handler: async (repoRoot, args) => {
460
+ // Get git-tracked files
461
+ let tracked;
462
+ try {
463
+ tracked = execSync("git ls-files -z --cached", {
464
+ cwd: repoRoot,
465
+ encoding: "utf8",
466
+ maxBuffer: 10 * 1024 * 1024,
467
+ });
468
+ }
469
+ catch {
470
+ return errorResult("Could not list Git-tracked files. Ensure the repo has a Git checkout and git is on PATH.");
471
+ }
472
+ const allFiles = tracked.split("\0").filter(Boolean);
473
+ const sourceExts = new Set([
474
+ ".ts",
475
+ ".tsx",
476
+ ".js",
477
+ ".jsx",
478
+ ".py",
479
+ ".rs",
480
+ ".go",
481
+ ".java",
482
+ ".kt",
483
+ ".swift",
484
+ ".c",
485
+ ".cpp",
486
+ ".h",
487
+ ".hpp",
488
+ ".cs",
489
+ ".rb",
490
+ ".php",
491
+ ".scala",
492
+ ".clj",
493
+ ".ex",
494
+ ".exs",
495
+ ".elm",
496
+ ".hs",
497
+ ".lua",
498
+ ".r",
499
+ ".nim",
500
+ ".zig",
501
+ ".ml",
502
+ ".mli",
503
+ ".yaml",
504
+ ".yml",
505
+ ".toml",
506
+ ".json",
507
+ ".md",
508
+ ".mdx",
509
+ ]);
510
+ const index = await readIndex(repoRoot);
511
+ const indexedPaths = new Set();
512
+ if (index) {
513
+ for (const entry of Object.values(index.byCommentrayPath)) {
514
+ indexedPaths.add(entry.sourcePath);
515
+ }
516
+ }
517
+ const uncommented = [];
518
+ for (const f of allFiles) {
519
+ const ext = path.extname(f).toLowerCase();
520
+ if (!sourceExts.has(ext))
521
+ continue;
522
+ if (indexedPaths.has(f))
523
+ continue;
524
+ uncommented.push(f);
525
+ if (uncommented.length >= args.maxFiles)
526
+ break;
527
+ }
528
+ const totalSource = allFiles.filter((f) => sourceExts.has(path.extname(f).toLowerCase())).length;
529
+ const commented = totalSource - uncommented.length;
530
+ if (uncommented.length === 0) {
531
+ return textResult(`All ${totalSource} tracked source files have commentary. Great job!`);
532
+ }
533
+ const lines = [
534
+ `${uncommented.length} uncommented source file(s) (${commented} already have commentary, ${totalSource} total tracked source files):`,
535
+ ];
536
+ for (const f of uncommented) {
537
+ lines.push(` ${f}`);
538
+ }
539
+ if (uncommented.length >= args.maxFiles) {
540
+ lines.push(` ... (capped at ${args.maxFiles}; increase maxFiles to see more)`);
541
+ }
542
+ return textResult(lines.join("\n"));
543
+ },
544
+ },
545
+ {
546
+ name: "commentray_get_index",
547
+ description: "Return the full Commentray index as formatted JSON. " +
548
+ "Shows all tracked source files, their companion paths, block IDs, anchors, and marker IDs. " +
549
+ "Use this to understand the complete state of the project's commentary.",
550
+ schema: {},
551
+ handler: async (repoRoot) => {
552
+ const index = await readIndex(repoRoot);
553
+ if (!index) {
554
+ return errorResult(`No index found. Run commentray_init first.`);
555
+ }
556
+ const summary = {
557
+ schemaVersion: index.schemaVersion,
558
+ pairCount: Object.keys(index.byCommentrayPath).length,
559
+ pairs: Object.entries(index.byCommentrayPath).map(([cp, entry]) => ({
560
+ sourcePath: entry.sourcePath,
561
+ commentrayPath: cp,
562
+ blockCount: entry.blocks.length,
563
+ blocks: entry.blocks.map((b) => ({
564
+ id: b.id,
565
+ anchor: b.anchor,
566
+ markerId: b.markerId,
567
+ })),
568
+ })),
569
+ };
570
+ return textResult(JSON.stringify(summary, null, 2));
571
+ },
572
+ },
573
+ ];
574
+ //# sourceMappingURL=mcp-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Walk up from `cwd` looking for a Commentray project root.
3
+ * Checks for `.commentray.toml` first, then `.git` as fallback.
4
+ * Returns `cwd` if nothing found.
5
+ */
6
+ export declare function repoRootFrom(cwd: string): Promise<string>;
7
+ //# sourceMappingURL=repo-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-root.d.ts","sourceRoot":"","sources":["../src/repo-root.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB/D"}
@@ -0,0 +1,32 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ /**
4
+ * Walk up from `cwd` looking for a Commentray project root.
5
+ * Checks for `.commentray.toml` first, then `.git` as fallback.
6
+ * Returns `cwd` if nothing found.
7
+ */
8
+ export async function repoRootFrom(cwd) {
9
+ let current = path.resolve(cwd);
10
+ for (;;) {
11
+ try {
12
+ await fs.access(path.join(current, ".commentray.toml"));
13
+ return current;
14
+ }
15
+ catch {
16
+ // not found
17
+ }
18
+ try {
19
+ await fs.access(path.join(current, ".git"));
20
+ return current;
21
+ }
22
+ catch {
23
+ // not found
24
+ }
25
+ const parent = path.dirname(current);
26
+ if (parent === current)
27
+ break;
28
+ current = parent;
29
+ }
30
+ return path.resolve(cwd);
31
+ }
32
+ //# sourceMappingURL=repo-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-root.js","sourceRoot":"","sources":["../src/repo-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC;YACxD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YAC5C,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM;QAC9B,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP server entry point — stdio transport.
4
+ *
5
+ * Connect an MCP client (Claude Desktop, VS Code Copilot, etc.) by configuring
6
+ * it to run this script with the Commentray project root as the working directory.
7
+ *
8
+ * Usage:
9
+ * node dist/stdio-entry.js (from within a Commentray project)
10
+ * commentray mcp serve (CLI wrapper)
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=stdio-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-entry.d.ts","sourceRoot":"","sources":["../src/stdio-entry.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP server entry point — stdio transport.
4
+ *
5
+ * Connect an MCP client (Claude Desktop, VS Code Copilot, etc.) by configuring
6
+ * it to run this script with the Commentray project root as the working directory.
7
+ *
8
+ * Usage:
9
+ * node dist/stdio-entry.js (from within a Commentray project)
10
+ * commentray mcp serve (CLI wrapper)
11
+ */
12
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
+ import { createMcpServer } from "./mcp-server.js";
14
+ import { repoRootFrom } from "./repo-root.js";
15
+ async function main() {
16
+ const repoRoot = await repoRootFrom(process.cwd());
17
+ const server = createMcpServer(repoRoot);
18
+ const transport = new StdioServerTransport();
19
+ await server.connect(transport);
20
+ }
21
+ main().catch((err) => {
22
+ console.error("commentray-mcp: fatal error during startup:", err);
23
+ process.exit(1);
24
+ });
25
+ //# sourceMappingURL=stdio-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-entry.js","sourceRoot":"","sources":["../src/stdio-entry.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,KAAK,UAAU,IAAI;IACjB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,GAAG,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Create a temporary directory with a minimal Commentray project.
3
+ * Writes .commentray.toml, initializes index.json, creates a sample source file.
4
+ * Returns the repo root path and the source file relative path.
5
+ */
6
+ export declare function setupTempCommentrayProject(): Promise<{
7
+ repoRoot: string;
8
+ sourceRel: string;
9
+ cleanup: () => Promise<void>;
10
+ }>;
11
+ //# sourceMappingURL=test-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/test/test-helpers.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAkCD"}
@@ -0,0 +1,26 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ /**
5
+ * Create a temporary directory with a minimal Commentray project.
6
+ * Writes .commentray.toml, initializes index.json, creates a sample source file.
7
+ * Returns the repo root path and the source file relative path.
8
+ */
9
+ export async function setupTempCommentrayProject() {
10
+ const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), "commentray-mcp-test-"));
11
+ const sourceRel = "src/example.ts";
12
+ // Create dirs
13
+ await fs.mkdir(path.join(repoRoot, "src"), { recursive: true });
14
+ await fs.mkdir(path.join(repoRoot, ".commentray", "metadata"), { recursive: true });
15
+ // Write .commentray.toml
16
+ await fs.writeFile(path.join(repoRoot, ".commentray.toml"), ["[storage]", 'dir = ".commentray"', "", "[scm]", 'provider = "git"', ""].join("\n"), "utf8");
17
+ // Write index.json (empty, current schema)
18
+ await fs.writeFile(path.join(repoRoot, ".commentray", "metadata", "index.json"), JSON.stringify({ schemaVersion: 3, byCommentrayPath: {} }), "utf8");
19
+ // Write sample source file
20
+ await fs.writeFile(path.join(repoRoot, sourceRel), "// example.ts\n\nexport function hello(): string {\n return 'hello';\n}\n", "utf8");
21
+ const cleanup = async () => {
22
+ await fs.rm(repoRoot, { recursive: true, force: true });
23
+ };
24
+ return { repoRoot, sourceRel, cleanup };
25
+ }
26
+ //# sourceMappingURL=test-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../src/test/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAK9C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAClF,MAAM,SAAS,GAAG,gBAAgB,CAAC;IAEnC,cAAc;IACd,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpF,yBAAyB;IACzB,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EACvC,CAAC,WAAW,EAAE,qBAAqB,EAAE,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EACpF,MAAM,CACP,CAAC;IAEF,2CAA2C;IAC3C,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,EAC5D,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC,EAC1D,MAAM,CACP,CAAC;IAEF,2BAA2B;IAC3B,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EAC9B,4EAA4E,EAC5E,MAAM,CACP,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@commentray/mcp-server",
3
+ "version": "0.4.1",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "MCP (Model Context Protocol) server for Commentray — exposes CLI commands as AI coding assistant tools",
8
+ "license": "MPL-2.0",
9
+ "type": "module",
10
+ "sideEffects": false,
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.build.json",
25
+ "clean": "rm -rf dist"
26
+ },
27
+ "dependencies": {
28
+ "@commentray/core": "0.3.6",
29
+ "@commentray/render": "0.3.6",
30
+ "@modelcontextprotocol/sdk": "^1.29.0",
31
+ "zod": "^4.4.3"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^26.0.1"
35
+ }
36
+ }