Skip to content

Commit 4758d56

Browse files
authored
feat(mcp-insights): project flag (#95218)
1 parent 6f18d89 commit 4758d56

File tree

9 files changed

+85
-1
lines changed

9 files changed

+85
-1
lines changed

migrations_lockfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ preprod: 0010_actual_drop_preprod_artifact_analysis_file_id_col
2727

2828
replays: 0006_add_bulk_delete_job
2929

30-
sentry: 0945_move_discover_models
30+
sentry: 0946_add_has_mcp_insights_flag
3131

3232
social_auth: 0003_social_auth_json_field
3333

src/sentry/api/serializers/models/project.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ class ProjectSerializerBaseResponse(_ProjectSerializerOptionalBaseResponse):
284284
hasInsightsQueues: bool
285285
hasInsightsLlmMonitoring: bool
286286
hasInsightsAgentMonitoring: bool
287+
hasInsightsMCP: bool
287288

288289

289290
class ProjectSerializerResponse(ProjectSerializerBaseResponse):
@@ -552,6 +553,7 @@ def serialize(
552553
"hasInsightsQueues": bool(obj.flags.has_insights_queues),
553554
"hasInsightsLlmMonitoring": bool(obj.flags.has_insights_llm_monitoring),
554555
"hasInsightsAgentMonitoring": bool(obj.flags.has_insights_agent_monitoring),
556+
"hasInsightsMCP": bool(obj.flags.has_insights_mcp),
555557
"isInternal": obj.is_internal_project(),
556558
"isPublic": obj.public,
557559
# Projects don't have avatar uploads, but we need to maintain the payload shape for
@@ -800,6 +802,7 @@ def serialize( # type: ignore[override] # intentionally different data shape
800802
hasInsightsQueues=bool(obj.flags.has_insights_queues),
801803
hasInsightsLlmMonitoring=bool(obj.flags.has_insights_llm_monitoring),
802804
hasInsightsAgentMonitoring=bool(obj.flags.has_insights_agent_monitoring),
805+
hasInsightsMCP=bool(obj.flags.has_insights_mcp),
803806
platform=obj.platform,
804807
platforms=attrs["platforms"],
805808
latestRelease=attrs["latest_release"],

src/sentry/apidocs/examples/organization_examples.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class OrganizationExamples:
388388
"hasInsightsQueues": False,
389389
"hasInsightsLlmMonitoring": False,
390390
"hasInsightsAgentMonitoring": False,
391+
"hasInsightsMCP": False,
391392
"platform": "node",
392393
"platforms": [],
393394
"latestRelease": None,
@@ -452,6 +453,7 @@ class OrganizationExamples:
452453
"hasInsightsQueues": False,
453454
"hasInsightsLlmMonitoring": False,
454455
"hasInsightsAgentMonitoring": False,
456+
"hasInsightsMCP": False,
455457
"latestRelease": None,
456458
}
457459
],

src/sentry/apidocs/examples/project_examples.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
"hasInsightsQueues": False,
103103
"hasInsightsLlmMonitoring": False,
104104
"hasInsightsAgentMonitoring": False,
105+
"hasInsightsMCP": False,
105106
"isInternal": False,
106107
"isPublic": False,
107108
"avatar": {"avatarType": "letter_avatar", "avatarUuid": None},
@@ -341,6 +342,7 @@
341342
"hasInsightsQueues": True,
342343
"hasInsightsLlmMonitoring": False,
343344
"hasInsightsAgentMonitoring": False,
345+
"hasInsightsMCP": False,
344346
"platform": "node-express",
345347
"platforms": [],
346348
"latestRelease": None,

src/sentry/apidocs/examples/team_examples.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ class TeamExamples:
249249
"hasInsightsQueues": False,
250250
"hasInsightsLlmMonitoring": False,
251251
"hasInsightsAgentMonitoring": False,
252+
"hasInsightsMCP": False,
252253
"isInternal": False,
253254
"isPublic": False,
254255
"avatar": {"avatarType": "letter_avatar", "avatarUuid": None},
@@ -307,6 +308,7 @@ class TeamExamples:
307308
"hasInsightsQueues": False,
308309
"hasInsightsLlmMonitoring": False,
309310
"hasInsightsAgentMonitoring": False,
311+
"hasInsightsMCP": False,
310312
"isInternal": False,
311313
"isPublic": False,
312314
"avatar": {"avatarType": "letter_avatar", "avatarUuid": None},
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Generated by Django 5.2.1 on 2025-07-10 09:55
2+
3+
from django.db import migrations
4+
5+
import bitfield.models
6+
from sentry.new_migrations.migrations import CheckedMigration
7+
8+
9+
class Migration(CheckedMigration):
10+
# This flag is used to mark that a migration shouldn't be automatically run in production.
11+
# This should only be used for operations where it's safe to run the migration after your
12+
# code has deployed. So this should not be used for most operations that alter the schema
13+
# of a table.
14+
# Here are some things that make sense to mark as post deployment:
15+
# - Large data migrations. Typically we want these to be run manually so that they can be
16+
# monitored and not block the deploy for a long period of time while they run.
17+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
18+
# run this outside deployments so that we don't block them. Note that while adding an index
19+
# is a schema change, it's completely safe to run the operation after the code has deployed.
20+
# Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment
21+
22+
is_post_deployment = False
23+
24+
dependencies = [
25+
("sentry", "0945_move_discover_models"),
26+
]
27+
28+
operations = [
29+
migrations.AlterField(
30+
model_name="project",
31+
name="flags",
32+
field=bitfield.models.BitField(
33+
[
34+
"has_releases",
35+
"has_issue_alerts_targeting",
36+
"has_transactions",
37+
"has_alert_filters",
38+
"has_sessions",
39+
"has_profiles",
40+
"has_replays",
41+
"has_feedbacks",
42+
"has_new_feedbacks",
43+
"spike_protection_error_currently_active",
44+
"spike_protection_transaction_currently_active",
45+
"spike_protection_attachment_currently_active",
46+
"has_minified_stack_trace",
47+
"has_cron_monitors",
48+
"has_cron_checkins",
49+
"has_sourcemaps",
50+
"has_custom_metrics",
51+
"has_high_priority_alerts",
52+
"has_insights_http",
53+
"has_insights_db",
54+
"has_insights_assets",
55+
"has_insights_app_start",
56+
"has_insights_screen_load",
57+
"has_insights_vitals",
58+
"has_insights_caches",
59+
"has_insights_queues",
60+
"has_insights_llm_monitoring",
61+
"has_flags",
62+
"has_insights_agent_monitoring",
63+
"has_insights_mcp",
64+
],
65+
default=10,
66+
),
67+
),
68+
]

src/sentry/models/project.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ class flags(TypedClassBitField):
349349
# This Project has sent insight agent monitoring spans
350350
has_insights_agent_monitoring: bool
351351

352+
# This Project has sent insight MCP spans
353+
has_insights_mcp: bool
354+
352355
bitfield_default = 10
353356

354357
objects: ClassVar[ProjectManager] = ProjectManager(cache_fields=["pk"])

src/sentry/projects/services/project/model.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class RpcProjectFlags(RpcModel):
5858
has_insights_llm_monitoring: bool
5959
has_flags: bool
6060
has_insights_agent_monitoring: bool
61+
has_insights_mcp: bool
6162

6263

6364
class RpcProject(RpcModel):

tests/sentry/api/serializers/test_project.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ def test_has_insight_module_flags(self):
456456
assert result["hasInsightsQueues"] is False
457457
assert result["hasInsightsLlmMonitoring"] is False
458458
assert result["hasInsightsAgentMonitoring"] is False
459+
assert result["hasInsightsMCP"] is False
459460

460461
self.project.first_event = timezone.now()
461462
self.project.update(flags=F("flags").bitor(Project.flags.has_insights_http))
@@ -468,6 +469,7 @@ def test_has_insight_module_flags(self):
468469
self.project.update(flags=F("flags").bitor(Project.flags.has_insights_queues))
469470
self.project.update(flags=F("flags").bitor(Project.flags.has_insights_llm_monitoring))
470471
self.project.update(flags=F("flags").bitor(Project.flags.has_insights_agent_monitoring))
472+
self.project.update(flags=F("flags").bitor(Project.flags.has_insights_mcp))
471473

472474
result = serialize(self.project, self.user, ProjectSummarySerializer())
473475
assert result["hasInsightsHttp"] is True
@@ -480,6 +482,7 @@ def test_has_insight_module_flags(self):
480482
assert result["hasInsightsQueues"] is True
481483
assert result["hasInsightsLlmMonitoring"] is True
482484
assert result["hasInsightsAgentMonitoring"] is True
485+
assert result["hasInsightsMCP"] is True
483486

484487
def test_has_flags_flag(self):
485488
result = serialize(self.project, self.user, ProjectSummarySerializer())

0 commit comments

Comments
 (0)