claude-sessions-mcp 0.3.0 → 0.4.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.
- package/README.md +25 -78
- package/dist/index.js +308 -0
- package/dist/index.js.map +1 -0
- package/package.json +14 -64
- package/dist/chunk-7MUU7A32.js +0 -47
- package/dist/chunk-7MUU7A32.js.map +0 -1
- package/dist/mcp/index.js +0 -714
- package/dist/mcp/index.js.map +0 -1
- package/dist/server.d.ts +0 -10
- package/dist/server.js +0 -9
- package/dist/server.js.map +0 -1
- package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css +0 -1
- package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css.br +0 -0
- package/dist/web/client/_app/immutable/assets/0.XO-DXdC4.css.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js +0 -1
- package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/B2IHY0Hs.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js +0 -1
- package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/BCJVXGHY.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js +0 -1
- package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/CMwK7N_O.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/CZTho13P.js +0 -1
- package/dist/web/client/_app/immutable/chunks/CZTho13P.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/CZTho13P.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js +0 -2
- package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/F-H9hLgW.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js +0 -2
- package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/gR9AL7GA.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js +0 -2
- package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js.br +0 -0
- package/dist/web/client/_app/immutable/entry/app.Boej0hfY.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js +0 -1
- package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js.br +0 -2
- package/dist/web/client/_app/immutable/entry/start.CVYJWPd9.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js +0 -1
- package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/0.Lbeu1dpo.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js +0 -1
- package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/1.DvRsCtcA.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js +0 -73
- package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/2.CjVN0Bwe.js.gz +0 -0
- package/dist/web/client/_app/version.json +0 -1
- package/dist/web/client/_app/version.json.br +0 -0
- package/dist/web/client/_app/version.json.gz +0 -0
- package/dist/web/client/favicon.png +0 -0
- package/dist/web/env.js +0 -45
- package/dist/web/handler.js +0 -1390
- package/dist/web/index.js +0 -334
- package/dist/web/server/chunks/0-C_hzGzlo.js +0 -17
- package/dist/web/server/chunks/0-C_hzGzlo.js.map +0 -1
- package/dist/web/server/chunks/1-CSNAjAzD.js +0 -9
- package/dist/web/server/chunks/1-CSNAjAzD.js.map +0 -1
- package/dist/web/server/chunks/2-D_ZAFGkV.js +0 -9
- package/dist/web/server/chunks/2-D_ZAFGkV.js.map +0 -1
- package/dist/web/server/chunks/_layout.svelte-BWDuddeu.js +0 -33
- package/dist/web/server/chunks/_layout.svelte-BWDuddeu.js.map +0 -1
- package/dist/web/server/chunks/_page.svelte-BTPPI5f9.js +0 -113
- package/dist/web/server/chunks/_page.svelte-BTPPI5f9.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-B0JVJ9FB.js +0 -28
- package/dist/web/server/chunks/_server.ts-B0JVJ9FB.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-BLGLFyUk.js +0 -19
- package/dist/web/server/chunks/_server.ts-BLGLFyUk.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-BaqmP9oG.js +0 -14
- package/dist/web/server/chunks/_server.ts-BaqmP9oG.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-Beze9L3_.js +0 -19
- package/dist/web/server/chunks/_server.ts-Beze9L3_.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-BlgHsHoW.js +0 -8
- package/dist/web/server/chunks/_server.ts-BlgHsHoW.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-Bw_uJ6TN.js +0 -11
- package/dist/web/server/chunks/_server.ts-Bw_uJ6TN.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-CHX8x48n.js +0 -27
- package/dist/web/server/chunks/_server.ts-CHX8x48n.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-Cb5-fa8C.js +0 -37
- package/dist/web/server/chunks/_server.ts-Cb5-fa8C.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-ChE2aT-W.js +0 -29
- package/dist/web/server/chunks/_server.ts-ChE2aT-W.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-Cksv90lD.js +0 -18
- package/dist/web/server/chunks/_server.ts-Cksv90lD.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-D80JJ66s.js +0 -26
- package/dist/web/server/chunks/_server.ts-D80JJ66s.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-DjWf5N-i.js +0 -18
- package/dist/web/server/chunks/_server.ts-DjWf5N-i.js.map +0 -1
- package/dist/web/server/chunks/_server.ts-DmMLJ93T.js +0 -18
- package/dist/web/server/chunks/_server.ts-DmMLJ93T.js.map +0 -1
- package/dist/web/server/chunks/context-R2425nfV.js +0 -64
- package/dist/web/server/chunks/context-R2425nfV.js.map +0 -1
- package/dist/web/server/chunks/error.svelte-DazOwnSn.js +0 -45
- package/dist/web/server/chunks/error.svelte-DazOwnSn.js.map +0 -1
- package/dist/web/server/chunks/exports-BzHwARwz.js +0 -326
- package/dist/web/server/chunks/exports-BzHwARwz.js.map +0 -1
- package/dist/web/server/chunks/index-CXFDTUAl.js +0 -913
- package/dist/web/server/chunks/index-CXFDTUAl.js.map +0 -1
- package/dist/web/server/chunks/index-CoD1IJuy.js +0 -190
- package/dist/web/server/chunks/index-CoD1IJuy.js.map +0 -1
- package/dist/web/server/chunks/session-DmOGNZUD.js +0 -781
- package/dist/web/server/chunks/session-DmOGNZUD.js.map +0 -1
- package/dist/web/server/index.js +0 -7938
- package/dist/web/server/index.js.map +0 -1
- package/dist/web/server/manifest.js +0 -137
- package/dist/web/server/manifest.js.map +0 -1
- package/dist/web/shims.js +0 -32
- /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
|
|
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**:
|
|
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:
|
|
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
|
-
##
|
|
62
|
+
## MCP Tools
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
81
|
-
pnpm build
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## MCP Server Tools
|
|
78
|
+
## Related Packages
|
|
85
79
|
|
|
86
|
-
|
|
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
|
-
- **
|
|
103
|
-
- **
|
|
104
|
-
- **
|
|
105
|
-
- **
|
|
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,308 @@
|
|
|
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 { 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(port = 5173, openBrowser = true) {
|
|
17
|
+
const localCliPath = resolve(__dirname, "../../web/dist/cli.js");
|
|
18
|
+
const useLocal = existsSync(localCliPath);
|
|
19
|
+
const child = useLocal ? spawn("node", [localCliPath, "--port", String(port)], {
|
|
20
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
21
|
+
env: { ...process.env }
|
|
22
|
+
}) : spawn("npx", ["@claude-sessions/web", "--port", String(port)], {
|
|
23
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
24
|
+
env: { ...process.env }
|
|
25
|
+
});
|
|
26
|
+
await new Promise((resolve2, reject) => {
|
|
27
|
+
const timeout = setTimeout(() => reject(new Error("Server startup timeout")), 3e4);
|
|
28
|
+
child.stdout?.on("data", (data) => {
|
|
29
|
+
const output = data.toString();
|
|
30
|
+
if (output.includes("Listening on") || output.includes("localhost") || output.includes("Local:")) {
|
|
31
|
+
clearTimeout(timeout);
|
|
32
|
+
resolve2();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
child.stderr?.on("data", (data) => {
|
|
36
|
+
const output = data.toString();
|
|
37
|
+
if (output.includes("Listening on") || output.includes("localhost")) {
|
|
38
|
+
clearTimeout(timeout);
|
|
39
|
+
resolve2();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
child.on("error", (err) => {
|
|
43
|
+
clearTimeout(timeout);
|
|
44
|
+
reject(err);
|
|
45
|
+
});
|
|
46
|
+
child.on("exit", (code) => {
|
|
47
|
+
if (code !== 0) {
|
|
48
|
+
clearTimeout(timeout);
|
|
49
|
+
reject(new Error(`Server exited with code ${code}`));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
if (openBrowser) {
|
|
54
|
+
const url = `http://localhost:${port}`;
|
|
55
|
+
const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
56
|
+
spawn(openCmd, [url], { stdio: "ignore", detached: true }).unref();
|
|
57
|
+
}
|
|
58
|
+
return { process: child, port };
|
|
59
|
+
}
|
|
60
|
+
async function stopWebServer(server2) {
|
|
61
|
+
server2.process.kill("SIGTERM");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/index.ts
|
|
65
|
+
var server = new McpServer({
|
|
66
|
+
name: "claude-sessions-mcp",
|
|
67
|
+
version: "0.4.0"
|
|
68
|
+
});
|
|
69
|
+
server.tool("list_projects", "List all Claude Code projects with session counts", {}, async () => {
|
|
70
|
+
const result = await Effect.runPromise(session.listProjects);
|
|
71
|
+
return {
|
|
72
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
server.tool(
|
|
76
|
+
"list_sessions",
|
|
77
|
+
"List all sessions in a project",
|
|
78
|
+
{
|
|
79
|
+
project_name: z.string().describe("Project folder name (e.g., '-Users-young-works-myproject')")
|
|
80
|
+
},
|
|
81
|
+
async ({ project_name }) => {
|
|
82
|
+
const result = await Effect.runPromise(session.listSessions(project_name));
|
|
83
|
+
return {
|
|
84
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
server.tool(
|
|
89
|
+
"rename_session",
|
|
90
|
+
"Rename a session by adding a title prefix to the first message",
|
|
91
|
+
{
|
|
92
|
+
project_name: z.string().describe("Project folder name"),
|
|
93
|
+
session_id: z.string().describe("Session ID (filename without .jsonl)"),
|
|
94
|
+
new_title: z.string().describe("New title to add as prefix")
|
|
95
|
+
},
|
|
96
|
+
async ({ project_name, session_id, new_title }) => {
|
|
97
|
+
const result = await Effect.runPromise(
|
|
98
|
+
session.renameSession(project_name, session_id, new_title)
|
|
99
|
+
);
|
|
100
|
+
return {
|
|
101
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
server.tool(
|
|
106
|
+
"delete_session",
|
|
107
|
+
"Delete a session (moves to .bak folder for recovery)",
|
|
108
|
+
{
|
|
109
|
+
project_name: z.string().describe("Project folder name"),
|
|
110
|
+
session_id: z.string().describe("Session ID to delete")
|
|
111
|
+
},
|
|
112
|
+
async ({ project_name, session_id }) => {
|
|
113
|
+
const result = await Effect.runPromise(session.deleteSession(project_name, session_id));
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
server.tool(
|
|
120
|
+
"delete_message",
|
|
121
|
+
"Delete a message from a session and repair the parentUuid chain",
|
|
122
|
+
{
|
|
123
|
+
project_name: z.string().describe("Project folder name"),
|
|
124
|
+
session_id: z.string().describe("Session ID"),
|
|
125
|
+
message_uuid: z.string().describe("UUID of the message to delete")
|
|
126
|
+
},
|
|
127
|
+
async ({ project_name, session_id, message_uuid }) => {
|
|
128
|
+
const result = await Effect.runPromise(
|
|
129
|
+
session.deleteMessage(project_name, session_id, message_uuid)
|
|
130
|
+
);
|
|
131
|
+
return {
|
|
132
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
server.tool(
|
|
137
|
+
"preview_cleanup",
|
|
138
|
+
"Preview sessions that would be cleaned (empty and invalid API key sessions)",
|
|
139
|
+
{
|
|
140
|
+
project_name: z.string().optional().describe("Optional: filter by project name")
|
|
141
|
+
},
|
|
142
|
+
async ({ project_name }) => {
|
|
143
|
+
const result = await Effect.runPromise(session.previewCleanup(project_name));
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
server.tool(
|
|
150
|
+
"clear_sessions",
|
|
151
|
+
"Delete all empty sessions and invalid API key sessions",
|
|
152
|
+
{
|
|
153
|
+
project_name: z.string().optional().describe("Optional: filter by project name"),
|
|
154
|
+
clear_empty: z.boolean().default(true).describe("Clear empty sessions (default: true)"),
|
|
155
|
+
clear_invalid: z.boolean().default(true).describe("Clear invalid API key sessions (default: true)"),
|
|
156
|
+
clear_orphan_agents: z.boolean().default(true).describe("Clear orphan agent files whose session no longer exists (default: true)")
|
|
157
|
+
},
|
|
158
|
+
async ({ project_name, clear_empty, clear_invalid, clear_orphan_agents }) => {
|
|
159
|
+
const result = await Effect.runPromise(
|
|
160
|
+
session.clearSessions({
|
|
161
|
+
projectName: project_name,
|
|
162
|
+
clearEmpty: clear_empty,
|
|
163
|
+
clearInvalid: clear_invalid,
|
|
164
|
+
clearOrphanAgents: clear_orphan_agents
|
|
165
|
+
})
|
|
166
|
+
);
|
|
167
|
+
return {
|
|
168
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
server.tool(
|
|
173
|
+
"get_session_files",
|
|
174
|
+
"Get list of all files changed in a session (from file-history-snapshot and tool_use)",
|
|
175
|
+
{
|
|
176
|
+
project_name: z.string().describe("Project folder name"),
|
|
177
|
+
session_id: z.string().describe("Session ID")
|
|
178
|
+
},
|
|
179
|
+
async ({ project_name, session_id }) => {
|
|
180
|
+
const result = await Effect.runPromise(session.getSessionFiles(project_name, session_id));
|
|
181
|
+
return {
|
|
182
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
server.tool(
|
|
187
|
+
"split_session",
|
|
188
|
+
"Split a session at a specific message, creating a new session with messages from that point onwards",
|
|
189
|
+
{
|
|
190
|
+
project_name: z.string().describe("Project folder name"),
|
|
191
|
+
session_id: z.string().describe("Session ID to split"),
|
|
192
|
+
message_uuid: z.string().describe(
|
|
193
|
+
"UUID of the message where the split starts (this message becomes the first message of the new session)"
|
|
194
|
+
)
|
|
195
|
+
},
|
|
196
|
+
async ({ project_name, session_id, message_uuid }) => {
|
|
197
|
+
const result = await Effect.runPromise(
|
|
198
|
+
session.splitSession(project_name, session_id, message_uuid)
|
|
199
|
+
);
|
|
200
|
+
return {
|
|
201
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
var webServerInstance = null;
|
|
206
|
+
server.tool(
|
|
207
|
+
"start_gui",
|
|
208
|
+
"Start the web GUI for session management and open it in browser",
|
|
209
|
+
{
|
|
210
|
+
port: z.number().default(5173).describe("Port to run the web server on (default: 5173)"),
|
|
211
|
+
open_browser: z.boolean().default(true).describe("Whether to open browser automatically (default: true)"),
|
|
212
|
+
restart: z.boolean().default(false).describe("Restart the server if already running (default: false)")
|
|
213
|
+
},
|
|
214
|
+
async ({ port, open_browser, restart }) => {
|
|
215
|
+
try {
|
|
216
|
+
if (webServerInstance) {
|
|
217
|
+
if (restart) {
|
|
218
|
+
await stopWebServer(webServerInstance);
|
|
219
|
+
webServerInstance = null;
|
|
220
|
+
} else {
|
|
221
|
+
return {
|
|
222
|
+
content: [
|
|
223
|
+
{
|
|
224
|
+
type: "text",
|
|
225
|
+
text: JSON.stringify(
|
|
226
|
+
{
|
|
227
|
+
success: true,
|
|
228
|
+
message: "Web GUI is already running",
|
|
229
|
+
url: `http://localhost:${port}`
|
|
230
|
+
},
|
|
231
|
+
null,
|
|
232
|
+
2
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
webServerInstance = await startWebServer(port, open_browser);
|
|
240
|
+
return {
|
|
241
|
+
content: [
|
|
242
|
+
{
|
|
243
|
+
type: "text",
|
|
244
|
+
text: JSON.stringify(
|
|
245
|
+
{
|
|
246
|
+
success: true,
|
|
247
|
+
message: "Web GUI started successfully",
|
|
248
|
+
url: `http://localhost:${port}`,
|
|
249
|
+
pid: process.pid
|
|
250
|
+
},
|
|
251
|
+
null,
|
|
252
|
+
2
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
};
|
|
257
|
+
} catch (error) {
|
|
258
|
+
return {
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: "text",
|
|
262
|
+
text: JSON.stringify(
|
|
263
|
+
{
|
|
264
|
+
success: false,
|
|
265
|
+
error: String(error)
|
|
266
|
+
},
|
|
267
|
+
null,
|
|
268
|
+
2
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
]
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
server.tool("stop_gui", "Stop the web GUI server", {}, async () => {
|
|
277
|
+
if (webServerInstance) {
|
|
278
|
+
const port = webServerInstance.port;
|
|
279
|
+
try {
|
|
280
|
+
await fetch(`http://localhost:${port}/api/shutdown`, { method: "POST" });
|
|
281
|
+
} catch {
|
|
282
|
+
}
|
|
283
|
+
await stopWebServer(webServerInstance);
|
|
284
|
+
webServerInstance = null;
|
|
285
|
+
return {
|
|
286
|
+
content: [
|
|
287
|
+
{
|
|
288
|
+
type: "text",
|
|
289
|
+
text: JSON.stringify({ success: true, message: "Web GUI stopped successfully" }, null, 2)
|
|
290
|
+
}
|
|
291
|
+
]
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
content: [
|
|
296
|
+
{
|
|
297
|
+
type: "text",
|
|
298
|
+
text: JSON.stringify({ success: true, message: "Web GUI was not running" }, null, 2)
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
async function main() {
|
|
304
|
+
const transport = new StdioServerTransport();
|
|
305
|
+
await server.connect(transport);
|
|
306
|
+
}
|
|
307
|
+
main().catch(console.error);
|
|
308
|
+
//# 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 { Effect } from 'effect'\nimport { z } from 'zod'\nimport * as session from '@claude-sessions/core'\nimport { startWebServer, stopWebServer, type WebServer } from './server.js'\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 Effect.runPromise(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 Effect.runPromise(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 Effect.runPromise(\n session.renameSession(project_name, session_id, new_title)\n )\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 Effect.runPromise(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 Effect.runPromise(\n session.deleteMessage(project_name, session_id, message_uuid)\n )\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 Effect.runPromise(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 Effect.runPromise(\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 Effect.runPromise(session.getSessionFiles(project_name, session_id))\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 Effect.runPromise(\n session.splitSession(project_name, session_id, message_uuid)\n )\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 },\n async ({ port, open_browser, restart }) => {\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(port, open_browser)\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 async function startWebServer(\n port: number = 5173,\n openBrowser: boolean = true\n): Promise<WebServer> {\n // Try local build first, fallback to npx\n const localCliPath = resolve(__dirname, '../../web/dist/cli.js')\n const useLocal = existsSync(localCliPath)\n\n const child = useLocal\n ? spawn('node', [localCliPath, '--port', String(port)], {\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env },\n })\n : spawn('npx', ['@claude-sessions/web', '--port', String(port)], {\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"]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-sessions-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "MCP server for managing Claude Code conversation sessions",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"packageManager": "pnpm@9.15.0",
|
|
7
6
|
"license": "MIT",
|
|
8
7
|
"author": "es6.kr <drumrobot43@gmail.com>",
|
|
9
8
|
"repository": {
|
|
10
9
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/es6kr/claude-sessions
|
|
10
|
+
"url": "https://github.com/es6kr/claude-code-sessions",
|
|
11
|
+
"directory": "packages/mcp"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"claude",
|
|
@@ -19,82 +19,32 @@
|
|
|
19
19
|
],
|
|
20
20
|
"exports": {
|
|
21
21
|
".": {
|
|
22
|
-
"import": "./dist/
|
|
23
|
-
"types": "./dist/
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts"
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"bin": {
|
|
27
|
-
"claude-sessions-mcp": "./dist/
|
|
27
|
+
"claude-sessions-mcp": "./dist/index.js"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
|
-
"scripts": {
|
|
33
|
-
"dev": "pnpm --filter web dev",
|
|
34
|
-
"dev:mcp": "tsx watch src/mcp/index.ts",
|
|
35
|
-
"build": "pnpm run build:mcp && pnpm run build:web",
|
|
36
|
-
"build:mcp": "tsup",
|
|
37
|
-
"build:web": "pnpm --filter web build",
|
|
38
|
-
"lint": "eslint src",
|
|
39
|
-
"prepare": "husky",
|
|
40
|
-
"typecheck": "tsc --noEmit",
|
|
41
|
-
"version": "node -e \"const fs=require('fs');const p=require('./web/package.json');p.version=process.env.npm_package_version;fs.writeFileSync('./web/package.json',JSON.stringify(p,null,2)+'\\n')\" && git add web/package.json"
|
|
42
|
-
},
|
|
43
32
|
"dependencies": {
|
|
33
|
+
"@claude-sessions/core": "^0.1.0",
|
|
44
34
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
45
35
|
"effect": "^3.12.0",
|
|
46
|
-
"marked": "^17.0.1",
|
|
47
36
|
"zod": "^3.24.0"
|
|
48
37
|
},
|
|
49
38
|
"devDependencies": {
|
|
50
|
-
"@eslint/js": "^9.39.1",
|
|
51
39
|
"@types/node": "^22.0.0",
|
|
52
|
-
"editorconfig-checker": "^6.1.1",
|
|
53
|
-
"eslint": "^9.0.0",
|
|
54
|
-
"eslint-config-prettier": "^10.1.8",
|
|
55
|
-
"eslint-plugin-svelte": "^3.13.1",
|
|
56
|
-
"globals": "^16.5.0",
|
|
57
|
-
"husky": "^9.1.7",
|
|
58
|
-
"lint-staged": "^16.2.7",
|
|
59
|
-
"prettier": "^3.7.4",
|
|
60
|
-
"prettier-plugin-svelte": "^3.4.0",
|
|
61
|
-
"svelte-eslint-parser": "^1.4.1",
|
|
62
40
|
"tsup": "^8.3.0",
|
|
63
41
|
"tsx": "^4.19.0",
|
|
64
|
-
"typescript": "^5.7.0"
|
|
65
|
-
"typescript-eslint": "^8.49.0"
|
|
42
|
+
"typescript": "^5.7.0"
|
|
66
43
|
},
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"*.{js,ts}": [
|
|
73
|
-
"prettier --write",
|
|
74
|
-
"eslint --fix",
|
|
75
|
-
"editorconfig-checker"
|
|
76
|
-
],
|
|
77
|
-
"*.{json,md,css,html,yaml,yml}": [
|
|
78
|
-
"prettier --write",
|
|
79
|
-
"editorconfig-checker"
|
|
80
|
-
]
|
|
81
|
-
},
|
|
82
|
-
"prettier": {
|
|
83
|
-
"printWidth": 100,
|
|
84
|
-
"semi": false,
|
|
85
|
-
"singleQuote": true,
|
|
86
|
-
"tabWidth": 2,
|
|
87
|
-
"trailingComma": "es5",
|
|
88
|
-
"plugins": [
|
|
89
|
-
"prettier-plugin-svelte"
|
|
90
|
-
],
|
|
91
|
-
"overrides": [
|
|
92
|
-
{
|
|
93
|
-
"files": "*.svelte",
|
|
94
|
-
"options": {
|
|
95
|
-
"parser": "svelte"
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
]
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"dev": "tsx watch src/index.ts",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"lint": "eslint src"
|
|
99
49
|
}
|
|
100
|
-
}
|
|
50
|
+
}
|
package/dist/chunk-7MUU7A32.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// src/server.ts
|
|
2
|
-
import { spawn } from "child_process";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import path from "path";
|
|
5
|
-
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
var webServerPath = path.join(__dirname, "web", "index.js");
|
|
7
|
-
async function startWebServer(port = 5173, openBrowser = true) {
|
|
8
|
-
const child = spawn("node", [webServerPath], {
|
|
9
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
10
|
-
env: { ...process.env, PORT: String(port) }
|
|
11
|
-
});
|
|
12
|
-
await new Promise((resolve, reject) => {
|
|
13
|
-
const timeout = setTimeout(() => reject(new Error("Server startup timeout")), 1e4);
|
|
14
|
-
child.stdout?.on("data", (data) => {
|
|
15
|
-
const output = data.toString();
|
|
16
|
-
if (output.includes("Listening on") || output.includes("localhost") || output.includes("Local:")) {
|
|
17
|
-
clearTimeout(timeout);
|
|
18
|
-
resolve();
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
child.on("error", (err) => {
|
|
22
|
-
clearTimeout(timeout);
|
|
23
|
-
reject(err);
|
|
24
|
-
});
|
|
25
|
-
child.on("exit", (code) => {
|
|
26
|
-
if (code !== 0) {
|
|
27
|
-
clearTimeout(timeout);
|
|
28
|
-
reject(new Error(`Server exited with code ${code}`));
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
if (openBrowser) {
|
|
33
|
-
const url = `http://localhost:${port}`;
|
|
34
|
-
const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
35
|
-
spawn(openCmd, [url], { stdio: "ignore", detached: true }).unref();
|
|
36
|
-
}
|
|
37
|
-
return { process: child, port };
|
|
38
|
-
}
|
|
39
|
-
async function stopWebServer(server) {
|
|
40
|
-
server.process.kill("SIGTERM");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export {
|
|
44
|
-
startWebServer,
|
|
45
|
-
stopWebServer
|
|
46
|
-
};
|
|
47
|
-
//# sourceMappingURL=chunk-7MUU7A32.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process'\nimport { fileURLToPath } from 'node:url'\nimport path from 'node:path'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n// dist/web/index.js is the built SvelteKit server (adapter-node)\nconst webServerPath = path.join(__dirname, 'web', 'index.js')\n\ninterface WebServer {\n process: ChildProcess\n port: number\n}\n\nexport async function startWebServer(\n port: number = 5173,\n openBrowser: boolean = true\n): Promise<WebServer> {\n // Run the built SvelteKit server directly with Node\n const child = spawn('node', [webServerPath], {\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env, PORT: String(port) },\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')), 10000)\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.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":";AAAA,SAAS,aAAgC;AACzC,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AAEjB,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,IAAM,gBAAgB,KAAK,KAAK,WAAW,OAAO,UAAU;AAO5D,eAAsB,eACpB,OAAe,MACf,cAAuB,MACH;AAEpB,QAAM,QAAQ,MAAM,QAAQ,CAAC,aAAa,GAAG;AAAA,IAC3C,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAChC,KAAK,EAAE,GAAG,QAAQ,KAAK,MAAM,OAAO,IAAI,EAAE;AAAA,EAC5C,CAAC;AAGD,QAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAM,UAAU,WAAW,MAAM,OAAO,IAAI,MAAM,wBAAwB,CAAC,GAAG,GAAK;AAEnF,UAAM,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACzC,YAAM,SAAS,KAAK,SAAS;AAE7B,UACE,OAAO,SAAS,cAAc,KAC9B,OAAO,SAAS,WAAW,KAC3B,OAAO,SAAS,QAAQ,GACxB;AACA,qBAAa,OAAO;AACpB,gBAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,mBAAa,OAAO;AACpB,aAAO,GAAG;AAAA,IACZ,CAAC;AAED,UAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,UAAI,SAAS,GAAG;AACd,qBAAa,OAAO;AACpB,eAAO,IAAI,MAAM,2BAA2B,IAAI,EAAE,CAAC;AAAA,MACrD;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAGD,MAAI,aAAa;AACf,UAAM,MAAM,oBAAoB,IAAI;AACpC,UAAM,UACJ,QAAQ,aAAa,WAAW,SAAS,QAAQ,aAAa,UAAU,UAAU;AACpF,UAAM,SAAS,CAAC,GAAG,GAAG,EAAE,OAAO,UAAU,UAAU,KAAK,CAAC,EAAE,MAAM;AAAA,EACnE;AAEA,SAAO,EAAE,SAAS,OAAO,KAAK;AAChC;AAEA,eAAsB,cAAc,QAAkC;AACpE,SAAO,QAAQ,KAAK,SAAS;AAC/B;","names":[]}
|