@tokamohsen/sentry-mcp 0.29.5 → 0.29.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/dist/{chunk-C0xms8kb.cjs → chunk-rXqPaSPc.cjs} +26 -0
- package/dist/cli/{parse-M8aGwIO5.d.ts → parse-CX7Bcldr.d.ts} +2 -2
- package/dist/cli/{parse-M8aGwIO5.d.ts.map → parse-CX7Bcldr.d.ts.map} +1 -1
- package/dist/cli/parse.cjs +1 -1
- package/dist/cli/{resolve-kNjr_UaF.d.ts → resolve-BVtyZcQM.d.ts} +2 -2
- package/dist/cli/resolve-BVtyZcQM.d.ts.map +1 -0
- package/dist/cli/resolve.cjs +9 -10
- package/dist/cli/resolve.cjs.map +1 -1
- package/dist/cli/resolve.js +2 -2
- package/dist/cli/{types-B2hDXVnQ.d.ts → types-CnTkIHzd.d.ts} +1 -1
- package/dist/cli/{types-B2hDXVnQ.d.ts.map → types-CnTkIHzd.d.ts.map} +1 -1
- package/dist/cli/{usage-BMxqEEQ3.d.ts → usage-BhCVaC5j.d.ts} +1 -1
- package/dist/cli/usage-BhCVaC5j.d.ts.map +1 -0
- package/dist/config-CzqCJmB9.js +613 -0
- package/dist/config-CzqCJmB9.js.map +1 -0
- package/dist/config-DMt6phB6.cjs +630 -0
- package/dist/config-DMt6phB6.cjs.map +1 -0
- package/dist/constants-BrEVt86y.js +194 -0
- package/dist/constants-BrEVt86y.js.map +1 -0
- package/dist/constants-C14tQf_s.cjs +217 -0
- package/dist/constants-C14tQf_s.cjs.map +1 -0
- package/dist/index.cjs +163 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +191 -6
- package/dist/index.js.map +1 -1
- package/dist/server-DduxvXpe.js +32499 -0
- package/dist/server-DduxvXpe.js.map +1 -0
- package/dist/server-lur5iSHk.cjs +32530 -0
- package/dist/server-lur5iSHk.cjs.map +1 -0
- package/dist/skills-DOgs9MAy.cjs +96 -0
- package/dist/skills-DOgs9MAy.cjs.map +1 -0
- package/dist/skills-DfqlqYXj.js +72 -0
- package/dist/skills-DfqlqYXj.js.map +1 -0
- package/dist/token-CO5Bq1Ct.js +50 -0
- package/dist/token-CO5Bq1Ct.js.map +1 -0
- package/dist/token-GX19_oyM.cjs +54 -0
- package/dist/token-GX19_oyM.cjs.map +1 -0
- package/dist/token-util-1O_mwf8r.js +358 -0
- package/dist/token-util-1O_mwf8r.js.map +1 -0
- package/dist/token-util-Cw83HNFN.cjs +362 -0
- package/dist/token-util-Cw83HNFN.cjs.map +1 -0
- package/dist/transports/{stdio-DVcJU1wB.d.ts → stdio-DKQR8J7l.d.ts} +1 -1
- package/dist/transports/{stdio-DVcJU1wB.d.ts.map → stdio-DKQR8J7l.d.ts.map} +1 -1
- package/dist/transports/stdio.cjs +3 -3
- package/dist/transports/stdio.js +1 -1
- package/dist/url-utils-BHhxlntO.js +119 -0
- package/dist/url-utils-BHhxlntO.js.map +1 -0
- package/dist/url-utils-N2ExJl9F.cjs +161 -0
- package/dist/url-utils-N2ExJl9F.cjs.map +1 -0
- package/dist/version-4iOZzjiD.js +7 -0
- package/dist/version-4iOZzjiD.js.map +1 -0
- package/dist/version-BD4r13ze.cjs +19 -0
- package/dist/version-BD4r13ze.cjs.map +1 -0
- package/package.json +3 -3
- package/dist/cli/resolve-kNjr_UaF.d.ts.map +0 -1
- package/dist/cli/usage-BMxqEEQ3.d.ts.map +0 -1
- /package/dist/{index-DgNgxUxv.d.ts → index-UKPmYT-S.d.ts} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1,17 +1,160 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
3
|
+
const require_chunk = require('./chunk-rXqPaSPc.cjs');
|
|
4
|
+
const require_skills = require('./skills-DOgs9MAy.cjs');
|
|
5
|
+
require('./constants-C14tQf_s.cjs');
|
|
6
|
+
const require_server = require('./server-lur5iSHk.cjs');
|
|
7
|
+
const require_version = require('./version-BD4r13ze.cjs');
|
|
3
8
|
const require_transports_stdio = require('./transports/stdio.cjs');
|
|
4
9
|
const require_cli_usage = require('./cli/usage.cjs');
|
|
5
10
|
const require_cli_parse = require('./cli/parse.cjs');
|
|
6
11
|
const require_cli_resolve = require('./cli/resolve.cjs');
|
|
7
|
-
let _sentry_mcp_core_server = require("@sentry/mcp-core/server");
|
|
8
12
|
let _sentry_node = require("@sentry/node");
|
|
9
13
|
_sentry_node = require_chunk.__toESM(_sentry_node);
|
|
10
|
-
let _sentry_mcp_core_version = require("@sentry/mcp-core/version");
|
|
11
|
-
let _sentry_mcp_core_skills = require("@sentry/mcp-core/skills");
|
|
12
|
-
let _sentry_mcp_core_telem_sentry = require("@sentry/mcp-core/telem/sentry");
|
|
13
|
-
let _sentry_mcp_core_internal_agents_provider_factory = require("@sentry/mcp-core/internal/agents/provider-factory");
|
|
14
14
|
|
|
15
|
+
//#region ../../node_modules/.pnpm/@vercel+oidc@3.1.0/node_modules/@vercel/oidc/dist/token-error.js
|
|
16
|
+
var require_token_error = /* @__PURE__ */ require_chunk.__commonJSMin(((exports, module) => {
|
|
17
|
+
var __defProp = Object.defineProperty;
|
|
18
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
19
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
20
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
21
|
+
var __export = (target, all) => {
|
|
22
|
+
for (var name in all) __defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
var __copyProps = (to, from, except, desc) => {
|
|
28
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
29
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
30
|
+
get: () => from[key],
|
|
31
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return to;
|
|
35
|
+
};
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
var token_error_exports = {};
|
|
38
|
+
__export(token_error_exports, { VercelOidcTokenError: () => VercelOidcTokenError });
|
|
39
|
+
module.exports = __toCommonJS(token_error_exports);
|
|
40
|
+
var VercelOidcTokenError = class extends Error {
|
|
41
|
+
constructor(message, cause) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "VercelOidcTokenError";
|
|
44
|
+
this.cause = cause;
|
|
45
|
+
}
|
|
46
|
+
toString() {
|
|
47
|
+
if (this.cause) return `${this.name}: ${this.message}: ${this.cause}`;
|
|
48
|
+
return `${this.name}: ${this.message}`;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region ../mcp-core/dist/telem/sentry.js
|
|
55
|
+
const SCRUB_PATTERNS = [
|
|
56
|
+
{
|
|
57
|
+
pattern: /\bsk-[a-zA-Z0-9]{48}\b/g,
|
|
58
|
+
replacement: "[REDACTED_OPENAI_KEY]",
|
|
59
|
+
description: "OpenAI API key"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+={0,}/g,
|
|
63
|
+
replacement: "Bearer [REDACTED_TOKEN]",
|
|
64
|
+
description: "Bearer token"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
pattern: /\bsntrys_[a-zA-Z0-9_]+\b/g,
|
|
68
|
+
replacement: "[REDACTED_SENTRY_TOKEN]",
|
|
69
|
+
description: "Sentry access token"
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
const MAX_SCRUB_DEPTH = 20;
|
|
73
|
+
/**
|
|
74
|
+
* Recursively scrub sensitive data from any value.
|
|
75
|
+
* Returns tuple of [scrubbedValue, didScrub, descriptionsOfMatchedPatterns]
|
|
76
|
+
*/
|
|
77
|
+
function scrubValue(value, depth = 0) {
|
|
78
|
+
if (depth >= MAX_SCRUB_DEPTH) return [
|
|
79
|
+
"[MAX_DEPTH_EXCEEDED]",
|
|
80
|
+
false,
|
|
81
|
+
[]
|
|
82
|
+
];
|
|
83
|
+
if (typeof value === "string") {
|
|
84
|
+
let scrubbed = value;
|
|
85
|
+
let didScrub = false;
|
|
86
|
+
const matchedDescriptions = [];
|
|
87
|
+
for (const { pattern, replacement, description } of SCRUB_PATTERNS) {
|
|
88
|
+
pattern.lastIndex = 0;
|
|
89
|
+
if (pattern.test(scrubbed)) {
|
|
90
|
+
didScrub = true;
|
|
91
|
+
matchedDescriptions.push(description);
|
|
92
|
+
pattern.lastIndex = 0;
|
|
93
|
+
scrubbed = scrubbed.replace(pattern, replacement);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return [
|
|
97
|
+
scrubbed,
|
|
98
|
+
didScrub,
|
|
99
|
+
matchedDescriptions
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(value)) {
|
|
103
|
+
let arrayDidScrub = false;
|
|
104
|
+
const arrayDescriptions = [];
|
|
105
|
+
return [
|
|
106
|
+
value.map((item) => {
|
|
107
|
+
const [scrubbed, didScrub, descriptions] = scrubValue(item, depth + 1);
|
|
108
|
+
if (didScrub) {
|
|
109
|
+
arrayDidScrub = true;
|
|
110
|
+
arrayDescriptions.push(...descriptions);
|
|
111
|
+
}
|
|
112
|
+
return scrubbed;
|
|
113
|
+
}),
|
|
114
|
+
arrayDidScrub,
|
|
115
|
+
arrayDescriptions
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
if (value && typeof value === "object") {
|
|
119
|
+
let objectDidScrub = false;
|
|
120
|
+
const objectDescriptions = [];
|
|
121
|
+
const scrubbed = {};
|
|
122
|
+
for (const [key, val] of Object.entries(value)) {
|
|
123
|
+
const [scrubbedVal, didScrub, descriptions] = scrubValue(val, depth + 1);
|
|
124
|
+
if (didScrub) {
|
|
125
|
+
objectDidScrub = true;
|
|
126
|
+
objectDescriptions.push(...descriptions);
|
|
127
|
+
}
|
|
128
|
+
scrubbed[key] = scrubbedVal;
|
|
129
|
+
}
|
|
130
|
+
return [
|
|
131
|
+
scrubbed,
|
|
132
|
+
objectDidScrub,
|
|
133
|
+
objectDescriptions
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
return [
|
|
137
|
+
value,
|
|
138
|
+
false,
|
|
139
|
+
[]
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Sentry beforeSend hook that scrubs sensitive data from events
|
|
144
|
+
* and applies custom fingerprinting for specific error types.
|
|
145
|
+
*/
|
|
146
|
+
function sentryBeforeSend(event, hint) {
|
|
147
|
+
const firstException = event?.exception?.values?.[0];
|
|
148
|
+
if (firstException?.type === "AI_APICallError" && firstException.value) event.fingerprint = ["AI_APICallError", firstException.value];
|
|
149
|
+
const [scrubbedEvent, didScrub, descriptions] = scrubValue(event);
|
|
150
|
+
if (didScrub) {
|
|
151
|
+
const uniqueDescriptions = [...new Set(descriptions)];
|
|
152
|
+
console.warn(`[Sentry] Event contained sensitive data: ${uniqueDescriptions.join(", ")}`);
|
|
153
|
+
}
|
|
154
|
+
return scrubbedEvent;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
//#endregion
|
|
15
158
|
//#region src/index.ts
|
|
16
159
|
/**
|
|
17
160
|
* Main CLI entry point for the Sentry MCP server.
|
|
@@ -27,7 +170,7 @@ let _sentry_mcp_core_internal_agents_provider_factory = require("@sentry/mcp-cor
|
|
|
27
170
|
* ```
|
|
28
171
|
*/
|
|
29
172
|
const packageName = "@tokamohsen/sentry-mcp";
|
|
30
|
-
const usageText = require_cli_usage.buildUsage(packageName, Object.keys(
|
|
173
|
+
const usageText = require_cli_usage.buildUsage(packageName, Object.keys(require_skills.SKILLS));
|
|
31
174
|
function die(message) {
|
|
32
175
|
console.error(message);
|
|
33
176
|
console.error(usageText);
|
|
@@ -39,7 +182,7 @@ if (cli.help) {
|
|
|
39
182
|
process.exit(0);
|
|
40
183
|
}
|
|
41
184
|
if (cli.version) {
|
|
42
|
-
console.log(`${packageName} ${
|
|
185
|
+
console.log(`${packageName} ${require_version.LIB_VERSION}`);
|
|
43
186
|
process.exit(0);
|
|
44
187
|
}
|
|
45
188
|
if (cli.unknownArgs.length > 0) {
|
|
@@ -55,8 +198,8 @@ const cfg = (() => {
|
|
|
55
198
|
die(err instanceof Error ? err.message : String(err));
|
|
56
199
|
}
|
|
57
200
|
})();
|
|
58
|
-
if (cfg.agentProvider)
|
|
59
|
-
|
|
201
|
+
if (cfg.agentProvider) require_server.setAgentProvider(cfg.agentProvider);
|
|
202
|
+
require_server.setProviderBaseUrls({
|
|
60
203
|
openaiBaseUrl: cfg.openaiBaseUrl,
|
|
61
204
|
anthropicBaseUrl: cfg.anthropicBaseUrl
|
|
62
205
|
});
|
|
@@ -93,7 +236,7 @@ function getProviderSource() {
|
|
|
93
236
|
if (process.env.EMBEDDED_AGENT_PROVIDER) return "from EMBEDDED_AGENT_PROVIDER";
|
|
94
237
|
return "auto-detected";
|
|
95
238
|
}
|
|
96
|
-
const resolvedProvider =
|
|
239
|
+
const resolvedProvider = require_server.getResolvedProviderType();
|
|
97
240
|
if (!resolvedProvider) {
|
|
98
241
|
const mismatchInfo = hasProviderMismatch();
|
|
99
242
|
if (hasProviderConflict()) {
|
|
@@ -131,9 +274,9 @@ _sentry_node.init({
|
|
|
131
274
|
dsn: cfg.sentryDsn,
|
|
132
275
|
sendDefaultPii: true,
|
|
133
276
|
tracesSampleRate: 1,
|
|
134
|
-
beforeSend:
|
|
277
|
+
beforeSend: sentryBeforeSend,
|
|
135
278
|
initialScope: { tags: {
|
|
136
|
-
"mcp.server_version":
|
|
279
|
+
"mcp.server_version": require_version.LIB_VERSION,
|
|
137
280
|
"mcp.transport": "stdio",
|
|
138
281
|
"mcp.agent_mode": cli.agent ? "true" : "false",
|
|
139
282
|
"mcp.experimental_mode": cli.experimental ? "true" : "false",
|
|
@@ -193,7 +336,7 @@ const context = {
|
|
|
193
336
|
agentMode: cli.agent,
|
|
194
337
|
experimentalMode: cli.experimental
|
|
195
338
|
};
|
|
196
|
-
require_transports_stdio.startStdio(
|
|
339
|
+
require_transports_stdio.startStdio(require_server.buildServer({
|
|
197
340
|
context,
|
|
198
341
|
agentMode: cli.agent,
|
|
199
342
|
experimentalMode: cli.experimental
|
|
@@ -205,4 +348,10 @@ require_transports_stdio.startStdio((0, _sentry_mcp_core_server.buildServer)({
|
|
|
205
348
|
});
|
|
206
349
|
|
|
207
350
|
//#endregion
|
|
351
|
+
Object.defineProperty(exports, 'require_token_error', {
|
|
352
|
+
enumerable: true,
|
|
353
|
+
get: function () {
|
|
354
|
+
return require_token_error;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
208
357
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["buildUsage","SKILLS","parseArgv","LIB_VERSION","parseEnv","finalize","merge","Sentry","sentryBeforeSend","startStdio"],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Main CLI entry point for the Sentry MCP server.\n *\n * Handles command-line argument parsing, environment configuration, Sentry\n * initialization, and starts the MCP server with stdio transport. Requires\n * a Sentry access token and optionally accepts host and DSN configuration.\n *\n * @example CLI Usage\n * ```bash\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --host=sentry.io\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --url=https://sentry.example.com\n * ```\n */\n\nimport { buildServer } from \"@sentry/mcp-core/server\";\nimport { startStdio } from \"./transports/stdio\";\nimport * as Sentry from \"@sentry/node\";\nimport { LIB_VERSION } from \"@sentry/mcp-core/version\";\nimport { buildUsage } from \"./cli/usage\";\nimport { parseArgv, parseEnv, merge } from \"./cli/parse\";\nimport { finalize } from \"./cli/resolve\";\nimport { sentryBeforeSend } from \"@sentry/mcp-core/telem/sentry\";\nimport { SKILLS } from \"@sentry/mcp-core/skills\";\nimport {\n setAgentProvider,\n setProviderBaseUrls,\n getResolvedProviderType,\n} from \"@sentry/mcp-core/internal/agents/provider-factory\";\n\nconst packageName = \"@tokamohsen/sentry-mcp\";\nconst allSkills = Object.keys(SKILLS) as ReadonlyArray<\n (typeof SKILLS)[keyof typeof SKILLS][\"id\"]\n>;\nconst usageText = buildUsage(packageName, allSkills);\n\nfunction die(message: string): never {\n console.error(message);\n console.error(usageText);\n process.exit(1);\n}\nconst cli = parseArgv(process.argv.slice(2));\nif (cli.help) {\n console.log(usageText);\n process.exit(0);\n}\nif (cli.version) {\n console.log(`${packageName} ${LIB_VERSION}`);\n process.exit(0);\n}\nif (cli.unknownArgs.length > 0) {\n console.error(\"Error: Invalid argument(s):\", cli.unknownArgs.join(\", \"));\n console.error(usageText);\n process.exit(1);\n}\n\nconst env = parseEnv(process.env);\nconst cfg = (() => {\n try {\n return finalize(merge(cli, env));\n } catch (err) {\n die(err instanceof Error ? err.message : String(err));\n }\n})();\n\n// Configure embedded agent provider\nif (cfg.agentProvider) {\n setAgentProvider(cfg.agentProvider);\n}\nsetProviderBaseUrls({\n openaiBaseUrl: cfg.openaiBaseUrl,\n anthropicBaseUrl: cfg.anthropicBaseUrl,\n});\nif (cfg.openaiModel) {\n process.env.OPENAI_MODEL = cfg.openaiModel;\n}\nif (cfg.anthropicModel) {\n process.env.ANTHROPIC_MODEL = cfg.anthropicModel;\n}\n\n// Helper functions for provider status messages\nfunction hasProviderConflict(): boolean {\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n const hasExplicitProvider =\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER;\n return hasAnthropic && hasOpenAI && !hasExplicitProvider;\n}\n\nfunction getConfiguredProvider(): string | undefined {\n return (\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER?.toLowerCase()\n );\n}\n\nfunction hasProviderMismatch(): {\n mismatch: boolean;\n configured?: string;\n availableKey?: string;\n} {\n const configured = getConfiguredProvider();\n if (!configured) return { mismatch: false };\n\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n\n // Check if configured provider's key is missing but other key is present\n if (configured === \"openai\" && !hasOpenAI && hasAnthropic) {\n return {\n mismatch: true,\n configured: \"openai\",\n availableKey: \"ANTHROPIC_API_KEY\",\n };\n }\n if (configured === \"anthropic\" && !hasAnthropic && hasOpenAI) {\n return {\n mismatch: true,\n configured: \"anthropic\",\n availableKey: \"OPENAI_API_KEY\",\n };\n }\n\n return { mismatch: false };\n}\n\nfunction getProviderSource(): string {\n // Check CLI flag first (cli.agentProvider is only set by --agent-provider flag)\n if (cli.agentProvider) return \"explicitly configured\";\n // Then check env var (process.env takes precedence over cfg since cfg merges both)\n if (process.env.EMBEDDED_AGENT_PROVIDER)\n return \"from EMBEDDED_AGENT_PROVIDER\";\n return \"auto-detected\";\n}\n\n// Check for LLM API keys and warn if none available\nconst resolvedProvider = getResolvedProviderType();\n\nif (!resolvedProvider) {\n const mismatchInfo = hasProviderMismatch();\n if (hasProviderConflict()) {\n console.warn(\n \"Warning: Both ANTHROPIC_API_KEY and OPENAI_API_KEY are set, but no provider is explicitly configured.\",\n );\n console.warn(\n \"Please set EMBEDDED_AGENT_PROVIDER='openai' or 'anthropic' to specify which provider to use.\",\n );\n console.warn(\n \"AI-powered search tools will be unavailable until a provider is selected.\",\n );\n } else if (mismatchInfo.mismatch) {\n const expectedKey =\n mismatchInfo.configured === \"openai\"\n ? \"OPENAI_API_KEY\"\n : \"ANTHROPIC_API_KEY\";\n const configuredViaCliFlag = Boolean(cli.agentProvider);\n const providerSetting = configuredViaCliFlag\n ? `--agent-provider=${mismatchInfo.configured}`\n : `EMBEDDED_AGENT_PROVIDER='${mismatchInfo.configured}'`;\n const changeProviderHint = configuredViaCliFlag\n ? \"Change --agent-provider to match your available API key\"\n : \"Change EMBEDDED_AGENT_PROVIDER to match your available API key\";\n console.warn(`Warning: ${providerSetting} but ${expectedKey} is not set.`);\n console.warn(`Found ${mismatchInfo.availableKey} instead. Either:`);\n console.warn(\n ` - Set ${expectedKey} to use the ${mismatchInfo.configured} provider, or`,\n );\n console.warn(` - ${changeProviderHint}`);\n console.warn(\n \"AI-powered search tools will be unavailable until this is resolved.\",\n );\n } else {\n console.warn(\n \"Warning: No LLM API key found (OPENAI_API_KEY or ANTHROPIC_API_KEY).\",\n );\n console.warn(\"The following AI-powered search tools will be unavailable:\");\n console.warn(\n \" - search_events, search_issues, search_issue_events, use_sentry\",\n );\n console.warn(\n \"Use list_issues and list_events for direct Sentry query syntax instead.\",\n );\n }\n console.warn(\"\");\n} else {\n const providerSource = getProviderSource();\n console.warn(\n `Using ${resolvedProvider} for AI-powered search tools (${providerSource}).`,\n );\n // Warn about auto-detection deprecation\n if (providerSource === \"auto-detected\") {\n console.warn(\n \"Deprecation warning: Auto-detection of LLM provider is deprecated.\",\n );\n console.warn(\n `Please set EMBEDDED_AGENT_PROVIDER='${resolvedProvider}' explicitly.`,\n );\n console.warn(\"Auto-detection will be removed in a future release.\");\n }\n console.warn(\"\");\n}\n\nSentry.init({\n dsn: cfg.sentryDsn,\n sendDefaultPii: true,\n tracesSampleRate: 1,\n beforeSend: sentryBeforeSend,\n initialScope: {\n tags: {\n \"mcp.server_version\": LIB_VERSION,\n \"mcp.transport\": \"stdio\",\n \"mcp.agent_mode\": cli.agent ? \"true\" : \"false\",\n \"mcp.experimental_mode\": cli.experimental ? \"true\" : \"false\",\n \"sentry.host\": cfg.sentryHost,\n \"mcp.mcp-url\": cfg.mcpUrl,\n },\n },\n release: process.env.SENTRY_RELEASE,\n integrations: [\n Sentry.consoleLoggingIntegration(),\n Sentry.zodErrorsIntegration(),\n Sentry.vercelAIIntegration({\n recordInputs: true,\n recordOutputs: true,\n }),\n ],\n environment:\n process.env.SENTRY_ENVIRONMENT ??\n (process.env.NODE_ENV !== \"production\" ? \"development\" : \"production\"),\n});\n\n// Log agent mode status\nif (cli.agent) {\n console.warn(\"Agent mode enabled: Only use_sentry tool is available.\");\n console.warn(\n \"The use_sentry tool provides access to all Sentry operations through natural language.\",\n );\n console.warn(\"\");\n}\n\n// Log experimental mode status\nif (cli.experimental) {\n console.warn(\"Experimental mode enabled: Experimental tools are available.\");\n console.warn(\"\");\n}\n\nconst SENTRY_TIMEOUT = 5000; // 5 seconds\n\n// Graceful shutdown handlers\nasync function shutdown(signal: string) {\n console.error(`${signal} received, shutting down...`);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(0);\n}\n\nprocess.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n// Uncaught error handlers\nprocess.on(\"uncaughtException\", async (error) => {\n console.error(\"Uncaught exception:\", error);\n Sentry.captureException(error);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", async (reason) => {\n console.error(\"Unhandled rejection:\", reason);\n Sentry.captureException(reason);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\n// Build context once for server configuration and runtime\nconst context = {\n accessToken: cfg.accessToken,\n grantedSkills: cfg.finalSkills,\n constraints: {\n organizationSlug: cfg.organizationSlug ?? null,\n projectSlug: cfg.projectSlug ?? null,\n },\n sentryHost: cfg.sentryHost,\n mcpUrl: cfg.mcpUrl,\n openaiBaseUrl: cfg.openaiBaseUrl,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n};\n\n// Build server with context to filter tools based on granted skills\n// Use agentMode when --agent flag is set (only exposes use_sentry tool)\n// Use experimentalMode when --experimental flag is set (includes experimental tools)\nconst server = buildServer({\n context,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n});\n\nstartStdio(server, context).catch(async (err) => {\n console.error(\"Server error:\", err);\n Sentry.captureException(err);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAM,cAAc;AAIpB,MAAM,YAAYA,6BAAW,aAHX,OAAO,KAAKC,+BAAO,CAGe;AAEpD,SAAS,IAAI,SAAwB;AACnC,SAAQ,MAAM,QAAQ;AACtB,SAAQ,MAAM,UAAU;AACxB,SAAQ,KAAK,EAAE;;AAEjB,MAAM,MAAMC,4BAAU,QAAQ,KAAK,MAAM,EAAE,CAAC;AAC5C,IAAI,IAAI,MAAM;AACZ,SAAQ,IAAI,UAAU;AACtB,SAAQ,KAAK,EAAE;;AAEjB,IAAI,IAAI,SAAS;AACf,SAAQ,IAAI,GAAG,YAAY,GAAGC,uCAAc;AAC5C,SAAQ,KAAK,EAAE;;AAEjB,IAAI,IAAI,YAAY,SAAS,GAAG;AAC9B,SAAQ,MAAM,+BAA+B,IAAI,YAAY,KAAK,KAAK,CAAC;AACxE,SAAQ,MAAM,UAAU;AACxB,SAAQ,KAAK,EAAE;;AAGjB,MAAM,MAAMC,2BAAS,QAAQ,IAAI;AACjC,MAAM,aAAa;AACjB,KAAI;AACF,SAAOC,6BAASC,wBAAM,KAAK,IAAI,CAAC;UACzB,KAAK;AACZ,MAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;;IAErD;AAGJ,IAAI,IAAI,cACN,yEAAiB,IAAI,cAAc;2EAEjB;CAClB,eAAe,IAAI;CACnB,kBAAkB,IAAI;CACvB,CAAC;AACF,IAAI,IAAI,YACN,SAAQ,IAAI,eAAe,IAAI;AAEjC,IAAI,IAAI,eACN,SAAQ,IAAI,kBAAkB,IAAI;AAIpC,SAAS,sBAA+B;CACtC,MAAM,eAAe,QAAQ,QAAQ,IAAI,kBAAkB;CAC3D,MAAM,YAAY,QAAQ,QAAQ,IAAI,eAAe;CACrD,MAAM,sBACJ,IAAI,iBAAiB,QAAQ,IAAI;AACnC,QAAO,gBAAgB,aAAa,CAAC;;AAGvC,SAAS,wBAA4C;AACnD,QACE,IAAI,iBAAiB,QAAQ,IAAI,yBAAyB,aAAa;;AAI3E,SAAS,sBAIP;CACA,MAAM,aAAa,uBAAuB;AAC1C,KAAI,CAAC,WAAY,QAAO,EAAE,UAAU,OAAO;CAE3C,MAAM,eAAe,QAAQ,QAAQ,IAAI,kBAAkB;CAC3D,MAAM,YAAY,QAAQ,QAAQ,IAAI,eAAe;AAGrD,KAAI,eAAe,YAAY,CAAC,aAAa,aAC3C,QAAO;EACL,UAAU;EACV,YAAY;EACZ,cAAc;EACf;AAEH,KAAI,eAAe,eAAe,CAAC,gBAAgB,UACjD,QAAO;EACL,UAAU;EACV,YAAY;EACZ,cAAc;EACf;AAGH,QAAO,EAAE,UAAU,OAAO;;AAG5B,SAAS,oBAA4B;AAEnC,KAAI,IAAI,cAAe,QAAO;AAE9B,KAAI,QAAQ,IAAI,wBACd,QAAO;AACT,QAAO;;AAIT,MAAM,mGAA4C;AAElD,IAAI,CAAC,kBAAkB;CACrB,MAAM,eAAe,qBAAqB;AAC1C,KAAI,qBAAqB,EAAE;AACzB,UAAQ,KACN,wGACD;AACD,UAAQ,KACN,+FACD;AACD,UAAQ,KACN,4EACD;YACQ,aAAa,UAAU;EAChC,MAAM,cACJ,aAAa,eAAe,WACxB,mBACA;EACN,MAAM,uBAAuB,QAAQ,IAAI,cAAc;EACvD,MAAM,kBAAkB,uBACpB,oBAAoB,aAAa,eACjC,4BAA4B,aAAa,WAAW;EACxD,MAAM,qBAAqB,uBACvB,4DACA;AACJ,UAAQ,KAAK,YAAY,gBAAgB,OAAO,YAAY,cAAc;AAC1E,UAAQ,KAAK,SAAS,aAAa,aAAa,mBAAmB;AACnE,UAAQ,KACN,WAAW,YAAY,cAAc,aAAa,WAAW,eAC9D;AACD,UAAQ,KAAK,OAAO,qBAAqB;AACzC,UAAQ,KACN,sEACD;QACI;AACL,UAAQ,KACN,uEACD;AACD,UAAQ,KAAK,6DAA6D;AAC1E,UAAQ,KACN,oEACD;AACD,UAAQ,KACN,0EACD;;AAEH,SAAQ,KAAK,GAAG;OACX;CACL,MAAM,iBAAiB,mBAAmB;AAC1C,SAAQ,KACN,SAAS,iBAAiB,gCAAgC,eAAe,IAC1E;AAED,KAAI,mBAAmB,iBAAiB;AACtC,UAAQ,KACN,qEACD;AACD,UAAQ,KACN,uCAAuC,iBAAiB,eACzD;AACD,UAAQ,KAAK,sDAAsD;;AAErE,SAAQ,KAAK,GAAG;;AAGlBC,aAAO,KAAK;CACV,KAAK,IAAI;CACT,gBAAgB;CAChB,kBAAkB;CAClB,YAAYC;CACZ,cAAc,EACZ,MAAM;EACJ,sBAAsBL;EACtB,iBAAiB;EACjB,kBAAkB,IAAI,QAAQ,SAAS;EACvC,yBAAyB,IAAI,eAAe,SAAS;EACrD,eAAe,IAAI;EACnB,eAAe,IAAI;EACpB,EACF;CACD,SAAS,QAAQ,IAAI;CACrB,cAAc;EACZI,aAAO,2BAA2B;EAClCA,aAAO,sBAAsB;EAC7BA,aAAO,oBAAoB;GACzB,cAAc;GACd,eAAe;GAChB,CAAC;EACH;CACD,aACE,QAAQ,IAAI,uBACX,QAAQ,IAAI,aAAa,eAAe,gBAAgB;CAC5D,CAAC;AAGF,IAAI,IAAI,OAAO;AACb,SAAQ,KAAK,yDAAyD;AACtE,SAAQ,KACN,yFACD;AACD,SAAQ,KAAK,GAAG;;AAIlB,IAAI,IAAI,cAAc;AACpB,SAAQ,KAAK,+DAA+D;AAC5E,SAAQ,KAAK,GAAG;;AAGlB,MAAM,iBAAiB;AAGvB,eAAe,SAAS,QAAgB;AACtC,SAAQ,MAAM,GAAG,OAAO,6BAA6B;AACrD,OAAMA,aAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;;AAGjB,QAAQ,GAAG,iBAAiB,SAAS,UAAU,CAAC;AAChD,QAAQ,GAAG,gBAAgB,SAAS,SAAS,CAAC;AAG9C,QAAQ,GAAG,qBAAqB,OAAO,UAAU;AAC/C,SAAQ,MAAM,uBAAuB,MAAM;AAC3C,cAAO,iBAAiB,MAAM;AAC9B,OAAMA,aAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;EACf;AAEF,QAAQ,GAAG,sBAAsB,OAAO,WAAW;AACjD,SAAQ,MAAM,wBAAwB,OAAO;AAC7C,cAAO,iBAAiB,OAAO;AAC/B,OAAMA,aAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;EACf;AAGF,MAAM,UAAU;CACd,aAAa,IAAI;CACjB,eAAe,IAAI;CACnB,aAAa;EACX,kBAAkB,IAAI,oBAAoB;EAC1C,aAAa,IAAI,eAAe;EACjC;CACD,YAAY,IAAI;CAChB,QAAQ,IAAI;CACZ,eAAe,IAAI;CACnB,WAAW,IAAI;CACf,kBAAkB,IAAI;CACvB;AAWDE,6EAN2B;CACzB;CACA,WAAW,IAAI;CACf,kBAAkB,IAAI;CACvB,CAAC,EAEiB,QAAQ,CAAC,MAAM,OAAO,QAAQ;AAC/C,SAAQ,MAAM,iBAAiB,IAAI;AACnC,cAAO,iBAAiB,IAAI;AAC5B,OAAMF,aAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;EACf"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["buildUsage","SKILLS","parseArgv","LIB_VERSION","parseEnv","finalize","merge","setProviderBaseUrls","getResolvedProviderType","Sentry","startStdio","buildServer"],"sources":["../../../node_modules/.pnpm/@vercel+oidc@3.1.0/node_modules/@vercel/oidc/dist/token-error.js","../../mcp-core/dist/telem/sentry.js","../src/index.ts"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\nvar token_error_exports = {};\n__export(token_error_exports, {\n VercelOidcTokenError: () => VercelOidcTokenError\n});\nmodule.exports = __toCommonJS(token_error_exports);\nclass VercelOidcTokenError extends Error {\n constructor(message, cause) {\n super(message);\n this.name = \"VercelOidcTokenError\";\n this.cause = cause;\n }\n toString() {\n if (this.cause) {\n return `${this.name}: ${this.message}: ${this.cause}`;\n }\n return `${this.name}: ${this.message}`;\n }\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n VercelOidcTokenError\n});\n","//#region src/telem/sentry.ts\nconst SCRUB_PATTERNS = [\n\t{\n\t\tpattern: /\\bsk-[a-zA-Z0-9]{48}\\b/g,\n\t\treplacement: \"[REDACTED_OPENAI_KEY]\",\n\t\tdescription: \"OpenAI API key\"\n\t},\n\t{\n\t\tpattern: /\\bBearer\\s+[a-zA-Z0-9\\-._~+/]+={0,}/g,\n\t\treplacement: \"Bearer [REDACTED_TOKEN]\",\n\t\tdescription: \"Bearer token\"\n\t},\n\t{\n\t\tpattern: /\\bsntrys_[a-zA-Z0-9_]+\\b/g,\n\t\treplacement: \"[REDACTED_SENTRY_TOKEN]\",\n\t\tdescription: \"Sentry access token\"\n\t}\n];\nconst MAX_SCRUB_DEPTH = 20;\n/**\n* Recursively scrub sensitive data from any value.\n* Returns tuple of [scrubbedValue, didScrub, descriptionsOfMatchedPatterns]\n*/\nfunction scrubValue(value, depth = 0) {\n\tif (depth >= MAX_SCRUB_DEPTH) return [\n\t\t\"[MAX_DEPTH_EXCEEDED]\",\n\t\tfalse,\n\t\t[]\n\t];\n\tif (typeof value === \"string\") {\n\t\tlet scrubbed = value;\n\t\tlet didScrub = false;\n\t\tconst matchedDescriptions = [];\n\t\tfor (const { pattern, replacement, description } of SCRUB_PATTERNS) {\n\t\t\tpattern.lastIndex = 0;\n\t\t\tif (pattern.test(scrubbed)) {\n\t\t\t\tdidScrub = true;\n\t\t\t\tmatchedDescriptions.push(description);\n\t\t\t\tpattern.lastIndex = 0;\n\t\t\t\tscrubbed = scrubbed.replace(pattern, replacement);\n\t\t\t}\n\t\t}\n\t\treturn [\n\t\t\tscrubbed,\n\t\t\tdidScrub,\n\t\t\tmatchedDescriptions\n\t\t];\n\t}\n\tif (Array.isArray(value)) {\n\t\tlet arrayDidScrub = false;\n\t\tconst arrayDescriptions = [];\n\t\treturn [\n\t\t\tvalue.map((item) => {\n\t\t\t\tconst [scrubbed, didScrub, descriptions] = scrubValue(item, depth + 1);\n\t\t\t\tif (didScrub) {\n\t\t\t\t\tarrayDidScrub = true;\n\t\t\t\t\tarrayDescriptions.push(...descriptions);\n\t\t\t\t}\n\t\t\t\treturn scrubbed;\n\t\t\t}),\n\t\t\tarrayDidScrub,\n\t\t\tarrayDescriptions\n\t\t];\n\t}\n\tif (value && typeof value === \"object\") {\n\t\tlet objectDidScrub = false;\n\t\tconst objectDescriptions = [];\n\t\tconst scrubbed = {};\n\t\tfor (const [key, val] of Object.entries(value)) {\n\t\t\tconst [scrubbedVal, didScrub, descriptions] = scrubValue(val, depth + 1);\n\t\t\tif (didScrub) {\n\t\t\t\tobjectDidScrub = true;\n\t\t\t\tobjectDescriptions.push(...descriptions);\n\t\t\t}\n\t\t\tscrubbed[key] = scrubbedVal;\n\t\t}\n\t\treturn [\n\t\t\tscrubbed,\n\t\t\tobjectDidScrub,\n\t\t\tobjectDescriptions\n\t\t];\n\t}\n\treturn [\n\t\tvalue,\n\t\tfalse,\n\t\t[]\n\t];\n}\n/**\n* Sentry beforeSend hook that scrubs sensitive data from events\n* and applies custom fingerprinting for specific error types.\n*/\nfunction sentryBeforeSend(event, hint) {\n\tconst firstException = event?.exception?.values?.[0];\n\tif (firstException?.type === \"AI_APICallError\" && firstException.value) event.fingerprint = [\"AI_APICallError\", firstException.value];\n\tconst [scrubbedEvent, didScrub, descriptions] = scrubValue(event);\n\tif (didScrub) {\n\t\tconst uniqueDescriptions = [...new Set(descriptions)];\n\t\tconsole.warn(`[Sentry] Event contained sensitive data: ${uniqueDescriptions.join(\", \")}`);\n\t}\n\treturn scrubbedEvent;\n}\n\n//#endregion\nexport { sentryBeforeSend };\n//# sourceMappingURL=sentry.js.map","#!/usr/bin/env node\n\n/**\n * Main CLI entry point for the Sentry MCP server.\n *\n * Handles command-line argument parsing, environment configuration, Sentry\n * initialization, and starts the MCP server with stdio transport. Requires\n * a Sentry access token and optionally accepts host and DSN configuration.\n *\n * @example CLI Usage\n * ```bash\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --host=sentry.io\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --url=https://sentry.example.com\n * ```\n */\n\nimport { buildServer } from \"@sentry/mcp-core/server\";\nimport { startStdio } from \"./transports/stdio\";\nimport * as Sentry from \"@sentry/node\";\nimport { LIB_VERSION } from \"@sentry/mcp-core/version\";\nimport { buildUsage } from \"./cli/usage\";\nimport { parseArgv, parseEnv, merge } from \"./cli/parse\";\nimport { finalize } from \"./cli/resolve\";\nimport { sentryBeforeSend } from \"@sentry/mcp-core/telem/sentry\";\nimport { SKILLS } from \"@sentry/mcp-core/skills\";\nimport {\n setAgentProvider,\n setProviderBaseUrls,\n getResolvedProviderType,\n} from \"@sentry/mcp-core/internal/agents/provider-factory\";\n\nconst packageName = \"@tokamohsen/sentry-mcp\";\nconst allSkills = Object.keys(SKILLS) as ReadonlyArray<\n (typeof SKILLS)[keyof typeof SKILLS][\"id\"]\n>;\nconst usageText = buildUsage(packageName, allSkills);\n\nfunction die(message: string): never {\n console.error(message);\n console.error(usageText);\n process.exit(1);\n}\nconst cli = parseArgv(process.argv.slice(2));\nif (cli.help) {\n console.log(usageText);\n process.exit(0);\n}\nif (cli.version) {\n console.log(`${packageName} ${LIB_VERSION}`);\n process.exit(0);\n}\nif (cli.unknownArgs.length > 0) {\n console.error(\"Error: Invalid argument(s):\", cli.unknownArgs.join(\", \"));\n console.error(usageText);\n process.exit(1);\n}\n\nconst env = parseEnv(process.env);\nconst cfg = (() => {\n try {\n return finalize(merge(cli, env));\n } catch (err) {\n die(err instanceof Error ? err.message : String(err));\n }\n})();\n\n// Configure embedded agent provider\nif (cfg.agentProvider) {\n setAgentProvider(cfg.agentProvider);\n}\nsetProviderBaseUrls({\n openaiBaseUrl: cfg.openaiBaseUrl,\n anthropicBaseUrl: cfg.anthropicBaseUrl,\n});\nif (cfg.openaiModel) {\n process.env.OPENAI_MODEL = cfg.openaiModel;\n}\nif (cfg.anthropicModel) {\n process.env.ANTHROPIC_MODEL = cfg.anthropicModel;\n}\n\n// Helper functions for provider status messages\nfunction hasProviderConflict(): boolean {\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n const hasExplicitProvider =\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER;\n return hasAnthropic && hasOpenAI && !hasExplicitProvider;\n}\n\nfunction getConfiguredProvider(): string | undefined {\n return (\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER?.toLowerCase()\n );\n}\n\nfunction hasProviderMismatch(): {\n mismatch: boolean;\n configured?: string;\n availableKey?: string;\n} {\n const configured = getConfiguredProvider();\n if (!configured) return { mismatch: false };\n\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n\n // Check if configured provider's key is missing but other key is present\n if (configured === \"openai\" && !hasOpenAI && hasAnthropic) {\n return {\n mismatch: true,\n configured: \"openai\",\n availableKey: \"ANTHROPIC_API_KEY\",\n };\n }\n if (configured === \"anthropic\" && !hasAnthropic && hasOpenAI) {\n return {\n mismatch: true,\n configured: \"anthropic\",\n availableKey: \"OPENAI_API_KEY\",\n };\n }\n\n return { mismatch: false };\n}\n\nfunction getProviderSource(): string {\n // Check CLI flag first (cli.agentProvider is only set by --agent-provider flag)\n if (cli.agentProvider) return \"explicitly configured\";\n // Then check env var (process.env takes precedence over cfg since cfg merges both)\n if (process.env.EMBEDDED_AGENT_PROVIDER)\n return \"from EMBEDDED_AGENT_PROVIDER\";\n return \"auto-detected\";\n}\n\n// Check for LLM API keys and warn if none available\nconst resolvedProvider = getResolvedProviderType();\n\nif (!resolvedProvider) {\n const mismatchInfo = hasProviderMismatch();\n if (hasProviderConflict()) {\n console.warn(\n \"Warning: Both ANTHROPIC_API_KEY and OPENAI_API_KEY are set, but no provider is explicitly configured.\",\n );\n console.warn(\n \"Please set EMBEDDED_AGENT_PROVIDER='openai' or 'anthropic' to specify which provider to use.\",\n );\n console.warn(\n \"AI-powered search tools will be unavailable until a provider is selected.\",\n );\n } else if (mismatchInfo.mismatch) {\n const expectedKey =\n mismatchInfo.configured === \"openai\"\n ? \"OPENAI_API_KEY\"\n : \"ANTHROPIC_API_KEY\";\n const configuredViaCliFlag = Boolean(cli.agentProvider);\n const providerSetting = configuredViaCliFlag\n ? `--agent-provider=${mismatchInfo.configured}`\n : `EMBEDDED_AGENT_PROVIDER='${mismatchInfo.configured}'`;\n const changeProviderHint = configuredViaCliFlag\n ? \"Change --agent-provider to match your available API key\"\n : \"Change EMBEDDED_AGENT_PROVIDER to match your available API key\";\n console.warn(`Warning: ${providerSetting} but ${expectedKey} is not set.`);\n console.warn(`Found ${mismatchInfo.availableKey} instead. Either:`);\n console.warn(\n ` - Set ${expectedKey} to use the ${mismatchInfo.configured} provider, or`,\n );\n console.warn(` - ${changeProviderHint}`);\n console.warn(\n \"AI-powered search tools will be unavailable until this is resolved.\",\n );\n } else {\n console.warn(\n \"Warning: No LLM API key found (OPENAI_API_KEY or ANTHROPIC_API_KEY).\",\n );\n console.warn(\"The following AI-powered search tools will be unavailable:\");\n console.warn(\n \" - search_events, search_issues, search_issue_events, use_sentry\",\n );\n console.warn(\n \"Use list_issues and list_events for direct Sentry query syntax instead.\",\n );\n }\n console.warn(\"\");\n} else {\n const providerSource = getProviderSource();\n console.warn(\n `Using ${resolvedProvider} for AI-powered search tools (${providerSource}).`,\n );\n // Warn about auto-detection deprecation\n if (providerSource === \"auto-detected\") {\n console.warn(\n \"Deprecation warning: Auto-detection of LLM provider is deprecated.\",\n );\n console.warn(\n `Please set EMBEDDED_AGENT_PROVIDER='${resolvedProvider}' explicitly.`,\n );\n console.warn(\"Auto-detection will be removed in a future release.\");\n }\n console.warn(\"\");\n}\n\nSentry.init({\n dsn: cfg.sentryDsn,\n sendDefaultPii: true,\n tracesSampleRate: 1,\n beforeSend: sentryBeforeSend,\n initialScope: {\n tags: {\n \"mcp.server_version\": LIB_VERSION,\n \"mcp.transport\": \"stdio\",\n \"mcp.agent_mode\": cli.agent ? \"true\" : \"false\",\n \"mcp.experimental_mode\": cli.experimental ? \"true\" : \"false\",\n \"sentry.host\": cfg.sentryHost,\n \"mcp.mcp-url\": cfg.mcpUrl,\n },\n },\n release: process.env.SENTRY_RELEASE,\n integrations: [\n Sentry.consoleLoggingIntegration(),\n Sentry.zodErrorsIntegration(),\n Sentry.vercelAIIntegration({\n recordInputs: true,\n recordOutputs: true,\n }),\n ],\n environment:\n process.env.SENTRY_ENVIRONMENT ??\n (process.env.NODE_ENV !== \"production\" ? \"development\" : \"production\"),\n});\n\n// Log agent mode status\nif (cli.agent) {\n console.warn(\"Agent mode enabled: Only use_sentry tool is available.\");\n console.warn(\n \"The use_sentry tool provides access to all Sentry operations through natural language.\",\n );\n console.warn(\"\");\n}\n\n// Log experimental mode status\nif (cli.experimental) {\n console.warn(\"Experimental mode enabled: Experimental tools are available.\");\n console.warn(\"\");\n}\n\nconst SENTRY_TIMEOUT = 5000; // 5 seconds\n\n// Graceful shutdown handlers\nasync function shutdown(signal: string) {\n console.error(`${signal} received, shutting down...`);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(0);\n}\n\nprocess.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n// Uncaught error handlers\nprocess.on(\"uncaughtException\", async (error) => {\n console.error(\"Uncaught exception:\", error);\n Sentry.captureException(error);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", async (reason) => {\n console.error(\"Unhandled rejection:\", reason);\n Sentry.captureException(reason);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\n// Build context once for server configuration and runtime\nconst context = {\n accessToken: cfg.accessToken,\n grantedSkills: cfg.finalSkills,\n constraints: {\n organizationSlug: cfg.organizationSlug ?? null,\n projectSlug: cfg.projectSlug ?? null,\n },\n sentryHost: cfg.sentryHost,\n mcpUrl: cfg.mcpUrl,\n openaiBaseUrl: cfg.openaiBaseUrl,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n};\n\n// Build server with context to filter tools based on granted skills\n// Use agentMode when --agent flag is set (only exposes use_sentry tool)\n// Use experimentalMode when --experimental flag is set (includes experimental tools)\nconst server = buildServer({\n context,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n});\n\nstartStdio(server, context).catch(async (err) => {\n console.error(\"Server error:\", err);\n Sentry.captureException(err);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n"],"x_google_ignoreList":[0],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,200 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { n as SKILLS } from "./skills-DfqlqYXj.js";
|
|
3
|
+
import "./constants-BrEVt86y.js";
|
|
4
|
+
import { a as setProviderBaseUrls, i as setAgentProvider, r as getResolvedProviderType, t as buildServer } from "./server-DduxvXpe.js";
|
|
5
|
+
import { t as LIB_VERSION } from "./version-4iOZzjiD.js";
|
|
2
6
|
import { startStdio } from "./transports/stdio.js";
|
|
3
7
|
import { buildUsage } from "./cli/usage.js";
|
|
4
8
|
import { merge, parseArgv, parseEnv } from "./cli/parse.js";
|
|
5
9
|
import { finalize } from "./cli/resolve.js";
|
|
6
|
-
import {
|
|
10
|
+
import { createRequire } from "node:module";
|
|
7
11
|
import * as Sentry from "@sentry/node";
|
|
8
|
-
import { LIB_VERSION } from "@sentry/mcp-core/version";
|
|
9
|
-
import { SKILLS } from "@sentry/mcp-core/skills";
|
|
10
|
-
import { sentryBeforeSend } from "@sentry/mcp-core/telem/sentry";
|
|
11
|
-
import { getResolvedProviderType, setAgentProvider, setProviderBaseUrls } from "@sentry/mcp-core/internal/agents/provider-factory";
|
|
12
12
|
|
|
13
|
+
//#region \0rolldown/runtime.js
|
|
14
|
+
var __create = Object.create;
|
|
15
|
+
var __defProp = Object.defineProperty;
|
|
16
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
17
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
18
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
19
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
20
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
21
|
+
var __exportAll = (all, no_symbols) => {
|
|
22
|
+
let target = {};
|
|
23
|
+
for (var name in all) {
|
|
24
|
+
__defProp(target, name, {
|
|
25
|
+
get: all[name],
|
|
26
|
+
enumerable: true
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (!no_symbols) {
|
|
30
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
31
|
+
}
|
|
32
|
+
return target;
|
|
33
|
+
};
|
|
34
|
+
var __copyProps = (to, from, except, desc) => {
|
|
35
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
36
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
37
|
+
key = keys[i];
|
|
38
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
39
|
+
__defProp(to, key, {
|
|
40
|
+
get: ((k) => from[k]).bind(null, key),
|
|
41
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return to;
|
|
47
|
+
};
|
|
48
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
49
|
+
value: mod,
|
|
50
|
+
enumerable: true
|
|
51
|
+
}) : target, mod));
|
|
52
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region ../../node_modules/.pnpm/@vercel+oidc@3.1.0/node_modules/@vercel/oidc/dist/token-error.js
|
|
56
|
+
var require_token_error = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
57
|
+
var __defProp = Object.defineProperty;
|
|
58
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
59
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
60
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
61
|
+
var __export = (target, all) => {
|
|
62
|
+
for (var name in all) __defProp(target, name, {
|
|
63
|
+
get: all[name],
|
|
64
|
+
enumerable: true
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var __copyProps = (to, from, except, desc) => {
|
|
68
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
69
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
70
|
+
get: () => from[key],
|
|
71
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return to;
|
|
75
|
+
};
|
|
76
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
77
|
+
var token_error_exports = {};
|
|
78
|
+
__export(token_error_exports, { VercelOidcTokenError: () => VercelOidcTokenError });
|
|
79
|
+
module.exports = __toCommonJS(token_error_exports);
|
|
80
|
+
var VercelOidcTokenError = class extends Error {
|
|
81
|
+
constructor(message, cause) {
|
|
82
|
+
super(message);
|
|
83
|
+
this.name = "VercelOidcTokenError";
|
|
84
|
+
this.cause = cause;
|
|
85
|
+
}
|
|
86
|
+
toString() {
|
|
87
|
+
if (this.cause) return `${this.name}: ${this.message}: ${this.cause}`;
|
|
88
|
+
return `${this.name}: ${this.message}`;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region ../mcp-core/dist/telem/sentry.js
|
|
95
|
+
const SCRUB_PATTERNS = [
|
|
96
|
+
{
|
|
97
|
+
pattern: /\bsk-[a-zA-Z0-9]{48}\b/g,
|
|
98
|
+
replacement: "[REDACTED_OPENAI_KEY]",
|
|
99
|
+
description: "OpenAI API key"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+={0,}/g,
|
|
103
|
+
replacement: "Bearer [REDACTED_TOKEN]",
|
|
104
|
+
description: "Bearer token"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
pattern: /\bsntrys_[a-zA-Z0-9_]+\b/g,
|
|
108
|
+
replacement: "[REDACTED_SENTRY_TOKEN]",
|
|
109
|
+
description: "Sentry access token"
|
|
110
|
+
}
|
|
111
|
+
];
|
|
112
|
+
const MAX_SCRUB_DEPTH = 20;
|
|
113
|
+
/**
|
|
114
|
+
* Recursively scrub sensitive data from any value.
|
|
115
|
+
* Returns tuple of [scrubbedValue, didScrub, descriptionsOfMatchedPatterns]
|
|
116
|
+
*/
|
|
117
|
+
function scrubValue(value, depth = 0) {
|
|
118
|
+
if (depth >= MAX_SCRUB_DEPTH) return [
|
|
119
|
+
"[MAX_DEPTH_EXCEEDED]",
|
|
120
|
+
false,
|
|
121
|
+
[]
|
|
122
|
+
];
|
|
123
|
+
if (typeof value === "string") {
|
|
124
|
+
let scrubbed = value;
|
|
125
|
+
let didScrub = false;
|
|
126
|
+
const matchedDescriptions = [];
|
|
127
|
+
for (const { pattern, replacement, description } of SCRUB_PATTERNS) {
|
|
128
|
+
pattern.lastIndex = 0;
|
|
129
|
+
if (pattern.test(scrubbed)) {
|
|
130
|
+
didScrub = true;
|
|
131
|
+
matchedDescriptions.push(description);
|
|
132
|
+
pattern.lastIndex = 0;
|
|
133
|
+
scrubbed = scrubbed.replace(pattern, replacement);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return [
|
|
137
|
+
scrubbed,
|
|
138
|
+
didScrub,
|
|
139
|
+
matchedDescriptions
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
if (Array.isArray(value)) {
|
|
143
|
+
let arrayDidScrub = false;
|
|
144
|
+
const arrayDescriptions = [];
|
|
145
|
+
return [
|
|
146
|
+
value.map((item) => {
|
|
147
|
+
const [scrubbed, didScrub, descriptions] = scrubValue(item, depth + 1);
|
|
148
|
+
if (didScrub) {
|
|
149
|
+
arrayDidScrub = true;
|
|
150
|
+
arrayDescriptions.push(...descriptions);
|
|
151
|
+
}
|
|
152
|
+
return scrubbed;
|
|
153
|
+
}),
|
|
154
|
+
arrayDidScrub,
|
|
155
|
+
arrayDescriptions
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
if (value && typeof value === "object") {
|
|
159
|
+
let objectDidScrub = false;
|
|
160
|
+
const objectDescriptions = [];
|
|
161
|
+
const scrubbed = {};
|
|
162
|
+
for (const [key, val] of Object.entries(value)) {
|
|
163
|
+
const [scrubbedVal, didScrub, descriptions] = scrubValue(val, depth + 1);
|
|
164
|
+
if (didScrub) {
|
|
165
|
+
objectDidScrub = true;
|
|
166
|
+
objectDescriptions.push(...descriptions);
|
|
167
|
+
}
|
|
168
|
+
scrubbed[key] = scrubbedVal;
|
|
169
|
+
}
|
|
170
|
+
return [
|
|
171
|
+
scrubbed,
|
|
172
|
+
objectDidScrub,
|
|
173
|
+
objectDescriptions
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
return [
|
|
177
|
+
value,
|
|
178
|
+
false,
|
|
179
|
+
[]
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Sentry beforeSend hook that scrubs sensitive data from events
|
|
184
|
+
* and applies custom fingerprinting for specific error types.
|
|
185
|
+
*/
|
|
186
|
+
function sentryBeforeSend(event, hint) {
|
|
187
|
+
const firstException = event?.exception?.values?.[0];
|
|
188
|
+
if (firstException?.type === "AI_APICallError" && firstException.value) event.fingerprint = ["AI_APICallError", firstException.value];
|
|
189
|
+
const [scrubbedEvent, didScrub, descriptions] = scrubValue(event);
|
|
190
|
+
if (didScrub) {
|
|
191
|
+
const uniqueDescriptions = [...new Set(descriptions)];
|
|
192
|
+
console.warn(`[Sentry] Event contained sensitive data: ${uniqueDescriptions.join(", ")}`);
|
|
193
|
+
}
|
|
194
|
+
return scrubbedEvent;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
//#endregion
|
|
13
198
|
//#region src/index.ts
|
|
14
199
|
/**
|
|
15
200
|
* Main CLI entry point for the Sentry MCP server.
|
|
@@ -203,5 +388,5 @@ startStdio(buildServer({
|
|
|
203
388
|
});
|
|
204
389
|
|
|
205
390
|
//#endregion
|
|
206
|
-
export {
|
|
391
|
+
export { __toESM as a, __require as i, __commonJSMin as n, __exportAll as r, require_token_error as t };
|
|
207
392
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Main CLI entry point for the Sentry MCP server.\n *\n * Handles command-line argument parsing, environment configuration, Sentry\n * initialization, and starts the MCP server with stdio transport. Requires\n * a Sentry access token and optionally accepts host and DSN configuration.\n *\n * @example CLI Usage\n * ```bash\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --host=sentry.io\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --url=https://sentry.example.com\n * ```\n */\n\nimport { buildServer } from \"@sentry/mcp-core/server\";\nimport { startStdio } from \"./transports/stdio\";\nimport * as Sentry from \"@sentry/node\";\nimport { LIB_VERSION } from \"@sentry/mcp-core/version\";\nimport { buildUsage } from \"./cli/usage\";\nimport { parseArgv, parseEnv, merge } from \"./cli/parse\";\nimport { finalize } from \"./cli/resolve\";\nimport { sentryBeforeSend } from \"@sentry/mcp-core/telem/sentry\";\nimport { SKILLS } from \"@sentry/mcp-core/skills\";\nimport {\n setAgentProvider,\n setProviderBaseUrls,\n getResolvedProviderType,\n} from \"@sentry/mcp-core/internal/agents/provider-factory\";\n\nconst packageName = \"@tokamohsen/sentry-mcp\";\nconst allSkills = Object.keys(SKILLS) as ReadonlyArray<\n (typeof SKILLS)[keyof typeof SKILLS][\"id\"]\n>;\nconst usageText = buildUsage(packageName, allSkills);\n\nfunction die(message: string): never {\n console.error(message);\n console.error(usageText);\n process.exit(1);\n}\nconst cli = parseArgv(process.argv.slice(2));\nif (cli.help) {\n console.log(usageText);\n process.exit(0);\n}\nif (cli.version) {\n console.log(`${packageName} ${LIB_VERSION}`);\n process.exit(0);\n}\nif (cli.unknownArgs.length > 0) {\n console.error(\"Error: Invalid argument(s):\", cli.unknownArgs.join(\", \"));\n console.error(usageText);\n process.exit(1);\n}\n\nconst env = parseEnv(process.env);\nconst cfg = (() => {\n try {\n return finalize(merge(cli, env));\n } catch (err) {\n die(err instanceof Error ? err.message : String(err));\n }\n})();\n\n// Configure embedded agent provider\nif (cfg.agentProvider) {\n setAgentProvider(cfg.agentProvider);\n}\nsetProviderBaseUrls({\n openaiBaseUrl: cfg.openaiBaseUrl,\n anthropicBaseUrl: cfg.anthropicBaseUrl,\n});\nif (cfg.openaiModel) {\n process.env.OPENAI_MODEL = cfg.openaiModel;\n}\nif (cfg.anthropicModel) {\n process.env.ANTHROPIC_MODEL = cfg.anthropicModel;\n}\n\n// Helper functions for provider status messages\nfunction hasProviderConflict(): boolean {\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n const hasExplicitProvider =\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER;\n return hasAnthropic && hasOpenAI && !hasExplicitProvider;\n}\n\nfunction getConfiguredProvider(): string | undefined {\n return (\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER?.toLowerCase()\n );\n}\n\nfunction hasProviderMismatch(): {\n mismatch: boolean;\n configured?: string;\n availableKey?: string;\n} {\n const configured = getConfiguredProvider();\n if (!configured) return { mismatch: false };\n\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n\n // Check if configured provider's key is missing but other key is present\n if (configured === \"openai\" && !hasOpenAI && hasAnthropic) {\n return {\n mismatch: true,\n configured: \"openai\",\n availableKey: \"ANTHROPIC_API_KEY\",\n };\n }\n if (configured === \"anthropic\" && !hasAnthropic && hasOpenAI) {\n return {\n mismatch: true,\n configured: \"anthropic\",\n availableKey: \"OPENAI_API_KEY\",\n };\n }\n\n return { mismatch: false };\n}\n\nfunction getProviderSource(): string {\n // Check CLI flag first (cli.agentProvider is only set by --agent-provider flag)\n if (cli.agentProvider) return \"explicitly configured\";\n // Then check env var (process.env takes precedence over cfg since cfg merges both)\n if (process.env.EMBEDDED_AGENT_PROVIDER)\n return \"from EMBEDDED_AGENT_PROVIDER\";\n return \"auto-detected\";\n}\n\n// Check for LLM API keys and warn if none available\nconst resolvedProvider = getResolvedProviderType();\n\nif (!resolvedProvider) {\n const mismatchInfo = hasProviderMismatch();\n if (hasProviderConflict()) {\n console.warn(\n \"Warning: Both ANTHROPIC_API_KEY and OPENAI_API_KEY are set, but no provider is explicitly configured.\",\n );\n console.warn(\n \"Please set EMBEDDED_AGENT_PROVIDER='openai' or 'anthropic' to specify which provider to use.\",\n );\n console.warn(\n \"AI-powered search tools will be unavailable until a provider is selected.\",\n );\n } else if (mismatchInfo.mismatch) {\n const expectedKey =\n mismatchInfo.configured === \"openai\"\n ? \"OPENAI_API_KEY\"\n : \"ANTHROPIC_API_KEY\";\n const configuredViaCliFlag = Boolean(cli.agentProvider);\n const providerSetting = configuredViaCliFlag\n ? `--agent-provider=${mismatchInfo.configured}`\n : `EMBEDDED_AGENT_PROVIDER='${mismatchInfo.configured}'`;\n const changeProviderHint = configuredViaCliFlag\n ? \"Change --agent-provider to match your available API key\"\n : \"Change EMBEDDED_AGENT_PROVIDER to match your available API key\";\n console.warn(`Warning: ${providerSetting} but ${expectedKey} is not set.`);\n console.warn(`Found ${mismatchInfo.availableKey} instead. Either:`);\n console.warn(\n ` - Set ${expectedKey} to use the ${mismatchInfo.configured} provider, or`,\n );\n console.warn(` - ${changeProviderHint}`);\n console.warn(\n \"AI-powered search tools will be unavailable until this is resolved.\",\n );\n } else {\n console.warn(\n \"Warning: No LLM API key found (OPENAI_API_KEY or ANTHROPIC_API_KEY).\",\n );\n console.warn(\"The following AI-powered search tools will be unavailable:\");\n console.warn(\n \" - search_events, search_issues, search_issue_events, use_sentry\",\n );\n console.warn(\n \"Use list_issues and list_events for direct Sentry query syntax instead.\",\n );\n }\n console.warn(\"\");\n} else {\n const providerSource = getProviderSource();\n console.warn(\n `Using ${resolvedProvider} for AI-powered search tools (${providerSource}).`,\n );\n // Warn about auto-detection deprecation\n if (providerSource === \"auto-detected\") {\n console.warn(\n \"Deprecation warning: Auto-detection of LLM provider is deprecated.\",\n );\n console.warn(\n `Please set EMBEDDED_AGENT_PROVIDER='${resolvedProvider}' explicitly.`,\n );\n console.warn(\"Auto-detection will be removed in a future release.\");\n }\n console.warn(\"\");\n}\n\nSentry.init({\n dsn: cfg.sentryDsn,\n sendDefaultPii: true,\n tracesSampleRate: 1,\n beforeSend: sentryBeforeSend,\n initialScope: {\n tags: {\n \"mcp.server_version\": LIB_VERSION,\n \"mcp.transport\": \"stdio\",\n \"mcp.agent_mode\": cli.agent ? \"true\" : \"false\",\n \"mcp.experimental_mode\": cli.experimental ? \"true\" : \"false\",\n \"sentry.host\": cfg.sentryHost,\n \"mcp.mcp-url\": cfg.mcpUrl,\n },\n },\n release: process.env.SENTRY_RELEASE,\n integrations: [\n Sentry.consoleLoggingIntegration(),\n Sentry.zodErrorsIntegration(),\n Sentry.vercelAIIntegration({\n recordInputs: true,\n recordOutputs: true,\n }),\n ],\n environment:\n process.env.SENTRY_ENVIRONMENT ??\n (process.env.NODE_ENV !== \"production\" ? \"development\" : \"production\"),\n});\n\n// Log agent mode status\nif (cli.agent) {\n console.warn(\"Agent mode enabled: Only use_sentry tool is available.\");\n console.warn(\n \"The use_sentry tool provides access to all Sentry operations through natural language.\",\n );\n console.warn(\"\");\n}\n\n// Log experimental mode status\nif (cli.experimental) {\n console.warn(\"Experimental mode enabled: Experimental tools are available.\");\n console.warn(\"\");\n}\n\nconst SENTRY_TIMEOUT = 5000; // 5 seconds\n\n// Graceful shutdown handlers\nasync function shutdown(signal: string) {\n console.error(`${signal} received, shutting down...`);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(0);\n}\n\nprocess.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n// Uncaught error handlers\nprocess.on(\"uncaughtException\", async (error) => {\n console.error(\"Uncaught exception:\", error);\n Sentry.captureException(error);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", async (reason) => {\n console.error(\"Unhandled rejection:\", reason);\n Sentry.captureException(reason);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\n// Build context once for server configuration and runtime\nconst context = {\n accessToken: cfg.accessToken,\n grantedSkills: cfg.finalSkills,\n constraints: {\n organizationSlug: cfg.organizationSlug ?? null,\n projectSlug: cfg.projectSlug ?? null,\n },\n sentryHost: cfg.sentryHost,\n mcpUrl: cfg.mcpUrl,\n openaiBaseUrl: cfg.openaiBaseUrl,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n};\n\n// Build server with context to filter tools based on granted skills\n// Use agentMode when --agent flag is set (only exposes use_sentry tool)\n// Use experimentalMode when --experimental flag is set (includes experimental tools)\nconst server = buildServer({\n context,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n});\n\nstartStdio(server, context).catch(async (err) => {\n console.error(\"Server error:\", err);\n Sentry.captureException(err);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../node_modules/.pnpm/@vercel+oidc@3.1.0/node_modules/@vercel/oidc/dist/token-error.js","../../mcp-core/dist/telem/sentry.js","../src/index.ts"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\nvar token_error_exports = {};\n__export(token_error_exports, {\n VercelOidcTokenError: () => VercelOidcTokenError\n});\nmodule.exports = __toCommonJS(token_error_exports);\nclass VercelOidcTokenError extends Error {\n constructor(message, cause) {\n super(message);\n this.name = \"VercelOidcTokenError\";\n this.cause = cause;\n }\n toString() {\n if (this.cause) {\n return `${this.name}: ${this.message}: ${this.cause}`;\n }\n return `${this.name}: ${this.message}`;\n }\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n VercelOidcTokenError\n});\n","//#region src/telem/sentry.ts\nconst SCRUB_PATTERNS = [\n\t{\n\t\tpattern: /\\bsk-[a-zA-Z0-9]{48}\\b/g,\n\t\treplacement: \"[REDACTED_OPENAI_KEY]\",\n\t\tdescription: \"OpenAI API key\"\n\t},\n\t{\n\t\tpattern: /\\bBearer\\s+[a-zA-Z0-9\\-._~+/]+={0,}/g,\n\t\treplacement: \"Bearer [REDACTED_TOKEN]\",\n\t\tdescription: \"Bearer token\"\n\t},\n\t{\n\t\tpattern: /\\bsntrys_[a-zA-Z0-9_]+\\b/g,\n\t\treplacement: \"[REDACTED_SENTRY_TOKEN]\",\n\t\tdescription: \"Sentry access token\"\n\t}\n];\nconst MAX_SCRUB_DEPTH = 20;\n/**\n* Recursively scrub sensitive data from any value.\n* Returns tuple of [scrubbedValue, didScrub, descriptionsOfMatchedPatterns]\n*/\nfunction scrubValue(value, depth = 0) {\n\tif (depth >= MAX_SCRUB_DEPTH) return [\n\t\t\"[MAX_DEPTH_EXCEEDED]\",\n\t\tfalse,\n\t\t[]\n\t];\n\tif (typeof value === \"string\") {\n\t\tlet scrubbed = value;\n\t\tlet didScrub = false;\n\t\tconst matchedDescriptions = [];\n\t\tfor (const { pattern, replacement, description } of SCRUB_PATTERNS) {\n\t\t\tpattern.lastIndex = 0;\n\t\t\tif (pattern.test(scrubbed)) {\n\t\t\t\tdidScrub = true;\n\t\t\t\tmatchedDescriptions.push(description);\n\t\t\t\tpattern.lastIndex = 0;\n\t\t\t\tscrubbed = scrubbed.replace(pattern, replacement);\n\t\t\t}\n\t\t}\n\t\treturn [\n\t\t\tscrubbed,\n\t\t\tdidScrub,\n\t\t\tmatchedDescriptions\n\t\t];\n\t}\n\tif (Array.isArray(value)) {\n\t\tlet arrayDidScrub = false;\n\t\tconst arrayDescriptions = [];\n\t\treturn [\n\t\t\tvalue.map((item) => {\n\t\t\t\tconst [scrubbed, didScrub, descriptions] = scrubValue(item, depth + 1);\n\t\t\t\tif (didScrub) {\n\t\t\t\t\tarrayDidScrub = true;\n\t\t\t\t\tarrayDescriptions.push(...descriptions);\n\t\t\t\t}\n\t\t\t\treturn scrubbed;\n\t\t\t}),\n\t\t\tarrayDidScrub,\n\t\t\tarrayDescriptions\n\t\t];\n\t}\n\tif (value && typeof value === \"object\") {\n\t\tlet objectDidScrub = false;\n\t\tconst objectDescriptions = [];\n\t\tconst scrubbed = {};\n\t\tfor (const [key, val] of Object.entries(value)) {\n\t\t\tconst [scrubbedVal, didScrub, descriptions] = scrubValue(val, depth + 1);\n\t\t\tif (didScrub) {\n\t\t\t\tobjectDidScrub = true;\n\t\t\t\tobjectDescriptions.push(...descriptions);\n\t\t\t}\n\t\t\tscrubbed[key] = scrubbedVal;\n\t\t}\n\t\treturn [\n\t\t\tscrubbed,\n\t\t\tobjectDidScrub,\n\t\t\tobjectDescriptions\n\t\t];\n\t}\n\treturn [\n\t\tvalue,\n\t\tfalse,\n\t\t[]\n\t];\n}\n/**\n* Sentry beforeSend hook that scrubs sensitive data from events\n* and applies custom fingerprinting for specific error types.\n*/\nfunction sentryBeforeSend(event, hint) {\n\tconst firstException = event?.exception?.values?.[0];\n\tif (firstException?.type === \"AI_APICallError\" && firstException.value) event.fingerprint = [\"AI_APICallError\", firstException.value];\n\tconst [scrubbedEvent, didScrub, descriptions] = scrubValue(event);\n\tif (didScrub) {\n\t\tconst uniqueDescriptions = [...new Set(descriptions)];\n\t\tconsole.warn(`[Sentry] Event contained sensitive data: ${uniqueDescriptions.join(\", \")}`);\n\t}\n\treturn scrubbedEvent;\n}\n\n//#endregion\nexport { sentryBeforeSend };\n//# sourceMappingURL=sentry.js.map","#!/usr/bin/env node\n\n/**\n * Main CLI entry point for the Sentry MCP server.\n *\n * Handles command-line argument parsing, environment configuration, Sentry\n * initialization, and starts the MCP server with stdio transport. Requires\n * a Sentry access token and optionally accepts host and DSN configuration.\n *\n * @example CLI Usage\n * ```bash\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --host=sentry.io\n * npx @tokamohsen/sentry-mcp --access-token=TOKEN --url=https://sentry.example.com\n * ```\n */\n\nimport { buildServer } from \"@sentry/mcp-core/server\";\nimport { startStdio } from \"./transports/stdio\";\nimport * as Sentry from \"@sentry/node\";\nimport { LIB_VERSION } from \"@sentry/mcp-core/version\";\nimport { buildUsage } from \"./cli/usage\";\nimport { parseArgv, parseEnv, merge } from \"./cli/parse\";\nimport { finalize } from \"./cli/resolve\";\nimport { sentryBeforeSend } from \"@sentry/mcp-core/telem/sentry\";\nimport { SKILLS } from \"@sentry/mcp-core/skills\";\nimport {\n setAgentProvider,\n setProviderBaseUrls,\n getResolvedProviderType,\n} from \"@sentry/mcp-core/internal/agents/provider-factory\";\n\nconst packageName = \"@tokamohsen/sentry-mcp\";\nconst allSkills = Object.keys(SKILLS) as ReadonlyArray<\n (typeof SKILLS)[keyof typeof SKILLS][\"id\"]\n>;\nconst usageText = buildUsage(packageName, allSkills);\n\nfunction die(message: string): never {\n console.error(message);\n console.error(usageText);\n process.exit(1);\n}\nconst cli = parseArgv(process.argv.slice(2));\nif (cli.help) {\n console.log(usageText);\n process.exit(0);\n}\nif (cli.version) {\n console.log(`${packageName} ${LIB_VERSION}`);\n process.exit(0);\n}\nif (cli.unknownArgs.length > 0) {\n console.error(\"Error: Invalid argument(s):\", cli.unknownArgs.join(\", \"));\n console.error(usageText);\n process.exit(1);\n}\n\nconst env = parseEnv(process.env);\nconst cfg = (() => {\n try {\n return finalize(merge(cli, env));\n } catch (err) {\n die(err instanceof Error ? err.message : String(err));\n }\n})();\n\n// Configure embedded agent provider\nif (cfg.agentProvider) {\n setAgentProvider(cfg.agentProvider);\n}\nsetProviderBaseUrls({\n openaiBaseUrl: cfg.openaiBaseUrl,\n anthropicBaseUrl: cfg.anthropicBaseUrl,\n});\nif (cfg.openaiModel) {\n process.env.OPENAI_MODEL = cfg.openaiModel;\n}\nif (cfg.anthropicModel) {\n process.env.ANTHROPIC_MODEL = cfg.anthropicModel;\n}\n\n// Helper functions for provider status messages\nfunction hasProviderConflict(): boolean {\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n const hasExplicitProvider =\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER;\n return hasAnthropic && hasOpenAI && !hasExplicitProvider;\n}\n\nfunction getConfiguredProvider(): string | undefined {\n return (\n cfg.agentProvider || process.env.EMBEDDED_AGENT_PROVIDER?.toLowerCase()\n );\n}\n\nfunction hasProviderMismatch(): {\n mismatch: boolean;\n configured?: string;\n availableKey?: string;\n} {\n const configured = getConfiguredProvider();\n if (!configured) return { mismatch: false };\n\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);\n\n // Check if configured provider's key is missing but other key is present\n if (configured === \"openai\" && !hasOpenAI && hasAnthropic) {\n return {\n mismatch: true,\n configured: \"openai\",\n availableKey: \"ANTHROPIC_API_KEY\",\n };\n }\n if (configured === \"anthropic\" && !hasAnthropic && hasOpenAI) {\n return {\n mismatch: true,\n configured: \"anthropic\",\n availableKey: \"OPENAI_API_KEY\",\n };\n }\n\n return { mismatch: false };\n}\n\nfunction getProviderSource(): string {\n // Check CLI flag first (cli.agentProvider is only set by --agent-provider flag)\n if (cli.agentProvider) return \"explicitly configured\";\n // Then check env var (process.env takes precedence over cfg since cfg merges both)\n if (process.env.EMBEDDED_AGENT_PROVIDER)\n return \"from EMBEDDED_AGENT_PROVIDER\";\n return \"auto-detected\";\n}\n\n// Check for LLM API keys and warn if none available\nconst resolvedProvider = getResolvedProviderType();\n\nif (!resolvedProvider) {\n const mismatchInfo = hasProviderMismatch();\n if (hasProviderConflict()) {\n console.warn(\n \"Warning: Both ANTHROPIC_API_KEY and OPENAI_API_KEY are set, but no provider is explicitly configured.\",\n );\n console.warn(\n \"Please set EMBEDDED_AGENT_PROVIDER='openai' or 'anthropic' to specify which provider to use.\",\n );\n console.warn(\n \"AI-powered search tools will be unavailable until a provider is selected.\",\n );\n } else if (mismatchInfo.mismatch) {\n const expectedKey =\n mismatchInfo.configured === \"openai\"\n ? \"OPENAI_API_KEY\"\n : \"ANTHROPIC_API_KEY\";\n const configuredViaCliFlag = Boolean(cli.agentProvider);\n const providerSetting = configuredViaCliFlag\n ? `--agent-provider=${mismatchInfo.configured}`\n : `EMBEDDED_AGENT_PROVIDER='${mismatchInfo.configured}'`;\n const changeProviderHint = configuredViaCliFlag\n ? \"Change --agent-provider to match your available API key\"\n : \"Change EMBEDDED_AGENT_PROVIDER to match your available API key\";\n console.warn(`Warning: ${providerSetting} but ${expectedKey} is not set.`);\n console.warn(`Found ${mismatchInfo.availableKey} instead. Either:`);\n console.warn(\n ` - Set ${expectedKey} to use the ${mismatchInfo.configured} provider, or`,\n );\n console.warn(` - ${changeProviderHint}`);\n console.warn(\n \"AI-powered search tools will be unavailable until this is resolved.\",\n );\n } else {\n console.warn(\n \"Warning: No LLM API key found (OPENAI_API_KEY or ANTHROPIC_API_KEY).\",\n );\n console.warn(\"The following AI-powered search tools will be unavailable:\");\n console.warn(\n \" - search_events, search_issues, search_issue_events, use_sentry\",\n );\n console.warn(\n \"Use list_issues and list_events for direct Sentry query syntax instead.\",\n );\n }\n console.warn(\"\");\n} else {\n const providerSource = getProviderSource();\n console.warn(\n `Using ${resolvedProvider} for AI-powered search tools (${providerSource}).`,\n );\n // Warn about auto-detection deprecation\n if (providerSource === \"auto-detected\") {\n console.warn(\n \"Deprecation warning: Auto-detection of LLM provider is deprecated.\",\n );\n console.warn(\n `Please set EMBEDDED_AGENT_PROVIDER='${resolvedProvider}' explicitly.`,\n );\n console.warn(\"Auto-detection will be removed in a future release.\");\n }\n console.warn(\"\");\n}\n\nSentry.init({\n dsn: cfg.sentryDsn,\n sendDefaultPii: true,\n tracesSampleRate: 1,\n beforeSend: sentryBeforeSend,\n initialScope: {\n tags: {\n \"mcp.server_version\": LIB_VERSION,\n \"mcp.transport\": \"stdio\",\n \"mcp.agent_mode\": cli.agent ? \"true\" : \"false\",\n \"mcp.experimental_mode\": cli.experimental ? \"true\" : \"false\",\n \"sentry.host\": cfg.sentryHost,\n \"mcp.mcp-url\": cfg.mcpUrl,\n },\n },\n release: process.env.SENTRY_RELEASE,\n integrations: [\n Sentry.consoleLoggingIntegration(),\n Sentry.zodErrorsIntegration(),\n Sentry.vercelAIIntegration({\n recordInputs: true,\n recordOutputs: true,\n }),\n ],\n environment:\n process.env.SENTRY_ENVIRONMENT ??\n (process.env.NODE_ENV !== \"production\" ? \"development\" : \"production\"),\n});\n\n// Log agent mode status\nif (cli.agent) {\n console.warn(\"Agent mode enabled: Only use_sentry tool is available.\");\n console.warn(\n \"The use_sentry tool provides access to all Sentry operations through natural language.\",\n );\n console.warn(\"\");\n}\n\n// Log experimental mode status\nif (cli.experimental) {\n console.warn(\"Experimental mode enabled: Experimental tools are available.\");\n console.warn(\"\");\n}\n\nconst SENTRY_TIMEOUT = 5000; // 5 seconds\n\n// Graceful shutdown handlers\nasync function shutdown(signal: string) {\n console.error(`${signal} received, shutting down...`);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(0);\n}\n\nprocess.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n// Uncaught error handlers\nprocess.on(\"uncaughtException\", async (error) => {\n console.error(\"Uncaught exception:\", error);\n Sentry.captureException(error);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", async (reason) => {\n console.error(\"Unhandled rejection:\", reason);\n Sentry.captureException(reason);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n\n// Build context once for server configuration and runtime\nconst context = {\n accessToken: cfg.accessToken,\n grantedSkills: cfg.finalSkills,\n constraints: {\n organizationSlug: cfg.organizationSlug ?? null,\n projectSlug: cfg.projectSlug ?? null,\n },\n sentryHost: cfg.sentryHost,\n mcpUrl: cfg.mcpUrl,\n openaiBaseUrl: cfg.openaiBaseUrl,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n};\n\n// Build server with context to filter tools based on granted skills\n// Use agentMode when --agent flag is set (only exposes use_sentry tool)\n// Use experimentalMode when --experimental flag is set (includes experimental tools)\nconst server = buildServer({\n context,\n agentMode: cli.agent,\n experimentalMode: cli.experimental,\n});\n\nstartStdio(server, context).catch(async (err) => {\n console.error(\"Server error:\", err);\n Sentry.captureException(err);\n await Sentry.flush(SENTRY_TIMEOUT);\n process.exit(1);\n});\n"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACA,IAAI,YAAY,OAAO;CACvB,IAAI,mBAAmB,OAAO;CAC9B,IAAI,oBAAoB,OAAO;CAC/B,IAAI,eAAe,OAAO,UAAU;CACpC,IAAI,YAAY,QAAQ,QAAQ;AAC9B,OAAK,IAAI,QAAQ,IACf,WAAU,QAAQ,MAAM;GAAE,KAAK,IAAI;GAAO,YAAY;GAAM,CAAC;;CAEjE,IAAI,eAAe,IAAI,MAAM,QAAQ,SAAS;AAC5C,MAAI,QAAQ,OAAO,SAAS,YAAY,OAAO,SAAS,YACtD;QAAK,IAAI,OAAO,kBAAkB,KAAK,CACrC,KAAI,CAAC,aAAa,KAAK,IAAI,IAAI,IAAI,QAAQ,OACzC,WAAU,IAAI,KAAK;IAAE,WAAW,KAAK;IAAM,YAAY,EAAE,OAAO,iBAAiB,MAAM,IAAI,KAAK,KAAK;IAAY,CAAC;;AAExH,SAAO;;CAET,IAAI,gBAAgB,QAAQ,YAAY,UAAU,EAAE,EAAE,cAAc,EAAE,OAAO,MAAM,CAAC,EAAE,IAAI;CAC1F,IAAI,sBAAsB,EAAE;AAC5B,UAAS,qBAAqB,EAC5B,4BAA4B,sBAC7B,CAAC;AACF,QAAO,UAAU,aAAa,oBAAoB;CAClD,IAAM,uBAAN,cAAmC,MAAM;EACvC,YAAY,SAAS,OAAO;AAC1B,SAAM,QAAQ;AACd,QAAK,OAAO;AACZ,QAAK,QAAQ;;EAEf,WAAW;AACT,OAAI,KAAK,MACP,QAAO,GAAG,KAAK,KAAK,IAAI,KAAK,QAAQ,IAAI,KAAK;AAEhD,UAAO,GAAG,KAAK,KAAK,IAAI,KAAK;;;;;;;AChCjC,MAAM,iBAAiB;CACtB;EACC,SAAS;EACT,aAAa;EACb,aAAa;EACb;CACD;EACC,SAAS;EACT,aAAa;EACb,aAAa;EACb;CACD;EACC,SAAS;EACT,aAAa;EACb,aAAa;EACb;CACD;AACD,MAAM,kBAAkB;;;;;AAKxB,SAAS,WAAW,OAAO,QAAQ,GAAG;AACrC,KAAI,SAAS,gBAAiB,QAAO;EACpC;EACA;EACA,EAAE;EACF;AACD,KAAI,OAAO,UAAU,UAAU;EAC9B,IAAI,WAAW;EACf,IAAI,WAAW;EACf,MAAM,sBAAsB,EAAE;AAC9B,OAAK,MAAM,EAAE,SAAS,aAAa,iBAAiB,gBAAgB;AACnE,WAAQ,YAAY;AACpB,OAAI,QAAQ,KAAK,SAAS,EAAE;AAC3B,eAAW;AACX,wBAAoB,KAAK,YAAY;AACrC,YAAQ,YAAY;AACpB,eAAW,SAAS,QAAQ,SAAS,YAAY;;;AAGnD,SAAO;GACN;GACA;GACA;GACA;;AAEF,KAAI,MAAM,QAAQ,MAAM,EAAE;EACzB,IAAI,gBAAgB;EACpB,MAAM,oBAAoB,EAAE;AAC5B,SAAO;GACN,MAAM,KAAK,SAAS;IACnB,MAAM,CAAC,UAAU,UAAU,gBAAgB,WAAW,MAAM,QAAQ,EAAE;AACtE,QAAI,UAAU;AACb,qBAAgB;AAChB,uBAAkB,KAAK,GAAG,aAAa;;AAExC,WAAO;KACN;GACF;GACA;GACA;;AAEF,KAAI,SAAS,OAAO,UAAU,UAAU;EACvC,IAAI,iBAAiB;EACrB,MAAM,qBAAqB,EAAE;EAC7B,MAAM,WAAW,EAAE;AACnB,OAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,MAAM,EAAE;GAC/C,MAAM,CAAC,aAAa,UAAU,gBAAgB,WAAW,KAAK,QAAQ,EAAE;AACxE,OAAI,UAAU;AACb,qBAAiB;AACjB,uBAAmB,KAAK,GAAG,aAAa;;AAEzC,YAAS,OAAO;;AAEjB,SAAO;GACN;GACA;GACA;GACA;;AAEF,QAAO;EACN;EACA;EACA,EAAE;EACF;;;;;;AAMF,SAAS,iBAAiB,OAAO,MAAM;CACtC,MAAM,iBAAiB,OAAO,WAAW,SAAS;AAClD,KAAI,gBAAgB,SAAS,qBAAqB,eAAe,MAAO,OAAM,cAAc,CAAC,mBAAmB,eAAe,MAAM;CACrI,MAAM,CAAC,eAAe,UAAU,gBAAgB,WAAW,MAAM;AACjE,KAAI,UAAU;EACb,MAAM,qBAAqB,CAAC,GAAG,IAAI,IAAI,aAAa,CAAC;AACrD,UAAQ,KAAK,4CAA4C,mBAAmB,KAAK,KAAK,GAAG;;AAE1F,QAAO;;;;;;;;;;;;;;;;;;ACrER,MAAM,cAAc;AAIpB,MAAM,YAAY,WAAW,aAHX,OAAO,KAAK,OAAO,CAGe;AAEpD,SAAS,IAAI,SAAwB;AACnC,SAAQ,MAAM,QAAQ;AACtB,SAAQ,MAAM,UAAU;AACxB,SAAQ,KAAK,EAAE;;AAEjB,MAAM,MAAM,UAAU,QAAQ,KAAK,MAAM,EAAE,CAAC;AAC5C,IAAI,IAAI,MAAM;AACZ,SAAQ,IAAI,UAAU;AACtB,SAAQ,KAAK,EAAE;;AAEjB,IAAI,IAAI,SAAS;AACf,SAAQ,IAAI,GAAG,YAAY,GAAG,cAAc;AAC5C,SAAQ,KAAK,EAAE;;AAEjB,IAAI,IAAI,YAAY,SAAS,GAAG;AAC9B,SAAQ,MAAM,+BAA+B,IAAI,YAAY,KAAK,KAAK,CAAC;AACxE,SAAQ,MAAM,UAAU;AACxB,SAAQ,KAAK,EAAE;;AAGjB,MAAM,MAAM,SAAS,QAAQ,IAAI;AACjC,MAAM,aAAa;AACjB,KAAI;AACF,SAAO,SAAS,MAAM,KAAK,IAAI,CAAC;UACzB,KAAK;AACZ,MAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;;IAErD;AAGJ,IAAI,IAAI,cACN,kBAAiB,IAAI,cAAc;AAErC,oBAAoB;CAClB,eAAe,IAAI;CACnB,kBAAkB,IAAI;CACvB,CAAC;AACF,IAAI,IAAI,YACN,SAAQ,IAAI,eAAe,IAAI;AAEjC,IAAI,IAAI,eACN,SAAQ,IAAI,kBAAkB,IAAI;AAIpC,SAAS,sBAA+B;CACtC,MAAM,eAAe,QAAQ,QAAQ,IAAI,kBAAkB;CAC3D,MAAM,YAAY,QAAQ,QAAQ,IAAI,eAAe;CACrD,MAAM,sBACJ,IAAI,iBAAiB,QAAQ,IAAI;AACnC,QAAO,gBAAgB,aAAa,CAAC;;AAGvC,SAAS,wBAA4C;AACnD,QACE,IAAI,iBAAiB,QAAQ,IAAI,yBAAyB,aAAa;;AAI3E,SAAS,sBAIP;CACA,MAAM,aAAa,uBAAuB;AAC1C,KAAI,CAAC,WAAY,QAAO,EAAE,UAAU,OAAO;CAE3C,MAAM,eAAe,QAAQ,QAAQ,IAAI,kBAAkB;CAC3D,MAAM,YAAY,QAAQ,QAAQ,IAAI,eAAe;AAGrD,KAAI,eAAe,YAAY,CAAC,aAAa,aAC3C,QAAO;EACL,UAAU;EACV,YAAY;EACZ,cAAc;EACf;AAEH,KAAI,eAAe,eAAe,CAAC,gBAAgB,UACjD,QAAO;EACL,UAAU;EACV,YAAY;EACZ,cAAc;EACf;AAGH,QAAO,EAAE,UAAU,OAAO;;AAG5B,SAAS,oBAA4B;AAEnC,KAAI,IAAI,cAAe,QAAO;AAE9B,KAAI,QAAQ,IAAI,wBACd,QAAO;AACT,QAAO;;AAIT,MAAM,mBAAmB,yBAAyB;AAElD,IAAI,CAAC,kBAAkB;CACrB,MAAM,eAAe,qBAAqB;AAC1C,KAAI,qBAAqB,EAAE;AACzB,UAAQ,KACN,wGACD;AACD,UAAQ,KACN,+FACD;AACD,UAAQ,KACN,4EACD;YACQ,aAAa,UAAU;EAChC,MAAM,cACJ,aAAa,eAAe,WACxB,mBACA;EACN,MAAM,uBAAuB,QAAQ,IAAI,cAAc;EACvD,MAAM,kBAAkB,uBACpB,oBAAoB,aAAa,eACjC,4BAA4B,aAAa,WAAW;EACxD,MAAM,qBAAqB,uBACvB,4DACA;AACJ,UAAQ,KAAK,YAAY,gBAAgB,OAAO,YAAY,cAAc;AAC1E,UAAQ,KAAK,SAAS,aAAa,aAAa,mBAAmB;AACnE,UAAQ,KACN,WAAW,YAAY,cAAc,aAAa,WAAW,eAC9D;AACD,UAAQ,KAAK,OAAO,qBAAqB;AACzC,UAAQ,KACN,sEACD;QACI;AACL,UAAQ,KACN,uEACD;AACD,UAAQ,KAAK,6DAA6D;AAC1E,UAAQ,KACN,oEACD;AACD,UAAQ,KACN,0EACD;;AAEH,SAAQ,KAAK,GAAG;OACX;CACL,MAAM,iBAAiB,mBAAmB;AAC1C,SAAQ,KACN,SAAS,iBAAiB,gCAAgC,eAAe,IAC1E;AAED,KAAI,mBAAmB,iBAAiB;AACtC,UAAQ,KACN,qEACD;AACD,UAAQ,KACN,uCAAuC,iBAAiB,eACzD;AACD,UAAQ,KAAK,sDAAsD;;AAErE,SAAQ,KAAK,GAAG;;AAGlB,OAAO,KAAK;CACV,KAAK,IAAI;CACT,gBAAgB;CAChB,kBAAkB;CAClB,YAAY;CACZ,cAAc,EACZ,MAAM;EACJ,sBAAsB;EACtB,iBAAiB;EACjB,kBAAkB,IAAI,QAAQ,SAAS;EACvC,yBAAyB,IAAI,eAAe,SAAS;EACrD,eAAe,IAAI;EACnB,eAAe,IAAI;EACpB,EACF;CACD,SAAS,QAAQ,IAAI;CACrB,cAAc;EACZ,OAAO,2BAA2B;EAClC,OAAO,sBAAsB;EAC7B,OAAO,oBAAoB;GACzB,cAAc;GACd,eAAe;GAChB,CAAC;EACH;CACD,aACE,QAAQ,IAAI,uBACX,QAAQ,IAAI,aAAa,eAAe,gBAAgB;CAC5D,CAAC;AAGF,IAAI,IAAI,OAAO;AACb,SAAQ,KAAK,yDAAyD;AACtE,SAAQ,KACN,yFACD;AACD,SAAQ,KAAK,GAAG;;AAIlB,IAAI,IAAI,cAAc;AACpB,SAAQ,KAAK,+DAA+D;AAC5E,SAAQ,KAAK,GAAG;;AAGlB,MAAM,iBAAiB;AAGvB,eAAe,SAAS,QAAgB;AACtC,SAAQ,MAAM,GAAG,OAAO,6BAA6B;AACrD,OAAM,OAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;;AAGjB,QAAQ,GAAG,iBAAiB,SAAS,UAAU,CAAC;AAChD,QAAQ,GAAG,gBAAgB,SAAS,SAAS,CAAC;AAG9C,QAAQ,GAAG,qBAAqB,OAAO,UAAU;AAC/C,SAAQ,MAAM,uBAAuB,MAAM;AAC3C,QAAO,iBAAiB,MAAM;AAC9B,OAAM,OAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;EACf;AAEF,QAAQ,GAAG,sBAAsB,OAAO,WAAW;AACjD,SAAQ,MAAM,wBAAwB,OAAO;AAC7C,QAAO,iBAAiB,OAAO;AAC/B,OAAM,OAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;EACf;AAGF,MAAM,UAAU;CACd,aAAa,IAAI;CACjB,eAAe,IAAI;CACnB,aAAa;EACX,kBAAkB,IAAI,oBAAoB;EAC1C,aAAa,IAAI,eAAe;EACjC;CACD,YAAY,IAAI;CAChB,QAAQ,IAAI;CACZ,eAAe,IAAI;CACnB,WAAW,IAAI;CACf,kBAAkB,IAAI;CACvB;AAWD,WANe,YAAY;CACzB;CACA,WAAW,IAAI;CACf,kBAAkB,IAAI;CACvB,CAAC,EAEiB,QAAQ,CAAC,MAAM,OAAO,QAAQ;AAC/C,SAAQ,MAAM,iBAAiB,IAAI;AACnC,QAAO,iBAAiB,IAAI;AAC5B,OAAM,OAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,EAAE;EACf"}
|