@codeforbreakfast/commy-mcp 0.17.0 → 0.18.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +19 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeforbreakfast/commy-mcp",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "commy MCP server — the inter-agent communication substrate, runnable on node via npx.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
package/server.js CHANGED
@@ -56896,7 +56896,8 @@ var envConfig = exports_Config.all({
56896
56896
  botApiKey: optionalApiKey("COMMY_BOT_API_KEY"),
56897
56897
  subscribe: optionalUserConfig("COMMY_SUBSCRIBE"),
56898
56898
  project: optionalNonEmpty("COMMY_PROJECT"),
56899
- catchupWindowSeconds: optionalNonNegativeInt("COMMY_CATCHUP_WINDOW_SECONDS")
56899
+ catchupWindowSeconds: optionalNonNegativeInt("COMMY_CATCHUP_WINDOW_SECONDS"),
56900
+ downloadDir: optionalNonEmpty("COMMY_DOWNLOAD_DIR")
56900
56901
  }).pipe(exports_Config.mapOrFail((raw3) => {
56901
56902
  if (exports_Option.isSome(raw3.botApiKey) && exports_Option.isNone(raw3.botName)) {
56902
56903
  return exports_Either.left(exports_ConfigError.InvalidData(["COMMY_BOT_API_KEY"], "COMMY_BOT_API_KEY requires COMMY_BOT_NAME — the key identifies which provisioned persona to attach to"));
@@ -56916,6 +56917,10 @@ var envConfig = exports_Config.all({
56916
56917
  ...exports_Option.match(raw3.catchupWindowSeconds, {
56917
56918
  onNone: () => ({}),
56918
56919
  onSome: (catchupWindowSeconds) => ({ catchupWindowSeconds })
56920
+ }),
56921
+ ...exports_Option.match(raw3.downloadDir, {
56922
+ onNone: () => ({}),
56923
+ onSome: (downloadDir) => ({ downloadDir })
56919
56924
  })
56920
56925
  });
56921
56926
  }));
@@ -58762,7 +58767,7 @@ class Server extends Protocol {
58762
58767
  }
58763
58768
 
58764
58769
  // packages/mcp/mcp-server.ts
58765
- var PLUGIN_VERSION = "0.17.0";
58770
+ var PLUGIN_VERSION = "0.18.0";
58766
58771
  var COMMY_INSTRUCTIONS = `**Substrate.** commy is the inter-agent channel: agents and humans coordinate here. If you run it alongside other agent-messaging tools, keep one substrate canonical and don't fan the same message across all of them.
58767
58772
 
58768
58773
  **Channels.** Each project has one channel: \`#<project-slug>\` where the slug is resolved per session as \`COMMY_PROJECT\` env > git remote \`origin\` basename > git root basename. Sessions launched outside a git repo (e.g. \`/tmp\`, \`$HOME\`) have no project channel and should post to \`#general\` instead. Don't invent a channel name from a metaphor — never post to a literal \`#home\`, \`#project\`, or \`#<project>\`. Use \`list_channels\` to enumerate what actually exists in the realm; posting to a non-existent channel throws \`UnknownChannel\` rather than silently routing to Notification Bot.
@@ -58773,7 +58778,7 @@ var COMMY_INSTRUCTIONS = `**Substrate.** commy is the inter-agent channel: agent
58773
58778
 
58774
58779
  **Links.** Every ref the substrate hands you carries a ready-to-click \`permalink\` — on \`post\` results, \`read_channel\`/\`read_thread\` messages (message \`permalink\` plus \`channel.permalink\` and \`thread.permalink\`), \`list_channels\` (channel \`permalink\`), and inbound \`<channel source="commy">\` frames (\`permalink\` / \`channel_permalink\` / \`thread_permalink\` meta, \`target_permalink\` on reaction frames). **Whenever you show a human a message, channel, or topic reference, render it as that clickable permalink — never a bare name or numeric id.** A human can click a permalink straight to the message; a bare \`#channel > topic\` or message number makes them hunt. When you hold only a message id (e.g. one cited elsewhere, with no permalink to hand), \`message_link(message_id, channel_name?, thread?)\` returns its \`{permalink}\`.
58775
58780
 
58776
- **Tools.** \`post\` (channel; optionally thread or reply), \`react\`/\`unreact\` (emoji on a message), \`subscribe\`/\`unsubscribe\` (live target), \`read_channel\`/\`read_thread\` (history within a range), \`list_channels\` (enumerate channels in the realm), \`message_link\` (canonical permalink for a message id), \`resolve\` (identity by name), \`current_identity\` (passive — never acquires), \`download_file\` (fetch a \`/user_uploads/...\` attachment to a temp file — use Read on the returned path to view images), \`upload_file\` (upload a local file by absolute path; returns a \`reference\` string to embed in a \`post\` body).
58781
+ **Tools.** \`post\` (channel; optionally thread or reply), \`react\`/\`unreact\` (emoji on a message), \`subscribe\`/\`unsubscribe\` (live target), \`read_channel\`/\`read_thread\` (history within a range), \`list_channels\` (enumerate channels in the realm), \`message_link\` (canonical permalink for a message id), \`resolve\` (identity by name), \`current_identity\` (passive — never acquires), \`download_file\` (fetch a \`/user_uploads/...\` attachment to a temp file — rooted under the operator-set \`COMMY_DOWNLOAD_DIR\` when configured so it lands somewhere you can Read, else \`$TMPDIR\`; use Read on the returned path to view images), \`upload_file\` (upload a local file by absolute path; returns a \`reference\` string to embed in a \`post\` body).
58777
58782
 
58778
58783
  **session_id.** Pass your conversation's session id as the optional argument on \`post\`, \`edit_message\`, \`react\`, \`unreact\`, and \`current_identity\`. **Must be a UUID** (e.g. \`crypto.randomUUID()\`); anything else is rejected as malformed and the call routes to the "missing session_id" error rather than silently minting a \`cc-<garbage>\` identity. In Claude Code the plugin's PreToolUse hook injects the harness session id automatically. The server uses it to derive the ephemeral \`cc-<8>\` bot identity for this conversation and to detect transitions between conversations.`;
58779
58784
  var buildMcpServer = () => new Server({ name: "commy", version: PLUGIN_VERSION }, {
@@ -59602,7 +59607,7 @@ var buildToolDefs = (deps, cache) => {
59602
59607
  const download = deps.downloadFile;
59603
59608
  optionalTools.push({
59604
59609
  name: "download_file",
59605
- description: "Download a Zulip user upload by its /user_uploads/... path (visible in message bodies). Writes the file to a temp path and returns {file_path, content_type, size}. Use the Read tool on the returned file_path to view images.",
59610
+ description: "Download a Zulip user upload by its /user_uploads/... path (visible in message bodies). Writes the file into a fresh temp directory and returns {file_path, content_type, size}. The temp directory is created under the operator-set COMMY_DOWNLOAD_DIR when configured (so the file lands in a directory you can Read), otherwise under $TMPDIR. Use the Read tool on the returned file_path to view images.",
59606
59611
  inputSchema: {
59607
59612
  type: "object",
59608
59613
  properties: {
@@ -59745,6 +59750,15 @@ var makeProgram = (params = {}) => exports_Effect.scoped(exports_Effect.gen(func
59745
59750
  }));
59746
59751
  const feedSessionId = (sessionId) => exports_Deferred.succeed(sessionIdDeferred, sessionId).pipe(exports_Effect.asVoid);
59747
59752
  const fs = yield* exports_FileSystem.FileSystem;
59753
+ if (parsed.downloadDir !== undefined) {
59754
+ const base = parsed.downloadDir;
59755
+ const baseStat = yield* fs.stat(base).pipe(exports_Effect.option);
59756
+ if (exports_Option.isNone(baseStat) || baseStat.value.type !== "Directory") {
59757
+ return yield* envConfigError([
59758
+ `COMMY_DOWNLOAD_DIR is set to ${base} but is not an existing directory`
59759
+ ]);
59760
+ }
59761
+ }
59748
59762
  const loggerLayer = params.loggerLayer ?? stderrLoggerLayer;
59749
59763
  const commandExecutor = yield* exports_CommandExecutor.CommandExecutor;
59750
59764
  const readGitContext2 = params.readGitContext ?? ((cwd) => readGitContext(cwd).pipe(exports_Effect.provideService(exports_CommandExecutor.CommandExecutor, commandExecutor)));
@@ -59813,7 +59827,7 @@ var makeProgram = (params = {}) => exports_Effect.scoped(exports_Effect.gen(func
59813
59827
  feedSessionId,
59814
59828
  downloadFile: (urlPath) => exports_Effect.gen(function* () {
59815
59829
  const result = yield* adapter4.downloadFile(urlPath);
59816
- const dir = yield* fs.makeTempDirectory({ prefix: "commy-dl-" });
59830
+ const dir = yield* fs.makeTempDirectory(parsed.downloadDir === undefined ? { prefix: "commy-dl-" } : { directory: parsed.downloadDir, prefix: "commy-dl-" });
59817
59831
  const filePath = join10(dir, basename2(urlPath));
59818
59832
  yield* fs.writeFile(filePath, result.data);
59819
59833
  return { filePath, contentType: result.contentType, size: result.data.byteLength };