warp-context-mcp 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +176 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# warp-context-mcp
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that saves and restores conversation context across Warp account switches.
|
|
4
|
+
|
|
5
|
+
When using Warp AI, switching accounts loses all conversation context. This MCP server solves that by persisting context summaries locally, so you can seamlessly resume work in a new session.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **save_context** — Save current conversation context before switching accounts
|
|
10
|
+
- **load_context** — Restore context in a new conversation after switching
|
|
11
|
+
- **list_contexts** — List all saved project contexts
|
|
12
|
+
- **delete_context** — Delete a project's context records
|
|
13
|
+
|
|
14
|
+
Context is stored as local JSON files in `~/.warp-contexts/`, with up to 5 history entries per project.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
### Using npx (recommended)
|
|
19
|
+
|
|
20
|
+
No installation needed. Configure your MCP client to run:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"mcpServers": {
|
|
25
|
+
"warp-context-mcp": {
|
|
26
|
+
"command": "npx",
|
|
27
|
+
"args": ["-y", "warp-context-mcp"]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### For Warp
|
|
34
|
+
|
|
35
|
+
Add to your Warp MCP settings (`mcp_servers.json`):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"warp-context-mcp": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "warp-context-mcp"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### For Claude Desktop
|
|
49
|
+
|
|
50
|
+
Add to your Claude Desktop config (`claude_desktop_config.json`):
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"mcpServers": {
|
|
55
|
+
"warp-context-mcp": {
|
|
56
|
+
"command": "npx",
|
|
57
|
+
"args": ["-y", "warp-context-mcp"]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
### Save context (before switching accounts)
|
|
66
|
+
|
|
67
|
+
Tell your AI assistant:
|
|
68
|
+
> "Save the current context for project X"
|
|
69
|
+
|
|
70
|
+
### Load context (after switching accounts)
|
|
71
|
+
|
|
72
|
+
Tell your AI assistant:
|
|
73
|
+
> "Load the context for project X"
|
|
74
|
+
|
|
75
|
+
## How It Works
|
|
76
|
+
|
|
77
|
+
1. Before switching accounts, ask the AI to save the current context — it captures the task, progress, decisions, TODOs, key files, and next steps.
|
|
78
|
+
2. After switching to a new account, ask the AI to load the context — it restores all the saved information so you can continue where you left off.
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
// 上下文存储目录
|
|
9
|
+
const CONTEXTS_DIR = path.join(os.homedir(), ".warp-contexts");
|
|
10
|
+
// 确保存储目录存在
|
|
11
|
+
function ensureDir() {
|
|
12
|
+
if (!fs.existsSync(CONTEXTS_DIR)) {
|
|
13
|
+
fs.mkdirSync(CONTEXTS_DIR, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// 获取项目上下文文件路径
|
|
17
|
+
function getContextPath(project) {
|
|
18
|
+
// 用安全的文件名
|
|
19
|
+
const safeName = project.replace(/[<>:"/\\|?*]/g, "_");
|
|
20
|
+
return path.join(CONTEXTS_DIR, `${safeName}.json`);
|
|
21
|
+
}
|
|
22
|
+
// ========== MCP Server ==========
|
|
23
|
+
const server = new McpServer({
|
|
24
|
+
name: "warp-context-mcp",
|
|
25
|
+
version: "1.0.0",
|
|
26
|
+
});
|
|
27
|
+
// Tool 1: 保存上下文
|
|
28
|
+
server.tool("save_context", "保存当前对话的上下文摘要,用于换号后恢复。在对话即将结束时调用此工具。", {
|
|
29
|
+
project: z.string().describe("项目名称,如 warp-pro-rust"),
|
|
30
|
+
task: z.string().describe("当前正在做的任务描述"),
|
|
31
|
+
progress: z.string().describe("当前进度,做到了哪一步"),
|
|
32
|
+
decisions: z.array(z.string()).describe("已做出的关键技术决策"),
|
|
33
|
+
todos: z.array(z.string()).describe("待完成的事项列表"),
|
|
34
|
+
key_files: z.array(z.string()).describe("涉及的关键文件路径"),
|
|
35
|
+
next_steps: z.string().describe("下一步计划"),
|
|
36
|
+
notes: z.string().optional().describe("其他备注信息"),
|
|
37
|
+
}, async ({ project, task, progress, decisions, todos, key_files, next_steps, notes }) => {
|
|
38
|
+
ensureDir();
|
|
39
|
+
const entry = {
|
|
40
|
+
project,
|
|
41
|
+
timestamp: new Date().toISOString(),
|
|
42
|
+
task,
|
|
43
|
+
progress,
|
|
44
|
+
decisions,
|
|
45
|
+
todos,
|
|
46
|
+
key_files,
|
|
47
|
+
next_steps,
|
|
48
|
+
notes: notes ?? "",
|
|
49
|
+
};
|
|
50
|
+
const filePath = getContextPath(project);
|
|
51
|
+
// 读取已有记录,保留最近 5 条历史
|
|
52
|
+
let history = [];
|
|
53
|
+
if (fs.existsSync(filePath)) {
|
|
54
|
+
try {
|
|
55
|
+
history = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
history = [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
history.push(entry);
|
|
62
|
+
// 只保留最近 5 条
|
|
63
|
+
if (history.length > 5) {
|
|
64
|
+
history = history.slice(-5);
|
|
65
|
+
}
|
|
66
|
+
fs.writeFileSync(filePath, JSON.stringify(history, null, 2), "utf-8");
|
|
67
|
+
return {
|
|
68
|
+
content: [
|
|
69
|
+
{
|
|
70
|
+
type: "text",
|
|
71
|
+
text: `✅ 上下文已保存到项目 "${project}"(共 ${history.length} 条记录)\n文件: ${filePath}`,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
// Tool 2: 加载上下文
|
|
77
|
+
server.tool("load_context", "加载指定项目的上下文摘要,用于在新对话中恢复之前的工作状态。新对话开始时调用此工具。", {
|
|
78
|
+
project: z.string().describe("项目名称"),
|
|
79
|
+
history_count: z
|
|
80
|
+
.number()
|
|
81
|
+
.optional()
|
|
82
|
+
.describe("要加载的历史记录数量,默认为 1(最新一条)"),
|
|
83
|
+
}, async ({ project, history_count }) => {
|
|
84
|
+
ensureDir();
|
|
85
|
+
const filePath = getContextPath(project);
|
|
86
|
+
if (!fs.existsSync(filePath)) {
|
|
87
|
+
return {
|
|
88
|
+
content: [
|
|
89
|
+
{ type: "text", text: `❌ 未找到项目 "${project}" 的上下文记录` },
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
let history;
|
|
94
|
+
try {
|
|
95
|
+
history = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return {
|
|
99
|
+
content: [
|
|
100
|
+
{ type: "text", text: `❌ 读取项目 "${project}" 的上下文文件失败` },
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const count = history_count ?? 1;
|
|
105
|
+
const entries = history.slice(-count);
|
|
106
|
+
const output = entries
|
|
107
|
+
.map((e) => `## ${e.project} - ${e.timestamp}\n` +
|
|
108
|
+
`**任务**: ${e.task}\n` +
|
|
109
|
+
`**进度**: ${e.progress}\n` +
|
|
110
|
+
`**决策**: ${e.decisions.join("; ")}\n` +
|
|
111
|
+
`**待办**: ${e.todos.join("; ")}\n` +
|
|
112
|
+
`**关键文件**: ${e.key_files.join(", ")}\n` +
|
|
113
|
+
`**下一步**: ${e.next_steps}\n` +
|
|
114
|
+
(e.notes ? `**备注**: ${e.notes}\n` : ""))
|
|
115
|
+
.join("\n---\n");
|
|
116
|
+
return {
|
|
117
|
+
content: [{ type: "text", text: output }],
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
// Tool 3: 列出所有上下文
|
|
121
|
+
server.tool("list_contexts", "列出所有已保存的项目上下文记录概览", {}, async () => {
|
|
122
|
+
ensureDir();
|
|
123
|
+
const files = fs
|
|
124
|
+
.readdirSync(CONTEXTS_DIR)
|
|
125
|
+
.filter((f) => f.endsWith(".json"));
|
|
126
|
+
if (files.length === 0) {
|
|
127
|
+
return {
|
|
128
|
+
content: [{ type: "text", text: "📭 没有已保存的上下文记录" }],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const summaries = files.map((f) => {
|
|
132
|
+
const filePath = path.join(CONTEXTS_DIR, f);
|
|
133
|
+
try {
|
|
134
|
+
const history = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
135
|
+
const latest = history[history.length - 1];
|
|
136
|
+
return (`- **${latest.project}** (${history.length} 条记录)\n` +
|
|
137
|
+
` 最后更新: ${latest.timestamp}\n` +
|
|
138
|
+
` 任务: ${latest.task}`);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return `- **${f}** (读取失败)`;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text: summaries.join("\n\n") }],
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
// Tool 4: 删除上下文
|
|
149
|
+
server.tool("delete_context", "删除指定项目的上下文记录", {
|
|
150
|
+
project: z.string().describe("要删除的项目名称"),
|
|
151
|
+
}, async ({ project }) => {
|
|
152
|
+
const filePath = getContextPath(project);
|
|
153
|
+
if (!fs.existsSync(filePath)) {
|
|
154
|
+
return {
|
|
155
|
+
content: [
|
|
156
|
+
{
|
|
157
|
+
type: "text",
|
|
158
|
+
text: `❌ 未找到项目 "${project}" 的上下文记录`,
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
fs.unlinkSync(filePath);
|
|
164
|
+
return {
|
|
165
|
+
content: [
|
|
166
|
+
{ type: "text", text: `🗑️ 已删除项目 "${project}" 的上下文记录` },
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
// 启动 server
|
|
171
|
+
async function main() {
|
|
172
|
+
const transport = new StdioServerTransport();
|
|
173
|
+
await server.connect(transport);
|
|
174
|
+
console.error("warp-context-mcp server is running on stdio");
|
|
175
|
+
}
|
|
176
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "warp-context-mcp",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "MCP server for saving and restoring Warp conversation context across account switches",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"warp-context-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"model-context-protocol",
|
|
22
|
+
"warp",
|
|
23
|
+
"context",
|
|
24
|
+
"ai",
|
|
25
|
+
"claude"
|
|
26
|
+
],
|
|
27
|
+
"author": "",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
31
|
+
"zod": "^3.25.23"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "^5.8.3",
|
|
35
|
+
"@types/node": "^22.15.2"
|
|
36
|
+
}
|
|
37
|
+
}
|