@rui.branco/sentry-mcp 1.0.5 → 1.0.7
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 +246 -243
- package/index.js +1398 -1169
- package/package.json +35 -35
- package/setup.js +267 -266
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rui.branco/sentry-mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Sentry MCP server for any MCP-compatible AI client (Claude Code, Codex, Antigravity, Cursor, etc.) - fetch issues, search errors, resolve/ignore issues, get stack traces and breadcrumbs",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"sentry-mcp": "./index.js"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"index.js",
|
|
11
|
-
"setup.js",
|
|
12
|
-
"README.md"
|
|
13
|
-
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"setup": "node setup.js",
|
|
16
|
-
"test": "vitest run"
|
|
17
|
-
},
|
|
18
|
-
"keywords": [
|
|
19
|
-
"mcp",
|
|
20
|
-
"model-context-protocol",
|
|
21
|
-
"sentry",
|
|
22
|
-
"claude",
|
|
23
|
-
"claude-code",
|
|
24
|
-
"error-tracking"
|
|
25
|
-
],
|
|
26
|
-
"author": "Rui Branco",
|
|
27
|
-
"license": "MIT",
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
30
|
-
"node-fetch": "^2.7.0"
|
|
31
|
-
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"vitest": "^4.1.6"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@rui.branco/sentry-mcp",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"description": "Sentry MCP server for any MCP-compatible AI client (Claude Code, Codex, Antigravity, Cursor, etc.) - fetch issues, search errors, resolve/ignore issues, get stack traces and breadcrumbs",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sentry-mcp": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"setup.js",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"setup": "node setup.js",
|
|
16
|
+
"test": "vitest run"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"sentry",
|
|
22
|
+
"claude",
|
|
23
|
+
"claude-code",
|
|
24
|
+
"error-tracking"
|
|
25
|
+
],
|
|
26
|
+
"author": "Rui Branco",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
30
|
+
"node-fetch": "^2.7.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"vitest": "^4.1.6"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/setup.js
CHANGED
|
@@ -1,266 +1,267 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const readline = require("readline");
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
delete config.
|
|
54
|
-
delete config.
|
|
55
|
-
delete config.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
console.log("
|
|
161
|
-
console.log("
|
|
162
|
-
console.log("
|
|
163
|
-
console.log("
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
console.log("
|
|
204
|
-
console.log("
|
|
205
|
-
console.log("
|
|
206
|
-
console.log("
|
|
207
|
-
console.log("
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
console.log("\
|
|
258
|
-
console.log("
|
|
259
|
-
console.log("
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const readline = require("readline");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
const configDir = path.join(os.homedir(), ".config/sentry-mcp");
|
|
9
|
+
const configPath = path.join(configDir, "config.json");
|
|
10
|
+
|
|
11
|
+
// Check for command line arguments
|
|
12
|
+
let args = process.argv.slice(2);
|
|
13
|
+
// Skip "setup" arg if called via index.js
|
|
14
|
+
if (args[0] === "setup") args = args.slice(1);
|
|
15
|
+
|
|
16
|
+
// Load existing config if present
|
|
17
|
+
function loadConfig() {
|
|
18
|
+
try {
|
|
19
|
+
if (fs.existsSync(configPath)) {
|
|
20
|
+
return JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function saveConfig(config) {
|
|
27
|
+
if (!fs.existsSync(configDir)) {
|
|
28
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Non-interactive: setup add <name> <token> <baseUrl> <orgSlug> [projectSlug] [projects...]
|
|
34
|
+
if (args[0] === "add" && args.length >= 4) {
|
|
35
|
+
const [, name, token, baseUrl, orgSlug, projectSlug, ...projectArgs] = args;
|
|
36
|
+
const projects = projectArgs.length > 0
|
|
37
|
+
? projectArgs.join(",").split(",").map((p) => p.trim().toLowerCase()).filter(Boolean)
|
|
38
|
+
: [];
|
|
39
|
+
|
|
40
|
+
const config = loadConfig() || {};
|
|
41
|
+
|
|
42
|
+
// Migrate old format if needed
|
|
43
|
+
if (config.token && !config.instances) {
|
|
44
|
+
config.instances = [{
|
|
45
|
+
name: "default",
|
|
46
|
+
token: config.token,
|
|
47
|
+
baseUrl: config.baseUrl,
|
|
48
|
+
orgSlug: config.orgSlug,
|
|
49
|
+
projectSlug: config.projectSlug || "",
|
|
50
|
+
projects: [],
|
|
51
|
+
}];
|
|
52
|
+
config.defaultInstance = "default";
|
|
53
|
+
delete config.token;
|
|
54
|
+
delete config.baseUrl;
|
|
55
|
+
delete config.orgSlug;
|
|
56
|
+
delete config.projectSlug;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!config.instances) config.instances = [];
|
|
60
|
+
|
|
61
|
+
// Replace or add instance
|
|
62
|
+
const existing = config.instances.findIndex((i) => i.name === name);
|
|
63
|
+
const instance = {
|
|
64
|
+
name,
|
|
65
|
+
token,
|
|
66
|
+
baseUrl: baseUrl.replace(/\/+$/, ""),
|
|
67
|
+
orgSlug,
|
|
68
|
+
projectSlug: projectSlug || "",
|
|
69
|
+
projects,
|
|
70
|
+
};
|
|
71
|
+
if (existing >= 0) {
|
|
72
|
+
config.instances[existing] = instance;
|
|
73
|
+
} else {
|
|
74
|
+
config.instances.push(instance);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!config.defaultInstance) config.defaultInstance = name;
|
|
78
|
+
|
|
79
|
+
saveConfig(config);
|
|
80
|
+
console.log(`Instance "${name}" saved to ${configPath}`);
|
|
81
|
+
if (projects.length > 0) {
|
|
82
|
+
console.log(`Projects: ${projects.join(", ")}`);
|
|
83
|
+
}
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Non-interactive: setup remove <name>
|
|
88
|
+
if (args[0] === "remove" && args.length >= 2) {
|
|
89
|
+
const name = args[1];
|
|
90
|
+
const config = loadConfig();
|
|
91
|
+
|
|
92
|
+
if (!config || !config.instances) {
|
|
93
|
+
console.error("No multi-instance config found.");
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
config.instances = config.instances.filter((i) => i.name !== name);
|
|
98
|
+
if (config.defaultInstance === name) {
|
|
99
|
+
config.defaultInstance = config.instances[0]?.name || null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
saveConfig(config);
|
|
103
|
+
console.log(`Instance "${name}" removed.`);
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Non-interactive: setup <token> <baseUrl> <orgSlug> [projectSlug]
|
|
108
|
+
if (args.length >= 3 && args[0] !== "add" && args[0] !== "remove") {
|
|
109
|
+
const [token, baseUrl, orgSlug, projectSlug] = args;
|
|
110
|
+
saveConfig({
|
|
111
|
+
token,
|
|
112
|
+
baseUrl: baseUrl.replace(/\/+$/, ""),
|
|
113
|
+
orgSlug,
|
|
114
|
+
projectSlug: projectSlug || "",
|
|
115
|
+
});
|
|
116
|
+
console.log(`Config saved to ${configPath}`);
|
|
117
|
+
process.exit(0);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Interactive mode
|
|
121
|
+
const rl = readline.createInterface({
|
|
122
|
+
input: process.stdin,
|
|
123
|
+
output: process.stdout,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
function ask(question) {
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
rl.question(question, resolve);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function setup() {
|
|
133
|
+
const existing = loadConfig();
|
|
134
|
+
const hasInstances = existing?.instances?.length > 0;
|
|
135
|
+
const isOldFormat = existing?.token && !existing?.instances;
|
|
136
|
+
|
|
137
|
+
console.log("\n=== Sentry MCP Setup ===\n");
|
|
138
|
+
|
|
139
|
+
if (hasInstances || isOldFormat) {
|
|
140
|
+
if (isOldFormat) {
|
|
141
|
+
console.log(`Existing single-instance config found (${existing.baseUrl})\n`);
|
|
142
|
+
} else {
|
|
143
|
+
console.log("Existing instances:");
|
|
144
|
+
for (const inst of existing.instances) {
|
|
145
|
+
const isDefault = inst.name === existing.defaultInstance ? " (default)" : "";
|
|
146
|
+
const projs = inst.projects?.length > 0 ? ` [${inst.projects.join(", ")}]` : "";
|
|
147
|
+
console.log(` - ${inst.name}${isDefault}: ${inst.baseUrl} (org: ${inst.orgSlug})${projs}`);
|
|
148
|
+
}
|
|
149
|
+
console.log();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const action = await ask("Add new instance, or fresh setup? (add/fresh): ");
|
|
153
|
+
if (action.trim().toLowerCase() === "fresh") {
|
|
154
|
+
// Fall through to single setup
|
|
155
|
+
} else {
|
|
156
|
+
return await addInstance(existing);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
console.log("To get your Sentry API token:");
|
|
161
|
+
console.log("1. Go to https://sentry.io/settings/account/api/auth-tokens/");
|
|
162
|
+
console.log(" (or your self-hosted Sentry Settings > API > Auth Tokens)");
|
|
163
|
+
console.log("2. Create a new token with scopes: event:read, project:read, org:read, member:read");
|
|
164
|
+
console.log("3. Copy the token\n");
|
|
165
|
+
|
|
166
|
+
const token = await ask("Sentry API token: ");
|
|
167
|
+
const baseUrl = await ask("Sentry base URL (e.g., https://sentry.io or https://my-org.sentry.io): ");
|
|
168
|
+
const orgSlug = await ask("Organization slug: ");
|
|
169
|
+
const projectSlug = await ask("Default project slug (optional, press Enter to skip): ");
|
|
170
|
+
|
|
171
|
+
saveConfig({
|
|
172
|
+
token: token.trim(),
|
|
173
|
+
baseUrl: baseUrl.trim().replace(/\/+$/, ""),
|
|
174
|
+
orgSlug: orgSlug.trim(),
|
|
175
|
+
projectSlug: projectSlug.trim() || "",
|
|
176
|
+
});
|
|
177
|
+
console.log(`\nConfig saved to ${configPath}`);
|
|
178
|
+
|
|
179
|
+
printSetupComplete();
|
|
180
|
+
rl.close();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function addInstance(config) {
|
|
184
|
+
// Migrate old format if needed
|
|
185
|
+
if (config.token && !config.instances) {
|
|
186
|
+
const oldName = await ask("Name for your existing instance (e.g., work): ");
|
|
187
|
+
const oldProjects = await ask("Project slugs for existing instance (comma-separated): ");
|
|
188
|
+
config = {
|
|
189
|
+
instances: [{
|
|
190
|
+
name: oldName.trim() || "default",
|
|
191
|
+
token: config.token,
|
|
192
|
+
baseUrl: config.baseUrl,
|
|
193
|
+
orgSlug: config.orgSlug,
|
|
194
|
+
projectSlug: config.projectSlug || "",
|
|
195
|
+
projects: oldProjects.split(",").map((p) => p.trim().toLowerCase()).filter(Boolean),
|
|
196
|
+
}],
|
|
197
|
+
defaultInstance: oldName.trim() || "default",
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!config.instances) config.instances = [];
|
|
202
|
+
|
|
203
|
+
console.log("\n--- Add New Instance ---\n");
|
|
204
|
+
console.log("To get your Sentry API token:");
|
|
205
|
+
console.log("1. Go to https://sentry.io/settings/account/api/auth-tokens/");
|
|
206
|
+
console.log(" (or your self-hosted Sentry Settings > API > Auth Tokens)");
|
|
207
|
+
console.log("2. Create a new token with scopes: event:read, project:read, org:read, member:read");
|
|
208
|
+
console.log("3. Copy the token\n");
|
|
209
|
+
|
|
210
|
+
const name = await ask("Instance name (e.g., personal): ");
|
|
211
|
+
const token = await ask("Sentry API token: ");
|
|
212
|
+
const baseUrl = await ask("Sentry base URL (e.g., https://sentry.io or https://my-org.sentry.io): ");
|
|
213
|
+
const orgSlug = await ask("Organization slug: ");
|
|
214
|
+
const projectSlug = await ask("Default project slug (optional, press Enter to skip): ");
|
|
215
|
+
const projectsInput = await ask("Project slugs to route to this instance (comma-separated, optional): ");
|
|
216
|
+
const projects = projectsInput.split(",").map((p) => p.trim().toLowerCase()).filter(Boolean);
|
|
217
|
+
|
|
218
|
+
const instance = {
|
|
219
|
+
name: name.trim(),
|
|
220
|
+
token: token.trim(),
|
|
221
|
+
baseUrl: baseUrl.trim().replace(/\/+$/, ""),
|
|
222
|
+
orgSlug: orgSlug.trim(),
|
|
223
|
+
projectSlug: projectSlug.trim() || "",
|
|
224
|
+
projects,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// Replace or add
|
|
228
|
+
const idx = config.instances.findIndex((i) => i.name === instance.name);
|
|
229
|
+
if (idx >= 0) {
|
|
230
|
+
config.instances[idx] = instance;
|
|
231
|
+
} else {
|
|
232
|
+
config.instances.push(instance);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!config.defaultInstance) config.defaultInstance = instance.name;
|
|
236
|
+
|
|
237
|
+
const setDefault = await ask(`Set "${instance.name}" as default? (y/N): `);
|
|
238
|
+
if (setDefault.trim().toLowerCase() === "y") {
|
|
239
|
+
config.defaultInstance = instance.name;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
saveConfig(config);
|
|
243
|
+
console.log(`\nInstance "${instance.name}" saved to ${configPath}`);
|
|
244
|
+
|
|
245
|
+
console.log("\nAll instances:");
|
|
246
|
+
for (const inst of config.instances) {
|
|
247
|
+
const isDefault = inst.name === config.defaultInstance ? " (default)" : "";
|
|
248
|
+
const projs = inst.projects?.length > 0 ? ` [${inst.projects.join(", ")}]` : "";
|
|
249
|
+
console.log(` - ${inst.name}${isDefault}: ${inst.baseUrl} (org: ${inst.orgSlug})${projs}`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
printSetupComplete();
|
|
253
|
+
rl.close();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function printSetupComplete() {
|
|
257
|
+
console.log("\n=== Setup Complete ===");
|
|
258
|
+
console.log("\nIf you haven't already, add to Claude Code with:\n");
|
|
259
|
+
console.log(" claude mcp add --transport stdio sentry -- npx -y @rui.branco/sentry-mcp");
|
|
260
|
+
console.log("\nThen restart Claude Code and run /mcp to verify.");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
setup().catch((e) => {
|
|
264
|
+
console.error("Setup failed:", e.message);
|
|
265
|
+
rl.close();
|
|
266
|
+
process.exit(1);
|
|
267
|
+
});
|