@roamcode.ai/server 1.0.0 → 1.0.2

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 (99) hide show
  1. package/dist/index.d.ts +2406 -82
  2. package/dist/index.js +8324 -44
  3. package/dist/managed-update-helper.js +631 -26
  4. package/dist/mcp-send.js +76 -90
  5. package/dist/start.d.ts +591 -9
  6. package/dist/start.js +7629 -353
  7. package/package.json +3 -3
  8. package/dist/auth.d.ts +0 -63
  9. package/dist/auth.js +0 -133
  10. package/dist/claude-auth-service.d.ts +0 -76
  11. package/dist/claude-auth-service.js +0 -217
  12. package/dist/claude-latest-service.d.ts +0 -34
  13. package/dist/claude-latest-service.js +0 -61
  14. package/dist/config.d.ts +0 -78
  15. package/dist/config.js +0 -59
  16. package/dist/data-dir.d.ts +0 -42
  17. package/dist/data-dir.js +0 -70
  18. package/dist/diag.d.ts +0 -43
  19. package/dist/diag.js +0 -83
  20. package/dist/fs-service.d.ts +0 -90
  21. package/dist/fs-service.js +0 -290
  22. package/dist/managed-runtime.d.ts +0 -51
  23. package/dist/managed-runtime.js +0 -411
  24. package/dist/managed-update-helper.d.ts +0 -2
  25. package/dist/mcp-send.d.ts +0 -33
  26. package/dist/origin-check.d.ts +0 -37
  27. package/dist/origin-check.js +0 -101
  28. package/dist/pane-status.d.ts +0 -61
  29. package/dist/pane-status.js +0 -145
  30. package/dist/providers/claude-metadata-service.d.ts +0 -58
  31. package/dist/providers/claude-metadata-service.js +0 -352
  32. package/dist/providers/claude-provider.d.ts +0 -11
  33. package/dist/providers/claude-provider.js +0 -166
  34. package/dist/providers/codex-activity.d.ts +0 -21
  35. package/dist/providers/codex-activity.js +0 -122
  36. package/dist/providers/codex-app-server-client.d.ts +0 -90
  37. package/dist/providers/codex-app-server-client.js +0 -485
  38. package/dist/providers/codex-latest-service.d.ts +0 -50
  39. package/dist/providers/codex-latest-service.js +0 -174
  40. package/dist/providers/codex-metadata-service.d.ts +0 -161
  41. package/dist/providers/codex-metadata-service.js +0 -686
  42. package/dist/providers/codex-profile-client.d.ts +0 -16
  43. package/dist/providers/codex-profile-client.js +0 -52
  44. package/dist/providers/codex-profile-security.d.ts +0 -23
  45. package/dist/providers/codex-profile-security.js +0 -161
  46. package/dist/providers/codex-provider.d.ts +0 -15
  47. package/dist/providers/codex-provider.js +0 -174
  48. package/dist/providers/codex-thread-coordinator.d.ts +0 -18
  49. package/dist/providers/codex-thread-coordinator.js +0 -93
  50. package/dist/providers/codex-thread-persistence.d.ts +0 -9
  51. package/dist/providers/codex-thread-persistence.js +0 -45
  52. package/dist/providers/codex-thread-resolver.d.ts +0 -59
  53. package/dist/providers/codex-thread-resolver.js +0 -322
  54. package/dist/providers/options.d.ts +0 -7
  55. package/dist/providers/options.js +0 -155
  56. package/dist/providers/provider-artifacts.d.ts +0 -3
  57. package/dist/providers/provider-artifacts.js +0 -30
  58. package/dist/providers/registry.d.ts +0 -7
  59. package/dist/providers/registry.js +0 -23
  60. package/dist/providers/types.d.ts +0 -95
  61. package/dist/providers/types.js +0 -8
  62. package/dist/push-dispatch.d.ts +0 -81
  63. package/dist/push-dispatch.js +0 -100
  64. package/dist/push-store.d.ts +0 -25
  65. package/dist/push-store.js +0 -79
  66. package/dist/rate-limit.d.ts +0 -52
  67. package/dist/rate-limit.js +0 -72
  68. package/dist/server-config.d.ts +0 -60
  69. package/dist/server-config.js +0 -77
  70. package/dist/service-install.d.ts +0 -60
  71. package/dist/service-install.js +0 -221
  72. package/dist/session-defaults.d.ts +0 -26
  73. package/dist/session-defaults.js +0 -60
  74. package/dist/session-store.d.ts +0 -81
  75. package/dist/session-store.js +0 -654
  76. package/dist/static-routes.d.ts +0 -101
  77. package/dist/static-routes.js +0 -188
  78. package/dist/terminal-capability.d.ts +0 -5
  79. package/dist/terminal-capability.js +0 -27
  80. package/dist/terminal-manager.d.ts +0 -224
  81. package/dist/terminal-manager.js +0 -917
  82. package/dist/terminal-process.d.ts +0 -85
  83. package/dist/terminal-process.js +0 -238
  84. package/dist/terminal-shared.d.ts +0 -36
  85. package/dist/terminal-shared.js +0 -43
  86. package/dist/tmux-list.d.ts +0 -11
  87. package/dist/tmux-list.js +0 -39
  88. package/dist/transport.d.ts +0 -123
  89. package/dist/transport.js +0 -1559
  90. package/dist/updater.d.ts +0 -161
  91. package/dist/updater.js +0 -451
  92. package/dist/usage-service.d.ts +0 -118
  93. package/dist/usage-service.js +0 -173
  94. package/dist/vapid.d.ts +0 -17
  95. package/dist/vapid.js +0 -31
  96. package/dist/web-push-send.d.ts +0 -20
  97. package/dist/web-push-send.js +0 -21
  98. package/dist/ws-ticket.d.ts +0 -47
  99. package/dist/ws-ticket.js +0 -62
package/dist/mcp-send.js CHANGED
@@ -1,107 +1,93 @@
1
- /**
2
- * mcp-send — a stdio MCP server that lets Claude proactively SEND a file or image to the user's chat.
3
- *
4
- * roamcode spawns this as `claude`'s MCP subprocess (via --mcp-config). It exposes two tools
5
- * (send_image / send_file); on a call it POSTs the file PATH to roamcode's
6
- * `POST /sessions/:id/attach`, which validates the path (fsRoot+realpath) and pushes an `attachment`
7
- * frame over the session's WebSocket so the web renders it (image inline, file as a download).
8
- *
9
- * The connection params arrive via env, with Claude supplying RC_TOKEN directly and Codex supplying a
10
- * provider-owned RC_TOKEN_FILE. No ANTHROPIC_API_KEY, no @anthropic-ai dependency — only the MCP SDK + zod.
11
- */
12
- import { lstatSync, readFileSync } from "node:fs";
13
- import { basename, isAbsolute } from "node:path";
1
+ #!/usr/bin/env node
2
+
3
+ // src/mcp-send.ts
4
+ import { lstatSync, readFileSync } from "fs";
5
+ import { basename, isAbsolute } from "path";
14
6
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
15
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
8
  import { z } from "zod";
17
9
  function readTokenFile(path) {
18
- try {
19
- if (!isAbsolute(path))
20
- return undefined;
21
- const info = lstatSync(path);
22
- if (!info.isFile() || info.isSymbolicLink() || (info.mode & 0o077) !== 0 || info.size < 1 || info.size > 4096) {
23
- return undefined;
24
- }
25
- if (typeof process.getuid === "function" && info.uid !== process.getuid())
26
- return undefined;
27
- const token = readFileSync(path, "utf8");
28
- return token.length <= 4096 && !/[\p{Cc}\p{Zl}\p{Zp}]/u.test(token) ? token : undefined;
29
- }
30
- catch {
31
- return undefined;
10
+ try {
11
+ if (!isAbsolute(path)) return void 0;
12
+ const info = lstatSync(path);
13
+ if (!info.isFile() || info.isSymbolicLink() || (info.mode & 63) !== 0 || info.size < 1 || info.size > 4096) {
14
+ return void 0;
32
15
  }
16
+ if (typeof process.getuid === "function" && info.uid !== process.getuid()) return void 0;
17
+ const token = readFileSync(path, "utf8");
18
+ return token.length <= 4096 && !/[\p{Cc}\p{Zl}\p{Zp}]/u.test(token) ? token : void 0;
19
+ } catch {
20
+ return void 0;
21
+ }
33
22
  }
34
23
  function textResult(text, isError = false) {
35
- return isError ? { content: [{ type: "text", text }], isError: true } : { content: [{ type: "text", text }] };
24
+ return isError ? { content: [{ type: "text", text }], isError: true } : { content: [{ type: "text", text }] };
36
25
  }
37
- /**
38
- * Pure, unit-testable core: POST the attachment to roamcode and map the response to a tool-result.
39
- * NEVER throws a bad path, a down server, or a network error all return an `isError` tool-result so
40
- * Claude learns it failed and can tell the user. `fetchImpl` is injectable for tests (defaults to fetch).
41
- */
42
- export async function deliver(env, args, fetchImpl = fetch) {
43
- const { RC_BASE_URL, RC_SESSION_ID } = env;
44
- const token = env.RC_TOKEN || (env.RC_TOKEN_FILE ? readTokenFile(env.RC_TOKEN_FILE) : undefined);
45
- if (!RC_BASE_URL || !RC_SESSION_ID || !token) {
46
- return textResult("Attachment delivery is not configured (RC_BASE_URL / RC_SESSION_ID / RC_TOKEN missing).", true);
47
- }
48
- const url = `${RC_BASE_URL}/sessions/${RC_SESSION_ID}/attach`;
49
- let res;
26
+ async function deliver(env, args, fetchImpl = fetch) {
27
+ const { RC_BASE_URL, RC_SESSION_ID } = env;
28
+ const token = env.RC_TOKEN || (env.RC_TOKEN_FILE ? readTokenFile(env.RC_TOKEN_FILE) : void 0);
29
+ if (!RC_BASE_URL || !RC_SESSION_ID || !token) {
30
+ return textResult("Attachment delivery is not configured (RC_BASE_URL / RC_SESSION_ID / RC_TOKEN missing).", true);
31
+ }
32
+ const url = `${RC_BASE_URL}/sessions/${RC_SESSION_ID}/attach`;
33
+ let res;
34
+ try {
35
+ res = await fetchImpl(url, {
36
+ method: "POST",
37
+ headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
38
+ body: JSON.stringify({ path: args.path, caption: args.caption, kind: args.kind })
39
+ });
40
+ } catch (err) {
41
+ return textResult(`Could not reach roamcode to send the file: ${err.message}`, true);
42
+ }
43
+ if (!res.ok) {
44
+ let detail = `HTTP ${res.status}`;
50
45
  try {
51
- res = await fetchImpl(url, {
52
- method: "POST",
53
- headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
54
- body: JSON.stringify({ path: args.path, caption: args.caption, kind: args.kind }),
55
- });
46
+ const body = await res.json();
47
+ if (typeof body.error === "string") detail = body.error;
48
+ } catch {
56
49
  }
57
- catch (err) {
58
- return textResult(`Could not reach roamcode to send the file: ${err.message}`, true);
59
- }
60
- if (!res.ok) {
61
- // Surface the server's error body (e.g. "path is outside the allowed root") so Claude can explain it.
62
- let detail = `HTTP ${res.status}`;
63
- try {
64
- const body = (await res.json());
65
- if (typeof body.error === "string")
66
- detail = body.error;
67
- }
68
- catch {
69
- // non-JSON error body — keep the status code detail
70
- }
71
- return textResult(`Failed to send ${basename(args.path)}: ${detail}`, true);
72
- }
73
- return textResult(`Sent ${basename(args.path)} to the user.`);
50
+ return textResult(`Failed to send ${basename(args.path)}: ${detail}`, true);
51
+ }
52
+ return textResult(`Sent ${basename(args.path)} to the user.`);
74
53
  }
75
- const SEND_PARAMS = {
76
- path: z.string().describe("Absolute path to the file to send."),
77
- caption: z.string().optional().describe("Optional caption shown with the file in the chat."),
54
+ var SEND_PARAMS = {
55
+ path: z.string().describe("Absolute path to the file to send."),
56
+ caption: z.string().optional().describe("Optional caption shown with the file in the chat.")
78
57
  };
79
- /** Build the MCP server with the two send tools wired to `deliver`. Reads env lazily per call. */
80
- export function createMcpSendServer(env = process.env) {
81
- const server = new McpServer({ name: "roamcode-send", version: "0.0.0" });
82
- server.registerTool("send_image", {
83
- description: "Send an IMAGE to the user's chat so they can see it inline. Use when the user asks you to " +
84
- "show/send an image, or to deliver a generated image. `path` must be an absolute path to the file.",
85
- inputSchema: SEND_PARAMS,
86
- }, async ({ path, caption }) => deliver(env, { path, caption, kind: "image" }));
87
- server.registerTool("send_file", {
88
- description: "Send a FILE to the user's chat as a download. Use when the user asks you to send/deliver a " +
89
- "file. `path` must be an absolute path.",
90
- inputSchema: SEND_PARAMS,
91
- }, async ({ path, caption }) => deliver(env, { path, caption, kind: "file" }));
92
- return server;
58
+ function createMcpSendServer(env = process.env) {
59
+ const server = new McpServer({ name: "roamcode-send", version: "0.0.0" });
60
+ server.registerTool(
61
+ "send_image",
62
+ {
63
+ description: "Send an IMAGE to the user's chat so they can see it inline. Use when the user asks you to show/send an image, or to deliver a generated image. `path` must be an absolute path to the file.",
64
+ inputSchema: SEND_PARAMS
65
+ },
66
+ async ({ path, caption }) => deliver(env, { path, caption, kind: "image" })
67
+ );
68
+ server.registerTool(
69
+ "send_file",
70
+ {
71
+ description: "Send a FILE to the user's chat as a download. Use when the user asks you to send/deliver a file. `path` must be an absolute path.",
72
+ inputSchema: SEND_PARAMS
73
+ },
74
+ async ({ path, caption }) => deliver(env, { path, caption, kind: "file" })
75
+ );
76
+ return server;
93
77
  }
94
- /** Run the stdio server when executed directly (node dist/mcp-send.js). */
95
78
  async function main() {
96
- const server = createMcpSendServer();
97
- const transport = new StdioServerTransport();
98
- await server.connect(transport);
79
+ const server = createMcpSendServer();
80
+ const transport = new StdioServerTransport();
81
+ await server.connect(transport);
99
82
  }
100
- // Only run when invoked as the entry script, not when imported by a test.
101
83
  if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) {
102
- main().catch((err) => {
103
- // A stdio MCP server must keep stdout clean (it is the JSON-RPC channel) log to stderr.
104
- process.stderr.write(`mcp-send failed to start: ${err.message}\n`);
105
- process.exit(1);
106
- });
84
+ main().catch((err) => {
85
+ process.stderr.write(`mcp-send failed to start: ${err.message}
86
+ `);
87
+ process.exit(1);
88
+ });
107
89
  }
90
+ export {
91
+ createMcpSendServer,
92
+ deliver
93
+ };