claude-sessions-mcp 0.3.0 → 0.4.1-beta.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 (108) hide show
  1. package/README.md +25 -78
  2. package/dist/index.js +402 -0
  3. package/dist/index.js.map +1 -0
  4. package/package.json +20 -67
  5. package/dist/chunk-7MUU7A32.js +0 -47
  6. package/dist/chunk-7MUU7A32.js.map +0 -1
  7. package/dist/mcp/index.js +0 -714
  8. package/dist/mcp/index.js.map +0 -1
  9. package/dist/server.d.ts +0 -10
  10. package/dist/server.js +0 -9
  11. package/dist/server.js.map +0 -1
  12. package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css +0 -1
  13. package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css.br +0 -0
  14. package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css.gz +0 -0
  15. package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js +0 -1
  16. package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js.br +0 -0
  17. package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js.gz +0 -0
  18. package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js +0 -1
  19. package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js.br +0 -0
  20. package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js.gz +0 -0
  21. package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js +0 -1
  22. package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js.br +0 -0
  23. package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js.gz +0 -0
  24. package/dist/web/client/_app/immutable/chunks/CZTho13P.js +0 -1
  25. package/dist/web/client/_app/immutable/chunks/CZTho13P.js.br +0 -0
  26. package/dist/web/client/_app/immutable/chunks/CZTho13P.js.gz +0 -0
  27. package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js +0 -2
  28. package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js.br +0 -0
  29. package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js.gz +0 -0
  30. package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js +0 -2
  31. package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js.br +0 -0
  32. package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js.gz +0 -0
  33. package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js +0 -2
  34. package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js.br +0 -0
  35. package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js.gz +0 -0
  36. package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js +0 -1
  37. package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js.br +0 -2
  38. package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js.gz +0 -0
  39. package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js +0 -1
  40. package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js.br +0 -0
  41. package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js.gz +0 -0
  42. package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js +0 -1
  43. package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js.br +0 -0
  44. package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js.gz +0 -0
  45. package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js +0 -73
  46. package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js.br +0 -0
  47. package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js.gz +0 -0
  48. package/dist/web/client/_app/version.json +0 -1
  49. package/dist/web/client/_app/version.json.br +0 -0
  50. package/dist/web/client/_app/version.json.gz +0 -0
  51. package/dist/web/client/favicon.png +0 -0
  52. package/dist/web/env.js +0 -45
  53. package/dist/web/handler.js +0 -1390
  54. package/dist/web/index.js +0 -334
  55. package/dist/web/server/chunks/0-C_hzGzlo.js +0 -17
  56. package/dist/web/server/chunks/0-C_hzGzlo.js.map +0 -1
  57. package/dist/web/server/chunks/1-CSNAjAzD.js +0 -9
  58. package/dist/web/server/chunks/1-CSNAjAzD.js.map +0 -1
  59. package/dist/web/server/chunks/2-D_ZAFGkV.js +0 -9
  60. package/dist/web/server/chunks/2-D_ZAFGkV.js.map +0 -1
  61. package/dist/web/server/chunks/_layout.svelte-BWDuddeu.js +0 -33
  62. package/dist/web/server/chunks/_layout.svelte-BWDuddeu.js.map +0 -1
  63. package/dist/web/server/chunks/_page.svelte-BTPPI5f9.js +0 -113
  64. package/dist/web/server/chunks/_page.svelte-BTPPI5f9.js.map +0 -1
  65. package/dist/web/server/chunks/_server.ts-B0JVJ9FB.js +0 -28
  66. package/dist/web/server/chunks/_server.ts-B0JVJ9FB.js.map +0 -1
  67. package/dist/web/server/chunks/_server.ts-BLGLFyUk.js +0 -19
  68. package/dist/web/server/chunks/_server.ts-BLGLFyUk.js.map +0 -1
  69. package/dist/web/server/chunks/_server.ts-BaqmP9oG.js +0 -14
  70. package/dist/web/server/chunks/_server.ts-BaqmP9oG.js.map +0 -1
  71. package/dist/web/server/chunks/_server.ts-Beze9L3_.js +0 -19
  72. package/dist/web/server/chunks/_server.ts-Beze9L3_.js.map +0 -1
  73. package/dist/web/server/chunks/_server.ts-BlgHsHoW.js +0 -8
  74. package/dist/web/server/chunks/_server.ts-BlgHsHoW.js.map +0 -1
  75. package/dist/web/server/chunks/_server.ts-Bw_uJ6TN.js +0 -11
  76. package/dist/web/server/chunks/_server.ts-Bw_uJ6TN.js.map +0 -1
  77. package/dist/web/server/chunks/_server.ts-CHX8x48n.js +0 -27
  78. package/dist/web/server/chunks/_server.ts-CHX8x48n.js.map +0 -1
  79. package/dist/web/server/chunks/_server.ts-Cb5-fa8C.js +0 -37
  80. package/dist/web/server/chunks/_server.ts-Cb5-fa8C.js.map +0 -1
  81. package/dist/web/server/chunks/_server.ts-ChE2aT-W.js +0 -29
  82. package/dist/web/server/chunks/_server.ts-ChE2aT-W.js.map +0 -1
  83. package/dist/web/server/chunks/_server.ts-Cksv90lD.js +0 -18
  84. package/dist/web/server/chunks/_server.ts-Cksv90lD.js.map +0 -1
  85. package/dist/web/server/chunks/_server.ts-D80JJ66s.js +0 -26
  86. package/dist/web/server/chunks/_server.ts-D80JJ66s.js.map +0 -1
  87. package/dist/web/server/chunks/_server.ts-DjWf5N-i.js +0 -18
  88. package/dist/web/server/chunks/_server.ts-DjWf5N-i.js.map +0 -1
  89. package/dist/web/server/chunks/_server.ts-DmMLJ93T.js +0 -18
  90. package/dist/web/server/chunks/_server.ts-DmMLJ93T.js.map +0 -1
  91. package/dist/web/server/chunks/context-R2425nfV.js +0 -64
  92. package/dist/web/server/chunks/context-R2425nfV.js.map +0 -1
  93. package/dist/web/server/chunks/error.svelte-DazOwnSn.js +0 -45
  94. package/dist/web/server/chunks/error.svelte-DazOwnSn.js.map +0 -1
  95. package/dist/web/server/chunks/exports-BzHwARwz.js +0 -326
  96. package/dist/web/server/chunks/exports-BzHwARwz.js.map +0 -1
  97. package/dist/web/server/chunks/index-CXFDTUAl.js +0 -913
  98. package/dist/web/server/chunks/index-CXFDTUAl.js.map +0 -1
  99. package/dist/web/server/chunks/index-CoD1IJuy.js +0 -190
  100. package/dist/web/server/chunks/index-CoD1IJuy.js.map +0 -1
  101. package/dist/web/server/chunks/session-DmOGNZUD.js +0 -781
  102. package/dist/web/server/chunks/session-DmOGNZUD.js.map +0 -1
  103. package/dist/web/server/index.js +0 -7938
  104. package/dist/web/server/index.js.map +0 -1
  105. package/dist/web/server/manifest.js +0 -137
  106. package/dist/web/server/manifest.js.map +0 -1
  107. package/dist/web/shims.js +0 -32
  108. /package/dist/{mcp/index.d.ts → index.d.ts} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # claude-sessions-mcp
2
2
 
3
- MCP (Model Context Protocol) server and Web UI for managing Claude Code sessions.
3
+ MCP (Model Context Protocol) server for managing Claude Code sessions.
4
4
 
5
5
  ## Features
6
6
 
@@ -8,7 +8,7 @@ MCP (Model Context Protocol) server and Web UI for managing Claude Code sessions
8
8
  - **Session Management**: List, rename, and delete sessions
9
9
  - **Message Management**: View and delete messages within sessions
10
10
  - **Cleanup**: Clear empty sessions and remove invalid API key messages
11
- - **Web UI**: SvelteKit-based web interface
11
+ - **Web UI**: Launch built-in web interface for visual session management
12
12
 
13
13
  ## Installation
14
14
 
@@ -51,7 +51,7 @@ Launch the web interface via MCP tool (from Claude Code):
51
51
  > Use the start_gui tool to launch web interface
52
52
  ```
53
53
 
54
- The GUI opens at `http://localhost:5050` with features:
54
+ The GUI opens at `http://localhost:5173` with features:
55
55
 
56
56
  - Browse all projects and sessions
57
57
  - View full conversation history
@@ -59,87 +59,34 @@ The GUI opens at `http://localhost:5050` with features:
59
59
  - Delete unwanted sessions
60
60
  - Bulk cleanup of empty sessions
61
61
 
62
- ## Development
62
+ ## MCP Tools
63
63
 
64
- ```bash
65
- # Enable corepack
66
- corepack enable
67
-
68
- # Install dependencies
69
- pnpm install
70
-
71
- # Start web development server
72
- pnpm dev
73
-
74
- # MCP server development mode
75
- pnpm dev:mcp
76
- ```
77
-
78
- ## Build
64
+ | Tool | Description |
65
+ |------|-------------|
66
+ | `list_projects` | List Claude Code projects |
67
+ | `list_sessions` | List sessions in a project |
68
+ | `rename_session` | Rename a session |
69
+ | `delete_session` | Delete a session (moves to backup folder) |
70
+ | `delete_message` | Delete a message and repair UUID chain |
71
+ | `preview_cleanup` | Preview sessions to be cleaned |
72
+ | `clear_sessions` | Clear empty sessions and invalid messages |
73
+ | `get_session_files` | Get files changed in a session |
74
+ | `split_session` | Split session at a specific message |
75
+ | `start_gui` | Start the web UI |
76
+ | `stop_gui` | Stop the web UI |
79
77
 
80
- ```bash
81
- pnpm build
82
- ```
83
-
84
- ## MCP Server Tools
78
+ ## Related Packages
85
79
 
86
- ### Available Tools
87
-
88
- | Tool | Description |
89
- | ----------------- | ----------------------------------------- |
90
- | `list_projects` | List Claude Code projects |
91
- | `list_sessions` | List sessions in a project |
92
- | `rename_session` | Rename a session |
93
- | `delete_session` | Delete a session (moves to backup folder) |
94
- | `delete_message` | Delete a message and repair UUID chain |
95
- | `preview_cleanup` | Preview sessions to be cleaned |
96
- | `clear_sessions` | Clear empty sessions and invalid messages |
97
- | `start_gui` | Start the web UI |
98
- | `stop_gui` | Stop the web UI |
80
+ - [`@claude-sessions/core`](https://www.npmjs.com/package/@claude-sessions/core) - Core library
81
+ - [`@claude-sessions/web`](https://www.npmjs.com/package/@claude-sessions/web) - Standalone Web UI
99
82
 
100
83
  ## Tech Stack
101
84
 
102
- - **MCP Server**: Node.js + TypeScript + Effect
103
- - **Web UI**: SvelteKit + Svelte 5
104
- - **Build**: tsup (MCP), Vite (Web)
105
- - **Package Manager**: pnpm (corepack)
106
-
107
- ## Effect-TS Patterns
108
-
109
- This project uses [Effect](https://effect.website) for functional async operations:
110
-
111
- ```typescript
112
- import { Effect, pipe, Array as A, Option as O } from 'effect'
113
-
114
- // Define an Effect (lazy, composable)
115
- const listProjects = Effect.gen(function* () {
116
- const files = yield* Effect.tryPromise(() => fs.readdir(dir))
117
- return files.filter((f) => f.endsWith('.jsonl'))
118
- })
119
-
120
- // Parallel execution with concurrency control
121
- const results =
122
- yield *
123
- Effect.all(
124
- items.map((item) => processItem(item)),
125
- { concurrency: 10 }
126
- )
127
-
128
- // Option for nullable values
129
- const title = pipe(
130
- messages,
131
- A.findFirst((m) => m.type === 'user'),
132
- O.map((m) => extractTitle(m)),
133
- O.getOrElse(() => 'Untitled')
134
- )
135
-
136
- // Run in SvelteKit endpoint
137
- export const GET = async () => {
138
- const result = await Effect.runPromise(listProjects)
139
- return json(result)
140
- }
141
- ```
85
+ - **Runtime**: Node.js + TypeScript
86
+ - **MCP SDK**: @modelcontextprotocol/sdk
87
+ - **Async**: Effect-TS
88
+ - **Validation**: Zod
142
89
 
143
90
  ## License
144
91
 
145
- MIT
92
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,402 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { Cause, Effect } from "effect";
7
+ import { z } from "zod";
8
+ import * as session from "@claude-sessions/core";
9
+
10
+ // src/server.ts
11
+ import { spawn } from "child_process";
12
+ import { dirname, resolve } from "path";
13
+ import { fileURLToPath } from "url";
14
+ import { existsSync } from "fs";
15
+ var __dirname = dirname(fileURLToPath(import.meta.url));
16
+ async function startWebServer(options = {}) {
17
+ const { port = 5173, openBrowser = true, editor, home, project } = options;
18
+ const localCliPath = resolve(__dirname, "../../web/dist/cli.js");
19
+ const useLocal = existsSync(localCliPath);
20
+ const cliArgs = ["--port", String(port)];
21
+ if (editor) {
22
+ cliArgs.push("--editor", editor);
23
+ }
24
+ if (home) {
25
+ cliArgs.push("--home", home);
26
+ }
27
+ if (project) {
28
+ cliArgs.push("--project", project);
29
+ }
30
+ const child = useLocal ? spawn("node", [localCliPath, ...cliArgs], {
31
+ stdio: ["ignore", "pipe", "pipe"],
32
+ env: { ...process.env }
33
+ }) : spawn("npx", ["@claude-sessions/web@latest", ...cliArgs], {
34
+ stdio: ["ignore", "pipe", "pipe"],
35
+ env: { ...process.env }
36
+ });
37
+ await new Promise((resolve2, reject) => {
38
+ const timeout = setTimeout(() => reject(new Error("Server startup timeout")), 3e4);
39
+ child.stdout?.on("data", (data) => {
40
+ const output = data.toString();
41
+ if (output.includes("Listening on") || output.includes("localhost") || output.includes("Local:")) {
42
+ clearTimeout(timeout);
43
+ resolve2();
44
+ }
45
+ });
46
+ child.stderr?.on("data", (data) => {
47
+ const output = data.toString();
48
+ if (output.includes("Listening on") || output.includes("localhost")) {
49
+ clearTimeout(timeout);
50
+ resolve2();
51
+ }
52
+ });
53
+ child.on("error", (err) => {
54
+ clearTimeout(timeout);
55
+ reject(err);
56
+ });
57
+ child.on("exit", (code) => {
58
+ if (code !== 0) {
59
+ clearTimeout(timeout);
60
+ reject(new Error(`Server exited with code ${code}`));
61
+ }
62
+ });
63
+ });
64
+ if (openBrowser) {
65
+ const url = `http://localhost:${port}`;
66
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
67
+ spawn(openCmd, [url], { stdio: "ignore", detached: true }).unref();
68
+ }
69
+ return { process: child, port };
70
+ }
71
+ async function stopWebServer(server2) {
72
+ server2.process.kill("SIGTERM");
73
+ }
74
+
75
+ // src/index.ts
76
+ async function runEffect(effect) {
77
+ return Effect.runPromise(
78
+ effect.pipe(
79
+ Effect.catchAllCause((cause) => {
80
+ const prettyError = Cause.pretty(cause);
81
+ return Effect.die(new Error(prettyError));
82
+ })
83
+ )
84
+ );
85
+ }
86
+ var server = new McpServer({
87
+ name: "claude-sessions-mcp",
88
+ version: "0.4.0"
89
+ });
90
+ server.tool("list_projects", "List all Claude Code projects with session counts", {}, async () => {
91
+ const result = await runEffect(session.listProjects);
92
+ return {
93
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
94
+ };
95
+ });
96
+ server.tool(
97
+ "list_sessions",
98
+ "List all sessions in a project",
99
+ {
100
+ project_name: z.string().describe("Project folder name (e.g., '-Users-young-works-myproject')")
101
+ },
102
+ async ({ project_name }) => {
103
+ const result = await runEffect(session.listSessions(project_name));
104
+ return {
105
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
106
+ };
107
+ }
108
+ );
109
+ server.tool(
110
+ "rename_session",
111
+ "Rename a session by adding a title prefix to the first message",
112
+ {
113
+ project_name: z.string().describe("Project folder name"),
114
+ session_id: z.string().describe("Session ID (filename without .jsonl)"),
115
+ new_title: z.string().describe("New title to add as prefix")
116
+ },
117
+ async ({ project_name, session_id, new_title }) => {
118
+ const result = await runEffect(session.renameSession(project_name, session_id, new_title));
119
+ return {
120
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
121
+ };
122
+ }
123
+ );
124
+ server.tool(
125
+ "delete_session",
126
+ "Delete a session (moves to .bak folder for recovery)",
127
+ {
128
+ project_name: z.string().describe("Project folder name"),
129
+ session_id: z.string().describe("Session ID to delete")
130
+ },
131
+ async ({ project_name, session_id }) => {
132
+ const result = await runEffect(session.deleteSession(project_name, session_id));
133
+ return {
134
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
135
+ };
136
+ }
137
+ );
138
+ server.tool(
139
+ "delete_message",
140
+ "Delete a message from a session and repair the parentUuid chain",
141
+ {
142
+ project_name: z.string().describe("Project folder name"),
143
+ session_id: z.string().describe("Session ID"),
144
+ message_uuid: z.string().describe("UUID of the message to delete")
145
+ },
146
+ async ({ project_name, session_id, message_uuid }) => {
147
+ const result = await runEffect(session.deleteMessage(project_name, session_id, message_uuid));
148
+ return {
149
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
150
+ };
151
+ }
152
+ );
153
+ server.tool(
154
+ "preview_cleanup",
155
+ "Preview sessions that would be cleaned (empty and invalid API key sessions)",
156
+ {
157
+ project_name: z.string().optional().describe("Optional: filter by project name")
158
+ },
159
+ async ({ project_name }) => {
160
+ const result = await runEffect(session.previewCleanup(project_name));
161
+ return {
162
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
163
+ };
164
+ }
165
+ );
166
+ server.tool(
167
+ "clear_sessions",
168
+ "Delete all empty sessions and invalid API key sessions",
169
+ {
170
+ project_name: z.string().optional().describe("Optional: filter by project name"),
171
+ clear_empty: z.boolean().default(true).describe("Clear empty sessions (default: true)"),
172
+ clear_invalid: z.boolean().default(true).describe("Clear invalid API key sessions (default: true)"),
173
+ clear_orphan_agents: z.boolean().default(true).describe("Clear orphan agent files whose session no longer exists (default: true)")
174
+ },
175
+ async ({ project_name, clear_empty, clear_invalid, clear_orphan_agents }) => {
176
+ const result = await runEffect(
177
+ session.clearSessions({
178
+ projectName: project_name,
179
+ clearEmpty: clear_empty,
180
+ clearInvalid: clear_invalid,
181
+ clearOrphanAgents: clear_orphan_agents
182
+ })
183
+ );
184
+ return {
185
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
186
+ };
187
+ }
188
+ );
189
+ server.tool(
190
+ "get_session_files",
191
+ "Get list of all files changed in a session (from file-history-snapshot and tool_use)",
192
+ {
193
+ project_name: z.string().describe("Project folder name"),
194
+ session_id: z.string().describe("Session ID")
195
+ },
196
+ async ({ project_name, session_id }) => {
197
+ const result = await runEffect(session.getSessionFiles(project_name, session_id));
198
+ return {
199
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
200
+ };
201
+ }
202
+ );
203
+ server.tool(
204
+ "analyze_session",
205
+ "Analyze a session to get statistics, tool usage, patterns, and optimization insights",
206
+ {
207
+ project_name: z.string().describe("Project folder name"),
208
+ session_id: z.string().describe("Session ID")
209
+ },
210
+ async ({ project_name, session_id }) => {
211
+ const result = await runEffect(session.analyzeSession(project_name, session_id));
212
+ return {
213
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
214
+ };
215
+ }
216
+ );
217
+ server.tool(
218
+ "summarize_session",
219
+ "Summarize a session into compact user/assistant conversation format with timestamps",
220
+ {
221
+ project_name: z.string().describe("Project folder name"),
222
+ session_id: z.string().describe("Session ID"),
223
+ limit: z.number().default(50).describe("Maximum number of messages to include (default: 50)"),
224
+ max_length: z.number().default(100).describe("Maximum length for each message content (default: 100)")
225
+ },
226
+ async ({ project_name, session_id, limit, max_length }) => {
227
+ const result = await runEffect(
228
+ session.summarizeSession(project_name, session_id, {
229
+ limit,
230
+ maxLength: max_length
231
+ })
232
+ );
233
+ return {
234
+ content: [{ type: "text", text: result.formatted }]
235
+ };
236
+ }
237
+ );
238
+ server.tool(
239
+ "compress_session",
240
+ "Compress a session by removing redundant snapshots and truncating long tool outputs",
241
+ {
242
+ project_name: z.string().describe("Project folder name"),
243
+ session_id: z.string().describe("Session ID"),
244
+ keep_snapshots: z.enum(["first_last", "all", "none"]).default("first_last").describe("Which snapshots to keep: first_last (default), all, or none"),
245
+ max_tool_output_length: z.number().default(0).describe("Truncate tool outputs longer than this (0 = no limit)")
246
+ },
247
+ async ({ project_name, session_id, keep_snapshots, max_tool_output_length }) => {
248
+ const result = await runEffect(
249
+ session.compressSession(project_name, session_id, {
250
+ keepSnapshots: keep_snapshots,
251
+ maxToolOutputLength: max_tool_output_length
252
+ })
253
+ );
254
+ return {
255
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
256
+ };
257
+ }
258
+ );
259
+ server.tool(
260
+ "extract_project_knowledge",
261
+ "Extract patterns, hot files, workflows, and decisions from project sessions",
262
+ {
263
+ project_name: z.string().describe("Project folder name"),
264
+ session_ids: z.array(z.string()).optional().describe("Optional: specific session IDs to analyze (default: all sessions)")
265
+ },
266
+ async ({ project_name, session_ids }) => {
267
+ const result = await runEffect(session.extractProjectKnowledge(project_name, session_ids));
268
+ return {
269
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
270
+ };
271
+ }
272
+ );
273
+ server.tool(
274
+ "split_session",
275
+ "Split a session at a specific message, creating a new session with messages from that point onwards",
276
+ {
277
+ project_name: z.string().describe("Project folder name"),
278
+ session_id: z.string().describe("Session ID to split"),
279
+ message_uuid: z.string().describe(
280
+ "UUID of the message where the split starts (this message becomes the first message of the new session)"
281
+ )
282
+ },
283
+ async ({ project_name, session_id, message_uuid }) => {
284
+ const result = await runEffect(session.splitSession(project_name, session_id, message_uuid));
285
+ return {
286
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
287
+ };
288
+ }
289
+ );
290
+ var webServerInstance = null;
291
+ server.tool(
292
+ "start_gui",
293
+ "Start the web GUI for session management and open it in browser",
294
+ {
295
+ port: z.number().default(5173).describe("Port to run the web server on (default: 5173)"),
296
+ open_browser: z.boolean().default(true).describe("Whether to open browser automatically (default: true)"),
297
+ restart: z.boolean().default(false).describe("Restart the server if already running (default: false)"),
298
+ editor: z.string().optional().describe("Editor command to open files (default: code)"),
299
+ home: z.string().optional().describe("Home directory for ~ expansion (default: system homedir)"),
300
+ project: z.string().optional().describe("Current project name for priority sorting in project list")
301
+ },
302
+ async ({ port, open_browser, restart, editor, home, project }) => {
303
+ try {
304
+ if (webServerInstance) {
305
+ if (restart) {
306
+ await stopWebServer(webServerInstance);
307
+ webServerInstance = null;
308
+ } else {
309
+ return {
310
+ content: [
311
+ {
312
+ type: "text",
313
+ text: JSON.stringify(
314
+ {
315
+ success: true,
316
+ message: "Web GUI is already running",
317
+ url: `http://localhost:${port}`
318
+ },
319
+ null,
320
+ 2
321
+ )
322
+ }
323
+ ]
324
+ };
325
+ }
326
+ }
327
+ webServerInstance = await startWebServer({
328
+ port,
329
+ openBrowser: open_browser,
330
+ editor,
331
+ home,
332
+ project
333
+ });
334
+ return {
335
+ content: [
336
+ {
337
+ type: "text",
338
+ text: JSON.stringify(
339
+ {
340
+ success: true,
341
+ message: "Web GUI started successfully",
342
+ url: `http://localhost:${port}`,
343
+ pid: process.pid
344
+ },
345
+ null,
346
+ 2
347
+ )
348
+ }
349
+ ]
350
+ };
351
+ } catch (error) {
352
+ return {
353
+ content: [
354
+ {
355
+ type: "text",
356
+ text: JSON.stringify(
357
+ {
358
+ success: false,
359
+ error: String(error)
360
+ },
361
+ null,
362
+ 2
363
+ )
364
+ }
365
+ ]
366
+ };
367
+ }
368
+ }
369
+ );
370
+ server.tool("stop_gui", "Stop the web GUI server", {}, async () => {
371
+ if (webServerInstance) {
372
+ const port = webServerInstance.port;
373
+ try {
374
+ await fetch(`http://localhost:${port}/api/shutdown`, { method: "POST" });
375
+ } catch {
376
+ }
377
+ await stopWebServer(webServerInstance);
378
+ webServerInstance = null;
379
+ return {
380
+ content: [
381
+ {
382
+ type: "text",
383
+ text: JSON.stringify({ success: true, message: "Web GUI stopped successfully" }, null, 2)
384
+ }
385
+ ]
386
+ };
387
+ }
388
+ return {
389
+ content: [
390
+ {
391
+ type: "text",
392
+ text: JSON.stringify({ success: true, message: "Web GUI was not running" }, null, 2)
393
+ }
394
+ ]
395
+ };
396
+ });
397
+ async function main() {
398
+ const transport = new StdioServerTransport();
399
+ await server.connect(transport);
400
+ }
401
+ main().catch(console.error);
402
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * claude-sessions-mcp\n * MCP server for managing Claude Code conversation sessions\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { Cause, Effect } from 'effect'\nimport { z } from 'zod'\nimport * as session from '@claude-sessions/core'\nimport { startWebServer, stopWebServer, type WebServer } from './server.js'\n\n// Helper to run Effect with detailed error reporting\nasync function runEffect<A>(effect: Effect.Effect<A, unknown, never>): Promise<A> {\n return Effect.runPromise(\n effect.pipe(\n Effect.catchAllCause((cause) => {\n const prettyError = Cause.pretty(cause)\n return Effect.die(new Error(prettyError))\n })\n )\n ) as Promise<A>\n}\n\nconst server = new McpServer({\n name: 'claude-sessions-mcp',\n version: '0.4.0',\n})\n\n// List all projects\nserver.tool('list_projects', 'List all Claude Code projects with session counts', {}, async () => {\n const result = await runEffect(session.listProjects)\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n})\n\n// List sessions in a project\nserver.tool(\n 'list_sessions',\n 'List all sessions in a project',\n {\n project_name: z.string().describe(\"Project folder name (e.g., '-Users-young-works-myproject')\"),\n },\n async ({ project_name }) => {\n const result = await runEffect(session.listSessions(project_name))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Rename session\nserver.tool(\n 'rename_session',\n 'Rename a session by adding a title prefix to the first message',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID (filename without .jsonl)'),\n new_title: z.string().describe('New title to add as prefix'),\n },\n async ({ project_name, session_id, new_title }) => {\n const result = await runEffect(session.renameSession(project_name, session_id, new_title))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Delete session\nserver.tool(\n 'delete_session',\n 'Delete a session (moves to .bak folder for recovery)',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID to delete'),\n },\n async ({ project_name, session_id }) => {\n const result = await runEffect(session.deleteSession(project_name, session_id))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Delete message\nserver.tool(\n 'delete_message',\n 'Delete a message from a session and repair the parentUuid chain',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID'),\n message_uuid: z.string().describe('UUID of the message to delete'),\n },\n async ({ project_name, session_id, message_uuid }) => {\n const result = await runEffect(session.deleteMessage(project_name, session_id, message_uuid))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Preview cleanup\nserver.tool(\n 'preview_cleanup',\n 'Preview sessions that would be cleaned (empty and invalid API key sessions)',\n {\n project_name: z.string().optional().describe('Optional: filter by project name'),\n },\n async ({ project_name }) => {\n const result = await runEffect(session.previewCleanup(project_name))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Clear sessions\nserver.tool(\n 'clear_sessions',\n 'Delete all empty sessions and invalid API key sessions',\n {\n project_name: z.string().optional().describe('Optional: filter by project name'),\n clear_empty: z.boolean().default(true).describe('Clear empty sessions (default: true)'),\n clear_invalid: z\n .boolean()\n .default(true)\n .describe('Clear invalid API key sessions (default: true)'),\n clear_orphan_agents: z\n .boolean()\n .default(true)\n .describe('Clear orphan agent files whose session no longer exists (default: true)'),\n },\n async ({ project_name, clear_empty, clear_invalid, clear_orphan_agents }) => {\n const result = await runEffect(\n session.clearSessions({\n projectName: project_name,\n clearEmpty: clear_empty,\n clearInvalid: clear_invalid,\n clearOrphanAgents: clear_orphan_agents,\n })\n )\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Get changed files from a session\nserver.tool(\n 'get_session_files',\n 'Get list of all files changed in a session (from file-history-snapshot and tool_use)',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID'),\n },\n async ({ project_name, session_id }) => {\n const result = await runEffect(session.getSessionFiles(project_name, session_id))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Analyze session for optimization insights\nserver.tool(\n 'analyze_session',\n 'Analyze a session to get statistics, tool usage, patterns, and optimization insights',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID'),\n },\n async ({ project_name, session_id }) => {\n const result = await runEffect(session.analyzeSession(project_name, session_id))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Summarize session into user/assistant conversation format\nserver.tool(\n 'summarize_session',\n 'Summarize a session into compact user/assistant conversation format with timestamps',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID'),\n limit: z.number().default(50).describe('Maximum number of messages to include (default: 50)'),\n max_length: z\n .number()\n .default(100)\n .describe('Maximum length for each message content (default: 100)'),\n },\n async ({ project_name, session_id, limit, max_length }) => {\n const result = await runEffect(\n session.summarizeSession(project_name, session_id, {\n limit,\n maxLength: max_length,\n })\n )\n return {\n content: [{ type: 'text', text: result.formatted }],\n }\n }\n)\n\n// Compress session to reduce file size\nserver.tool(\n 'compress_session',\n 'Compress a session by removing redundant snapshots and truncating long tool outputs',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID'),\n keep_snapshots: z\n .enum(['first_last', 'all', 'none'])\n .default('first_last')\n .describe('Which snapshots to keep: first_last (default), all, or none'),\n max_tool_output_length: z\n .number()\n .default(0)\n .describe('Truncate tool outputs longer than this (0 = no limit)'),\n },\n async ({ project_name, session_id, keep_snapshots, max_tool_output_length }) => {\n const result = await runEffect(\n session.compressSession(project_name, session_id, {\n keepSnapshots: keep_snapshots,\n maxToolOutputLength: max_tool_output_length,\n })\n )\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Extract project knowledge from sessions\nserver.tool(\n 'extract_project_knowledge',\n 'Extract patterns, hot files, workflows, and decisions from project sessions',\n {\n project_name: z.string().describe('Project folder name'),\n session_ids: z\n .array(z.string())\n .optional()\n .describe('Optional: specific session IDs to analyze (default: all sessions)'),\n },\n async ({ project_name, session_ids }) => {\n const result = await runEffect(session.extractProjectKnowledge(project_name, session_ids))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Split session\nserver.tool(\n 'split_session',\n 'Split a session at a specific message, creating a new session with messages from that point onwards',\n {\n project_name: z.string().describe('Project folder name'),\n session_id: z.string().describe('Session ID to split'),\n message_uuid: z\n .string()\n .describe(\n 'UUID of the message where the split starts (this message becomes the first message of the new session)'\n ),\n },\n async ({ project_name, session_id, message_uuid }) => {\n const result = await runEffect(session.splitSession(project_name, session_id, message_uuid))\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n }\n }\n)\n\n// Start GUI\nlet webServerInstance: WebServer | null = null\n\nserver.tool(\n 'start_gui',\n 'Start the web GUI for session management and open it in browser',\n {\n port: z.number().default(5173).describe('Port to run the web server on (default: 5173)'),\n open_browser: z\n .boolean()\n .default(true)\n .describe('Whether to open browser automatically (default: true)'),\n restart: z\n .boolean()\n .default(false)\n .describe('Restart the server if already running (default: false)'),\n editor: z.string().optional().describe('Editor command to open files (default: code)'),\n home: z\n .string()\n .optional()\n .describe('Home directory for ~ expansion (default: system homedir)'),\n project: z\n .string()\n .optional()\n .describe('Current project name for priority sorting in project list'),\n },\n async ({ port, open_browser, restart, editor, home, project }) => {\n try {\n if (webServerInstance) {\n if (restart) {\n await stopWebServer(webServerInstance)\n webServerInstance = null\n } else {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n success: true,\n message: 'Web GUI is already running',\n url: `http://localhost:${port}`,\n },\n null,\n 2\n ),\n },\n ],\n }\n }\n }\n\n webServerInstance = await startWebServer({\n port,\n openBrowser: open_browser,\n editor,\n home,\n project,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n success: true,\n message: 'Web GUI started successfully',\n url: `http://localhost:${port}`,\n pid: process.pid,\n },\n null,\n 2\n ),\n },\n ],\n }\n } catch (error) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n success: false,\n error: String(error),\n },\n null,\n 2\n ),\n },\n ],\n }\n }\n }\n)\n\n// Stop GUI\nserver.tool('stop_gui', 'Stop the web GUI server', {}, async () => {\n if (webServerInstance) {\n const port = webServerInstance.port\n // Call shutdown API first for graceful shutdown\n try {\n await fetch(`http://localhost:${port}/api/shutdown`, { method: 'POST' })\n } catch {\n // Server might already be stopping\n }\n // Then kill the process if still running\n await stopWebServer(webServerInstance)\n webServerInstance = null\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ success: true, message: 'Web GUI stopped successfully' }, null, 2),\n },\n ],\n }\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({ success: true, message: 'Web GUI was not running' }, null, 2),\n },\n ],\n }\n})\n\n// Main entry\nasync function main() {\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n\nmain().catch(console.error)\n","/**\n * Web server management for MCP\n * Launches @claude-sessions/web\n */\nimport { spawn, type ChildProcess } from 'node:child_process'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { existsSync } from 'node:fs'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nexport interface WebServer {\n process: ChildProcess\n port: number\n}\n\nexport interface WebServerOptions {\n port?: number\n openBrowser?: boolean\n editor?: string\n home?: string\n project?: string\n}\n\nexport async function startWebServer(options: WebServerOptions = {}): Promise<WebServer> {\n const { port = 5173, openBrowser = true, editor, home, project } = options\n\n // Try local build first, fallback to npx\n const localCliPath = resolve(__dirname, '../../web/dist/cli.js')\n const useLocal = existsSync(localCliPath)\n\n // Build CLI arguments\n const cliArgs = ['--port', String(port)]\n if (editor) {\n cliArgs.push('--editor', editor)\n }\n if (home) {\n cliArgs.push('--home', home)\n }\n if (project) {\n cliArgs.push('--project', project)\n }\n\n const child = useLocal\n ? spawn('node', [localCliPath, ...cliArgs], {\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env },\n })\n : spawn('npx', ['@claude-sessions/web@latest', ...cliArgs], {\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env },\n })\n\n // Wait for server to start\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => reject(new Error('Server startup timeout')), 30000)\n\n child.stdout?.on('data', (data: Buffer) => {\n const output = data.toString()\n // SvelteKit adapter-node outputs \"Listening on http://0.0.0.0:PORT\"\n if (\n output.includes('Listening on') ||\n output.includes('localhost') ||\n output.includes('Local:')\n ) {\n clearTimeout(timeout)\n resolve()\n }\n })\n\n child.stderr?.on('data', (data: Buffer) => {\n const output = data.toString()\n // npm/npx progress output goes to stderr\n if (output.includes('Listening on') || output.includes('localhost')) {\n clearTimeout(timeout)\n resolve()\n }\n })\n\n child.on('error', (err) => {\n clearTimeout(timeout)\n reject(err)\n })\n\n child.on('exit', (code) => {\n if (code !== 0) {\n clearTimeout(timeout)\n reject(new Error(`Server exited with code ${code}`))\n }\n })\n })\n\n // Open browser if requested\n if (openBrowser) {\n const url = `http://localhost:${port}`\n const openCmd =\n process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open'\n spawn(openCmd, [url], { stdio: 'ignore', detached: true }).unref()\n }\n\n return { process: child, port }\n}\n\nexport async function stopWebServer(server: WebServer): Promise<void> {\n server.process.kill('SIGTERM')\n}\n"],"mappings":"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","names":["resolve","server"]}