This is page 1 of 20. Use http://codebase.md/getsentry/sentry-mcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .claude
│ ├── agents
│ │ └── claude-optimizer.md
│ ├── commands
│ │ ├── gh-pr.md
│ │ └── gh-review.md
│ └── settings.json
├── .craft.yml
├── .cursor
│ └── mcp.json
├── .env.example
├── .github
│ └── workflows
│ ├── deploy.yml
│ ├── eval.yml
│ ├── merge-jobs.yml
│ ├── release.yml
│ ├── smoke-tests.yml
│ ├── test.yml
│ └── token-cost.yml
├── .gitignore
├── .mcp.json
├── .vscode
│ ├── extensions.json
│ ├── mcp.json
│ └── settings.json
├── AGENTS.md
├── benchmark-agent.sh
├── bin
│ └── bump-version.sh
├── biome.json
├── CLAUDE.md
├── codecov.yml
├── core
├── docs
│ ├── adding-tools.md
│ ├── api-patterns.md
│ ├── architecture.md
│ ├── cloudflare
│ │ ├── architecture.md
│ │ ├── oauth-architecture.md
│ │ └── overview.md
│ ├── coding-guidelines.md
│ ├── common-patterns.md
│ ├── error-handling.md
│ ├── github-actions.md
│ ├── llms
│ │ ├── document-scopes.md
│ │ ├── documentation-style-guide.md
│ │ └── README.md
│ ├── logging.md
│ ├── monitoring.md
│ ├── pr-management.md
│ ├── quality-checks.md
│ ├── README.md
│ ├── releases
│ │ ├── cloudflare.md
│ │ └── stdio.md
│ ├── search-events-api-patterns.md
│ ├── security.md
│ ├── specs
│ │ ├── README.md
│ │ ├── search-events.md
│ │ └── subpath-constraints.md
│ ├── testing-remote.md
│ ├── testing-stdio.md
│ ├── testing.md
│ └── token-cost-tracking.md
├── LICENSE.md
├── Makefile
├── package.json
├── packages
│ ├── mcp-cloudflare
│ │ ├── .env.example
│ │ ├── components.json
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── public
│ │ │ ├── demo.cast
│ │ │ ├── favicon.ico
│ │ │ ├── flow-transparent.png
│ │ │ ├── flow.jpg
│ │ │ ├── keycap-⌘.png
│ │ │ ├── keycap-c.png
│ │ │ └── keycap-v.png
│ │ ├── src
│ │ │ ├── client
│ │ │ │ ├── app.tsx
│ │ │ │ ├── components
│ │ │ │ │ ├── animation
│ │ │ │ │ │ ├── browser-ui
│ │ │ │ │ │ │ ├── BrowserWindow.tsx
│ │ │ │ │ │ │ ├── BrowserWindowIconSidebar.tsx
│ │ │ │ │ │ │ ├── DiffBlock.tsx
│ │ │ │ │ │ │ ├── IDEWindow.tsx
│ │ │ │ │ │ │ ├── IssueDetails.tsx
│ │ │ │ │ │ │ ├── keys-copy.tsx
│ │ │ │ │ │ │ ├── LoadingSquares.tsx
│ │ │ │ │ │ │ ├── RootCause.tsx
│ │ │ │ │ │ │ ├── seer-clipmask.tsx
│ │ │ │ │ │ │ ├── seer-noisefilter.tsx
│ │ │ │ │ │ │ ├── seer.tsx
│ │ │ │ │ │ │ └── WindowHeader.tsx
│ │ │ │ │ │ ├── BrowserAnimation.tsx
│ │ │ │ │ │ ├── DataWire.tsx
│ │ │ │ │ │ ├── dracula.css
│ │ │ │ │ │ ├── terminal-ui
│ │ │ │ │ │ │ ├── keys-paste.tsx
│ │ │ │ │ │ │ ├── SpeedDisplay.tsx
│ │ │ │ │ │ │ └── StepsList.tsx
│ │ │ │ │ │ ├── TerminalAnimation.tsx
│ │ │ │ │ │ └── tests.tsx
│ │ │ │ │ ├── chat
│ │ │ │ │ │ ├── auth-form.tsx
│ │ │ │ │ │ ├── chat-input.tsx
│ │ │ │ │ │ ├── chat-message.tsx
│ │ │ │ │ │ ├── chat-messages.tsx
│ │ │ │ │ │ ├── chat-ui.tsx
│ │ │ │ │ │ ├── chat.tsx
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── tool-invocation.tsx
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ ├── docs
│ │ │ │ │ │ └── toc.tsx
│ │ │ │ │ ├── fragments
│ │ │ │ │ │ ├── install-tabs.tsx
│ │ │ │ │ │ ├── remote-setup.tsx
│ │ │ │ │ │ ├── setup-guide.tsx
│ │ │ │ │ │ └── stdio-setup.tsx
│ │ │ │ │ ├── getting-started.tsx
│ │ │ │ │ ├── hero
│ │ │ │ │ │ ├── header-divider.tsx
│ │ │ │ │ │ └── hero-block.tsx
│ │ │ │ │ ├── home-layout
│ │ │ │ │ │ ├── footer.tsx
│ │ │ │ │ │ └── sidebars.tsx
│ │ │ │ │ ├── ui
│ │ │ │ │ │ ├── accordion.tsx
│ │ │ │ │ │ ├── backdrop.tsx
│ │ │ │ │ │ ├── badge.tsx
│ │ │ │ │ │ ├── base.tsx
│ │ │ │ │ │ ├── button.tsx
│ │ │ │ │ │ ├── code-snippet.tsx
│ │ │ │ │ │ ├── header.tsx
│ │ │ │ │ │ ├── icon.tsx
│ │ │ │ │ │ ├── icons
│ │ │ │ │ │ │ ├── gemini.tsx
│ │ │ │ │ │ │ └── sentry.tsx
│ │ │ │ │ │ ├── interactive-markdown.tsx
│ │ │ │ │ │ ├── json-schema-params.tsx
│ │ │ │ │ │ ├── markdown.tsx
│ │ │ │ │ │ ├── note.tsx
│ │ │ │ │ │ ├── prose.tsx
│ │ │ │ │ │ ├── section.tsx
│ │ │ │ │ │ ├── slash-command-actions.tsx
│ │ │ │ │ │ ├── slash-command-text.tsx
│ │ │ │ │ │ ├── sliding-panel.tsx
│ │ │ │ │ │ ├── template-vars.tsx
│ │ │ │ │ │ ├── tool-actions.tsx
│ │ │ │ │ │ └── typewriter.tsx
│ │ │ │ │ └── usecases
│ │ │ │ │ ├── fix-bugs.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ ├── instrument.tsx
│ │ │ │ │ ├── search-things.tsx
│ │ │ │ │ └── search-visual.tsx
│ │ │ │ ├── contexts
│ │ │ │ │ └── auth-context.tsx
│ │ │ │ ├── hooks
│ │ │ │ │ ├── use-endpoint-mode.ts
│ │ │ │ │ ├── use-mcp-metadata.ts
│ │ │ │ │ ├── use-persisted-chat.ts
│ │ │ │ │ ├── use-scroll-lock.ts
│ │ │ │ │ └── use-streaming-simulation.ts
│ │ │ │ ├── index.css
│ │ │ │ ├── instrument.ts
│ │ │ │ ├── lib
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── main.tsx
│ │ │ │ ├── utils
│ │ │ │ │ ├── chat-error-handler.ts
│ │ │ │ │ ├── cursor-deeplink.ts
│ │ │ │ │ └── index.ts
│ │ │ │ └── vite-env.d.ts
│ │ │ ├── constants.ts
│ │ │ ├── server
│ │ │ │ ├── app.test.ts
│ │ │ │ ├── app.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── lib
│ │ │ │ │ ├── approval-dialog.test.ts
│ │ │ │ │ ├── approval-dialog.ts
│ │ │ │ │ ├── constraint-utils.test.ts
│ │ │ │ │ ├── constraint-utils.ts
│ │ │ │ │ ├── html-utils.ts
│ │ │ │ │ ├── mcp-handler.test.ts
│ │ │ │ │ ├── mcp-handler.ts
│ │ │ │ │ └── slug-validation.ts
│ │ │ │ ├── logging.ts
│ │ │ │ ├── oauth
│ │ │ │ │ ├── authorize.test.ts
│ │ │ │ │ ├── callback.test.ts
│ │ │ │ │ ├── constants.ts
│ │ │ │ │ ├── helpers.test.ts
│ │ │ │ │ ├── helpers.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── routes
│ │ │ │ │ │ ├── authorize.ts
│ │ │ │ │ │ ├── callback.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── state.ts
│ │ │ │ ├── routes
│ │ │ │ │ ├── chat-oauth.ts
│ │ │ │ │ ├── chat.ts
│ │ │ │ │ ├── mcp.ts
│ │ │ │ │ ├── metadata.ts
│ │ │ │ │ ├── search.test.ts
│ │ │ │ │ └── search.ts
│ │ │ │ ├── sentry.config.ts
│ │ │ │ ├── types
│ │ │ │ │ └── chat.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utils
│ │ │ │ ├── auth-errors.ts
│ │ │ │ ├── client-ip.test.ts
│ │ │ │ ├── client-ip.ts
│ │ │ │ ├── rate-limiter.test.ts
│ │ │ │ └── rate-limiter.ts
│ │ │ └── test-setup.ts
│ │ ├── tsconfig.client.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ ├── tsconfig.server.json
│ │ ├── vite.config.ts
│ │ ├── vitest.config.ts
│ │ ├── worker-configuration.d.ts
│ │ ├── wrangler.canary.jsonc
│ │ └── wrangler.jsonc
│ ├── mcp-core
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── scripts
│ │ │ ├── generate-definitions.ts
│ │ │ ├── generate-otel-namespaces.ts
│ │ │ ├── measure-token-cost.ts
│ │ │ └── validate-skills-mapping.ts
│ │ ├── src
│ │ │ ├── api-client
│ │ │ │ ├── client.test.ts
│ │ │ │ ├── client.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── schema.test.ts
│ │ │ │ ├── schema.ts
│ │ │ │ └── types.ts
│ │ │ ├── constants.ts
│ │ │ ├── errors.test.ts
│ │ │ ├── errors.ts
│ │ │ ├── internal
│ │ │ │ ├── agents
│ │ │ │ │ ├── callEmbeddedAgent.ts
│ │ │ │ │ ├── openai-provider.test.ts
│ │ │ │ │ ├── openai-provider.ts
│ │ │ │ │ └── tools
│ │ │ │ │ ├── data
│ │ │ │ │ │ ├── __namespaces.json
│ │ │ │ │ │ ├── android.json
│ │ │ │ │ │ ├── app.json
│ │ │ │ │ │ ├── artifact.json
│ │ │ │ │ │ ├── aspnetcore.json
│ │ │ │ │ │ ├── aws.json
│ │ │ │ │ │ ├── azure.json
│ │ │ │ │ │ ├── browser.json
│ │ │ │ │ │ ├── cassandra.json
│ │ │ │ │ │ ├── cicd.json
│ │ │ │ │ │ ├── CLAUDE.md
│ │ │ │ │ │ ├── client.json
│ │ │ │ │ │ ├── cloud.json
│ │ │ │ │ │ ├── cloudevents.json
│ │ │ │ │ │ ├── cloudfoundry.json
│ │ │ │ │ │ ├── code.json
│ │ │ │ │ │ ├── container.json
│ │ │ │ │ │ ├── cpu.json
│ │ │ │ │ │ ├── cpython.json
│ │ │ │ │ │ ├── database.json
│ │ │ │ │ │ ├── db.json
│ │ │ │ │ │ ├── deployment.json
│ │ │ │ │ │ ├── destination.json
│ │ │ │ │ │ ├── device.json
│ │ │ │ │ │ ├── disk.json
│ │ │ │ │ │ ├── dns.json
│ │ │ │ │ │ ├── dotnet.json
│ │ │ │ │ │ ├── elasticsearch.json
│ │ │ │ │ │ ├── enduser.json
│ │ │ │ │ │ ├── error.json
│ │ │ │ │ │ ├── faas.json
│ │ │ │ │ │ ├── feature_flags.json
│ │ │ │ │ │ ├── file.json
│ │ │ │ │ │ ├── gcp.json
│ │ │ │ │ │ ├── gen_ai.json
│ │ │ │ │ │ ├── geo.json
│ │ │ │ │ │ ├── go.json
│ │ │ │ │ │ ├── graphql.json
│ │ │ │ │ │ ├── hardware.json
│ │ │ │ │ │ ├── heroku.json
│ │ │ │ │ │ ├── host.json
│ │ │ │ │ │ ├── http.json
│ │ │ │ │ │ ├── ios.json
│ │ │ │ │ │ ├── jvm.json
│ │ │ │ │ │ ├── k8s.json
│ │ │ │ │ │ ├── linux.json
│ │ │ │ │ │ ├── log.json
│ │ │ │ │ │ ├── mcp.json
│ │ │ │ │ │ ├── messaging.json
│ │ │ │ │ │ ├── network.json
│ │ │ │ │ │ ├── nodejs.json
│ │ │ │ │ │ ├── oci.json
│ │ │ │ │ │ ├── opentracing.json
│ │ │ │ │ │ ├── os.json
│ │ │ │ │ │ ├── otel.json
│ │ │ │ │ │ ├── peer.json
│ │ │ │ │ │ ├── process.json
│ │ │ │ │ │ ├── profile.json
│ │ │ │ │ │ ├── rpc.json
│ │ │ │ │ │ ├── server.json
│ │ │ │ │ │ ├── service.json
│ │ │ │ │ │ ├── session.json
│ │ │ │ │ │ ├── signalr.json
│ │ │ │ │ │ ├── source.json
│ │ │ │ │ │ ├── system.json
│ │ │ │ │ │ ├── telemetry.json
│ │ │ │ │ │ ├── test.json
│ │ │ │ │ │ ├── thread.json
│ │ │ │ │ │ ├── tls.json
│ │ │ │ │ │ ├── url.json
│ │ │ │ │ │ ├── user.json
│ │ │ │ │ │ ├── v8js.json
│ │ │ │ │ │ ├── vcs.json
│ │ │ │ │ │ ├── webengine.json
│ │ │ │ │ │ └── zos.json
│ │ │ │ │ ├── dataset-fields.test.ts
│ │ │ │ │ ├── dataset-fields.ts
│ │ │ │ │ ├── otel-semantics.test.ts
│ │ │ │ │ ├── otel-semantics.ts
│ │ │ │ │ ├── utils.ts
│ │ │ │ │ ├── whoami.test.ts
│ │ │ │ │ └── whoami.ts
│ │ │ │ ├── constraint-helpers.test.ts
│ │ │ │ ├── constraint-helpers.ts
│ │ │ │ ├── error-handling.ts
│ │ │ │ ├── fetch-utils.test.ts
│ │ │ │ ├── fetch-utils.ts
│ │ │ │ ├── formatting.test.ts
│ │ │ │ ├── formatting.ts
│ │ │ │ ├── issue-helpers.test.ts
│ │ │ │ ├── issue-helpers.ts
│ │ │ │ ├── test-fixtures.ts
│ │ │ │ └── tool-helpers
│ │ │ │ ├── api.test.ts
│ │ │ │ ├── api.ts
│ │ │ │ ├── define.ts
│ │ │ │ ├── enhance-error.ts
│ │ │ │ ├── formatting.ts
│ │ │ │ ├── issue.ts
│ │ │ │ ├── seer.test.ts
│ │ │ │ ├── seer.ts
│ │ │ │ ├── validate-region-url.test.ts
│ │ │ │ └── validate-region-url.ts
│ │ │ ├── permissions.parseScopes.test.ts
│ │ │ ├── permissions.ts
│ │ │ ├── schema.ts
│ │ │ ├── server.ts
│ │ │ ├── skillDefinitions.json
│ │ │ ├── skillDefinitions.ts
│ │ │ ├── skills.test.ts
│ │ │ ├── skills.ts
│ │ │ ├── telem
│ │ │ │ ├── index.ts
│ │ │ │ ├── logging.ts
│ │ │ │ ├── sentry.test.ts
│ │ │ │ └── sentry.ts
│ │ │ ├── test-setup.ts
│ │ │ ├── test-utils
│ │ │ │ └── context.ts
│ │ │ ├── toolDefinitions.json
│ │ │ ├── toolDefinitions.ts
│ │ │ ├── tools
│ │ │ │ ├── analyze-issue-with-seer.test.ts
│ │ │ │ ├── analyze-issue-with-seer.ts
│ │ │ │ ├── create-dsn.test.ts
│ │ │ │ ├── create-dsn.ts
│ │ │ │ ├── create-project.test.ts
│ │ │ │ ├── create-project.ts
│ │ │ │ ├── create-team.test.ts
│ │ │ │ ├── create-team.ts
│ │ │ │ ├── find-dsns.test.ts
│ │ │ │ ├── find-dsns.ts
│ │ │ │ ├── find-organizations.test.ts
│ │ │ │ ├── find-organizations.ts
│ │ │ │ ├── find-projects.test.ts
│ │ │ │ ├── find-projects.ts
│ │ │ │ ├── find-releases.test.ts
│ │ │ │ ├── find-releases.ts
│ │ │ │ ├── find-teams.test.ts
│ │ │ │ ├── find-teams.ts
│ │ │ │ ├── get-doc.test.ts
│ │ │ │ ├── get-doc.ts
│ │ │ │ ├── get-event-attachment.test.ts
│ │ │ │ ├── get-event-attachment.ts
│ │ │ │ ├── get-issue-details.test.ts
│ │ │ │ ├── get-issue-details.ts
│ │ │ │ ├── get-trace-details.test.ts
│ │ │ │ ├── get-trace-details.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── search-docs.test.ts
│ │ │ │ ├── search-docs.ts
│ │ │ │ ├── search-events
│ │ │ │ │ ├── agent.ts
│ │ │ │ │ ├── CLAUDE.md
│ │ │ │ │ ├── config.ts
│ │ │ │ │ ├── formatters.ts
│ │ │ │ │ ├── handler.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── utils.test.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── search-events.test.ts
│ │ │ │ ├── search-issues
│ │ │ │ │ ├── agent.ts
│ │ │ │ │ ├── CLAUDE.md
│ │ │ │ │ ├── config.ts
│ │ │ │ │ ├── formatters.ts
│ │ │ │ │ ├── handler.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── README.md
│ │ │ │ ├── tools.test.ts
│ │ │ │ ├── types.ts
│ │ │ │ ├── update-issue.test.ts
│ │ │ │ ├── update-issue.ts
│ │ │ │ ├── update-project.test.ts
│ │ │ │ ├── update-project.ts
│ │ │ │ ├── use-sentry
│ │ │ │ │ ├── agent.ts
│ │ │ │ │ ├── CLAUDE.md
│ │ │ │ │ ├── config.ts
│ │ │ │ │ ├── handler.test.ts
│ │ │ │ │ ├── handler.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── tool-wrapper.test.ts
│ │ │ │ │ └── tool-wrapper.ts
│ │ │ │ ├── whoami.test.ts
│ │ │ │ └── whoami.ts
│ │ │ ├── types.ts
│ │ │ ├── utils
│ │ │ │ ├── slug-validation.test.ts
│ │ │ │ ├── slug-validation.ts
│ │ │ │ ├── url-utils.test.ts
│ │ │ │ └── url-utils.ts
│ │ │ └── version.ts
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.ts
│ │ └── vitest.config.ts
│ ├── mcp-server
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── cli
│ │ │ │ ├── parse.test.ts
│ │ │ │ ├── parse.ts
│ │ │ │ ├── resolve.test.ts
│ │ │ │ ├── resolve.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── usage.ts
│ │ │ ├── index.ts
│ │ │ └── transports
│ │ │ └── stdio.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── mcp-server-evals
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── bin
│ │ │ │ └── start-mock-stdio.ts
│ │ │ ├── evals
│ │ │ │ ├── autofix.eval.ts
│ │ │ │ ├── create-dsn.eval.ts
│ │ │ │ ├── create-project.eval.ts
│ │ │ │ ├── create-team.eval.ts
│ │ │ │ ├── get-issue.eval.ts
│ │ │ │ ├── get-trace-details.eval.ts
│ │ │ │ ├── list-dsns.eval.ts
│ │ │ │ ├── list-issues.eval.ts
│ │ │ │ ├── list-organizations.eval.ts
│ │ │ │ ├── list-projects.eval.ts
│ │ │ │ ├── list-releases.eval.ts
│ │ │ │ ├── list-tags.eval.ts
│ │ │ │ ├── list-teams.eval.ts
│ │ │ │ ├── search-docs.eval.ts
│ │ │ │ ├── search-events-agent.eval.ts
│ │ │ │ ├── search-events.eval.ts
│ │ │ │ ├── search-issues-agent.eval.ts
│ │ │ │ ├── search-issues.eval.ts
│ │ │ │ ├── update-issue.eval.ts
│ │ │ │ ├── update-project.eval.ts
│ │ │ │ └── utils
│ │ │ │ ├── fixtures.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── runner.ts
│ │ │ │ ├── structuredOutputScorer.ts
│ │ │ │ └── toolPredictionScorer.ts
│ │ │ └── setup-env.ts
│ │ ├── tsconfig.json
│ │ └── vitest.config.ts
│ ├── mcp-server-mocks
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── fixtures
│ │ │ │ ├── autofix-state.json
│ │ │ │ ├── csp-event.json
│ │ │ │ ├── csp-issue.json
│ │ │ │ ├── default-event.json
│ │ │ │ ├── event-attachments.json
│ │ │ │ ├── event.json
│ │ │ │ ├── generic-event.json
│ │ │ │ ├── issue.json
│ │ │ │ ├── performance-event.json
│ │ │ │ ├── performance-issue.json
│ │ │ │ ├── project.json
│ │ │ │ ├── regressed-issue.json
│ │ │ │ ├── tags.json
│ │ │ │ ├── team.json
│ │ │ │ ├── trace-event.json
│ │ │ │ ├── trace-items-attributes-logs-number.json
│ │ │ │ ├── trace-items-attributes-logs-string.json
│ │ │ │ ├── trace-items-attributes-spans-number.json
│ │ │ │ ├── trace-items-attributes-spans-string.json
│ │ │ │ ├── trace-items-attributes.json
│ │ │ │ ├── trace-meta-with-nulls.json
│ │ │ │ ├── trace-meta.json
│ │ │ │ ├── trace-mixed.json
│ │ │ │ ├── trace.json
│ │ │ │ ├── unknown-event.json
│ │ │ │ └── unsupported-issue.json
│ │ │ ├── fixtures.ts
│ │ │ ├── index.ts
│ │ │ └── utils.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── mcp-server-tsconfig
│ │ ├── package.json
│ │ ├── tsconfig.base.json
│ │ └── tsconfig.vite.json
│ ├── mcp-test-client
│ │ ├── .env.test
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── agent.ts
│ │ │ ├── auth
│ │ │ │ ├── config.ts
│ │ │ │ └── oauth.ts
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ ├── logger.test.ts
│ │ │ ├── logger.ts
│ │ │ ├── mcp-test-client-remote.ts
│ │ │ ├── mcp-test-client.ts
│ │ │ ├── types.ts
│ │ │ └── version.ts
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.ts
│ │ └── vitest.config.ts
│ └── smoke-tests
│ ├── package.json
│ ├── src
│ │ └── smoke.test.ts
│ └── vitest.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── README.md
├── scripts
│ └── check-doc-links.mjs
├── turbo.json
└── vitest.workspace.ts
```
# Files
--------------------------------------------------------------------------------
/.craft.yml:
--------------------------------------------------------------------------------
```yaml
1 | changelogPolicy: none
2 | preReleaseCommand: bash bin/bump-version.sh
3 | targets:
4 | - name: github
5 | - name: npm
6 | id: "@sentry/mcp-server"
7 | includeNames: /^sentry-mcp-server-\d.*\.tgz$/
8 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/.env.test:
--------------------------------------------------------------------------------
```
1 | # Test environment file
2 | # Copy this to .env and fill in your actual values
3 |
4 | # Dummy values for testing - will fail but show the flow
5 | ANTHROPIC_API_KEY=test-key
6 | SENTRY_ACCESS_TOKEN=test-token
7 | SENTRY_HOST=sentry.io
8 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Dependencies
2 | node_modules/
3 |
4 | # Build output
5 | dist/
6 | *.tsbuildinfo
7 |
8 | # Environment files
9 | .env
10 | .env.local
11 |
12 | # IDE
13 | .idea/
14 | .vscode/
15 | *.swp
16 | *.swo
17 |
18 | # OS
19 | .DS_Store
20 | Thumbs.db
21 |
22 | # Logs
23 | *.log
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 | pnpm-debug.log*
28 |
29 | # Testing
30 | coverage/
31 | *.junit.xml
```
--------------------------------------------------------------------------------
/.mcp.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "mcpServers": {
3 | "sentry": {
4 | "type": "http",
5 | "url": "https://mcp.sentry.dev/mcp/sentry/mcp-server?agent=1"
6 | },
7 | "sentry-dev": {
8 | "type": "http",
9 | "url": "http://localhost:5173/mcp/sentry/mcp-server"
10 | },
11 | "sentry-spotlight": {
12 | "type": "stdio",
13 | "command": "npx",
14 | "args": ["-y", "@spotlightjs/spotlight", "--stdio-mcp"],
15 | "env": {}
16 | }
17 | }
18 | }
19 |
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Logs
2 |
3 | logs
4 | _.log
5 | npm-debug.log_
6 | yarn-debug.log*
7 | yarn-error.log*
8 | lerna-debug.log*
9 | .pnpm-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 |
13 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
14 |
15 | # Runtime data
16 |
17 | pids
18 | _.pid
19 | _.seed
20 | *.pid.lock
21 |
22 | # Dependency directories
23 |
24 | node_modules/
25 | jspm_packages/
26 | .npm
27 | .node_repl_history
28 | *.tgz
29 | .cache
30 | dist
31 | .turbo/
32 | *.tsbuildinfo
33 | .DS_Store
34 |
35 | # dotenv environment variable files
36 |
37 | .env
38 | .env.development.local
39 | .env.test.local
40 | .env.production.local
41 | .env.local
42 |
43 | .vscode-test
44 |
45 | .yarn-integrity
46 | .yarn/cache
47 | .yarn/unplugged
48 | .yarn/build-state.yml
49 | .yarn/install-state.gz
50 | .pnp.\*
51 |
52 | # wrangler project
53 |
54 | .dev.vars
55 | .wrangler/
56 | wrangler.log
57 |
58 | *.junit.xml
59 | coverage
60 | *.lcov
61 |
62 | # Sentry Config File
63 | .env.sentry-build-plugin
64 |
65 | # Generated files
66 | packages/mcp-server/src/toolDefinitions.json
67 | packages/mcp-server/src/skillDefinitions.json
68 | packages/mcp-server-evals/eval-results.json
69 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/.env.example:
--------------------------------------------------------------------------------
```
1 | # Sentry OAuth Application Credentials
2 | # Create an OAuth app at: https://sentry.io/settings/account/api/applications/
3 | # - Homepage URL: http://localhost:5173 (for local dev)
4 | # - Authorized Redirect URIs: http://localhost:5173/oauth/callback (for local dev)
5 | SENTRY_CLIENT_ID=
6 |
7 | # Client Secret from your Sentry OAuth application
8 | # Generate this when creating your OAuth app in Sentry
9 | SENTRY_CLIENT_SECRET=
10 |
11 | # Cookie encryption secret for session management
12 | # Generate a random string (32+ characters recommended)
13 | # Example: openssl rand -base64 32
14 | COOKIE_SECRET=thisisasecret
15 |
16 | # OpenAI API key for AI-powered search tools (search_events, search_issues)
17 | # Get yours at: https://platform.openai.com/api-keys
18 | # Required for natural language query translation features
19 | OPENAI_API_KEY=sk-proj-generate-this
20 |
21 | # The URL where your MCP server is hosted
22 | # Local development: http://localhost:5173
23 | # Production: Your deployed URL (e.g., https://your-app.pages.dev)
24 | MCP_HOST=http://localhost:5173
25 |
26 | # Enable Spotlight
27 | SENTRY_SPOTLIGHT=1
28 |
```
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
```
1 | # Root Environment Configuration
2 | # This file provides default environment variables for all packages.
3 | # Individual packages can override these values with their own .env files.
4 |
5 | # OpenAI API key for AI-powered search tools (search_events, search_issues)
6 | # Get yours at: https://platform.openai.com/api-keys
7 | # Required for natural language query translation features
8 | OPENAI_API_KEY=sk-proj-agenerate-this
9 |
10 | # For mcp-test-client: Anthropic API key for Claude access
11 | # ANTHROPIC_API_KEY=your_anthropic_api_key
12 |
13 | # For mcp-test-client: Sentry access token (for stdio transport)
14 | # Get one from: https://sentry.io/settings/account/api/auth-tokens/
15 | # SENTRY_ACCESS_TOKEN=your_sentry_access_token
16 |
17 | # Sentry Spotlight - development environment tool for local debugging
18 | # Set to 1 to enable Spotlight integration (recommended for development)
19 | # Learn more: https://spotlightjs.com
20 | SENTRY_SPOTLIGHT=1
21 |
22 | # IMPORTANT: For local development, you also need to create:
23 | # - packages/mcp-cloudflare/.env - OAuth configuration (required for authentication)
24 | # Copy packages/mcp-cloudflare/.env.example to .env and fill in your OAuth credentials
25 |
```
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Contributor Docs
2 |
3 | This directory contains contributor documentation used by humans and LLMs. To avoid duplication, the canonical documentation map and contributor workflow live in `CLAUDE.md` (also available as `AGENTS.md`).
4 |
5 | ## Purpose
6 |
7 | - Central home for all contributor-focused docs (.md files)
8 | - Consumed by tools (e.g., Cursor) via direct file references
9 |
10 | ## Start Here
11 |
12 | - Doc map and workflow: see `CLAUDE.md` / `AGENTS.md`
13 | - Per-topic guides live in this folder (e.g., `adding-tools.md`)
14 |
15 | ## Integration with Tools
16 |
17 | - Cursor IDE: this folder is referenced directly as contextual rules
18 | - Other AI tools: reference specific `.md` files as needed
19 |
20 | ## LLM-Specific
21 |
22 | - Meta-docs live under `llms/` (e.g., `llms/document-scopes.md`)
23 |
24 | ## Maintenance
25 |
26 | Update docs when patterns change, new tools are added, or common issues arise. Keep the index in `CLAUDE.md` authoritative; avoid mirroring it here.
27 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # @sentry/mcp-server-evals
2 |
3 | Evaluation helpers and a local mock stdio runner used when developing and validating the Sentry MCP server.
4 |
5 | ## Mock stdio runner
6 |
7 | - Command: `pnpm --filter @sentry/mcp-server-evals start`
8 | - Entry: `src/bin/start-mock-stdio.ts`
9 | - Purpose: Boots the MCP server in-process with MSW mocks enabled for deterministic evals.
10 |
11 | ### Scopes policy
12 |
13 | The mock stdio script grants only the high-level admin scopes that imply all lower permissions via the hierarchy defined in `packages/mcp-server/src/permissions.ts`:
14 |
15 | - `org:admin`, `project:admin`, `team:admin`, `member:admin`, `event:admin`
16 | - Plus special non-hierarchical scope: `project:releases`
17 |
18 | This keeps permissions minimal and readable while still enabling every tool in eval runs. Avoid enumerating every read/write scope explicitly — rely on the hierarchy to expand implied permissions.
19 |
20 | ### Notes
21 |
22 | - No API keys are logged; MSW handles Sentry API mocking.
23 | - For code changes, ensure `pnpm run tsc && pnpm run lint && pnpm run test` all pass.
24 | - See `docs/adding-tools.md` and `docs/testing.md` for contribution guidance.
25 |
```
--------------------------------------------------------------------------------
/docs/llms/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # LLM-Specific Documentation
2 |
3 | This directory contains meta-documentation specifically for LLMs working with the Sentry MCP codebase.
4 |
5 | ## Contents
6 |
7 | ### documentation-style-guide.md
8 | Guidelines for writing effective documentation that LLMs can consume efficiently. Defines principles like assuming intelligence, being concise, and showing rather than telling.
9 |
10 | ### document-scopes.md
11 | Defines the specific purpose, content requirements, and line count targets for each documentation file. Helps maintain focus and prevent scope creep.
12 |
13 | ### documentation-todos.md
14 | Specific tasks for improving each document based on the style guide and scope definitions. Tracks the documentation refactoring effort.
15 |
16 | ## Purpose
17 |
18 | These documents help ensure that:
19 | - Documentation remains concise and focused
20 | - LLMs get project-specific information, not general programming knowledge
21 | - Redundancy is minimized through proper cross-referencing
22 | - Each document has a clear, defined purpose
23 |
24 | ## For Human Contributors
25 |
26 | While these documents are designed for LLM consumption, they also serve as excellent guidelines for human contributors who want to understand:
27 | - How to write documentation for this project
28 | - What belongs in each document
29 | - How to maintain consistency across docs
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/search-issues/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Search Issues Agent
2 |
3 | AI-powered natural language to Sentry issue search translation.
4 |
5 | ## Overview
6 |
7 | The `search_issues` tool uses an embedded AI agent to translate natural language queries into Sentry issue search syntax. It provides intelligent searching for grouped issues/problems rather than individual events.
8 |
9 | ## Architecture
10 |
11 | - **Handler**: `handler.ts` - MCP tool definition and orchestration
12 | - **Agent**: `agent.ts` - AI translation logic
13 | - **Config**: `config.ts` - System prompts and settings
14 | - **Formatters**: `formatters.ts` - Result formatting
15 |
16 | ## Agent Tools
17 |
18 | The AI agent has access to these shared agent tools from `../../agent-tools/`:
19 |
20 | 1. **issueFields**: Discovers available fields for issue searches using `dataset="search_issues"`
21 | 2. **whoami**: Gets current user information to resolve 'me' references
22 |
23 | ## Natural Language Examples
24 |
25 | - "critical bugs from last week" → `level:error is:unresolved lastSeen:-7d`
26 | - "issues assigned to me" → Uses whoami tool → `assignedOrSuggested:[email protected]`
27 | - "affecting 100+ users" → `userCount:>100`
28 | - "production errors" → `environment:production level:error`
29 |
30 | ## Features
31 |
32 | - ✅ Natural language query translation
33 | - ✅ Error feedback loop for self-correction
34 | - ✅ 'Me' reference resolution via whoami tool
35 | - ✅ Field discovery with custom tags
36 | - ✅ Smart sort options (date, freq, new, user)
37 | - ✅ Configurable result limits (1-100, default 10)
38 | - ✅ Project-specific and organization-wide searches
39 |
40 | ## Usage
41 |
42 | ```typescript
43 | search_issues({
44 | organizationSlug: "my-org",
45 | naturalLanguageQuery: "critical bugs from last week",
46 | limit: 25,
47 | includeExplanation: true
48 | })
49 | ```
```
--------------------------------------------------------------------------------
/docs/specs/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Feature Specifications
2 |
3 | This directory contains detailed specifications for features in the Sentry MCP server. Each feature has its own subdirectory with related design documents, technical specifications, and implementation guides.
4 |
5 |
6 | ## Purpose
7 |
8 | Feature specifications serve to:
9 |
10 | 1. **Document Design Decisions**: Capture the reasoning behind architectural choices
11 | 2. **Define Interfaces**: Specify tool inputs, outputs, and behavior
12 | 3. **Guide Implementation**: Provide clear direction for developers
13 | 4. **Enable Review**: Allow stakeholders to review and provide feedback
14 | 5. **Preserve Knowledge**: Maintain historical context for future reference
15 |
16 | ## Creating New Specifications
17 |
18 | When adding a new feature specification:
19 |
20 | 1. Create a new directory under `specs/` with a descriptive name
21 | 2. Create a **single, concise README.md file** that covers:
22 | - Problem statement and motivation
23 | - High-level design approach
24 | - Interface definitions (with code examples)
25 | - Key constraints and requirements
26 | - Migration/compatibility concerns
27 | 3. Update this README with a brief description
28 | 4. Link to the spec from relevant documentation
29 |
30 | **Important Guidelines**:
31 | - Keep specs in a single file (README.md)
32 | - Focus on WHAT and WHY, not HOW
33 | - Include code examples for interfaces and usage
34 | - Document constraints and meta concerns
35 | - Avoid implementation details (no function internals, prompts, etc.)
36 | - Think "contract" not "blueprint"
37 |
38 | ## Current Specifications
39 |
40 | ### search-events
41 | A unified event search tool that uses OpenAI GPT-5 to translate natural language queries into Sentry's search syntax. Replaced the separate `find_errors` and `find_transactions` tools with a single, more powerful interface.
42 |
43 | - **Status**: ✅ Complete
44 | - **Key Benefits**: Reduces tool count (20→19), improves UX, accessible to non-technical users
45 |
46 | ## Specification Template
47 |
48 | For consistency, new specifications should include:
49 |
50 | 1. **Overview**: Problem statement and proposed solution
51 | 2. **Motivation**: Why this feature is needed
52 | 3. **Design**: Technical architecture and approach
53 | 4. **Interface**: API/tool definitions
54 | 5. **Examples**: Usage scenarios and expected behavior
55 | 6. **Implementation**: Step-by-step plan (NO time estimates)
56 | 7. **Testing**: Validation strategy
57 | 8. **Migration**: If replacing existing functionality
58 | 9. **Future Work**: Potential enhancements
59 |
60 | **Important**: Do NOT include time windows, deadlines, or duration estimates in specifications. Implementation timing is determined by agents and project priorities, not by the spec.
61 |
62 | ## Review Process
63 |
64 | 1. Create specification documents in a feature branch
65 | 2. Open PR for review by team members
66 | 3. Address feedback and iterate
67 | 4. Merge once consensus is reached
68 | 5. Update status as implementation progresses
```
--------------------------------------------------------------------------------
/packages/mcp-core/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # sentry-mcp
2 |
3 | This is a prototype of an MCP server, acting as a middleware to the upstream Sentry API provider.
4 |
5 | This package is primarily for running the `stdio` MCP server. If you do not know what that is, or do not need it, we suggest using the public remote service:
6 |
7 | <https://mcp.sentry.dev>
8 |
9 | **Note:** Some tools require additional configuration:
10 | - **AI-powered search tools** (`search_events` and `search_issues`): These tools use OpenAI to translate natural language queries into Sentry's query syntax. They require an `OPENAI_API_KEY` environment variable. Without this key, these specific tools will be unavailable, but all other tools will function normally.
11 |
12 | ## Authorization
13 |
14 | The MCP server uses a **skills-based authorization system** that maps user-friendly capabilities to technical API permissions.
15 |
16 | ### Available Skills
17 |
18 | By default (no `--skills` flag), the MCP server grants **ALL skills** for non-interactive convenience:
19 |
20 | - **`inspect`** (default) - View organizations, projects, teams, issues, traces, and search for errors
21 | - **`docs`** (default) - Search and read Sentry SDK documentation
22 | - **`seer`** (default) - Use Seer to analyze issues and generate fix recommendations
23 | - **`triage`** - Resolve, assign, and update issues
24 | - **`project-management`** - Create and modify projects, teams, and DSNs
25 |
26 | ### Customizing Skills
27 |
28 | You can limit which skills are granted using the `--skills` flag:
29 |
30 | ```shell
31 | # Default: ALL skills (inspect, docs, seer, triage, project-management)
32 | npx @sentry/mcp-server@latest --access-token=sentry-user-token
33 |
34 | # Limit to specific skills only
35 | npx @sentry/mcp-server@latest --access-token=TOKEN --skills=inspect,docs
36 |
37 | # Self-hosted Sentry
38 | npx @sentry/mcp-server@latest --access-token=TOKEN --host=sentry.example.com
39 |
40 | # Override OpenAI endpoint for AI-powered tools (stdio only)
41 | npx @sentry/mcp-server@latest --access-token=TOKEN --openai-base-url=https://proxy.example.com/v1
42 | ```
43 |
44 | ### Constraint-Based Tool Exclusion
45 |
46 | When a session is scoped to a specific organization or project (tenant-bound context), certain list tools are automatically excluded since they cannot query other resources:
47 |
48 | - **`find_organizations`** is hidden when the session is constrained to a specific organization (`organizationSlug` constraint)
49 | - **`find_projects`** is hidden when the session is constrained to a specific project (`projectSlug` constraint)
50 |
51 | This ensures that only relevant tools are available in constrained contexts. When constraints are not set, all tools are available based on your granted skills.
52 |
53 | ### Environment Variables
54 |
55 | You can also use environment variables:
56 |
57 | ```shell
58 | SENTRY_ACCESS_TOKEN=your-token
59 | # Optional overrides. Leave unset to use the default SaaS host
60 | SENTRY_HOST=sentry.example.com # Self-hosted Sentry hostname
61 | MCP_SKILLS=inspect,docs,triage # Limit to specific skills
62 | MCP_SCOPES=org:read,event:read # Override default scopes (replaces defaults) - DEPRECATED, use MCP_SKILLS
63 | MCP_ADD_SCOPES=event:write # Add to default scopes (keeps defaults) - DEPRECATED, use MCP_SKILLS
64 |
65 | # OpenAI configuration for AI-powered search tools
66 | OPENAI_API_KEY=your-openai-key # Required for AI-powered search tools (search_events, search_issues)
67 | OPENAI_MODEL=gpt-5 # OpenAI model to use (default: "gpt-5")
68 | OPENAI_REASONING_EFFORT=low # Reasoning effort for o1 models: "low", "medium", "high", or "" to disable (default: "low")
69 |
70 | # No environment variable exists for the OpenAI base URL override; use --openai-base-url instead.
71 | # This restriction prevents unexpected environment overrides that could silently reroute requests to a
72 | # malicious proxy capable of harvesting the OpenAI API key provided at runtime.
73 | ```
74 |
75 | If `SENTRY_HOST` is not provided, the CLI automatically targets the Sentry SaaS endpoint. Configure this variable only when you operate a self-hosted Sentry deployment.
76 |
77 | **Note:** Command-line flags override environment variables.
78 |
79 | ### Required Sentry Token Scopes
80 |
81 | To utilize the `stdio` transport, create a User Auth Token in Sentry with these scopes:
82 |
83 | **Minimum (read-only)**:
84 | - `org:read`, `project:read`, `team:read`, `event:read`
85 |
86 | **Additional (for write operations)**:
87 | - `event:write` - Required for `triage` skill
88 | - `project:write`, `team:write` - Required for `project-management` skill
89 |
90 | The MCP server will automatically request the appropriate scopes based on your granted skills.
91 |
92 | ### Migration from Scopes (Deprecated)
93 |
94 | > ⚠️ **Deprecated**: The `--scopes` and `--add-scopes` flags are deprecated. Use `--skills` instead.
95 |
96 | If you're currently using scopes:
97 |
98 | ```shell
99 | # OLD (deprecated)
100 | npx @sentry/mcp-server --access-token=TOKEN --scopes=org:read,event:write
101 |
102 | # NEW (recommended)
103 | npx @sentry/mcp-server --access-token=TOKEN --skills=inspect,triage
104 | ```
105 |
106 | The host configuration accepts two distinct formats:
107 |
108 | - **`SENTRY_HOST`**: Hostname only (no protocol)
109 | - Examples: `sentry.example.com`, `sentry.internal.example.com`, `localhost:8000`
110 |
111 | **Note**: Only HTTPS connections are supported for security reasons.
112 |
113 | By default we also enable Sentry reporting (traces, errors) upstream to our cloud service. You can disable that, or send it to a different Sentry instance by using the `--sentry-dsn` flag:
114 |
115 | ```shell
116 | # disable sentry reporting
117 | npx @sentry/mcp-server@latest --sentry-dsn=
118 |
119 | # use custom sentry instance
120 | npx @sentry/mcp-server@latest --sentry-dsn=https://[email protected]/...
121 | ```
122 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # sentry-mcp
2 |
3 | [](https://codecov.io/gh/getsentry/sentry-mcp)
4 |
5 | Sentry's MCP service is primarily designed for human-in-the-loop coding agents. Our tool selection and priorities are focused on developer workflows and debugging use cases, rather than providing a general-purpose MCP server for all Sentry functionality.
6 |
7 | This remote MCP server acts as middleware to the upstream Sentry API, optimized for coding assistants like Cursor, Claude Code, and similar development tools. It's based on [Cloudflare's work towards remote MCPs](https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/).
8 |
9 | ## Getting Started
10 |
11 | You'll find everything you need to know by visiting the deployed service in production:
12 |
13 | <https://mcp.sentry.dev>
14 |
15 | If you're looking to contribute, learn how it works, or to run this for self-hosted Sentry, continue below.
16 |
17 | ### Stdio vs Remote
18 |
19 | While this repository is focused on acting as an MCP service, we also support a `stdio` transport. This is still a work in progress, but is the easiest way to adapt run the MCP against a self-hosted Sentry install.
20 |
21 | **Note:** The AI-powered search tools (`search_events` and `search_issues`) require an OpenAI API key. These tools use natural language processing to translate queries into Sentry's query syntax. Without the API key, these specific tools will be unavailable, but all other tools will function normally.
22 |
23 | To utilize the `stdio` transport, you'll need to create an User Auth Token in Sentry with the necessary scopes. As of writing this is:
24 |
25 | ```
26 | org:read
27 | project:read
28 | project:write
29 | team:read
30 | team:write
31 | event:write
32 | ```
33 |
34 | Launch the transport:
35 |
36 | ```shell
37 | npx @sentry/mcp-server@latest --access-token=sentry-user-token
38 | ```
39 |
40 | Need to connect to a self-hosted deployment? Add <code>--host</code> (hostname
41 | only, e.g. <code>--host=sentry.example.com</code>) when you run the command.
42 |
43 | Note: You can also use environment variables:
44 |
45 | ```shell
46 | SENTRY_ACCESS_TOKEN=
47 | # Optional overrides for self-hosted deployments
48 | SENTRY_HOST=
49 | OPENAI_API_KEY= # Required for AI-powered search tools (search_events, search_issues)
50 | ```
51 |
52 | If you leave the host variable unset, the CLI automatically targets the Sentry
53 | SaaS service. Only set the override when you operate self-hosted Sentry.
54 |
55 | ### MCP Inspector
56 |
57 | MCP includes an [Inspector](https://modelcontextprotocol.io/docs/tools/inspector), to easily test the service:
58 |
59 | ```shell
60 | pnpm inspector
61 | ```
62 |
63 | Enter the MCP server URL (<http://localhost:5173>) and hit connect. This should trigger the authentication flow for you.
64 |
65 | Note: If you have issues with your OAuth flow when accessing the inspector on `127.0.0.1`, try using `localhost` instead by visiting `http://localhost:6274`.
66 |
67 | ## Local Development
68 |
69 | To contribute changes, you'll need to set up your local environment:
70 |
71 | 1. **Set up environment files:**
72 |
73 | ```shell
74 | make setup-env # Creates both .env files from examples
75 | ```
76 |
77 | 2. **Create an OAuth App in Sentry** (Settings => API => [Applications](https://sentry.io/settings/account/api/applications/)):
78 |
79 | - Homepage URL: `http://localhost:5173`
80 | - Authorized Redirect URIs: `http://localhost:5173/oauth/callback`
81 | - Note your Client ID and generate a Client secret
82 |
83 | 3. **Configure your credentials:**
84 |
85 | - Edit `.env` in the root directory and add your `OPENAI_API_KEY`
86 | - Edit `packages/mcp-cloudflare/.env` and add:
87 | - `SENTRY_CLIENT_ID=your_development_sentry_client_id`
88 | - `SENTRY_CLIENT_SECRET=your_development_sentry_client_secret`
89 | - `COOKIE_SECRET=my-super-secret-cookie`
90 |
91 | 4. **Start the development server:**
92 |
93 | ```shell
94 | pnpm dev
95 | ```
96 |
97 | ### Verify
98 |
99 | Run the server locally to make it available at `http://localhost:5173`
100 |
101 | ```shell
102 | pnpm dev
103 | ```
104 |
105 | To test the local server, enter `http://localhost:5173/mcp` into Inspector and hit connect. Once you follow the prompts, you'll be able to "List Tools".
106 |
107 | ### Tests
108 |
109 | There are three test suites included: unit tests, evaluations, and manual testing.
110 |
111 | **Unit tests** can be run using:
112 |
113 | ```shell
114 | pnpm test
115 | ```
116 |
117 | **Evaluations** require a `.env` file in the project root with some config:
118 |
119 | ```shell
120 | # .env (in project root)
121 | OPENAI_API_KEY= # Also required for AI-powered search tools in production
122 | ```
123 |
124 | Note: The root `.env` file provides defaults for all packages. Individual packages can have their own `.env` files to override these defaults during development.
125 |
126 | Once that's done you can run them using:
127 |
128 | ```shell
129 | pnpm eval
130 | ```
131 |
132 | **Manual testing** (preferred for testing MCP changes):
133 |
134 | ```shell
135 | # Test with local dev server (default: http://localhost:5173)
136 | pnpm -w run cli "who am I?"
137 |
138 | # Test agent mode (use_sentry tool only)
139 | pnpm -w run cli --agent "who am I?"
140 |
141 | # Test against production
142 | pnpm -w run cli --mcp-host=https://mcp.sentry.dev "query"
143 |
144 | # Test with local stdio mode (requires SENTRY_ACCESS_TOKEN)
145 | pnpm -w run cli --access-token=TOKEN "query"
146 | ```
147 |
148 | Note: The CLI defaults to `http://localhost:5173`. Override with `--mcp-host` or set `MCP_URL` environment variable.
149 |
150 | **Comprehensive testing playbooks:**
151 | - **Stdio testing:** See `docs/testing-stdio.md` for complete guide on building, running, and testing the stdio implementation (IDEs, MCP Inspector)
152 | - **Remote testing:** See `docs/testing-remote.md` for complete guide on testing the remote server (OAuth, web UI, CLI client)
153 |
154 | ## Development Notes
155 |
156 | ### Automated Code Review
157 |
158 | This repository uses automated code review tools (like Cursor BugBot) to help identify potential issues in pull requests. These tools provide helpful feedback and suggestions, but **we do not recommend making these checks required** as the accuracy is still evolving and can produce false positives.
159 |
160 | The automated reviews should be treated as:
161 |
162 | - ✅ **Helpful suggestions** to consider during code review
163 | - ✅ **Starting points** for discussion and improvement
164 | - ❌ **Not blocking requirements** for merging PRs
165 | - ❌ **Not replacements** for human code review
166 |
167 | When addressing automated feedback, focus on the underlying concerns rather than strictly following every suggestion.
168 |
169 | ### Contributor Documentation
170 |
171 | Looking to contribute or explore the full documentation map? See `CLAUDE.md` (also available as `AGENTS.md`) for contributor workflows and the complete docs index. The `docs/` folder contains the per-topic guides and tool-integrated `.md` files.
172 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # MCP Client CLI
2 |
3 | A simple CLI tool to test the Sentry MCP server using stdio transport with an AI agent powered by Vercel's AI SDK.
4 |
5 | ## Features
6 |
7 | - 🤖 AI-powered interaction with Sentry MCP tools using GPT-4
8 | - 🔧 Full access to all MCP server tools
9 | - 💬 Interactive mode by default when no prompt provided
10 | - 🎨 Colorized output for better readability
11 | - 🔄 Streaming responses for real-time feedback
12 | - 🌐 Remote MCP server support via HTTP streaming (with OAuth)
13 | - 🏠 Local stdio transport for development
14 |
15 | ## Prerequisites
16 |
17 | - Node.js >= 20
18 | - pnpm package manager
19 | - OpenAI API key
20 | - Sentry access token with appropriate permissions
21 |
22 | ## Installation
23 |
24 | From the package directory:
25 |
26 | ```bash
27 | pnpm install
28 | pnpm build
29 | ```
30 |
31 | ## Configuration
32 |
33 | The MCP client supports multiple transport methods and authentication:
34 |
35 | ### 1. OAuth Authentication (Recommended for Remote Mode)
36 |
37 | When using remote mode (default), the MCP client can authenticate via OAuth 2.1 with the MCP server:
38 |
39 | ```bash
40 | # The client will automatically prompt for OAuth if no token is provided
41 | pnpm mcp-test-client
42 |
43 | # Or specify a custom MCP server
44 | pnpm mcp-test-client --mcp-host http://localhost:8787
45 | ```
46 |
47 | The OAuth flow uses PKCE (Proof Key for Code Exchange) and doesn't require a client secret, making it secure for CLI applications.
48 |
49 | ### 2. Environment Variables
50 |
51 | Create a `.env` file in the package directory:
52 |
53 | ```env
54 | # Required
55 | OPENAI_API_KEY=your_openai_api_key
56 |
57 | # Required - Sentry access token with appropriate permissions
58 | SENTRY_ACCESS_TOKEN=your_sentry_access_token
59 |
60 | # Optional (self-hosted only)
61 | # Leave unset to target the SaaS host
62 | SENTRY_HOST=sentry.example.com # Hostname only
63 | MCP_URL=https://mcp.sentry.dev # MCP server host (defaults to production)
64 | MCP_MODEL=gpt-4o # Override default model (GPT-4)
65 |
66 | # Optional - Error tracking
67 | SENTRY_DSN=your_sentry_dsn # Error tracking for the client itself
68 |
69 | # OAuth clients are automatically registered via Dynamic Client Registration (RFC 7591)
70 | # No manual client ID configuration needed
71 | ```
72 |
73 | ### 3. Command Line Flags
74 |
75 | ```bash
76 | pnpm mcp-test-client --access-token=your_token "Your prompt"
77 | ```
78 |
79 | ### Token Priority
80 |
81 | The client automatically determines the connection mode:
82 |
83 | **Local Mode (stdio transport)**: Used when an access token is provided via:
84 |
85 | 1. Command-line flag (`--access-token`)
86 | 2. Environment variable (`SENTRY_ACCESS_TOKEN`)
87 | 3. `.env` file
88 |
89 | **Remote Mode (HTTP streaming)**: Used when no access token is provided, prompts for OAuth authentication
90 |
91 | ### Required Sentry Permissions
92 |
93 | Your Sentry access token needs the following scopes:
94 |
95 | - `org:read`
96 | - `project:read`
97 | - `project:write`
98 | - `team:read`
99 | - `team:write`
100 | - `event:write`
101 |
102 | ## Usage
103 |
104 | ### Remote Mode (Default)
105 |
106 | Connect to the remote MCP server via HTTP streaming (uses OAuth for authentication):
107 |
108 | ```bash
109 | # Connect to production MCP server (uses /mcp endpoint)
110 | pnpm mcp-test-client
111 |
112 | # Connect to local development MCP server
113 | pnpm mcp-test-client --mcp-host http://localhost:8787
114 | ```
115 |
116 | **Note**: Remote mode uses HTTP streaming transport and connects to the `/mcp` endpoint on the MCP server.
117 |
118 | ### Local Mode
119 |
120 | Use the local stdio transport by providing a Sentry access token:
121 |
122 | ```bash
123 | # Using environment variable
124 | SENTRY_ACCESS_TOKEN=your_token pnpm mcp-test-client
125 |
126 | # Using command line flag
127 | pnpm mcp-test-client --access-token your_token
128 | ```
129 |
130 | ### Interactive Mode (Default)
131 |
132 | Start an interactive session by running without arguments:
133 |
134 | ```bash
135 | pnpm mcp-test-client
136 | ```
137 |
138 | In interactive mode:
139 |
140 | - Type your prompts and press Enter
141 | - Type `exit` or `quit` to end the session
142 | - The AI maintains context across prompts
143 |
144 | ### Single Prompt Mode
145 |
146 | Run with a specific prompt:
147 |
148 | ```bash
149 | pnpm mcp-test-client "List all unresolved issues in my project"
150 | ```
151 |
152 | ### Advanced Options
153 |
154 | Use a different AI model:
155 |
156 | ```bash
157 | pnpm mcp-test-client --model gpt-4-turbo "Analyze my error trends"
158 | ```
159 |
160 | Connect to a local MCP server:
161 |
162 | ```bash
163 | pnpm mcp-test-client --mcp-host http://localhost:8787 "List my projects"
164 | ```
165 |
166 | Use local stdio transport with custom Sentry host:
167 |
168 | ```bash
169 | SENTRY_HOST=sentry.example.com SENTRY_ACCESS_TOKEN=your_token pnpm mcp-test-client "Show my projects"
170 | ```
171 |
172 | Only configure `SENTRY_HOST` when you run self-hosted Sentry.
173 |
174 | ## Development
175 |
176 | ### Running from Source
177 |
178 | ```bash
179 | pnpm dev "Your prompt here"
180 | ```
181 |
182 | ### Building
183 |
184 | ```bash
185 | pnpm build
186 | ```
187 |
188 | ### Type Checking
189 |
190 | ```bash
191 | pnpm typecheck
192 | ```
193 |
194 | ## Troubleshooting
195 |
196 | ### Connection Issues
197 |
198 | If you see "Failed to connect to MCP server":
199 |
200 | 1. Ensure the mcp-server package is built
201 | 2. Check that your access token is valid
202 | 3. Verify the Sentry host URL is correct
203 |
204 | ### Authentication Errors
205 |
206 | If you get authentication errors:
207 |
208 | 1. Verify your OPENAI_API_KEY is set correctly
209 | 2. Check that your SENTRY_ACCESS_TOKEN has the required permissions
210 | 3. For self-hosted Sentry, ensure SENTRY_HOST is set
211 |
212 | ### Tool Errors
213 |
214 | If tools fail to execute:
215 |
216 | 1. Check the error message for missing parameters
217 | 2. Ensure your Sentry token has appropriate permissions
218 | 3. Verify you have access to the requested resources
219 |
220 | ## Examples
221 |
222 | ### Finding and Analyzing Issues
223 |
224 | ```bash
225 | # List recent issues
226 | pnpm mcp-test-client "Show me issues from the last 24 hours"
227 |
228 | # Search for specific errors
229 | pnpm mcp-test-client "Find all TypeError issues in the frontend project"
230 |
231 | # Get issue details
232 | pnpm mcp-test-client "Show me details about issue FRONTEND-123"
233 | ```
234 |
235 | ### Project Management
236 |
237 | ```bash
238 | # List all projects
239 | pnpm mcp-test-client "List all my projects with their platforms"
240 |
241 | # Get project settings
242 | pnpm mcp-test-client "Show me the alert settings for my React project"
243 |
244 | # View team assignments
245 | pnpm mcp-test-client "Which teams have access to the mobile app project?"
246 | ```
247 |
248 | ### Performance Analysis
249 |
250 | ```bash
251 | # Check slow transactions
252 | pnpm mcp-test-client "Find the slowest API endpoints in the last hour"
253 |
254 | # Analyze performance trends
255 | pnpm mcp-test-client "Show me performance metrics for the checkout flow"
256 | ```
257 |
258 | ## Testing the Installation
259 |
260 | After installation, you can verify everything is working:
261 |
262 | ```bash
263 | # Check CLI is installed
264 | pnpm mcp-test-client --help
265 |
266 | # Test basic functionality (no API keys required)
267 | SENTRY_ACCESS_TOKEN=dummy OPENAI_API_KEY=dummy pnpm mcp-test-client --help
268 |
269 | # Run the test script (requires valid credentials)
270 | ./examples/test-connection.sh
271 | ```
272 |
273 | ## Authentication Methods
274 |
275 | ### Remote Mode (OAuth)
276 |
277 | When connecting to a remote MCP server (default), the client supports OAuth 2.1 with PKCE:
278 |
279 | - No client secret required (secure for CLI applications)
280 | - Automatic browser-based authentication flow
281 | - Tokens are securely stored in memory during the session
282 |
283 | **Note**: OAuth clients are automatically registered using Dynamic Client Registration (RFC 7591). The client registration is cached in `~/.config/sentry-mcp/config.json` to avoid re-registration on subsequent authentications.
284 |
285 | ### Local Mode (Access Tokens)
286 |
287 | When using local stdio transport (automatic when access token is provided), you must provide a Sentry access token:
288 |
289 | - Set `SENTRY_ACCESS_TOKEN` environment variable
290 | - Or use `--access-token` command-line flag
291 | - Tokens need appropriate Sentry permissions (see Required Sentry Permissions section)
292 |
293 | ## Architecture
294 |
295 | The CLI consists of these main components:
296 |
297 | 1. **MCP Client** (`mcp-test-client.ts`) - Handles connection to the MCP server
298 | 2. **AI Agent** (`agent.ts`) - Integrates with Vercel AI SDK for Claude
299 | 3. **Auth** (`auth/`) - OAuth flow and secure token storage
300 | 4. **CLI Interface** (`index.ts`) - Command-line argument parsing and modes
301 |
302 | ### Technical Notes
303 |
304 | - The client uses `console.log` for all terminal output to maintain compatibility with the logger module
305 | - Error tracking is available via the `SENTRY_DSN` environment variable
306 | - All operations follow OpenTelemetry semantic conventions for observability
307 |
308 | ## Contributing
309 |
310 | When adding new features:
311 |
312 | 1. Follow the existing code style
313 | 2. Add new test scenarios if applicable
314 | 3. Update this README with new usage examples
315 | 4. Ensure all TypeScript types are properly defined
316 | 5. Run quality checks: `pnpm lint:fix && pnpm typecheck && pnpm test`
317 |
```
--------------------------------------------------------------------------------
/CLAUDE.md:
--------------------------------------------------------------------------------
```markdown
1 | AGENTS.md
```
--------------------------------------------------------------------------------
/AGENTS.md:
--------------------------------------------------------------------------------
```markdown
1 | # AGENTS.md
2 |
3 | Sentry MCP is a Model Context Protocol server that exposes Sentry's error tracking and performance monitoring to AI assistants through 19 tools.
4 |
5 | ## Principles
6 |
7 | - **Type Safety**: Prefer strict types over `any` - they catch bugs and improve tooling. Use `unknown` for truly unknown types.
8 | - **Security**: Never log secrets. Validate external input. See @docs/security.md.
9 | - **Simplicity**: Follow existing patterns. Check neighboring files before inventing new approaches.
10 |
11 | ## Constraints
12 |
13 | - **Tool count**: Target ≤20, hard limit 25 (AI agents have limited tool slots).
14 | - **Quality gate**: `pnpm run tsc && pnpm run lint && pnpm run test` must pass before committing.
15 |
16 | ## Repository Structure
17 |
18 | ```
19 | sentry-mcp/
20 | ├── packages/
21 | │ ├── mcp-core/ # Core MCP implementation (private)
22 | │ │ └── src/
23 | │ │ ├── tools/ # 19 tool modules
24 | │ │ ├── server.ts # buildServer()
25 | │ │ ├── api-client/ # Sentry API
26 | │ │ └── internal/ # Shared utils
27 | │ ├── mcp-server/ # stdio transport (@sentry/mcp-server on npm)
28 | │ ├── mcp-cloudflare/ # Web app + OAuth
29 | │ ├── mcp-server-evals/ # AI evaluation tests
30 | │ ├── mcp-server-mocks/ # MSW mocks
31 | │ └── mcp-test-client/ # CLI test client
32 | └── docs/ # All documentation
33 | ```
34 |
35 | ## Essential Documentation
36 |
37 | **Read before making changes:**
38 | - @docs/adding-tools.md — Tool implementation guide
39 | - @docs/testing.md — Testing requirements
40 | - @docs/common-patterns.md — Error handling, Zod schemas, response formatting
41 | - @docs/error-handling.md — Error types and propagation
42 |
43 | **Reference:**
44 | - @docs/architecture.md — System design
45 | - @docs/api-patterns.md — Sentry API client usage
46 | - @docs/quality-checks.md — Pre-commit checklist
47 | - @docs/pr-management.md — Commit/PR guidelines
48 | - @docs/security.md — Authentication patterns
49 | - @docs/releases/stdio.md — npm package release
50 | - @docs/releases/cloudflare.md — Cloudflare deployment
51 |
52 | ## Commands
53 |
54 | ```bash
55 | # Development
56 | pnpm run dev # Start dev server
57 | pnpm run build # Build all packages
58 |
59 | # Testing
60 | pnpm -w run cli "who am I?" # Test local dev server
61 | pnpm -w run cli --access-token=TOKEN "q" # Test stdio transport
62 | pnpm -w run cli --agent "query" # Test agent mode (~2x slower)
63 |
64 | # Quality (run before committing)
65 | pnpm run tsc && pnpm run lint && pnpm run test
66 |
67 | # Token overhead
68 | pnpm run measure-tokens # Check tool definition size
69 | ```
70 |
71 | ## Workflow
72 |
73 | 1. Check neighboring files for existing patterns before writing new code.
74 | 2. Update relevant docs when changing functionality.
75 | 3. Follow @docs/error-handling.md for error types.
76 | 4. Follow @docs/pr-management.md for commits and PRs.
77 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/search-events/CLAUDE.md:
--------------------------------------------------------------------------------
```markdown
1 | # search_events Tool - Embedded Agent Documentation
2 |
3 | This tool embeds an AI agent (GPT-4o) to translate natural language queries into Sentry's event search syntax.
4 |
5 | ## Architecture Overview
6 |
7 | The `search_events` tool uses an "agent-in-tool" pattern:
8 |
9 | 1. **MCP Tool Handler** (`handler.ts`) - Receives natural language query from calling agent
10 | 2. **Embedded AI Agent** (`agent.ts`) - Translates to Sentry search syntax
11 | 3. **API Execution** - Runs the translated query against Sentry's API
12 | 4. **Result Formatting** - Returns formatted results to calling agent
13 |
14 | ## Embedded Agent Behavior
15 |
16 | ### Available Tools
17 |
18 | The embedded agent has access to three tools:
19 |
20 | 1. **datasetAttributes** - Discovers available fields for the chosen dataset
21 | 2. **otelSemantics** - Looks up OpenTelemetry semantic conventions
22 | 3. **whoami** - Resolves "me" references to actual user IDs
23 |
24 | ### Translation Flow
25 |
26 | 1. Analyzes natural language query to determine dataset (spans/errors/logs)
27 | 2. Calls `datasetAttributes` to discover available fields
28 | 3. May call `otelSemantics` for standardized field names
29 | 4. Generates structured query with fields, sort, and timeRange
30 |
31 | ### Key Query Patterns
32 |
33 | #### Distinct/Unique Values
34 | - "distinct tool names" → `fields: ['mcp.tool.name', 'count()'], sort: '-count()'`
35 | - Always uses aggregate mode with count()
36 |
37 | #### Traffic/Volume Queries
38 | - "how much traffic" → `fields: ['count()'], sort: '-count()'`
39 | - "traffic by X" → `fields: ['X', 'count()'], sort: '-count()'`
40 |
41 | #### Mathematical Queries
42 | - "total tokens used" → `fields: ['sum(gen_ai.usage.input_tokens)', 'sum(gen_ai.usage.output_tokens)']`
43 | - Uses spans dataset for OpenTelemetry metrics
44 |
45 | #### Time Series (NOT SUPPORTED)
46 | - "X over time" → Returns error: "Time series aggregations are not currently supported."
47 |
48 | ## Error Handling
49 |
50 | The tool follows the MCP philosophy of single-attempt error handling:
51 |
52 | 1. **Agent generates query** - Using static system prompt
53 | 2. **Validation Error** - Returns clear UserInputError to calling agent
54 | 3. **Calling agent decides** - Whether to retry with corrections
55 |
56 | Common validation errors:
57 | - Missing sort parameter
58 | - Sort field not included in fields array
59 | - Missing fields for aggregate queries
60 | - Invalid field names or syntax
61 |
62 | This approach enables better LLM prompt caching and cleaner error boundaries.
63 |
64 | ## Limitations
65 |
66 | 1. **No Time Series** - Cannot do "over time" aggregations
67 | 2. **Dataset Constraints**:
68 | - Equations only work in spans dataset
69 | - Numeric aggregations limited by field types
70 | - Timestamp filtering differs between datasets
71 | 3. **Project Scope** - Fields vary by project based on instrumented data
72 |
73 | ## Common Issues and Solutions
74 |
75 | ### Issue: "Sort field not in fields array"
76 | **Cause**: Agent specified sort by a field not included in the fields array
77 | **Solution**: Error message guides agent to include the sort field
78 |
79 | ### Issue: "Time series not supported"
80 | **Cause**: User asked for data "over time"
81 | **Solution**: Return clear error message, no retry
82 |
83 | ### Issue: "Invalid aggregate function on non-numeric field"
84 | **Cause**: Using avg(), sum() etc. on string fields
85 | **Solution**: Agent uses field type information from datasetAttributes
86 |
87 | ## Testing Queries
88 |
89 | Test various query patterns:
90 | - Simple counts: "how many errors today"
91 | - Distinct values: "distinct user agents"
92 | - Grouped aggregations: "errors by type"
93 | - Token usage: "total tokens used by model"
94 | - Time-filtered: "errors in the last hour"
95 |
96 | ## Future Improvements
97 |
98 | 1. ~~Consider removing retry mechanism - let calling agent handle retries~~ ✅ Done
99 | 2. Add support for time bucketing fields (timestamp.to_hour, timestamp.to_day)
100 | 3. Extract createOtelLookupTool and createDatasetAttributesTool to shared modules
```
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
```markdown
1 | # Functional Source License, Version 1.1, Apache 2.0 Future License
2 |
3 | ## Abbreviation
4 |
5 | FSL-1.1-Apache-2.0
6 |
7 | ## Notice
8 |
9 | Copyright 2008-2024 Functional Software, Inc. dba Sentry
10 |
11 | ## Terms and Conditions
12 |
13 | ### Licensor ("We")
14 |
15 | The party offering the Software under these Terms and Conditions.
16 |
17 | ### The Software
18 |
19 | The "Software" is each version of the software that we make available under
20 | these Terms and Conditions, as indicated by our inclusion of these Terms and
21 | Conditions with the Software.
22 |
23 | ### License Grant
24 |
25 | Subject to your compliance with this License Grant and the Patents,
26 | Redistribution and Trademark clauses below, we hereby grant you the right to
27 | use, copy, modify, create derivative works, publicly perform, publicly display
28 | and redistribute the Software for any Permitted Purpose identified below.
29 |
30 | ### Permitted Purpose
31 |
32 | A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33 | means making the Software available to others in a commercial product or
34 | service that:
35 |
36 | 1. substitutes for the Software;
37 |
38 | 2. substitutes for any other product or service we offer using the Software
39 | that exists as of the date we make the Software available; or
40 |
41 | 3. offers the same or substantially similar functionality as the Software.
42 |
43 | Permitted Purposes specifically include using the Software:
44 |
45 | 1. for your internal use and access;
46 |
47 | 2. for non-commercial education;
48 |
49 | 3. for non-commercial research; and
50 |
51 | 4. in connection with professional services that you provide to a licensee
52 | using the Software in accordance with these Terms and Conditions.
53 |
54 | ### Patents
55 |
56 | To the extent your use for a Permitted Purpose would necessarily infringe our
57 | patents, the license grant above includes a license under our patents. If you
58 | make a claim against any party that the Software infringes or contributes to
59 | the infringement of any patent, then your patent license to the Software ends
60 | immediately.
61 |
62 | ### Redistribution
63 |
64 | The Terms and Conditions apply to all copies, modifications and derivatives of
65 | the Software.
66 |
67 | If you redistribute any copies, modifications or derivatives of the Software,
68 | you must include a copy of or a link to these Terms and Conditions and not
69 | remove any copyright notices provided in or with the Software.
70 |
71 | ### Disclaimer
72 |
73 | THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74 | IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75 | PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76 |
77 | IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78 | SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79 | EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80 |
81 | ### Trademarks
82 |
83 | Except for displaying the License Details and identifying us as the origin of
84 | the Software, you have no right under these Terms and Conditions to use our
85 | trademarks, trade names, service marks or product names.
86 |
87 | ## Grant of Future License
88 |
89 | We hereby irrevocably grant you an additional license to use the Software under
90 | the Apache License, Version 2.0 that is effective on the second anniversary of
91 | the date we make the Software available. On or after that date, you may use the
92 | Software under the Apache License, Version 2.0, in which case the following
93 | will apply:
94 |
95 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96 | this file except in compliance with the License.
97 |
98 | You may obtain a copy of the License at
99 |
100 | http://www.apache.org/licenses/LICENSE-2.0
101 |
102 | Unless required by applicable law or agreed to in writing, software distributed
103 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
105 | specific language governing permissions and limitations under the License.
106 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/search-issues/CLAUDE.md:
--------------------------------------------------------------------------------
```markdown
1 | # search_issues Tool - Embedded Agent Documentation
2 |
3 | This tool embeds an AI agent (GPT-4o) to translate natural language queries into Sentry's issue search syntax.
4 |
5 | ## Architecture Overview
6 |
7 | The `search_issues` tool uses an "agent-in-tool" pattern similar to `search_events`:
8 |
9 | 1. **MCP Tool Handler** (`handler.ts`) - Receives natural language query from calling agent
10 | 2. **Embedded AI Agent** (`agent.ts`) - Translates to Sentry issue search syntax
11 | 3. **API Execution** - Runs the translated query against Sentry's API
12 | 4. **Result Formatting** - Returns formatted grouped issues to calling agent
13 |
14 | ## Key Differences from search_events
15 |
16 | ### Purpose
17 | - `search_events`: Returns individual events or aggregated statistics
18 | - `search_issues`: Returns grouped issues (problems) with metadata
19 |
20 | ### Query Syntax
21 | - Uses Sentry's issue search syntax (different from event search)
22 | - No aggregate functions - issues are already grouped
23 | - Special fields like `is:`, `assigned:`, `firstSeen:`, `lastSeen:`
24 |
25 | ### No Datasets
26 | - Issues are a single unified view across all event types
27 | - No dataset selection required
28 |
29 | ## Embedded Agent Behavior
30 |
31 | ### Available Tools
32 |
33 | The embedded agent has access to two tools:
34 |
35 | 1. **discoverDatasetFields** - Discovers available issue fields
36 | 2. **whoami** - Resolves "me" references to actual user IDs
37 |
38 | ### Translation Flow
39 |
40 | 1. Analyzes natural language query for issue-specific patterns
41 | 2. Calls `discoverDatasetFields` to get available issue fields
42 | 3. May call `whoami` to resolve "me" references
43 | 4. Generates issue search query with proper syntax
44 |
45 | ### Key Query Patterns
46 |
47 | #### Status Queries
48 | - "unresolved issues" → `is:unresolved`
49 | - "ignored bugs" → `is:ignored`
50 | - "resolved yesterday" → `is:resolved` + timeRange
51 |
52 | #### Assignment Queries
53 | - "issues assigned to me" → `assigned:me` (or resolved email)
54 | - "unassigned errors" → `is:unassigned`
55 |
56 | #### Impact Queries
57 | - "issues affecting 100+ users" → `users:>100`
58 | - "high volume errors" → `events:>1000`
59 |
60 | #### Time-based Queries
61 | - "issues from last week" → Uses timeRange parameter
62 | - "errors seen today" → `lastSeen:-24h`
63 |
64 | ## Error Handling
65 |
66 | Follows the same MCP philosophy as search_events:
67 |
68 | 1. **Agent generates query** - Using static system prompt
69 | 2. **Validation Error** - Returns clear UserInputError to calling agent
70 | 3. **Calling agent decides** - Whether to retry with corrections
71 |
72 | Common validation errors:
73 | - Invalid issue field names
74 | - Incorrect query syntax
75 | - Missing required parameters
76 |
77 | This approach enables better LLM prompt caching and cleaner error boundaries.
78 |
79 | ## Issue-Specific Fields
80 |
81 | ### Status Fields
82 | - `is:` - resolved, unresolved, ignored, archived
83 | - `assigned:` - user email or "me"
84 | - `bookmarks:` - user email
85 |
86 | ### Time Fields
87 | - `firstSeen:` - When issue was first seen
88 | - `lastSeen:` - When issue was last seen
89 | - `age:` - How old the issue is
90 |
91 | ### Impact Fields
92 | - `users:` - Number of affected users
93 | - `events:` - Total event count
94 | - `level:` - error, warning, info, debug
95 |
96 | ## Limitations
97 |
98 | 1. **No Aggregations** - Issues are already grouped, no count()/sum()
99 | 2. **Limited Operators** - Simpler query syntax than events
100 | 3. **No Custom Fields** - Fixed set of issue attributes
101 |
102 | ## Common Issues and Solutions
103 |
104 | ### Issue: "Using event syntax for issues"
105 | **Cause**: Agent tries to use event search patterns
106 | **Solution**: Clear separation in prompt between issue and event search
107 |
108 | ### Issue: "Me resolution failures"
109 | **Cause**: User not authenticated or API error
110 | **Solution**: Fallback to suggesting user provide email
111 |
112 | ## Testing Queries
113 |
114 | Test various issue query patterns:
115 | - Status filters: "unresolved critical errors"
116 | - Assignment: "my issues", "unassigned bugs"
117 | - Impact: "issues affecting many users"
118 | - Time ranges: "issues from yesterday"
119 | - Combined: "unresolved errors assigned to me from last week"
120 |
121 | ## Future Improvements
122 |
123 | 1. ~~Consider removing retry mechanism - let calling agent handle retries~~ ✅ Done
124 | 2. Better integration with issue workflow commands (resolve, assign)
125 | 3. Extract shared agent tools to common module
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/CLAUDE.md:
--------------------------------------------------------------------------------
```markdown
1 | # OpenTelemetry Namespace Data
2 |
3 | This directory contains JSON files for OpenTelemetry semantic convention namespaces used by the search-events tool's embedded AI agent.
4 |
5 | ## File Format
6 |
7 | Each JSON file represents a namespace and follows this structure:
8 |
9 | ```json
10 | {
11 | "namespace": "namespace_name",
12 | "description": "Description of what this namespace covers",
13 | "attributes": {
14 | "attribute.name": {
15 | "description": "What this attribute represents",
16 | "type": "string|number|boolean",
17 | "examples": ["example1", "example2"],
18 | "note": "Additional notes (optional)",
19 | "stability": "stable|experimental|deprecated (optional)"
20 | }
21 | }
22 | }
23 | ```
24 |
25 | ## Generation Process
26 |
27 | ### OpenTelemetry Official Namespaces
28 |
29 | Most files are automatically generated from the OpenTelemetry semantic conventions repository:
30 |
31 | **Source**: https://github.com/open-telemetry/semantic-conventions/tree/main/model
32 |
33 | The generation script (`scripts/generate-otel-namespaces.ts`) fetches YAML files from the model directory and converts them to our JSON format.
34 |
35 | **Generation Command**: `pnpm run generate-otel-namespaces`
36 |
37 | **Caching**: The script caches downloaded YAML files in `.cache/` directory to avoid repeated network requests. Clear the cache to force fresh downloads.
38 |
39 | ### JSON Import Handling
40 |
41 | The JSON files are imported directly in the TypeScript code and bundled by tsdown/rolldown at build time. This approach works seamlessly with Cloudflare Workers since all data is embedded in the JavaScript bundle.
42 |
43 | ### Custom Namespaces
44 |
45 | Some namespaces are maintained manually for attributes not yet in the OpenTelemetry specification:
46 |
47 | - **mcp.json** - Model Context Protocol attributes (custom)
48 | - Any file marked with `"custom": true` will be skipped during regeneration
49 |
50 | ## Usage
51 |
52 | The `otel-semantics-lookup.ts` tool reads these JSON files to provide semantic guidance to the embedded AI agent when translating natural language queries.
53 |
54 | ## Key Namespaces
55 |
56 | ### Core OpenTelemetry Namespaces
57 |
58 | - **gen_ai** - Generative AI operations (models, tokens, conversations)
59 | - **db** - Database operations (queries, connections, systems)
60 | - **http** - HTTP client/server operations (requests, responses, status codes)
61 | - **rpc** - Remote procedure calls (gRPC, etc.)
62 | - **messaging** - Message queue operations (Kafka, RabbitMQ, etc.)
63 | - **faas** - Function as a Service operations (AWS Lambda, etc.)
64 | - **k8s** - Kubernetes operations (pods, services, deployments)
65 | - **cloud** - Cloud provider operations (AWS, Azure, GCP)
66 | - **network** - Network operations (TCP, UDP, protocols)
67 | - **server** - Server-side operations (addresses, ports)
68 | - **service** - Service identification (name, version, instance)
69 | - **error** - Error information (type, message, stack)
70 | - **user** - User identification (id, email, name)
71 |
72 | ### Custom Namespaces
73 |
74 | - **mcp** - Model Context Protocol operations (tool calls, sessions)
75 |
76 | ## Regeneration Process
77 |
78 | 1. **Automatic**: Run `pnpm run generate-otel-namespaces` to update all OpenTelemetry namespaces
79 | 2. **Manual**: Edit custom namespace files directly (they won't be overwritten)
80 | 3. **Selective**: The script only updates files for namespaces that exist in the OpenTelemetry repository
81 |
82 | ## File Organization
83 |
84 | ```
85 | data/
86 | ├── CLAUDE.md # This documentation
87 | ├── gen_ai.json # Generative AI attributes
88 | ├── db.json # Database attributes
89 | ├── http.json # HTTP attributes
90 | ├── rpc.json # RPC attributes
91 | ├── messaging.json # Messaging attributes
92 | ├── mcp.json # MCP attributes (custom)
93 | └── [other-namespaces].json
94 | ```
95 |
96 | ## Maintenance
97 |
98 | - **OpenTelemetry files**: Regenerate periodically to stay current with specifications
99 | - **Custom files**: Update manually as needed for new MCP or Sentry-specific attributes
100 | - **Validation**: Ensure all files follow the expected JSON schema format
101 |
102 | The embedded AI agent uses these definitions to provide accurate semantic guidance when users query for things like "agent calls" (maps to gen_ai.*) vs "tool calls" (maps to mcp.*).
```
--------------------------------------------------------------------------------
/docs/security.md:
--------------------------------------------------------------------------------
```markdown
1 | # Security
2 |
3 | Authentication and security patterns for the Sentry MCP server.
4 |
5 | ## OAuth Architecture
6 |
7 | The MCP server acts as an OAuth proxy between clients and Sentry:
8 |
9 | ```
10 | MCP Client → MCP Server → Sentry OAuth → Sentry API
11 | ```
12 |
13 | ### Key Components
14 |
15 | 1. **OAuth Provider** (@cloudflare/workers-oauth-provider)
16 | - Manages client authorization
17 | - Stores tokens in KV storage
18 | - Handles state management
19 | - Sets auth props in ExecutionContext
20 |
21 | 2. **Client Approval**
22 | - First-time clients require user approval
23 | - Approved clients stored in signed cookies
24 | - Per-organization access control
25 |
26 | 3. **Token Management**
27 | - Access tokens encrypted in KV storage
28 | - Tokens scoped to organizations
29 |
30 | ## Implementation Patterns
31 |
32 | ### OAuth Flow Handler
33 |
34 | See implementation: `packages/mcp-cloudflare/src/server/oauth/authorize.ts` and `packages/mcp-cloudflare/src/server/oauth/callback.ts`
35 |
36 | Key endpoints:
37 |
38 | - `/authorize` - Client approval and redirect to Sentry
39 | - `/callback` - Handle Sentry callback, store tokens
40 | - `/approve` - Process user approval
41 |
42 | ### Required OAuth Scopes
43 |
44 | ```typescript
45 | const REQUIRED_SCOPES = [
46 | "org:read",
47 | "project:read",
48 | "issue:read",
49 | "issue:write"
50 | ];
51 | ```
52 |
53 | ### Security Context
54 |
55 | ```typescript
56 | interface ServerContext {
57 | userId?: string;
58 | clientId: string;
59 | accessToken: string;
60 | grantedSkills: Set<Skill>; // Primary authorization method
61 | // grantedScopes is deprecated and will be removed Jan 1, 2026
62 | constraints: Constraints;
63 | sentryHost: string;
64 | mcpUrl?: string;
65 | }
66 | ```
67 |
68 | Context captured in closures during server build and propagated through:
69 |
70 | - Tool handlers (via closure capture and direct parameter passing)
71 | - API client initialization
72 | - Error messages (sanitized)
73 |
74 | ## Security Measures
75 |
76 | ### SSRF Protection
77 |
78 | The MCP server validates `regionUrl` parameters to prevent Server-Side Request Forgery (SSRF) attacks:
79 |
80 | ```typescript
81 | // Region URL validation rules:
82 | // 1. By default, only the base host itself is allowed as regionUrl
83 | // 2. Additional domains must be in SENTRY_ALLOWED_REGION_DOMAINS allowlist
84 | // 3. Must use HTTPS protocol for security
85 | // 4. Empty/undefined regionUrl means use the base host
86 |
87 | // Base host always allowed
88 | validateRegionUrl("https://sentry.io", "sentry.io"); // ✅ Base host match
89 | validateRegionUrl("https://mycompany.com", "mycompany.com"); // ✅ Base host match
90 |
91 | // Allowlist domains (sentry.io, us.sentry.io, de.sentry.io)
92 | validateRegionUrl("https://us.sentry.io", "sentry.io"); // ✅ In allowlist
93 | validateRegionUrl("https://de.sentry.io", "mycompany.com"); // ✅ In allowlist
94 | validateRegionUrl("https://sentry.io", "mycompany.com"); // ✅ In allowlist
95 |
96 | // Rejected domains
97 | validateRegionUrl("https://evil.com", "sentry.io"); // ❌ Not in allowlist
98 | validateRegionUrl("http://us.sentry.io", "sentry.io"); // ❌ Must use HTTPS
99 | validateRegionUrl("https://eu.sentry.io", "sentry.io"); // ❌ Not in allowlist
100 | validateRegionUrl("https://sub.mycompany.com", "mycompany.com"); // ❌ Not base host or allowlist
101 | ```
102 |
103 | Implementation: `packages/mcp-server/src/internal/tool-helpers/validate-region-url.ts`
104 |
105 | ### Prompt Injection Protection
106 |
107 | Tools that accept user input are vulnerable to prompt injection attacks. Key mitigations:
108 |
109 | 1. **Parameter Validation**: All tool inputs validated with Zod schemas
110 | 2. **URL Validation**: URLs parsed and validated before use
111 | 3. **Region Constraints**: Region URLs restricted to known Sentry domains
112 | 4. **No Direct Command Execution**: Tools don't execute user-provided commands
113 |
114 | Example protection in tools:
115 |
116 | ```typescript
117 | // URLs must be valid and from expected domains
118 | if (!issueUrl.includes('sentry.io')) {
119 | throw new UserInputError("Invalid Sentry URL");
120 | }
121 |
122 | // Region URLs validated against base host
123 | const validatedHost = validateRegionUrl(regionUrl, baseHost);
124 | ```
125 |
126 | ### State Parameter Protection
127 |
128 | The OAuth `state` is a compact HMAC-signed payload with a 10‑minute expiry:
129 |
130 | ```typescript
131 | // Payload contains only what's needed on callback
132 | type OAuthState = {
133 | clientId: string;
134 | redirectUri: string; // must be a valid URL
135 | scope: string[]; // from OAuth provider parseAuthRequest
136 | permissions?: string[]; // user selections from approval
137 | iat: number; // issued at (ms)
138 | exp: number; // expires at (ms)
139 | };
140 |
141 | // Sign: `${hex(hmacSHA256(json))}.${btoa(json)}` using COOKIE_SECRET
142 | const signed = `${signatureHex}.${btoa(JSON.stringify(state))}`;
143 |
144 | // On callback: split, verify signature, parse, check exp > Date.now()
145 | ```
146 |
147 | Implementation: `packages/mcp-cloudflare/src/server/oauth/state.ts`
148 |
149 | ### Input Validation
150 |
151 | All user inputs sanitized:
152 |
153 | - HTML content escaped
154 | - URLs validated
155 | - OAuth parameters verified
156 |
157 | ### Cookie Security
158 |
159 | ```typescript
160 | // Signed cookie for approved clients
161 | const cookie = await signCookie(
162 | `approved_clients=${JSON.stringify(approvedClients)}`,
163 | COOKIE_SECRET
164 | );
165 |
166 | // Cookie attributes
167 | "HttpOnly; Secure; SameSite=Lax; Max-Age=2592000" // 30 days
168 | ```
169 |
170 | ## Error Handling
171 |
172 | Security-aware error responses:
173 |
174 | - No token/secret exposure in errors
175 | - Generic messages for auth failures
176 | - Detailed logging server-side only
177 |
178 | ```typescript
179 | catch (error) {
180 | if (error.message.includes("token")) {
181 | return new Response("Authentication failed", { status: 401 });
182 | }
183 | // Log full error server-side
184 | console.error("OAuth error:", error);
185 | return new Response("An error occurred", { status: 500 });
186 | }
187 | ```
188 |
189 | ## Multi-Tenant Security
190 |
191 | ### Organization Isolation
192 |
193 | - Tokens scoped to organizations
194 | - Users can switch organizations
195 | - Each organization requires separate approval
196 |
197 | ### Access Control
198 |
199 | ```typescript
200 | // Verify organization access
201 | const orgs = await apiService.listOrganizations();
202 | if (!orgs.find(org => org.slug === requestedOrg)) {
203 | throw new UserInputError("No access to organization");
204 | }
205 | ```
206 |
207 | ## Environment Variables
208 |
209 | Required for OAuth:
210 |
211 | ```bash
212 | SENTRY_CLIENT_ID=your_oauth_app_id
213 | SENTRY_CLIENT_SECRET=your_oauth_app_secret
214 | COOKIE_SECRET=random_32_char_string
215 | ```
216 |
217 | ## CORS Configuration
218 |
219 | ```typescript
220 | // Allowed origins for OAuth flow
221 | const ALLOWED_ORIGINS = [
222 | "https://sentry.io",
223 | "https://*.sentry.io"
224 | ];
225 | ```
226 |
227 | ## References
228 |
229 | - OAuth implementation: `packages/mcp-cloudflare/src/server/oauth/*`
230 | - Cookie utilities: `packages/mcp-cloudflare/src/server/utils/cookies.ts`
231 | - OAuth Provider: `packages/mcp-cloudflare/src/server/bindings.ts`
232 | - Sentry OAuth docs: <https://docs.sentry.io/api/guides/oauth/>
233 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/use-sentry/CLAUDE.md:
--------------------------------------------------------------------------------
```markdown
1 | # use_sentry Tool - Embedded Agent Documentation
2 |
3 | This tool embeds an AI agent (GPT-5) that can call all Sentry MCP tools to fulfill natural language requests.
4 |
5 | ## Architecture Overview
6 |
7 | The `use_sentry` tool uses an "agent-in-tool" pattern with **in-memory MCP protocol**:
8 |
9 | 1. **MCP Tool Handler** (`handler.ts`) - Receives natural language request from calling agent
10 | 2. **In-Memory MCP Server** - Creates internal MCP server with InMemoryTransport from MCP SDK
11 | 3. **MCP Client** - Embedded agent accesses tools through MCP protocol (zero network overhead)
12 | 4. **Embedded AI Agent** (`agent.ts`) - Calls tools via MCP client to fulfill request
13 | 5. **Result Return** - Returns final results directly to calling agent
14 |
15 | **Key Innovation**: Uses `InMemoryTransport.createLinkedPair()` from `@modelcontextprotocol/sdk` for full MCP protocol compliance without network overhead.
16 |
17 | ## Key Components
18 |
19 | ### Tool Wrapper (`tool-wrapper.ts`)
20 |
21 | The `wrapToolForAgent()` function is a **generic wrapper** that can wrap ANY MCP tool:
22 |
23 | ```typescript
24 | wrapToolForAgent(toolDefinition, { context })
25 | ```
26 |
27 | **What it does:**
28 | - Takes any MCP tool definition (from `defineTool`)
29 | - Pre-binds the ServerContext so the agent doesn't need it
30 | - Applies session constraints automatically (org, project, region)
31 | - Uses `agentTool()` for automatic error handling
32 | - Returns structured `{error?, result?}` responses
33 |
34 | **Benefits:**
35 | - Single implementation works for all tools
36 | - DRY principle - no duplication per tool
37 | - Consistent error handling across all tools
38 | - Type-safe parameter handling
39 |
40 | ### Embedded Agent (`agent.ts`)
41 |
42 | The agent has access to ALL 19 Sentry MCP tools (20 total - use_sentry itself):
43 |
44 | **Discovery Tools:**
45 | - `whoami` - Get authenticated user info
46 | - `find_organizations` - List available organizations
47 | - `find_teams` - List teams in an organization
48 | - `find_projects` - List projects
49 | - `find_releases` - Find releases
50 |
51 | **Issue Management:**
52 | - `get_issue_details` - Get detailed issue information
53 | - `search_issues` - Search for grouped issues
54 | - `update_issue` - Update issue status/properties
55 | - `analyze_issue_with_seer` - Get AI analysis of issues
56 |
57 | **Event Analysis:**
58 | - `search_events` - Search events with aggregations
59 | - `get_trace_details` - Get trace information
60 | - `get_event_attachment` - Download event attachments
61 |
62 | **Resource Creation:**
63 | - `create_team` - Create a new team
64 | - `create_project` - Create a new project
65 | - `update_project` - Update project settings
66 | - `create_dsn` - Create a new DSN
67 | - `find_dsns` - List project DSNs
68 |
69 | **Documentation:**
70 | - `search_docs` - Search Sentry documentation
71 | - `get_doc` - Fetch full documentation pages
72 |
73 | ### Agent Behavior
74 |
75 | **Multi-step operations:**
76 | The agent can chain multiple tool calls:
77 | 1. Call `find_organizations` to discover orgs
78 | 2. Call `find_projects` to find specific project
79 | 3. Call `search_issues` to get issues in that project
80 |
81 | **Constraint handling:**
82 | - If ServerContext has `constraints.organizationSlug`, it's automatically injected
83 | - If ServerContext has `constraints.projectSlug`, it's automatically injected
84 | - Agent focuses on parameters that aren't pre-constrained
85 |
86 | **Error handling:**
87 | - Each tool returns `{error?, result?}` via `agentTool()` wrapper
88 | - Agent can see errors and retry with corrections
89 | - Agent can report errors to user if retry fails
90 |
91 | ## Example Request Flows
92 |
93 | ### Simple Request: "Who am I?"
94 | ```
95 | User → use_sentry("who am I")
96 | → Agent calls whoami tool
97 | → Returns user info
98 | ```
99 |
100 | ### Complex Request: "Find unresolved issues in frontend"
101 | ```
102 | User → use_sentry("find unresolved issues in frontend")
103 | → Agent calls find_projects(query="frontend")
104 | → Agent calls search_issues(projectSlug="frontend", query="is:unresolved")
105 | → Returns issues list
106 | ```
107 |
108 | ### Multi-tool Request: "Analyze the top error"
109 | ```
110 | User → use_sentry("analyze the top error")
111 | → Agent calls search_issues(query="is:unresolved", sort="-count()")
112 | → Agent extracts top issue ID
113 | → Agent calls analyze_issue_with_seer(issueId="...")
114 | → Returns analysis
115 | ```
116 |
117 | ## Configuration
118 |
119 | - **System Prompt**: Comprehensive guide in `config.ts`
120 | - **Output Schema**: Simple `{ result: string }` format
121 | - **Max Steps**: 10 (allows complex multi-tool operations)
122 | - **Model**: GPT-5 via OpenAI (configurable via `configureOpenAIProvider`)
123 |
124 | ## Debugging
125 |
126 | ### Trace Parameter
127 |
128 | The `trace` parameter enables visibility into the embedded agent's tool execution:
129 |
130 | **Usage:**
131 | ```typescript
132 | use_sentry({
133 | request: "what's up with https://sentry.io/issues/123",
134 | trace: true
135 | })
136 | ```
137 |
138 | **Output Format:**
139 | When `trace: true`, the response appends a "Tool Call Trace" section showing all tool calls:
140 |
141 | ```markdown
142 | ## Tool Call Trace
143 |
144 | ### 1. get_issue_details
145 |
146 | **Arguments:**
147 | ```json
148 | {
149 | "issueUrl": "https://sentry.io/issues/123"
150 | }
151 | ```
152 |
153 | ### 2. analyze_issue_with_seer
154 |
155 | **Arguments:**
156 | ```json
157 | {
158 | "issueId": "PROJECT-123"
159 | }
160 | ```
161 | ```
162 |
163 | **When to use:**
164 | - Debugging unexpected agent behavior
165 | - Verifying the agent calls tools correctly
166 | - Understanding multi-step request flows
167 | - Diagnosing parameter passing issues
168 |
169 | ## Error Handling
170 |
171 | The tool follows MCP's single-attempt philosophy:
172 |
173 | 1. **Agent calls tools** - Multiple calls if needed
174 | 2. **Tool errors** - Returned as `{error: "..."}` to agent
175 | 3. **Agent retries** - Can adjust parameters and retry
176 | 4. **Final failure** - Agent returns clear error to user
177 | 5. **Calling agent decides** - Whether to retry the entire request
178 |
179 | **Security:**
180 | - All error messages are trusted (Sentry API, UserInputError, system templates)
181 | - No prompt injection risk - errors are sanitized
182 |
183 | ## Testing
184 |
185 | ### Manual Testing
186 |
187 | The preferred way to test the use_sentry tool is using the MCP test client:
188 |
189 | ```bash
190 | # Test with local dev server (default: http://localhost:5173)
191 | pnpm -w run cli --agent "who am I"
192 |
193 | # Test against production
194 | pnpm -w run cli --mcp-host=https://mcp.sentry.dev --agent "who am I"
195 |
196 | # Test with local stdio mode (requires SENTRY_ACCESS_TOKEN)
197 | pnpm -w run cli --access-token=TOKEN --agent "who am I"
198 | ```
199 |
200 | Note: The CLI defaults to `http://localhost:5173`. Override with `--mcp-host` or set `MCP_URL` environment variable.
201 |
202 | ### Test Scenarios
203 |
204 | - **Single tool**: "who am I" → calls whoami
205 | - **Discovery**: "list my projects" → calls find_projects
206 | - **Search**: "show me errors from yesterday" → calls search_events
207 | - **Multi-step**: "find issues in frontend and analyze the top one"
208 | - **Constrained**: With org constraint, verify agent doesn't need to provide org
209 |
210 | ## Implementation Notes
211 |
212 | ### Generic Wrapper Pattern
213 |
214 | The key innovation is using ONE wrapper for ALL tools:
215 |
216 | ```typescript
217 | // Instead of 18 separate factory functions:
218 | createWhoamiTool()
219 | createFindOrgsTool()
220 | createFindProjectsTool()
221 | // ...
222 |
223 | // We use a single generic wrapper:
224 | wrapToolForAgent(whoamiTool, { context })
225 | wrapToolForAgent(findOrganizationsTool, { context })
226 | wrapToolForAgent(findProjectsTool, { context })
227 | // ...
228 | ```
229 |
230 | This makes the code:
231 | - Easier to maintain (one implementation)
232 | - More consistent (same behavior for all tools)
233 | - Easier to extend (add new tools without new wrapper functions)
234 |
235 | ### Constraint Injection
236 |
237 | Session constraints are automatically injected by `wrapToolForAgent()`:
238 |
239 | ```typescript
240 | // If context.constraints.organizationSlug = "my-org"
241 | // Agent calls: find_projects()
242 | // Actual tool call: find_projects({ organizationSlug: "my-org" })
243 | ```
244 |
245 | This ensures the agent respects session scope without needing to know about it.
246 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/vite-env.d.ts:
--------------------------------------------------------------------------------
```typescript
1 | /// <reference types="vite/client" />
2 |
```
--------------------------------------------------------------------------------
/vitest.workspace.ts:
--------------------------------------------------------------------------------
```typescript
1 | export default ["packages/*", "apps/*"];
2 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/utils/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | export * from "./chat-error-handler";
2 | export * from "./cursor-deeplink";
3 |
```
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "recommendations": ["biomejs.biome"],
3 | "unwantedRecommendations": []
4 | }
5 |
```
--------------------------------------------------------------------------------
/.vscode/mcp.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "servers": {
3 | "sentry": {
4 | "url": "https://mcp.sentry.dev/mcp"
5 | }
6 | }
7 | }
8 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/test-setup.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { startMockServer } from "@sentry/mcp-server-mocks";
2 |
3 | startMockServer({ ignoreOpenAI: true });
4 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/api-client/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | export * from "./client";
2 | export * from "./schema";
3 | export * from "./types";
4 | export * from "./errors";
5 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/src/version.ts:
--------------------------------------------------------------------------------
```typescript
1 | export const LIB_VERSION =
2 | (typeof process !== "undefined" && process.env?.npm_package_version) ||
3 | "0.0.0";
4 |
```
--------------------------------------------------------------------------------
/.cursor/mcp.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "mcpServers": {
3 | "sentry": {
4 | "type": "http",
5 | "url": "https://mcp.sentry.dev/mcp/sentry/mcp-server"
6 | }
7 | }
8 | }
9 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/use-sentry/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Export the use_sentry handler
2 | export { default } from "./handler";
3 |
4 | // Export the agent for testing
5 | export { useSentryAgent } from "./agent";
6 |
```
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
```yaml
1 | coverage:
2 | status:
3 | project:
4 | default:
5 | informational: true
6 | patch:
7 | default:
8 | informational: true
9 |
10 | comment: false
11 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/search-events/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Export the search-events handler
2 | export { default } from "./handler";
3 |
4 | // Export the agent for testing
5 | export { searchEventsAgent } from "./agent";
6 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/search-issues/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Export the search-issues handler
2 | export { default } from "./handler";
3 |
4 | // Export the agent for testing
5 | export { searchIssuesAgent } from "./agent";
6 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-tsconfig/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "@sentry/mcp-server-tsconfig",
3 | "version": "0.24.0",
4 | "private": true,
5 | "files": [
6 | "tsconfig.base.json",
7 | "tsconfig.vite.json"
8 | ]
9 | }
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.client.json" },
5 | { "path": "./tsconfig.node.json" },
6 | { "path": "./tsconfig.server.json" }
7 | ]
8 | }
9 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/vitest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { defineConfig } from "vitest/config";
2 |
3 | export default defineConfig({
4 | test: {
5 | globals: true,
6 | environment: "node",
7 | testTimeout: 30000,
8 | },
9 | });
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/lib/utils.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { clsx, type ClassValue } from "clsx";
2 | import { twMerge } from "tailwind-merge";
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
7 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/utils/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | export { FIXTURES } from "./fixtures";
2 | export { NoOpTaskRunner } from "./runner";
3 | export {
4 | ToolPredictionScorer,
5 | type ExpectedToolCall,
6 | } from "./toolPredictionScorer";
7 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/ui/note.tsx:
--------------------------------------------------------------------------------
```typescript
1 | export default function Note({ children }: { children: React.ReactNode }) {
2 | return (
3 | <div className="mb-6">
4 | <p className="text-slate-300 text-base">{children}</p>
5 | </div>
6 | );
7 | }
8 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/version.ts:
--------------------------------------------------------------------------------
```typescript
1 | export const LIB_VERSION =
2 | (typeof process !== "undefined" && process.env?.npm_package_version) ||
3 | "0.0.0";
4 |
5 | export const USER_AGENT = `sentry-mcp/${LIB_VERSION} (https://mcp.sentry.dev)`;
6 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/tool-helpers/define.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type { z } from "zod";
2 | import type { ToolConfig } from "../../tools/types";
3 |
4 | export function defineTool<TSchema extends Record<string, z.ZodType>>(
5 | config: ToolConfig<TSchema>,
6 | ) {
7 | return config;
8 | }
9 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "../mcp-server-tsconfig/tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "./dist",
5 | "rootDir": "./src"
6 | },
7 | "include": ["src/**/*"],
8 | "exclude": ["node_modules", "dist", "**/*.test.ts"]
9 | }
```
--------------------------------------------------------------------------------
/packages/mcp-server/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "@sentry/mcp-server-tsconfig/tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "./dist",
5 | "rootDir": "./src"
6 | },
7 | "include": ["src/**/*"],
8 | "exclude": ["node_modules", "dist", "**/*.test.ts"]
9 | }
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "@sentry/mcp-server-tsconfig/tsconfig.base.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
5 | "outDir": "dist",
6 | "rootDir": "src"
7 | },
8 | "include": ["src"]
9 | }
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "@sentry/mcp-server-tsconfig/tsconfig.base.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
5 | "outDir": "dist",
6 | "rootDir": "src"
7 | },
8 | "include": ["src"]
9 | }
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "@sentry/mcp-server-tsconfig/tsconfig.base.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
5 | "outDir": "dist",
6 | "rootDir": "src"
7 | },
8 | "include": ["src"]
9 | }
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/tsconfig.server.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "./tsconfig.node.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.server.tsbuildinfo",
5 | "types": [
6 | "@cloudflare/workers-types"
7 | ]
8 | },
9 | "include": [
10 | "src/server"
11 | ]
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/tsconfig.node.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "@sentry/mcp-server-tsconfig/tsconfig.base.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5 | "outDir": "dist",
6 | "rootDir": ""
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/tsdown.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { defineConfig } from "tsdown";
2 |
3 | export default defineConfig({
4 | entry: ["src/**/*.ts"],
5 | format: ["cjs", "esm"], // Build for commonJS and ESmodules
6 | dts: true, // Generate declaration file (.d.ts)
7 | sourcemap: true,
8 | clean: true,
9 | });
10 |
```
--------------------------------------------------------------------------------
/packages/smoke-tests/vitest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { defineConfig } from "vitest/config";
2 |
3 | export default defineConfig({
4 | test: {
5 | globals: true,
6 | environment: "node",
7 | testTimeout: 30000, // 30 seconds for network requests
8 | hookTimeout: 60000, // 60 seconds for setup/teardown
9 | },
10 | });
11 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/system.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "system",
3 | "description": "Describes System attributes",
4 | "attributes": {
5 | "system.device": {
6 | "description": "The device identifier",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["(identifier)"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/src/fixtures/event-attachments.json:
--------------------------------------------------------------------------------
```json
1 | [
2 | {
3 | "id": "123",
4 | "name": "screenshot.png",
5 | "type": "event.attachment",
6 | "size": 1024,
7 | "mimetype": "image/png",
8 | "dateCreated": "2025-04-08T21:15:04.000Z",
9 | "sha1": "abc123def456",
10 | "headers": {
11 | "Content-Type": "image/png"
12 | }
13 | }
14 | ]
15 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/go.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "go",
3 | "description": "This document defines Go related attributes.\n",
4 | "attributes": {
5 | "go.memory.type": {
6 | "description": "The type of memory.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["stack", "other"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/bin/bump-version.sh:
--------------------------------------------------------------------------------
```bash
1 | #!/bin/bash
2 | ### Example of a version-bumping script for an NPM project.
3 | ### Located at: ./bin/bump-version.sh
4 | set -eux
5 | OLD_VERSION="${1}"
6 | NEW_VERSION="${2}"
7 |
8 | # Do not tag and commit changes made by "npm version"
9 | export npm_config_git_tag_version=false
10 | pnpm -r exec npm version "${NEW_VERSION}"
11 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/nodejs.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "nodejs",
3 | "description": "Describes Node.js related attributes.",
4 | "attributes": {
5 | "nodejs.eventloop.state": {
6 | "description": "The state of event loop time.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["active", "idle"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/linux.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "linux",
3 | "description": "Describes Linux Memory attributes",
4 | "attributes": {
5 | "linux.memory.slab.state": {
6 | "description": "The Linux Slab memory state",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["reclaimable", "unreclaimable"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/server/oauth/routes/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { Hono } from "hono";
2 | import type { Env } from "../../types";
3 | import authorizeApp from "./authorize";
4 | import callbackApp from "./callback";
5 |
6 | // Compose and export the main OAuth Hono app
7 | export default new Hono<{ Bindings: Env }>()
8 | .route("/authorize", authorizeApp)
9 | .route("/callback", callbackApp);
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/disk.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "disk",
3 | "description": "These attributes may be used for any disk related operation.\n",
4 | "attributes": {
5 | "disk.io.direction": {
6 | "description": "The disk IO operation direction.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["read", "write"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/tsconfig.client.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "extends": "@sentry/mcp-server-tsconfig/tsconfig.vite.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.client.tsbuildinfo",
5 | "baseUrl": ".",
6 | "paths": {
7 | "@/*": [
8 | "./src/*"
9 | ]
10 | },
11 | "outDir": "dist",
12 | "rootDir": "src"
13 | },
14 | "include": ["src/client"]
15 | }
16 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/constants.ts:
--------------------------------------------------------------------------------
```typescript
1 | // https://docs.sentry.io/api/permissions/
2 | export const SCOPES = {
3 | "org:read": "Read organization data",
4 | "project:write": "Write project data",
5 | "team:write": "Write team data",
6 | "event:write": "Write event data",
7 | };
8 |
9 | export const NPM_PACKAGE_NAME = "@sentry/mcp-server";
10 |
11 | export const NPM_REMOTE_NAME = "mcp-remote";
12 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/cpython.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "cpython",
3 | "description": "This document defines CPython related attributes.\n",
4 | "attributes": {
5 | "cpython.gc.generation": {
6 | "description": "Value of the garbage collector collection generation.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["0", "1", "2"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/tool-helpers/issue.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Re-export of issue parsing utilities for tool modules.
3 | * These utilities handle flexible input formats for Sentry issues.
4 | */
5 | export { parseIssueParams } from "../../internal/issue-helpers";
6 |
7 | /**
8 | * Re-export of issue formatting utilities for tool modules.
9 | */
10 | export { formatIssueOutput } from "../../internal/formatting";
11 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/instrument.ts:
--------------------------------------------------------------------------------
```typescript
1 | import * as Sentry from "@sentry/react";
2 | import { sentryBeforeSend } from "@sentry/mcp-core/telem/sentry";
3 |
4 | Sentry.init({
5 | dsn: import.meta.env.VITE_SENTRY_DSN,
6 | sendDefaultPii: true,
7 | tracesSampleRate: 1,
8 | beforeSend: sentryBeforeSend,
9 | environment:
10 | import.meta.env.VITE_SENTRY_ENVIRONMENT ?? import.meta.env.NODE_ENV,
11 | });
12 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/log.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "log",
3 | "description": "This document defines log attributes\n",
4 | "attributes": {
5 | "log.iostream": {
6 | "description": "The stream associated with the log. See below for a list of well-known values.\n",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["stdout", "stderr"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-tsconfig/tsconfig.vite.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Vite (React) Library",
4 | "extends": "./tsconfig.base.json",
5 | "compilerOptions": {
6 | "jsx": "react-jsx",
7 | "target": "ES2020",
8 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
9 | "useDefineForClassFields": true,
10 | "module": "ESNext",
11 | "types": ["vite/client"]
12 | }
13 | }
14 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/dotnet.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "dotnet",
3 | "description": "This document defines .NET related attributes.\n",
4 | "attributes": {
5 | "dotnet.gc.heap.generation": {
6 | "description": "Name of the garbage collector managed heap generation.",
7 | "type": "string",
8 | "stability": "stable",
9 | "examples": ["gen0", "gen1", "gen2", "loh", "poh"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/smoke-tests/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "@sentry/mcp-smoke-tests",
3 | "version": "0.24.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "test": "vitest run",
8 | "test:ci": "vitest run --reporter=default --reporter=junit --outputFile=tests.junit.xml",
9 | "test:watch": "vitest"
10 | },
11 | "devDependencies": {
12 | "vitest": "catalog:",
13 | "@types/node": "catalog:"
14 | }
15 | }
16 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/src/fixtures/trace-items-attributes-logs-number.json:
--------------------------------------------------------------------------------
```json
1 | [
2 | {
3 | "key": "severity_number",
4 | "name": "Severity Number"
5 | },
6 | {
7 | "key": "sentry.observed_timestamp_nanos",
8 | "name": "Observed Timestamp (Nanos)"
9 | },
10 | {
11 | "key": "timestamp",
12 | "name": "Timestamp"
13 | },
14 | {
15 | "key": "custom.duration",
16 | "name": "Custom Duration"
17 | },
18 | {
19 | "key": "custom.bytes",
20 | "name": "Custom Bytes"
21 | }
22 | ]
23 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/vitest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | /// <reference types="vitest" />
2 | import { defineConfig } from "vitest/config";
3 |
4 | export default defineConfig({
5 | test: {
6 | include: ["**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
7 | coverage: {
8 | provider: "v8",
9 | reporter: ["text", "json", "html"],
10 | include: ["**/*.ts"],
11 | },
12 | setupFiles: ["dotenv/config", "src/test-setup.ts"],
13 | },
14 | });
15 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/usecases/index.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import FixBugs from "./fix-bugs";
2 | import Instrument from "./instrument";
3 | import SearchThings from "./search-things";
4 |
5 | export default function UseCases() {
6 | return (
7 | <section className="scroll-mt-20 grid lg:grid-cols-3 relative container mx-auto border-y border-dashed border-white/20">
8 | <FixBugs />
9 | <Instrument />
10 | <SearchThings />
11 | </section>
12 | );
13 | }
14 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/ui/prose.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { cn } from "@/client/lib/utils";
2 |
3 | export function Prose({
4 | children,
5 | className,
6 | ...props
7 | }: { children: React.ReactNode } & React.HTMLAttributes<HTMLDivElement>) {
8 | return (
9 | <div
10 | className={cn(
11 | "prose prose-invert prose-slate max-w-none prose-a:text-violet-300",
12 | className,
13 | )}
14 | {...props}
15 | >
16 | {children}
17 | </div>
18 | );
19 | }
20 |
```
--------------------------------------------------------------------------------
/.claude/commands/gh-review.md:
--------------------------------------------------------------------------------
```markdown
1 | Address feedback and checks in a Pull Request.
2 |
3 | We use the GitHub CLI (`gh`) to manage pull requests.
4 |
5 | Review the status checks for this PR, and identify any failures from them.
6 |
7 | If there are no failures, review the PR feedback.
8 |
9 | Do NOT assume feedback is valid. You should always verify that the feedback is truthful (the bug is real, for example), and then attempt to address it.
10 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/vitest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | /// <reference types="vitest" />
2 | import { defineConfig } from "vitest/config";
3 |
4 | export default defineConfig({
5 | test: {
6 | include: ["**/*.eval.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
7 | reporters: ["vitest-evals/reporter"],
8 | coverage: {
9 | provider: "v8",
10 | reporter: ["text", "json", "html"],
11 | include: ["**/*.ts"],
12 | },
13 | setupFiles: ["./src/setup-env.ts"],
14 | },
15 | });
16 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/elasticsearch.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "elasticsearch",
3 | "description": "This section defines attributes for Elasticsearch.\n",
4 | "attributes": {
5 | "elasticsearch.node.name": {
6 | "description": "Represents the human-readable identifier of the node/instance to which a request was routed.\n",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["instance-0000000001"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/server/oauth/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Re-export the main OAuth Hono app
2 | export { default } from "./routes/index";
3 |
4 | // Re-export helper functions and constants for external use
5 | export { tokenExchangeCallback } from "./helpers";
6 | export {
7 | SENTRY_AUTH_URL,
8 | SENTRY_TOKEN_URL,
9 | TokenResponseSchema,
10 | } from "./constants";
11 | export {
12 | getUpstreamAuthorizeUrl,
13 | exchangeCodeForAccessToken,
14 | refreshAccessToken,
15 | } from "./helpers";
16 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/animation/browser-ui/seer-clipmask.tsx:
--------------------------------------------------------------------------------
```typescript
1 | export default function SeerClipMask({ id }: { id: string }) {
2 | return (
3 | <svg className="absolute" height="0" width="0">
4 | <title>Seer's Triangle</title>
5 | <defs>
6 | <clipPath clipPathUnits="objectBoundingBox" id={id}>
7 | <path d="M0.5 0 A2.5 2.5 0 0 1 1 0.866025 A2.5 2.5 0 0 1 0 0.866025 A2.5 2.5 0 0 1 0.5 0 Z" />
8 | </clipPath>
9 | </defs>
10 | </svg>
11 | );
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/opentracing.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "opentracing",
3 | "description": "Attributes used by the OpenTracing Shim layer.",
4 | "attributes": {
5 | "opentracing.ref_type": {
6 | "description": "Parent-child Reference type",
7 | "type": "string",
8 | "note": "The causal relationship between a child Span and a parent Span.\n",
9 | "stability": "development",
10 | "examples": ["child_of", "follows_from"]
11 | }
12 | }
13 | }
14 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/components.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "new-york",
4 | "rsc": false,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "",
8 | "css": "src/client/index.css",
9 | "baseColor": "neutral",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils",
16 | "ui": "@/components/ui",
17 | "lib": "@/lib",
18 | "hooks": "@/hooks"
19 | },
20 | "iconLibrary": "lucide"
21 | }
22 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/telem/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Telemetry and observability utilities.
3 | *
4 | * This module provides logging, error tracking, and instrumentation utilities
5 | * for monitoring and debugging MCP server operations.
6 | */
7 |
8 | // Re-export logging utilities
9 | export {
10 | getLogger,
11 | logDebug,
12 | logInfo,
13 | logWarn,
14 | logError,
15 | logIssue,
16 | type LogIssueOptions,
17 | } from "./logging";
18 |
19 | // Re-export Sentry instrumentation utilities
20 | export { sentryBeforeSend } from "./sentry";
21 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/peer.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "peer",
3 | "description": "Operations that access some remote service.\n",
4 | "attributes": {
5 | "peer.service": {
6 | "description": "The [`service.name`](/docs/resource/README.md#service) of the remote service. SHOULD be equal to the actual `service.name` resource attribute of the remote service if any.\n",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["AuthTokenCache"]
10 | }
11 | }
12 | }
13 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/utils/runner.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * A no-op task runner that doesn't execute tools, just returns the input
3 | * for use with ToolPredictionScorer. This allows tests to focus on predicting
4 | * which tools would be called without actually executing them.
5 | */
6 | export function NoOpTaskRunner() {
7 | return async function NoOpTaskRunner(input: string) {
8 | // Just return the input as the result, no tool execution
9 | return {
10 | result: input,
11 | toolCalls: [],
12 | };
13 | };
14 | }
15 |
```
--------------------------------------------------------------------------------
/packages/mcp-server/tsdown.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { defineConfig } from "tsdown";
2 |
3 | export default defineConfig({
4 | entry: ["src/**/*.ts", "!src/**/*.test.ts"],
5 | format: ["cjs", "esm"],
6 | dts: true,
7 | sourcemap: true,
8 | clean: true,
9 | external: [
10 | // Only mark test-only packages as external
11 | "@sentry/mcp-server-mocks",
12 | // Everything else (including @sentry/mcp-core) will be bundled
13 | ],
14 | env: {
15 | SENTRY_ENVIRONMENT: "stdio",
16 | npm_package_version: "{{version}}",
17 | },
18 | });
19 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/fragments/setup-guide.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import {
2 | AccordionContent,
3 | AccordionItem,
4 | AccordionTrigger,
5 | } from "../ui/accordion";
6 | import { Prose } from "../ui/prose";
7 |
8 | export default function SetupGuide({
9 | id,
10 | title,
11 | children,
12 | }: { id: string; title: string; children: React.ReactNode }) {
13 | return (
14 | <AccordionItem value={id}>
15 | <AccordionTrigger>{title}</AccordionTrigger>
16 | <AccordionContent>
17 | <Prose>{children}</Prose>
18 | </AccordionContent>
19 | </AccordionItem>
20 | );
21 | }
22 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/skillDefinitions.ts:
--------------------------------------------------------------------------------
```typescript
1 | import skillDefinitionsData from "./skillDefinitions.json";
2 |
3 | // Skill definition for UI/external consumption
4 | export interface SkillDefinition {
5 | id: string;
6 | name: string;
7 | description: string;
8 | defaultEnabled: boolean;
9 | order: number;
10 | toolCount?: number;
11 | tools?: Array<{
12 | name: string;
13 | description: string;
14 | requiredScopes: string[];
15 | }>;
16 | }
17 |
18 | const skillDefinitions = skillDefinitionsData as SkillDefinition[];
19 |
20 | export default skillDefinitions;
21 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/toolDefinitions.ts:
--------------------------------------------------------------------------------
```typescript
1 | import toolDefinitionsData from "./toolDefinitions.json";
2 | import type { Scope } from "./permissions";
3 |
4 | // Tool definition for UI/external consumption
5 | export interface ToolDefinition {
6 | name: string;
7 | description: string;
8 | // Full JSON Schema object for parameters
9 | inputSchema: unknown;
10 | // Sentry API scopes required to use the tool
11 | requiredScopes: Scope[];
12 | }
13 |
14 | const toolDefinitions = toolDefinitionsData as ToolDefinition[];
15 |
16 | export default toolDefinitions;
17 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/src/constants.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Default MCP Server
2 | export const DEFAULT_MCP_URL = "https://mcp.sentry.dev";
3 |
4 | // Default AI model - using GPT-4
5 | export const DEFAULT_MODEL = "gpt-4o";
6 |
7 | // OAuth configuration
8 | export const OAUTH_REDIRECT_PORT = 8765;
9 | export const OAUTH_REDIRECT_URI = `http://localhost:${OAUTH_REDIRECT_PORT}/callback`;
10 |
11 | // Default OAuth scopes
12 | export const DEFAULT_OAUTH_SCOPES = [
13 | "org:read",
14 | "project:read",
15 | "project:write",
16 | "team:read",
17 | "team:write",
18 | "event:write",
19 | ];
20 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/ui/icon.tsx:
--------------------------------------------------------------------------------
```typescript
1 | interface IconProps {
2 | className?: string;
3 | path: string;
4 | viewBox?: string;
5 | title?: string;
6 | }
7 |
8 | export function Icon({
9 | className,
10 | path,
11 | viewBox = "0 0 32 32",
12 | title = "Icon",
13 | }: IconProps) {
14 | return (
15 | <svg
16 | className={className}
17 | viewBox={viewBox}
18 | fill="none"
19 | xmlns="http://www.w3.org/2000/svg"
20 | aria-labelledby="icon-title"
21 | >
22 | <title id="icon-title">{title}</title>
23 | <path d={path} fill="currentColor" />
24 | </svg>
25 | );
26 | }
27 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/ui/section.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import type { ReactNode } from "react";
2 | import { Heading } from "./base";
3 | import { cn } from "@/client/lib/utils";
4 |
5 | export default function Section({
6 | heading,
7 | children,
8 | className,
9 | ...props
10 | }: {
11 | heading?: string | ReactNode;
12 | children: ReactNode;
13 | className?: string;
14 | } & React.HTMLAttributes<HTMLDivElement>) {
15 | return (
16 | <section className={cn("space-y-4 mb-10", className)} {...props}>
17 | {heading && <Heading>{heading}</Heading>}
18 | {children}
19 | </section>
20 | );
21 | }
22 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/src/types.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Shared types for MCP client
2 |
3 | export interface MCPConnection {
4 | client: any; // TODO: Replace with proper type from experimental MCP client
5 | tools: Map<string, any>;
6 | disconnect: () => Promise<void>;
7 | sessionId: string;
8 | transport: "stdio" | "http";
9 | }
10 |
11 | export interface MCPConfig {
12 | accessToken: string;
13 | host?: string;
14 | sentryDsn?: string;
15 | useAgentEndpoint?: boolean;
16 | }
17 |
18 | export interface RemoteMCPConfig {
19 | mcpHost?: string;
20 | accessToken?: string;
21 | useAgentEndpoint?: boolean;
22 | }
23 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/src/fixtures/trace-items-attributes-spans-number.json:
--------------------------------------------------------------------------------
```json
1 | [
2 | {
3 | "key": "span.duration",
4 | "name": "Span Duration"
5 | },
6 | {
7 | "key": "transaction.duration",
8 | "name": "Transaction Duration"
9 | },
10 | {
11 | "key": "http.status_code",
12 | "name": "HTTP Status Code"
13 | },
14 | {
15 | "key": "custom.count",
16 | "name": "Custom Count"
17 | },
18 | {
19 | "key": "custom.score",
20 | "name": "Custom Score"
21 | },
22 | {
23 | "key": "custom.latency_ms",
24 | "name": "Custom Latency (ms)"
25 | },
26 | {
27 | "key": "custom.db.pool_size",
28 | "name": "Custom DB Pool Size"
29 | }
30 | ]
31 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/server/oauth/constants.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { z } from "zod";
2 |
3 | // Sentry OAuth endpoints
4 | export const SENTRY_AUTH_URL = "/oauth/authorize/";
5 | export const SENTRY_TOKEN_URL = "/oauth/token/";
6 |
7 | export const TokenResponseSchema = z.object({
8 | access_token: z.string(),
9 | refresh_token: z.string(),
10 | token_type: z.string(), // should be "bearer"
11 | expires_in: z.number(),
12 | expires_at: z.string().datetime(),
13 | user: z.object({
14 | email: z.string().email(),
15 | id: z.string(),
16 | name: z.string().nullable(),
17 | }),
18 | scope: z.string(),
19 | });
20 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/list-organizations.eval.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describeEval } from "vitest-evals";
2 | import { NoOpTaskRunner, ToolPredictionScorer } from "./utils";
3 |
4 | describeEval("list-organizations", {
5 | data: async () => {
6 | return [
7 | {
8 | input: `What organizations do I have access to in Sentry`,
9 | expectedTools: [
10 | {
11 | name: "find_organizations",
12 | arguments: {},
13 | },
14 | ],
15 | },
16 | ];
17 | },
18 | task: NoOpTaskRunner(),
19 | scorers: [ToolPredictionScorer()],
20 | threshold: 0.6,
21 | timeout: 30000,
22 | });
23 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/tool-helpers/formatting.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type { z } from "zod";
2 | import type { AssignedToSchema } from "../../api-client/index";
3 |
4 | type AssignedTo = z.infer<typeof AssignedToSchema>;
5 |
6 | /**
7 | * Helper function to format assignedTo field for display
8 | */
9 | export function formatAssignedTo(assignedTo: AssignedTo): string {
10 | if (!assignedTo) {
11 | return "Unassigned";
12 | }
13 |
14 | if (typeof assignedTo === "string") {
15 | return assignedTo;
16 | }
17 |
18 | if (typeof assignedTo === "object" && assignedTo.name) {
19 | return assignedTo.name;
20 | }
21 |
22 | return "Unknown";
23 | }
24 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/profile.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "profile",
3 | "description": "Describes the origin of a single frame in a Profile.\n",
4 | "attributes": {
5 | "profile.frame.type": {
6 | "description": "Describes the interpreter or compiler of a single frame.\n",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": [
10 | "dotnet",
11 | "jvm",
12 | "kernel",
13 | "native",
14 | "perl",
15 | "php",
16 | "cpython",
17 | "ruby",
18 | "v8js",
19 | "beam",
20 | "go",
21 | "rust"
22 | ]
23 | }
24 | }
25 | }
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/thread.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "thread",
3 | "description": "These attributes may be used for any operation to store information about a thread that started a span.\n",
4 | "attributes": {
5 | "thread.id": {
6 | "description": "Current \"managed\" thread ID (as opposed to OS thread ID).\n",
7 | "type": "number",
8 | "stability": "development",
9 | "examples": ["42"]
10 | },
11 | "thread.name": {
12 | "description": "Current thread name.\n",
13 | "type": "string",
14 | "stability": "development",
15 | "examples": ["main"]
16 | }
17 | }
18 | }
19 |
```
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll.biome": "explicit"
5 | },
6 | "files.trimTrailingWhitespace": false,
7 | "files.trimFinalNewlines": false,
8 | "files.insertFinalNewline": true,
9 | "cursor.general.enableShadowWorkspace": true,
10 | "[json]": {
11 | "editor.tabSize": 2,
12 | "editor.defaultFormatter": "biomejs.biome"
13 | },
14 | "[typescript]": {
15 | "editor.tabSize": 2,
16 | "editor.defaultFormatter": "biomejs.biome"
17 | },
18 | "[typescriptreact]": {
19 | "editor.defaultFormatter": "biomejs.biome"
20 | }
21 | }
22 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/find-projects.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describe, it, expect } from "vitest";
2 | import findProjects from "./find-projects.js";
3 | import { getServerContext } from "../test-setup.js";
4 |
5 | describe("find_projects", () => {
6 | it("serializes", async () => {
7 | const result = await findProjects.handler(
8 | {
9 | organizationSlug: "sentry-mcp-evals",
10 | regionUrl: null,
11 | query: null,
12 | },
13 | getServerContext(),
14 | );
15 | expect(result).toMatchInlineSnapshot(`
16 | "# Projects in **sentry-mcp-evals**
17 |
18 | - **cloudflare-mcp**
19 | "
20 | `);
21 | });
22 | });
23 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/cpu.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "cpu",
3 | "description": "Attributes specific to a cpu instance.",
4 | "attributes": {
5 | "cpu.mode": {
6 | "description": "The mode of the CPU",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": [
10 | "user",
11 | "system",
12 | "nice",
13 | "idle",
14 | "iowait",
15 | "interrupt",
16 | "steal",
17 | "kernel"
18 | ]
19 | },
20 | "cpu.logical_number": {
21 | "description": "The logical CPU number [0..n-1]",
22 | "type": "number",
23 | "stability": "development",
24 | "examples": ["1"]
25 | }
26 | }
27 | }
28 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/animation/BrowserAnimation.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import BrowserWindow from "./browser-ui/BrowserWindow";
2 | import IDEWindow from "./browser-ui/IDEWindow";
3 | import LoadingSquares from "./browser-ui/LoadingSquares";
4 | import ValidationSummary from "./tests";
5 |
6 | export default function BrowserAnimation({
7 | globalIndex,
8 | }: {
9 | globalIndex: number;
10 | }) {
11 | return (
12 | <div className="relative h-full w-full hidden md:block bg-dots bg-fixed">
13 | <IDEWindow step={globalIndex} />
14 | <BrowserWindow step={globalIndex} />
15 | <LoadingSquares step={globalIndex} />
16 | <ValidationSummary step={globalIndex} />
17 | </div>
18 | );
19 | }
20 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/find-teams.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describe, it, expect } from "vitest";
2 | import findTeams from "./find-teams.js";
3 |
4 | describe("find_teams", () => {
5 | it("serializes", async () => {
6 | const result = await findTeams.handler(
7 | {
8 | organizationSlug: "sentry-mcp-evals",
9 | query: null,
10 | regionUrl: null,
11 | },
12 | {
13 | constraints: {
14 | organizationSlug: null,
15 | },
16 | accessToken: "access-token",
17 | userId: "1",
18 | },
19 | );
20 | expect(result).toMatchInlineSnapshot(`
21 | "# Teams in **sentry-mcp-evals**
22 |
23 | - the-goats
24 | "
25 | `);
26 | });
27 | });
28 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "@sentry/mcp-server-mocks",
3 | "version": "0.24.0",
4 | "private": true,
5 | "type": "module",
6 | "engines": {
7 | "node": ">=20"
8 | },
9 | "license": "FSL-1.1-ALv2",
10 | "exports": {
11 | ".": {
12 | "types": "./dist/index.d.ts",
13 | "default": "./dist/index.js"
14 | },
15 | "./utils": {
16 | "types": "./dist/utils.d.ts",
17 | "default": "./dist/utils.js"
18 | }
19 | },
20 | "scripts": {
21 | "build": "tsdown",
22 | "dev": "tsdown -w"
23 | },
24 | "devDependencies": {
25 | "@sentry/mcp-server-tsconfig": "workspace:*",
26 | "tsdown": "catalog:"
27 | },
28 | "dependencies": {
29 | "msw": "catalog:"
30 | }
31 | }
32 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/server/logging.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type { MiddlewareHandler } from "hono";
2 | import { logInfo } from "@sentry/mcp-core/telem/logging";
3 |
4 | /**
5 | * Hono middleware that logs every request once the response is ready.
6 | */
7 | export function createRequestLogger(
8 | loggerScope: readonly string[] = ["cloudflare", "http"],
9 | ): MiddlewareHandler {
10 | return async (c, next) => {
11 | const start = Date.now();
12 | await next();
13 |
14 | const url = new URL(c.req.url);
15 | logInfo(`${c.req.method} ${url.pathname}`, {
16 | loggerScope,
17 | extra: {
18 | status: c.res.status,
19 | duration_ms: Date.now() - start,
20 | },
21 | });
22 | };
23 | }
24 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/signalr.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "signalr",
3 | "description": "SignalR attributes",
4 | "attributes": {
5 | "signalr.connection.status": {
6 | "description": "SignalR HTTP connection closure status.",
7 | "type": "string",
8 | "stability": "stable",
9 | "examples": ["normal_closure", "timeout", "app_shutdown"]
10 | },
11 | "signalr.transport": {
12 | "description": "[SignalR transport type](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/TransportProtocols.md)",
13 | "type": "string",
14 | "stability": "stable",
15 | "examples": ["server_sent_events", "long_polling", "web_sockets"]
16 | }
17 | }
18 | }
19 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/tools.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { assert, test } from "vitest";
2 | import * as tools from "./index.js";
3 |
4 | // VSCode (via OpenAI) limits to 1024 characters, but its tough to hit that right now,
5 | // so instead lets limit the blast damage and hope that e.g. OpenAI will increase the limit.
6 | const DESCRIPTION_MAX_LENGTH = 2048;
7 |
8 | test(`all tool descriptions under maximum length`, () => {
9 | for (const tool of Object.values(tools.default)) {
10 | const length = tool.description.length;
11 | assert(
12 | length < DESCRIPTION_MAX_LENGTH,
13 | `${tool.name} description must be less than ${DESCRIPTION_MAX_LENGTH} characters (was ${length})`,
14 | );
15 | }
16 | });
17 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/ui/backdrop.tsx:
--------------------------------------------------------------------------------
```typescript
1 | interface BackdropProps {
2 | isOpen: boolean;
3 | onClose: () => void;
4 | }
5 |
6 | export function Backdrop({ isOpen, onClose }: BackdropProps) {
7 | return (
8 | <div
9 | className={`fixed inset-0 bg-black/50 backdrop-blur-sm transition-all duration-500 ease-out ${
10 | isOpen ? "opacity-100" : "opacity-0"
11 | }`}
12 | onClick={isOpen ? onClose : undefined}
13 | onKeyDown={
14 | isOpen
15 | ? (e: React.KeyboardEvent) => e.key === "Escape" && onClose()
16 | : undefined
17 | }
18 | role={isOpen ? "button" : undefined}
19 | tabIndex={isOpen ? 0 : -1}
20 | aria-label={isOpen ? "Close chat panel" : undefined}
21 | />
22 | );
23 | }
24 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/zos.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "zos",
3 | "description": "This document defines attributes of a z/OS resource.\n",
4 | "attributes": {
5 | "zos.smf.id": {
6 | "description": "The System Management Facility (SMF) Identifier uniquely identified a z/OS system within a SYSPLEX or mainframe environment and is used for system and performance analysis.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["SYS1"]
10 | },
11 | "zos.sysplex.name": {
12 | "description": "The name of the SYSPLEX to which the z/OS system belongs too.",
13 | "type": "string",
14 | "stability": "development",
15 | "examples": ["SYSPLEX1"]
16 | }
17 | }
18 | }
19 |
```
--------------------------------------------------------------------------------
/packages/mcp-test-client/tsdown.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { defineConfig } from "tsdown";
2 | import { readFileSync } from "node:fs";
3 |
4 | const packageVersion =
5 | process.env.npm_package_version ??
6 | JSON.parse(readFileSync("./package.json", "utf-8")).version;
7 |
8 | export default defineConfig({
9 | entry: ["src/index.ts"],
10 | format: ["esm"],
11 | clean: true,
12 | platform: "node",
13 | minify: false,
14 | shims: true,
15 | banner: {
16 | js: "#!/usr/bin/env node",
17 | },
18 | env: {
19 | DEFAULT_SENTRY_DSN:
20 | "https://[email protected]/4509062593708032",
21 | SENTRY_ENVIRONMENT: "mcp-test-client",
22 | SENTRY_RELEASE: packageVersion,
23 | npm_package_version: packageVersion,
24 | },
25 | });
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/vitest.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | /// <reference types="vitest" />
2 | import { defineConfig } from "vitest/config";
3 |
4 | export default defineConfig({
5 | test: {
6 | // Use thread-based workers to avoid process-kill issues in sandboxed environments
7 | pool: "threads",
8 | poolOptions: {
9 | workers: {
10 | miniflare: {},
11 | wrangler: { configPath: "./wrangler.jsonc" },
12 | },
13 | },
14 | deps: {
15 | interopDefault: true,
16 | },
17 | include: ["**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
18 | coverage: {
19 | provider: "v8",
20 | reporter: ["text", "json", "html"],
21 | include: ["**/*.ts"],
22 | },
23 | setupFiles: ["dotenv/config", "src/test-setup.ts"],
24 | },
25 | });
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/ios.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "ios",
3 | "description": "This group describes iOS-specific attributes.\n",
4 | "attributes": {
5 | "ios.app.state": {
6 | "description": "This attribute represents the state of the application.\n",
7 | "type": "string",
8 | "note": "The iOS lifecycle states are defined in the [UIApplicationDelegate documentation](https://developer.apple.com/documentation/uikit/uiapplicationdelegate), and from which the `OS terminology` column values are derived.\n",
9 | "stability": "development",
10 | "examples": [
11 | "active",
12 | "inactive",
13 | "background",
14 | "foreground",
15 | "terminate"
16 | ]
17 | }
18 | }
19 | }
20 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/list-dsns.eval.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describeEval } from "vitest-evals";
2 | import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";
3 |
4 | describeEval("list-dsns", {
5 | data: async () => {
6 | return [
7 | {
8 | input: `What is the SENTRY_DSN for ${FIXTURES.organizationSlug}/${FIXTURES.projectSlug}?`,
9 | expectedTools: [
10 | {
11 | name: "find_dsns",
12 | arguments: {
13 | organizationSlug: FIXTURES.organizationSlug,
14 | projectSlug: FIXTURES.projectSlug,
15 | },
16 | },
17 | ],
18 | },
19 | ];
20 | },
21 | task: NoOpTaskRunner(),
22 | scorers: [ToolPredictionScorer()],
23 | threshold: 0.6,
24 | timeout: 30000,
25 | });
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/animation/dracula.css:
--------------------------------------------------------------------------------
```css
1 | .asciinema-player-theme-dracula {
2 | /* Foreground (default text) color */
3 | --term-color-foreground: #f8f8f288;
4 |
5 | /* Background color */
6 | --term-color-background: #282a3600;
7 |
8 | /* Palette of 16 standard ANSI colors */
9 | --term-color-0: #21222c;
10 | --term-color-1: #ff5555;
11 | --term-color-2: #50fa7b;
12 | --term-color-3: #f1fa8c;
13 | --term-color-4: #bd93f9;
14 | --term-color-5: #ff79c6;
15 | --term-color-6: #8be9fd;
16 | --term-color-7: #f8f8f2;
17 | --term-color-8: #6272a4;
18 | --term-color-9: #ff6e6e;
19 | --term-color-10: #69ff94;
20 | --term-color-11: #ffffa5;
21 | --term-color-12: #d6acff;
22 | --term-color-13: #ff92df;
23 | --term-color-14: #a4ffff;
24 | --term-color-15: #ffffff;
25 | }
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/gcp.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "gcp",
3 | "description": "Attributes for Google Cloud client libraries.\n",
4 | "attributes": {
5 | "gcp.client.service": {
6 | "description": "Identifies the Google Cloud service for which the official client library is intended.",
7 | "type": "string",
8 | "note": "Intended to be a stable identifier for Google Cloud client libraries that is uniform across implementation languages. The value should be derived from the canonical service domain for the service; for example, 'foo.googleapis.com' should result in a value of 'foo'.\n",
9 | "stability": "development",
10 | "examples": ["appengine", "run", "firestore", "alloydb", "spanner"]
11 | }
12 | }
13 | }
14 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/chat/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Chat components
2 | export { Chat } from "./chat";
3 | export { ChatUI } from "./chat-ui";
4 | export { ChatMessages } from "./chat-messages";
5 | export { ChatInput } from "./chat-input";
6 | export { MessagePart, TextPart, ToolPart } from "./chat-message";
7 | export { ToolContent, ToolInvocation } from "./tool-invocation";
8 |
9 | // Auth components
10 | export { AuthForm } from "./auth-form";
11 |
12 | // Export types
13 | export type {
14 | ChatProps,
15 | ChatUIProps,
16 | ChatMessagesProps,
17 | ChatInputProps,
18 | AuthFormProps,
19 | MessagePartProps,
20 | TextPartProps,
21 | ToolPartProps,
22 | ToolInvocationProps,
23 | AuthState,
24 | AuthActions,
25 | AuthContextType,
26 | ChatToolInvocation,
27 | ToolMessage,
28 | ProcessedMessagePart,
29 | } from "./types";
30 |
```
--------------------------------------------------------------------------------
/.claude/commands/gh-pr.md:
--------------------------------------------------------------------------------
```markdown
1 | Create (or update) a Pull Request.
2 |
3 | We use the GitHub CLI (`gh`) to manage pull requests.
4 |
5 | If this branch does not already have a pull request, create one:
6 |
7 | - If we're on the main branch, switch to a working branch.
8 | - Commit our changes if we haven't already.
9 |
10 | If we already have one:
11 |
12 | - Verify our changes against the base branch and update the PR title and description to maintain accuracy.
13 |
14 | We should never focus on a test plan in the PR, but rather a concise description of the changes (features, breaking changes, major bug fixes, and architectural changes). Only include changes if they're present. We're always contrasting against our base branch when we describe these changes.
15 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/hero/header-divider.tsx:
--------------------------------------------------------------------------------
```typescript
1 | export function HeaderDivider() {
2 | return (
3 | <div className="sticky top-17 z-50 sm:-mb-64 sm:mt-64 md:-mb-58 md:mt-58 xl:-mb-44 xl:mt-44 2xl:-mb-38 2xl:mt-38 w-screen border-b-[1px] border-violet-300/20 [--x:0] sm:[--x:40rem] md:[--x:48rem] lg:[--x:64rem] xl:[--x:80rem] 2xl:[--x:96rem]">
4 | <div className="absolute top-0 left-[calc((100vw-var(--x))/2)] -translate-x-[calc(50%+0.5px)] -translate-y-1/2 h-4 w-4 border bg-white/5 backdrop-blur border-violet-300/20" />
5 | <div className="absolute top-0 right-0 sm:right-[calc((100vw-var(--x))/2)] translate-x-[calc(50%+0.5px)] -translate-y-1/2 h-4 w-4 border bg-white/5 backdrop-blur border-violet-300/20" />
6 | </div>
7 | );
8 | }
9 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/vite.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { sentryVitePlugin } from "@sentry/vite-plugin";
2 | import { defineConfig } from "vite";
3 | import react from "@vitejs/plugin-react";
4 | import { cloudflare } from "@cloudflare/vite-plugin";
5 | import tailwindcss from "@tailwindcss/vite";
6 | import path from "node:path";
7 |
8 | export default defineConfig({
9 | plugins: [
10 | react(),
11 | cloudflare(),
12 | tailwindcss(),
13 | sentryVitePlugin({
14 | org: "sentry",
15 | project: "mcp-server",
16 | }),
17 | ],
18 | resolve: {
19 | alias: {
20 | "@": path.resolve(__dirname, "./src"),
21 | },
22 | },
23 | build: {
24 | sourcemap: true,
25 | },
26 | server: {
27 | port: 5173,
28 | strictPort: true, // Fail if port is already in use instead of trying another port
29 | },
30 | });
31 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/src/fixtures/team.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "id": "4509106740854784",
3 | "slug": "the-goats",
4 | "name": "the-goats",
5 | "dateCreated": "2025-04-06T14:11:23.961739Z",
6 | "isMember": true,
7 | "teamRole": "admin",
8 | "flags": { "idp:provisioned": false },
9 | "access": [
10 | "team:read",
11 | "alerts:read",
12 | "event:write",
13 | "team:write",
14 | "team:admin",
15 | "event:read",
16 | "org:read",
17 | "member:read",
18 | "project:admin",
19 | "project:write",
20 | "org:integrations",
21 | "project:releases",
22 | "alerts:write",
23 | "event:admin",
24 | "project:read"
25 | ],
26 | "hasAccess": true,
27 | "isPending": false,
28 | "memberCount": 1,
29 | "avatar": { "avatarType": "letter_avatar", "avatarUuid": null },
30 | "externalTeams": [],
31 | "projects": []
32 | }
33 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-mocks/src/fixtures/trace-items-attributes-logs-string.json:
--------------------------------------------------------------------------------
```json
1 | [
2 | {
3 | "key": "message",
4 | "name": "Log Message"
5 | },
6 | {
7 | "key": "severity",
8 | "name": "Log Severity"
9 | },
10 | {
11 | "key": "sentry.item_id",
12 | "name": "Sentry Item ID"
13 | },
14 | {
15 | "key": "project",
16 | "name": "Project"
17 | },
18 | {
19 | "key": "environment",
20 | "name": "Environment"
21 | },
22 | {
23 | "key": "release",
24 | "name": "Release"
25 | },
26 | {
27 | "key": "trace",
28 | "name": "Trace ID"
29 | },
30 | {
31 | "key": "level",
32 | "name": "Log Level"
33 | },
34 | {
35 | "key": "logger",
36 | "name": "Logger Name"
37 | },
38 | {
39 | "key": "module",
40 | "name": "Module"
41 | },
42 | {
43 | "key": "custom.service",
44 | "name": "Service Name"
45 | },
46 | {
47 | "key": "custom.component",
48 | "name": "Component"
49 | }
50 | ]
51 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/create-dsn.eval.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describeEval } from "vitest-evals";
2 | import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";
3 |
4 | describeEval("create-dsn", {
5 | data: async () => {
6 | return [
7 | {
8 | input: `Create a new DSN named "Production" for '${FIXTURES.organizationSlug}/${FIXTURES.projectSlug}'`,
9 | expectedTools: [
10 | {
11 | name: "create_dsn",
12 | arguments: {
13 | organizationSlug: FIXTURES.organizationSlug,
14 | projectSlug: FIXTURES.projectSlug,
15 | name: "Production",
16 | },
17 | },
18 | ],
19 | },
20 | ];
21 | },
22 | task: NoOpTaskRunner(),
23 | scorers: [ToolPredictionScorer()],
24 | threshold: 0.6,
25 | timeout: 30000,
26 | });
27 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/list-tags.eval.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describeEval } from "vitest-evals";
2 | import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";
3 |
4 | describeEval("list-tags", {
5 | data: async () => {
6 | return [
7 | {
8 | input: `What are common tags in ${FIXTURES.organizationSlug}`,
9 | expectedTools: [
10 | {
11 | name: "find_organizations",
12 | arguments: {},
13 | },
14 | {
15 | name: "find_tags",
16 | arguments: {
17 | organizationSlug: FIXTURES.organizationSlug,
18 | regionUrl: "https://us.sentry.io",
19 | },
20 | },
21 | ],
22 | },
23 | ];
24 | },
25 | task: NoOpTaskRunner(),
26 | scorers: [ToolPredictionScorer()],
27 | threshold: 0.6,
28 | timeout: 30000,
29 | });
30 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/errors.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Error thrown when user input validation fails.
3 | * These errors should be returned to the user directly without logging to Sentry.
4 | */
5 | export class UserInputError extends Error {
6 | constructor(message: string, options?: ErrorOptions) {
7 | super(message, options);
8 | this.name = "UserInputError";
9 | }
10 | }
11 |
12 | /**
13 | * Error thrown when configuration is invalid or missing.
14 | * These errors should be returned to the user directly without logging to Sentry.
15 | * Typically used for environment configuration issues, connection settings, etc.
16 | */
17 | export class ConfigurationError extends Error {
18 | constructor(message: string, options?: ErrorOptions) {
19 | super(message, options);
20 | this.name = "ConfigurationError";
21 | }
22 | }
23 |
```
--------------------------------------------------------------------------------
/.claude/settings.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "permissions": {
3 | "allow": [
4 | "WebFetch(domain:mcp.sentry.dev)",
5 | "WebFetch(domain:docs.sentry.io)",
6 | "WebFetch(domain:develop.sentry.dev)",
7 | "WebFetch(domain:modelcontextprotocol.io)",
8 | "WebFetch(domain:docs.anthropic.com)",
9 | "Bash(grep:*)",
10 | "Bash(jq:*)",
11 | "Bash(pnpx vitest:*)",
12 | "Bash(pnpm test:*)",
13 | "Bash(pnpm run typecheck:*)",
14 | "Bash(pnpm run check:*)",
15 | "Bash(pnpm run:*)",
16 | "Bash(pnpx tsx:*)",
17 | "Bash(gh pr checks:*)",
18 | "Bash(gh pr view:*)",
19 | "Bash(gh run view:*)",
20 | "Bash(git status:*)"
21 | ],
22 | "deny": []
23 | },
24 | "enableAllProjectMcpServers": true,
25 | "includeCoAuthoredBy": true,
26 | "enabledMcpjsonServers": ["sentry"]
27 | }
28 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/aws.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "aws",
3 | "description": "This section defines generic attributes for AWS services.\n",
4 | "attributes": {
5 | "aws.request_id": {
6 | "description": "The AWS request ID as returned in the response headers `x-amzn-requestid`, `x-amzn-request-id` or `x-amz-request-id`.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["79b9da39-b7ae-508a-a6bc-864b2829c622", "C9ER4AJX75574TDJ"]
10 | },
11 | "aws.extended_request_id": {
12 | "description": "The AWS extended request ID as returned in the response header `x-amz-id-2`.",
13 | "type": "string",
14 | "stability": "development",
15 | "examples": [
16 | "wzHcyEWfmOGDIE5QOhTAqFDoDWP3y8IUvpNINCwL9N4TEHbUw0/gZJ+VZTmCNCWR7fezEN3eCiQ="
17 | ]
18 | }
19 | }
20 | }
21 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/list-projects.eval.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describeEval } from "vitest-evals";
2 | import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";
3 |
4 | describeEval("list-projects", {
5 | data: async () => {
6 | return [
7 | {
8 | input: `What projects do I have access to in Sentry for '${FIXTURES.organizationSlug}'`,
9 | expectedTools: [
10 | {
11 | name: "find_organizations",
12 | arguments: {},
13 | },
14 | {
15 | name: "find_projects",
16 | arguments: {
17 | organizationSlug: FIXTURES.organizationSlug,
18 | regionUrl: "https://us.sentry.io",
19 | },
20 | },
21 | ],
22 | },
23 | ];
24 | },
25 | task: NoOpTaskRunner(),
26 | scorers: [ToolPredictionScorer()],
27 | threshold: 0.6,
28 | timeout: 30000,
29 | });
30 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/tools/create-team.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describe, it, expect } from "vitest";
2 | import createTeam from "./create-team.js";
3 |
4 | describe("create_team", () => {
5 | it("serializes", async () => {
6 | const result = await createTeam.handler(
7 | {
8 | organizationSlug: "sentry-mcp-evals",
9 | name: "the-goats",
10 | regionUrl: null,
11 | },
12 | {
13 | constraints: {
14 | organizationSlug: null,
15 | },
16 | accessToken: "access-token",
17 | userId: "1",
18 | },
19 | );
20 | expect(result).toMatchInlineSnapshot(`
21 | "# New Team in **sentry-mcp-evals**
22 |
23 | **ID**: 4509109078196224
24 | **Slug**: the-goats
25 | **Name**: the-goats
26 | # Using this information
27 |
28 | - You should always inform the user of the Team Slug value.
29 | "
30 | `);
31 | });
32 | });
33 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/test-utils/context.ts:
--------------------------------------------------------------------------------
```typescript
1 | import type { ServerContext } from "../types";
2 | import { SKILLS, type Skill } from "../skills";
3 |
4 | /**
5 | * Create a test context with default values for testing tools
6 | */
7 | export function createTestContext(
8 | overrides: Partial<ServerContext> = {},
9 | ): ServerContext {
10 | // Default to all skills for testing
11 | const allSkills = Object.keys(SKILLS) as Skill[];
12 | return {
13 | accessToken: "test-access-token",
14 | constraints: {},
15 | grantedSkills: new Set<Skill>(allSkills),
16 | ...overrides,
17 | };
18 | }
19 |
20 | /**
21 | * Create a test context with specific constraints
22 | */
23 | export function createTestContextWithConstraints(
24 | constraints: ServerContext["constraints"],
25 | overrides: Partial<ServerContext> = {},
26 | ): ServerContext {
27 | return createTestContext({
28 | constraints,
29 | ...overrides,
30 | });
31 | }
32 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/tsdown.config.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { defineConfig } from "tsdown";
2 | import { readFileSync } from "node:fs";
3 |
4 | const packageVersion =
5 | process.env.npm_package_version ??
6 | JSON.parse(readFileSync("./package.json", "utf-8")).version;
7 |
8 | export default defineConfig({
9 | entry: ["src/**/*.ts", "!src/**/*.test.ts"],
10 | format: ["cjs", "esm"], // Build for commonJS and ESmodules
11 | dts: true, // Generate declaration file (.d.ts)
12 | sourcemap: true,
13 | clean: true,
14 | external: [
15 | // Keep workspace dependencies external (don't bundle them)
16 | "@sentry/mcp-server-mocks",
17 | ],
18 | env: {
19 | DEFAULT_SENTRY_DSN:
20 | "https://[email protected]/4509062593708032",
21 | SENTRY_ENVIRONMENT: "stdio",
22 | SENTRY_RELEASE: packageVersion,
23 | npm_package_version: packageVersion,
24 | },
25 | });
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/v8js.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "v8js",
3 | "description": "Describes V8 JS Engine Runtime related attributes.",
4 | "attributes": {
5 | "v8js.gc.type": {
6 | "description": "The type of garbage collection.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["major", "minor", "incremental", "weakcb"]
10 | },
11 | "v8js.heap.space.name": {
12 | "description": "The name of the space type of heap memory.",
13 | "type": "string",
14 | "note": "Value can be retrieved from value `space_name` of [`v8.getHeapSpaceStatistics()`](https://nodejs.org/api/v8.html#v8getheapspacestatistics)\n",
15 | "stability": "development",
16 | "examples": [
17 | "new_space",
18 | "old_space",
19 | "code_space",
20 | "map_space",
21 | "large_object_space"
22 | ]
23 | }
24 | }
25 | }
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/setup-env.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { config } from "dotenv";
2 | import path from "node:path";
3 | import { fileURLToPath } from "node:url";
4 |
5 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
6 |
7 | // Load environment variables from multiple possible locations
8 | // IMPORTANT: Do NOT use override:true as it would overwrite shell/CI environment variables
9 | const rootDir = path.resolve(__dirname, "../../../");
10 |
11 | // Load local package .env first (for package-specific overrides)
12 | config({ path: path.resolve(__dirname, "../.env") });
13 |
14 | // Load root .env second (for shared defaults - won't override local or shell vars)
15 | config({ path: path.join(rootDir, ".env") });
16 |
17 | // Start the shared MSW server for all eval tests
18 | import { startMockServer } from "@sentry/mcp-server-mocks/utils";
19 |
20 | startMockServer({ ignoreOpenAI: true });
21 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/heroku.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "heroku",
3 | "description": "This document defines attributes for the Heroku platform on which application/s are running.\n",
4 | "attributes": {
5 | "heroku.release.creation_timestamp": {
6 | "description": "Time and date the release was created\n",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["2022-10-23T18:00:42Z"]
10 | },
11 | "heroku.release.commit": {
12 | "description": "Commit hash for the current release\n",
13 | "type": "string",
14 | "stability": "development",
15 | "examples": ["e6134959463efd8966b20e75b913cafe3f5ec"]
16 | },
17 | "heroku.app.id": {
18 | "description": "Unique identifier for the application\n",
19 | "type": "string",
20 | "stability": "development",
21 | "examples": ["2daa2797-e42b-4624-9322-ec3f968df4da"]
22 | }
23 | }
24 | }
25 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/graphql.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "graphql",
3 | "description": "This document defines attributes for GraphQL.",
4 | "attributes": {
5 | "graphql.operation.name": {
6 | "description": "The name of the operation being executed.",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["findBookById"]
10 | },
11 | "graphql.operation.type": {
12 | "description": "The type of the operation being executed.",
13 | "type": "string",
14 | "stability": "development",
15 | "examples": ["query", "mutation", "subscription"]
16 | },
17 | "graphql.document": {
18 | "description": "The GraphQL document being executed.",
19 | "type": "string",
20 | "note": "The value may be sanitized to exclude sensitive information.",
21 | "stability": "development",
22 | "examples": ["query findBookById { bookById(id: ?) { name } }"]
23 | }
24 | }
25 | }
26 |
```
--------------------------------------------------------------------------------
/packages/mcp-server-evals/src/evals/create-team.eval.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describeEval } from "vitest-evals";
2 | import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";
3 |
4 | describeEval("create-team", {
5 | data: async () => {
6 | return [
7 | {
8 | input: `Create a new team in Sentry for '${FIXTURES.organizationSlug}' called 'the-goats' response with **only** the team slug and no other text.`,
9 | expectedTools: [
10 | {
11 | name: "find_organizations",
12 | arguments: {},
13 | },
14 | {
15 | name: "create_team",
16 | arguments: {
17 | organizationSlug: FIXTURES.organizationSlug,
18 | name: "the-goats",
19 | regionUrl: "https://us.sentry.io",
20 | },
21 | },
22 | ],
23 | },
24 | ];
25 | },
26 | task: NoOpTaskRunner(),
27 | scorers: [ToolPredictionScorer()],
28 | threshold: 0.6,
29 | timeout: 30000,
30 | });
31 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/oci.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "oci",
3 | "description": "An OCI image manifest.\n",
4 | "attributes": {
5 | "oci.manifest.digest": {
6 | "description": "The digest of the OCI image manifest. For container images specifically is the digest by which the container image is known.\n",
7 | "type": "string",
8 | "note": "Follows [OCI Image Manifest Specification](https://github.com/opencontainers/image-spec/blob/main/manifest.md), and specifically the [Digest property](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests).\nAn example can be found in [Example Image Manifest](https://github.com/opencontainers/image-spec/blob/main/manifest.md#example-image-manifest).\n",
9 | "stability": "development",
10 | "examples": [
11 | "sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4"
12 | ]
13 | }
14 | }
15 | }
16 |
```
--------------------------------------------------------------------------------
/packages/mcp-cloudflare/src/client/components/ui/base.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { cn } from "../../lib/utils";
2 |
3 | export function Heading({
4 | children,
5 | as,
6 | className,
7 | ...props
8 | }: {
9 | children: React.ReactNode;
10 | as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
11 | } & React.HTMLAttributes<HTMLHeadingElement>) {
12 | const Tag = as || "h2";
13 | return (
14 | <Tag
15 | className={cn("text-2xl font-bold mb-6 text-white", className)}
16 | {...props}
17 | >
18 | <div className="flex flex-row gap-2">{children}</div>
19 | <div className="h-[2px] mt-1 bg-violet-300 w-full" />
20 | </Tag>
21 | );
22 | }
23 |
24 | export function Link({
25 | children,
26 | className,
27 | href,
28 | ...props
29 | }: {
30 | children: React.ReactNode;
31 | href: string;
32 | } & React.HTMLAttributes<HTMLAnchorElement>) {
33 | return (
34 | <a
35 | href={href}
36 | className={cn("text-violet-300 font-semibold underline", className)}
37 | {...props}
38 | >
39 | {children}
40 | </a>
41 | );
42 | }
43 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/webengine.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "webengine",
3 | "description": "This document defines the attributes used to describe the packaged software running the application code.\n",
4 | "attributes": {
5 | "webengine.name": {
6 | "description": "The name of the web engine.\n",
7 | "type": "string",
8 | "stability": "development",
9 | "examples": ["WildFly"]
10 | },
11 | "webengine.version": {
12 | "description": "The version of the web engine.\n",
13 | "type": "string",
14 | "stability": "development",
15 | "examples": ["21.0.0"]
16 | },
17 | "webengine.description": {
18 | "description": "Additional description of the web engine (e.g. detailed version and edition information).\n",
19 | "type": "string",
20 | "stability": "development",
21 | "examples": [
22 | "WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - 2.2.2.Final"
23 | ]
24 | }
25 | }
26 | }
27 |
```
--------------------------------------------------------------------------------
/packages/mcp-core/src/internal/agents/tools/data/dns.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "namespace": "dns",
3 | "description": "This document defines the shared attributes used to report a DNS query.\n",
4 | "attributes": {
5 | "dns.question.name": {
6 | "description": "The name being queried.",
7 | "type": "string",
8 | "note": "If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \\t, \\r, and \\n respectively.\n",
9 | "stability": "development",
10 | "examples": ["www.example.com", "opentelemetry.io"]
11 | },
12 | "dns.answers": {
13 | "description": "The list of IPv4 or IPv6 addresses resolved during DNS lookup.",
14 | "type": "string",
15 | "stability": "development",
16 | "examples": ["[\"10.0.0.1\",\"2001:0db8:85a3:0000:0000:8a2e:0370:7334\"]"]
17 | }
18 | }
19 | }
20 |
```