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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions packages/mcp-core/src/api-client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2945,6 +2945,61 @@ export class SentryApiService {
return MonitorSchema.parse(body);
}

/**
* Create a cron monitor.
*
* POST /organizations/{org}/monitors/
* Source: src/sentry/monitors/endpoints/organization_monitor_index.py
* Body fields: src/sentry/monitors/validators.py (MonitorValidator, ConfigValidator)
*/
async createMonitor(
{
organizationSlug,
projectSlug,
name,
slug,
status,
owner,
config,
}: {
organizationSlug: string;
projectSlug: string;
name: string;
slug?: string;
status?: "active" | "disabled";
owner?: string;
config: {
schedule_type: "crontab" | "interval";
schedule: string | [number, string];
checkin_margin?: number;
max_runtime?: number;
timezone?: string;
failure_issue_threshold?: number;
recovery_threshold?: number;
};
},
opts?: RequestOptions,
): Promise<Monitor> {
const payload: Record<string, unknown> = {
project: projectSlug,
name,
config,
};
if (slug !== undefined) payload.slug = slug;
if (status !== undefined) payload.status = status;
if (owner !== undefined) payload.owner = owner;

const body = await this.requestJSON(
apiPath`/organizations/${organizationSlug}/monitors/`,
{
method: "POST",
body: JSON.stringify(payload),
},
opts,
);
return MonitorSchema.parse(body);
}

/**
* Schedule deletion of a cron monitor environment. Returns 202 with no body.
* Source: src/sentry/monitors/endpoints/project_monitor_environment_details.py
Expand Down
11 changes: 8 additions & 3 deletions packages/mcp-core/src/skillDefinitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
{
"name": "find_monitors",
"description": "Find Sentry cron monitors.\n\nUse this tool when you need to:\n- List cron monitors in an organization\n- Find a monitor by name or slug before getting details\n- Check monitor status, owner, project, schedule, or recent environment state\n- When `hasMore` is true, narrow the results with project, environment, owner, or query filters\n\n<examples>\nfind_monitors(organizationSlug='my-organization')\nfind_monitors(organizationSlug='my-organization', projectSlug='backend', query='billing')\n</examples>",
"description": "Find Sentry cron monitors.\n\nUse this tool when you need to:\n- List cron monitors in an organization\n- Find a monitor by name or slug before getting details\n- Check monitor status, owner, project, schedule, or recent environment state\n- When `hasMore` is true, narrow the results with project, environment, owner, or query filters\n\nTo create a cron monitor, use create_monitor.\n\n<examples>\nfind_monitors(organizationSlug='my-organization')\nfind_monitors(organizationSlug='my-organization', projectSlug='backend', query='billing')\n</examples>",
"requiredScopes": ["org:read"]
},
{
Expand Down Expand Up @@ -538,10 +538,10 @@
{
"id": "project-management",
"name": "Manage Projects & Teams",
"description": "Create and modify projects, teams, DSNs, cron monitor environments, uptime monitors, metric monitors, and alert rules",
"description": "Create and modify projects, teams, DSNs, cron monitors and their environments, uptime monitors, metric monitors, and alert rules",
"defaultEnabled": false,
"order": 5,
"toolCount": 24,
"toolCount": 25,
"tools": [
{
"name": "add_team_to_project",
Expand All @@ -563,6 +563,11 @@
"description": "Create a Sentry Metric Monitor with Static, Percent or Dynamic detection in a project.\nProvide the complete query, detection config and conditions. Time windows and comparison deltas use seconds. Percent comparisons are absolute: 110 means 10% higher.\nTo copy a monitor, use the query, config and conditionGroup from get_metric_monitor_details. Component IDs are discarded; new condition groups use logicType='any'.\nNew monitors start ACTIVE and immediately evaluate data. Initially disabled creation is not supported. Use update_metric_monitor to disable an existing monitor.\nworkflowIds optionally connect existing notification Alerts, including shared Alerts, without modifying their configuration. Create an Alert separately with create_alert_rule if needed.\nDataset access, quota, aggregate, window and historical-data requirements are enforced by Sentry. Dynamic detection requires sufficient history and Seer availability.\nCreation can fail after persisting a monitor, especially during Dynamic setup. After an error or timeout, use find_metric_monitors with the name and project before retrying; do not assume rollback or blindly repeat creation.\ncreate_metric_monitor(organizationSlug='my-org', projectSlug='backend', name='High error count', query={dataset:'events', query:'level:error', aggregate:'count()', eventTypes:['error'], timeWindowSeconds:300}, config={detectionType:'static'}, conditionGroup={conditions:[{type:'gt', comparison:100, conditionResult:75}, {type:'lte', comparison:50, conditionResult:0}]})",
"requiredScopes": ["org:read", "project:read", "alerts:write"]
},
{
"name": "create_monitor",
"description": "Create a Sentry cron monitor.\n\nUse this tool when you need to:\n- Monitor a scheduled job (cron job, scheduled task) for missed, failed, or slow runs\n- Set up a cron monitor before instrumenting check-ins\n\nSet `schedule` to exactly one crontab or interval schedule. Check-ins must still be sent by the job (SDK `monitor_config`/check-ins or `sentry monitor run`) using the returned slug.\nAfter an error or timeout, use find_monitors with the name and project before retrying; creation is not idempotent.\n\n<examples>\ncreate_monitor(organizationSlug='my-organization', projectSlug='backend', name='Nightly Import', schedule={ type: 'crontab', crontab: '0 3 * * *' }, timezone='America/Los_Angeles', checkInMargin=5, maxRuntime=30)\ncreate_monitor(organizationSlug='my-organization', projectSlug='backend', name='Queue Drain', schedule={ type: 'interval', value: 15, unit: 'minute' })\n</examples>",
"requiredScopes": ["org:read", "project:read", "alerts:write"]
},
{
"name": "create_project",
"description": "Create a new project in Sentry (provisions DSN automatically).\n\nUSE THIS TOOL WHEN USERS WANT TO:\n- 'Create a new project'\n- 'Set up a project for [app/service] with team [X]'\n- 'I need a new Sentry project'\n- Create project AND need DSN in one step\n- Create project and link an existing repository\n\nReturns the created project slug and a usable SENTRY_DSN when key setup succeeds.\n\nBe careful when using this tool!\n\n<examples>\n### Create new project with team\n```\ncreate_project(organizationSlug='my-organization', teamSlug='my-team', name='my-project', platform='javascript')\n```\n### Create project with an explicit slug\n```\ncreate_project(organizationSlug='my-organization', teamSlug='my-team', name='My Project', slug='my-project', platform='javascript')\n```\n### Create project and link to a repository\n```\ncreate_project(organizationSlug='my-organization', teamSlug='my-team', name='my-project', platform='javascript', repository='getsentry/sentry')\n```\n</examples>",
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-core/src/skills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const SKILLS: Record<Skill, SkillDefinition> = {
id: "project-management",
name: "Manage Projects & Teams",
description:
"Create and modify projects, teams, DSNs, cron monitor environments, uptime monitors, metric monitors, and alert rules",
"Create and modify projects, teams, DSNs, cron monitors and their environments, uptime monitors, metric monitors, and alert rules",
defaultEnabled: false,
order: 5,
},
Expand Down
194 changes: 193 additions & 1 deletion packages/mcp-core/src/toolDefinitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,198 @@
"skills": ["project-management"],
"surface": "catalog"
},
{
"name": "create_monitor",
"description": "Create a Sentry cron monitor.\n\nUse this tool when you need to:\n- Monitor a scheduled job (cron job, scheduled task) for missed, failed, or slow runs\n- Set up a cron monitor before instrumenting check-ins\n\nSet `schedule` to exactly one crontab or interval schedule. Check-ins must still be sent by the job (SDK `monitor_config`/check-ins or `sentry monitor run`) using the returned slug.\nAfter an error or timeout, use find_monitors with the name and project before retrying; creation is not idempotent.\n\n<examples>\ncreate_monitor(organizationSlug='my-organization', projectSlug='backend', name='Nightly Import', schedule={ type: 'crontab', crontab: '0 3 * * *' }, timezone='America/Los_Angeles', checkInMargin=5, maxRuntime=30)\ncreate_monitor(organizationSlug='my-organization', projectSlug='backend', name='Queue Drain', schedule={ type: 'interval', value: 15, unit: 'minute' })\n</examples>",
"inputSchema": {
"type": "object",
"properties": {
"organizationSlug": {
"type": "string",
"description": "The organization's slug. You can find a existing list of organizations you have access to using the `find_organizations()` tool."
},
"regionUrl": {
"default": null,
"anyOf": [
{
"type": "string",
"description": "The region URL for the organization you're querying, if known. For Sentry's Cloud Service (sentry.io), this is typically the region-specific URL like 'https://us.sentry.io'. For self-hosted Sentry installations, this parameter is usually not needed and should be omitted. You can find the correct regionUrl from the organization details using the `find_organizations()` tool."
},
{
"type": "null"
}
]
},
"projectSlug": {
"type": "string",
"description": "The project's slug. You can find a list of existing projects in an organization using the `find_projects()` tool."
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Monitor display name."
},
"slug": {
"type": "string",
"minLength": 1,
"description": "Optional monitor slug used by check-ins. Derived from the name when omitted."
},
"schedule": {
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "crontab"
},
"crontab": {
"type": "string",
"minLength": 1,
"description": "Five-field crontab schedule or `@` alias, e.g. `0 3 * * *` or `@daily`. Seconds fields are not supported."
}
},
"required": ["type", "crontab"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "interval"
},
"value": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"unit": {
"type": "string",
"enum": ["minute", "hour", "day", "week", "month", "year"]
}
},
"required": ["type", "value", "unit"],
"additionalProperties": false
}
],
"description": "Monitor schedule: exactly one of `{ type: 'crontab', crontab: '0 3 * * *' }` or `{ type: 'interval', value: 15, unit: 'minute' }`."
},
"timezone": {
"type": "string",
"minLength": 1,
"description": "tz database timezone for the schedule, e.g. `UTC`."
},
"checkInMargin": {
"type": "integer",
"minimum": 0,
"maximum": 40320,
"description": "Minutes after the expected time before a check-in counts as missed. Sentry treats 0 as 1."
},
"maxRuntime": {
"type": "integer",
"minimum": 1,
"maximum": 10080,
"description": "Minutes a check-in may stay in progress before it fails."
},
"failureIssueThreshold": {
"type": "integer",
"minimum": 1,
"maximum": 720,
"description": "Consecutive failed or missed check-ins before an issue opens."
},
"recoveryThreshold": {
"type": "integer",
"minimum": 1,
"maximum": 720,
"description": "Consecutive successful check-ins before the issue resolves."
},
"status": {
"type": "string",
"enum": ["active", "disabled"],
"description": "Monitor status. Disabled monitors ignore check-ins."
},
"owner": {
"type": "string",
"pattern": "^(user|team):\\d+$",
"description": "Owner actor in `user:ID` or `team:ID` format."
}
},
"required": ["organizationSlug", "projectSlug", "name", "schedule"]
},
"outputSchema": {
"type": "object",
"properties": {
"monitor": {
"type": "object",
"properties": {
"id": {
"type": ["string", "null"]
},
"slug": {
"type": "string"
},
"name": {
"type": "string"
},
"projectSlug": {
"type": ["string", "null"]
},
"status": {
"type": ["string", "null"]
},
"scheduleType": {
"type": ["string", "null"]
},
"schedule": {
"type": ["string", "null"]
},
"timezone": {
"type": ["string", "null"]
},
"checkInMargin": {
"type": ["number", "null"]
},
"maxRuntime": {
"type": ["number", "null"]
},
"failureIssueThreshold": {
"type": ["number", "null"]
},
"recoveryThreshold": {
"type": ["number", "null"]
},
"webUrl": {
"type": "string",
"format": "uri"
}
},
"required": [
"id",
"slug",
"name",
"projectSlug",
"status",
"scheduleType",
"schedule",
"timezone",
"checkInMargin",
"maxRuntime",
"failureIssueThreshold",
"recoveryThreshold",
"webUrl"
],
"additionalProperties": false
}
},
"required": ["monitor"],
"additionalProperties": false
},
"requiredScopes": ["org:read", "project:read", "alerts:write"],
"skills": ["project-management"],
"surface": "catalog"
},
{
"name": "create_project",
"description": "Create a new project in Sentry (provisions DSN automatically).\n\nUSE THIS TOOL WHEN USERS WANT TO:\n- 'Create a new project'\n- 'Set up a project for [app/service] with team [X]'\n- 'I need a new Sentry project'\n- Create project AND need DSN in one step\n- Create project and link an existing repository\n\nReturns the created project slug and a usable SENTRY_DSN when key setup succeeds.\n\nBe careful when using this tool!\n\n<examples>\n### Create new project with team\n```\ncreate_project(organizationSlug='my-organization', teamSlug='my-team', name='my-project', platform='javascript')\n```\n### Create project with an explicit slug\n```\ncreate_project(organizationSlug='my-organization', teamSlug='my-team', name='My Project', slug='my-project', platform='javascript')\n```\n### Create project and link to a repository\n```\ncreate_project(organizationSlug='my-organization', teamSlug='my-team', name='my-project', platform='javascript', repository='getsentry/sentry')\n```\n</examples>",
Expand Down Expand Up @@ -2350,7 +2542,7 @@
},
{
"name": "find_monitors",
"description": "Find Sentry cron monitors.\n\nUse this tool when you need to:\n- List cron monitors in an organization\n- Find a monitor by name or slug before getting details\n- Check monitor status, owner, project, schedule, or recent environment state\n- When `hasMore` is true, narrow the results with project, environment, owner, or query filters\n\n<examples>\nfind_monitors(organizationSlug='my-organization')\nfind_monitors(organizationSlug='my-organization', projectSlug='backend', query='billing')\n</examples>",
"description": "Find Sentry cron monitors.\n\nUse this tool when you need to:\n- List cron monitors in an organization\n- Find a monitor by name or slug before getting details\n- Check monitor status, owner, project, schedule, or recent environment state\n- When `hasMore` is true, narrow the results with project, environment, owner, or query filters\n\nTo create a cron monitor, use create_monitor.\n\n<examples>\nfind_monitors(organizationSlug='my-organization')\nfind_monitors(organizationSlug='my-organization', projectSlug='backend', query='billing')\n</examples>",
"inputSchema": {
"type": "object",
"properties": {
Expand Down
Loading
Loading