diff --git a/apps/docs/docs.json b/apps/docs/docs.json index f18c464448..6bc79ffffa 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -155,6 +155,7 @@ "integrations/asana", "integrations/better-stack", "integrations/braintrust", + "integrations/circleci", "integrations/elevenlabs", "integrations/exa", "integrations/grafana", diff --git a/apps/docs/integrations/circleci.mdx b/apps/docs/integrations/circleci.mdx new file mode 100644 index 0000000000..088a3b3a0a --- /dev/null +++ b/apps/docs/integrations/circleci.mdx @@ -0,0 +1,29 @@ +--- +title: CircleCI +description: Inspect CircleCI runs, logs, tests, and artifacts from Roomote tasks. +icon: 'https://api.iconify.design/simple-icons:circleci.svg?color=currentColor' +--- + +Connect CircleCI when tasks need CI run status, job details, logs, test results, +artifacts, or organization usage data. + +## How setup works + +A deployment operator connects CircleCI once from **Settings > Integrations** +using OAuth. CircleCI uses dynamic client registration and grants access based +on the projects available to the authorizing account. + +This integration uses CircleCI's hosted MCP server. It does not install the +CircleCI CLI MCP, and it does not use CircleCI's deprecated local `npx` server. + +## Safer defaults + +Roomote enables diagnostic tools by default. Workflow reruns and cancellations +start disabled because they change shared CI state. An admin can opt in to +either tool from **Settings > Integrations > CircleCI > Manage tools**. + +## Verify the connection + +Start by listing recent runs or reading logs for a failed job. If a project is +missing, confirm that the connected CircleCI account can access it, then +reconnect if its permissions changed. diff --git a/apps/docs/integrations/index.mdx b/apps/docs/integrations/index.mdx index ae26253607..73158acb62 100644 --- a/apps/docs/integrations/index.mdx +++ b/apps/docs/integrations/index.mdx @@ -79,6 +79,7 @@ from [Personal Settings](/personal-settings). | | Project and task context from Asana | Admin connection once | | | Monitoring and incident context | Admin connection once | | | Prompts, runs, and evaluation context | Enable first, then teammates link accounts | +| | CI runs, logs, tests, and artifacts | Admin connection once | | | Voice narration for feature-demo videos | Admin connection once | | | Keyless web search; optional Agent research | Admin enables; API key optional | | | Dashboards, alerting, and monitoring context | Admin connection once | diff --git a/apps/web/src/components/settings/Integrations.tsx b/apps/web/src/components/settings/Integrations.tsx index bd77e8cfa2..73b55e97b2 100644 --- a/apps/web/src/components/settings/Integrations.tsx +++ b/apps/web/src/components/settings/Integrations.tsx @@ -109,6 +109,8 @@ const DEEP_LINK_ENABLE_DESCRIPTIONS: Record = { 'Roomote will be able to inspect monitoring, incidents, and telemetry.', braintrust: 'Roomote will be able to inspect prompts, evaluations, and AI run history.', + circleci: + 'Roomote will be able to inspect CircleCI runs, workflows, jobs, logs, tests, and artifacts. Reruns and cancellations start disabled.', grafana: 'Roomote will be able to inspect dashboards, alert rules, live alert state, annotations, and data sources.', granola: diff --git a/apps/web/src/components/system/custom/logos/brand-icon.tsx b/apps/web/src/components/system/custom/logos/brand-icon.tsx index 5243066afc..375f3ce02c 100644 --- a/apps/web/src/components/system/custom/logos/brand-icon.tsx +++ b/apps/web/src/components/system/custom/logos/brand-icon.tsx @@ -4,6 +4,7 @@ import { siAsana, siBetterstack, siBraintrust, + siCircleci, siElevenlabs, siDependabot, siDatadog, @@ -42,6 +43,7 @@ const SIMPLE_ICONS: Record = { asana: siAsana, betterstack: siBetterstack, braintrust: siBraintrust, + circleci: siCircleci, elevenlabs: siElevenlabs, dependabot: siDependabot, datadog: siDatadog, diff --git a/apps/worker/src/mcp/roomote-mcp-server/integration-setup.ts b/apps/worker/src/mcp/roomote-mcp-server/integration-setup.ts index 5ea3a3bd73..d136d3b459 100644 --- a/apps/worker/src/mcp/roomote-mcp-server/integration-setup.ts +++ b/apps/worker/src/mcp/roomote-mcp-server/integration-setup.ts @@ -53,6 +53,14 @@ Sentry uses the workspace MCP integration: Once connected, tasks can inspect Sentry issue and project context, and scheduled Sentry triage automation uses the same read-only MCP connection. +# CircleCI + +CircleCI uses OAuth: +1. A deployment operator enables CircleCI from Settings > Integrations. +2. That operator connects CircleCI once for the deployment via OAuth. + +Once connected, I can inspect runs, workflows, jobs, logs, tests, artifacts, and usage data for projects available to the connected account. Workflow reruns and cancellations stay disabled until an administrator enables those tools from Manage tools. + # Pylon Pylon uses OAuth: diff --git a/packages/cloud-agents/src/server/mcp-self-setup/catalog.ts b/packages/cloud-agents/src/server/mcp-self-setup/catalog.ts index 6b47f76431..a90d03ce32 100644 --- a/packages/cloud-agents/src/server/mcp-self-setup/catalog.ts +++ b/packages/cloud-agents/src/server/mcp-self-setup/catalog.ts @@ -38,6 +38,13 @@ export const MCP_SETUP_INTEGRATION_METADATA: Record< string, SetupMcpIntegrationMetadata > = { + circleci: { + capabilities: [ + 'Inspect CircleCI runs, workflows, jobs, and step results', + 'Read job logs, test results, artifacts, and usage exports', + 'Opt in to workflow reruns and cancellations when needed', + ], + }, asana: { capabilities: [ 'Inspect Asana workspaces, projects, and tasks', diff --git a/packages/slack/src/mcp-recommendations.ts b/packages/slack/src/mcp-recommendations.ts index ba8722fae4..13c29e1962 100644 --- a/packages/slack/src/mcp-recommendations.ts +++ b/packages/slack/src/mcp-recommendations.ts @@ -57,6 +57,8 @@ const SLACK_ENABLE_DESCRIPTIONS: Record = { 'Roomote will be able to inspect and manage shared email infrastructure.', braintrust: 'Roomote will be able to inspect prompts, evaluations, and AI run history.', + circleci: + 'Roomote will be able to inspect CircleCI runs, workflows, jobs, logs, tests, and artifacts. Reruns and cancellations start disabled.', linear: 'Roomote will be able to pull issue, project, and roadmap context into tasks.', monday: diff --git a/packages/types/src/__tests__/mcp-oauth.test.ts b/packages/types/src/__tests__/mcp-oauth.test.ts index f4c07bc745..ff4e30e8bb 100644 --- a/packages/types/src/__tests__/mcp-oauth.test.ts +++ b/packages/types/src/__tests__/mcp-oauth.test.ts @@ -18,6 +18,7 @@ import { LINEAR_APP_OAUTH_SCOPES, MONDAY_MCP_READ_ONLY_OAUTH_SCOPES, RESEND_DEFAULT_DISABLED_TOOL_NAMES, + CIRCLECI_DEFAULT_DISABLED_TOOL_NAMES, } from '../mcp-oauth'; describe('integration data policy', () => { @@ -89,6 +90,25 @@ describe('monday.com OAuth', () => { }); }); +describe('CircleCI OAuth', () => { + it('uses the hosted MCP with deployment-scoped DCR and safe defaults', () => { + expect(getMcpIntegration('circleci')).toMatchObject({ + name: 'CircleCI', + url: 'https://mcp.circleci.com/v1/mcp', + connectionScope: 'deployment', + oauthResource: 'https://mcp.circleci.com/v1/mcp', + }); + expect(getMcpIntegration('circleci')?.oauthClientEnv).toBeUndefined(); + expect(getMcpIntegrationDefaultDisabledTools('circleci')).toEqual( + CIRCLECI_DEFAULT_DISABLED_TOOL_NAMES, + ); + expect(CIRCLECI_DEFAULT_DISABLED_TOOL_NAMES).toEqual([ + 'rerun_workflow', + 'cancel_workflow', + ]); + }); +}); + describe('Notion internal integration', () => { it('uses a deployment-scoped native MCP with admin-managed credentials', () => { expect(getMcpIntegration('notion')).toMatchObject({ diff --git a/packages/types/src/mcp-oauth.ts b/packages/types/src/mcp-oauth.ts index 5976586312..3d6fea5c18 100644 --- a/packages/types/src/mcp-oauth.ts +++ b/packages/types/src/mcp-oauth.ts @@ -547,6 +547,11 @@ export const RESEND_DEFAULT_DISABLED_TOOL_NAMES = [ 'update-webhook', ] as const; +export const CIRCLECI_DEFAULT_DISABLED_TOOL_NAMES = [ + 'rerun_workflow', + 'cancel_workflow', +] as const; + /** * Path prefixes of the API-hosted MCP proxy mounts. URL producers build proxy * URLs from these, and consumers (e.g. the Fast integration broker) use the @@ -652,6 +657,18 @@ export const MCP_INTEGRATIONS: McpIntegration[] = [ instructions: 'Sentry advertises only a few tools directly (find_organizations, find_projects, search_issues, search_events, get_sentry_resource). Reach everything else (issue details, event stack traces, breadcrumbs, tag values, issue events, releases, traces, replays, attachments, monitors, alert rules, docs) by calling search_sentry_tools with a short query, then execute_sentry_tool with the returned tool name and arguments. Which tools exist depends on the access the admin granted when connecting. Treat Sentry as read-only unless the request explicitly asks to change Sentry state: do not resolve, assign, ignore, or otherwise update issues, and do not create or modify projects, teams, DSNs, or monitors on your own initiative.', }, + { + id: 'circleci', + name: 'CircleCI', + url: 'https://mcp.circleci.com/v1/mcp', + description: `Inspect CircleCI runs, workflows, jobs, logs, tests, and artifacts from ${PRODUCT_NAME} tasks`, + icon: 'circleci', + connectionScope: 'deployment', + oauthResource: 'https://mcp.circleci.com/v1/mcp', + defaultDisabledTools: [...CIRCLECI_DEFAULT_DISABLED_TOOL_NAMES], + instructions: + 'Use CircleCI to inspect runs, workflows, jobs, logs, tests, artifacts, and usage data. Workflow reruns and cancellations are disabled until an administrator enables them in Manage tools; when enabled, invoke them only for an explicit user request.', + }, { id: 'pylon', name: 'Pylon', diff --git a/packages/types/src/mcp-service-detection.ts b/packages/types/src/mcp-service-detection.ts index dc10746db7..d38d46c451 100644 --- a/packages/types/src/mcp-service-detection.ts +++ b/packages/types/src/mcp-service-detection.ts @@ -90,6 +90,14 @@ const X_APP_PATH_REGEX = /^\/(?:search|explore)(?:\/|$)|^\/i\/(?:lists|communities|spaces)\//; export const SLACK_MCP_SETUP_SERVICES: SlackMcpSetupServiceDefinition[] = [ + { + id: 'circleci', + name: 'CircleCI', + availabilityKind: 'curated_oauth', + hostSuffixes: ['app.circleci.com'], + deploymentSettingsPath: '/integrations', + userSettingsPath: '/settings/personal', + }, { id: 'asana', name: 'Asana',