Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ Launch the transport:
npx @sentry/mcp-server@latest --access-token=sentry-user-token
```

If you've already authenticated with the [Sentry CLI](https://cli.sentry.dev/),
you can omit the token and the stdio server will reuse the token from
`~/.sentry/cli.db`:

```shell
sentry auth
npx @sentry/mcp-server@latest
```

Need to connect to a self-hosted deployment? Add <code>--host</code> (hostname
only, e.g. <code>--host=sentry.example.com</code>) when you run the command.

Expand All @@ -65,7 +74,7 @@ npx @sentry/mcp-server@latest --access-token=TOKEN --host=sentry.example.com --d
#### Environment Variables

```shell
SENTRY_ACCESS_TOKEN= # Required: Your Sentry auth token
SENTRY_ACCESS_TOKEN= # Optional: explicit auth token override

# LLM Provider Configuration (required for AI-powered search tools)
EMBEDDED_AGENT_PROVIDER= # Required: 'openai' or 'anthropic'
Expand Down Expand Up @@ -213,7 +222,7 @@ pnpm -w run cli --agent "who am I?"
# Test against production
pnpm -w run cli --mcp-host=https://mcp.sentry.dev "query"

# Test with local stdio mode (requires SENTRY_ACCESS_TOKEN)
# Test with local stdio mode (explicit token or Sentry CLI auth)
pnpm -w run cli --access-token=TOKEN "query"
```

Expand Down
12 changes: 9 additions & 3 deletions docs/releases/stdio.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,14 @@ Add to `.cursor/mcp.json`:

## Environment Variables

Required:
- `SENTRY_ACCESS_TOKEN` - Sentry API access token
Authentication:
- `SENTRY_ACCESS_TOKEN` - Explicit Sentry API access token

If the user has already authenticated with the
[Sentry CLI](https://cli.sentry.dev/commands/auth/), the stdio server can reuse
the token stored in `~/.sentry/cli.db` without requiring `SENTRY_ACCESS_TOKEN`.

Host:
- `SENTRY_HOST` - Sentry instance hostname (default: `sentry.io`)

Optional:
Expand Down Expand Up @@ -162,7 +168,7 @@ npm pack
npm install -g ./sentry-mcp-server-1.2.3.tgz

# Run stdio server
SENTRY_ACCESS_TOKEN=... @sentry/mcp-server
@sentry/mcp-server
```

### Beta Releases
Expand Down
30 changes: 25 additions & 5 deletions docs/testing-stdio.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ cd packages/mcp-server
pnpm start --access-token=YOUR_TOKEN
```

If you've already authenticated with the
[Sentry CLI](https://cli.sentry.dev/commands/auth/), you can omit
`--access-token` and the stdio server will reuse the token stored in
`~/.sentry/cli.db`.

This uses `tsx` to run TypeScript directly without building.

### Option 2: Using the Built Package (Production-like)
Expand All @@ -103,6 +108,9 @@ node packages/mcp-server/dist/index.js --access-token=YOUR_TOKEN

# Or use the workspace command
pnpm -w run mcp-server --access-token=YOUR_TOKEN

# Or reuse stored Sentry CLI auth
node packages/mcp-server/dist/index.js
```

### Option 3: Using npx (End-user Experience)
Expand All @@ -117,6 +125,9 @@ npx @sentry/mcp-server@latest --access-token=YOUR_TOKEN
cd packages/mcp-server
pnpm pack
npx ./sentry-mcp-server-*.tgz --access-token=YOUR_TOKEN

# Or reuse stored Sentry CLI auth
npx @sentry/mcp-server@latest
```

## Testing with MCP Inspector
Expand Down Expand Up @@ -206,7 +217,8 @@ The `mcp-test-client` package provides a CLI-based way to test the stdio transpo

The CLI client automatically selects the transport based on flags:

- **Stdio transport**: `--access-token` flag provided
- **Stdio transport**: explicit token provided or
[Sentry CLI](https://cli.sentry.dev/commands/auth/)-managed auth state available
- **Remote HTTP transport**: `--mcp-host` flag or no access token

### Basic Usage
Expand Down Expand Up @@ -374,7 +386,7 @@ Add to `.vscode/settings.json`:

```bash
# Basic usage
--access-token=TOKEN # Sentry access token (required)
--access-token=TOKEN # Optional explicit Sentry access token

# Host configuration
--host=sentry.example.com # Self-hosted Sentry (hostname only)
Expand Down Expand Up @@ -497,18 +509,26 @@ pnpm build
node dist/index.js --access-token=TOKEN
```

### "Missing required parameter: access-token"
### "No access token was provided"

**Cause:** No authentication provided.

Reuse stored auth by running
[Sentry CLI auth](https://cli.sentry.dev/commands/auth/) first:

**Solution:**
```bash
# Option 1: CLI flag
# Option 1: Reuse stored Sentry CLI auth
sentry auth
pnpm start

# Option 2: CLI flag
pnpm start --access-token=YOUR_TOKEN

# Option 2: Environment variable
# Option 3: Environment variable
export SENTRY_ACCESS_TOKEN=YOUR_TOKEN
pnpm start

```

### "AI-powered search tools unavailable"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export default function StdioSetup() {
Create a User Auth Token in your account settings with the following
scopes:
</p>
<p>
If you've already authenticated with the{" "}
<Link href="https://cli.sentry.dev/commands/auth/">Sentry CLI</Link>,
you can skip the explicit token and the stdio server will reuse the
token stored in <code>~/.sentry/cli.db</code>.
</p>
<p>
<strong>AI-powered search:</strong> If you want the
<code>search_events</code> and <code>search_issues</code> tools to
Expand Down Expand Up @@ -89,7 +95,11 @@ export default function StdioSetup() {
<dt className="font-medium text-slate-100">
<code>--access-token</code> / <code>SENTRY_ACCESS_TOKEN</code>
</dt>
<dd className="text-slate-300">Required user auth token.</dd>
<dd className="text-slate-300">
Explicit user auth token override. If omitted, the stdio server
falls back to Sentry CLI auth from <code>~/.sentry/cli.db</code>
when available.
</dd>

<dt className="font-medium text-slate-100">
<code>--host</code> / <code>SENTRY_HOST</code>
Expand Down
5 changes: 5 additions & 0 deletions packages/mcp-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@
"types": "./dist/internal/agents/types.ts",
"default": "./dist/internal/agents/types.js"
},
"./internal/sentry-cli-auth": {
"types": "./dist/internal/sentry-cli-auth.ts",
"default": "./dist/internal/sentry-cli-auth.js"
},
"./utils/url-utils": {
"types": "./dist/utils/url-utils.ts",
"default": "./dist/utils/url-utils.js"
Expand Down Expand Up @@ -157,6 +161,7 @@
"@logtape/sentry": "^1.1.1",
"@modelcontextprotocol/sdk": "catalog:",
"@sentry/core": "catalog:",
"better-sqlite3": "catalog:",
"ai": "catalog:",
"dotenv": "catalog:",
"zod": "catalog:"
Expand Down
64 changes: 64 additions & 0 deletions packages/mcp-core/src/internal/sentry-cli-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Database from "better-sqlite3";
import { homedir } from "node:os";
import { join } from "node:path";

const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000;

export type SentryCliAccessTokenSource = "sentry_cli_db";

type AuthRow = {
token: string | null;
expires_at: number | null;
};

export function normalizeAccessToken(
token?: string | null,
): string | undefined {
const trimmed = token?.trim();
return trimmed ? trimmed : undefined;
}

export function getSentryCliDbPath(homeDir = homedir()): string {
return join(homeDir, ".sentry", "cli.db");
}

export function readAccessTokenFromSentryCliDb({
nowMs,
homeDir,
}: {
nowMs: number;
homeDir?: string;
}): string | undefined {
const cliDbPath = getSentryCliDbPath(homeDir);

try {
const db = new Database(cliDbPath, {
readonly: true,
fileMustExist: true,
});

try {
const row = db
.prepare("SELECT token, expires_at FROM auth WHERE id = 1")
.get() as AuthRow | undefined;
const token = normalizeAccessToken(row?.token);

if (!token) {
return undefined;
}

if (
typeof row?.expires_at === "number" &&
nowMs + TOKEN_EXPIRY_BUFFER_MS >= row.expires_at
) {
return undefined;
}

return token;
} finally {
db.close();
}
} catch {
return undefined;
}
}
1 change: 1 addition & 0 deletions packages/mcp-core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"outDir": "dist",
"rootDir": "src"
},
"files": ["../mcp-server-tsconfig/better-sqlite3.d.ts"],
"include": ["src"]
}
1 change: 1 addition & 0 deletions packages/mcp-core/tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default defineConfig({
external: [
// Keep workspace dependencies external (don't bundle them)
"@sentry/mcp-server-mocks",
"better-sqlite3",
],
env: {
DEFAULT_SENTRY_DSN:
Expand Down
20 changes: 20 additions & 0 deletions packages/mcp-server-tsconfig/better-sqlite3.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
declare module "better-sqlite3" {
export type DatabaseOptions = {
readonly?: boolean;
fileMustExist?: boolean;
};

export type Statement<Result = Record<string, unknown>> = {
get(...params: unknown[]): Result | undefined;
run(...params: unknown[]): unknown;
};

export default class Database {
constructor(filename: string, options?: DatabaseOptions);
prepare<Result = Record<string, unknown>>(
source: string,
): Statement<Result>;
exec(source: string): this;
close(): this;
}
}
5 changes: 1 addition & 4 deletions packages/mcp-server-tsconfig/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@
"name": "@sentry/mcp-server-tsconfig",
"version": "0.29.0",
"private": true,
"files": [
"tsconfig.base.json",
"tsconfig.vite.json"
]
"files": ["better-sqlite3.d.ts", "tsconfig.base.json", "tsconfig.vite.json"]
}
11 changes: 3 additions & 8 deletions packages/mcp-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@
"license": "FSL-1.1-ALv2",
"author": "Sentry",
"homepage": "https://github.com/getsentry/sentry-mcp",
"keywords": [
"sentry",
"mcp",
"model-context-protocol"
],
"keywords": ["sentry", "mcp", "model-context-protocol"],
"bugs": {
"url": "https://github.com/getsentry/sentry-mcp/issues"
},
Expand All @@ -28,9 +24,7 @@
"bin": {
"sentry-mcp": "./dist/index.js"
},
"files": [
"./dist/*"
],
"files": ["./dist/*"],
"exports": {
".": {
"types": "./dist/index.ts",
Expand All @@ -53,6 +47,7 @@
"@modelcontextprotocol/sdk": "catalog:",
"@sentry/node": "catalog:",
"@sentry/core": "catalog:",
"better-sqlite3": "catalog:",
"dotenv": "catalog:",
"zod": "catalog:"
},
Expand Down
Loading
Loading