Skip to content

Conversation

@codeman9
Copy link
Contributor

@codeman9 codeman9 commented Aug 15, 2025

Summary

Adds support for selective workflow loading in static mode via the XCODEBUILDMCP_ENABLED_WORKFLOWS environment variable.

Problem

Clients that don't support MCP sampling cannot use dynamic tools but still want to reduce context window usage by loading only specific tool workflows.

Solution

  • Added registerSelectedWorkflows() function to load only specified workflows
  • Modified main server initialization to check for XCODEBUILDMCP_ENABLED_WORKFLOWS in static mode
  • Updated documentation with usage examples and available workflows

Usage

{
  "env": {
    "XCODEBUILDMCP_ENABLED_WORKFLOWS": "simulator,device,logging"
  }
}

Testing

  • All existing tests pass
  • Linting passes
  • Build succeeds
  • Feature works as expected (tested locally)

Summary by CodeRabbit

  • New Features

    • Enable selective loading of specific workflows in Static Mode via an environment variable, helping reduce resource usage for clients without sampling support.
    • Added startup logs listing the workflows selected when this option is used.
  • Documentation

    • Added guidance on configuring selective workflow loading, with examples and notes on compatibility (Dynamic Tools require sampling; fallback to Static Mode).
    • Updated CHANGELOG with an Unreleased entry describing the new environment variable.

…e workflow loading

- Added registerSelectedWorkflows() function to load only specified workflows
- Modified main server initialization to check for XCODEBUILDMCP_ENABLED_WORKFLOWS in static mode
- Updated documentation with usage examples and available workflows
- Allows clients without MCP sampling to reduce context window usage
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 15, 2025

Walkthrough

Introduces selective static workflow loading via XCODEBUILDMCP_ENABLED_WORKFLOWS. Updates startup flow in static mode to register only specified workflows; dynamic mode unchanged. Adds new registerSelectedWorkflows utility. Updates README and CHANGELOG to document the environment variable and static-mode behavior.

Changes

Cohort / File(s) Summary of Changes
Documentation
CHANGELOG.md, README.md
Added Unreleased note and README section on selective static workflow loading with XCODEBUILDMCP_ENABLED_WORKFLOWS, including example configuration and client compatibility notes. No API changes.
Server startup flow
src/index.ts
Imported registerSelectedWorkflows. In static mode, if XCODEBUILDMCP_ENABLED_WORKFLOWS is set, parse names and call registerSelectedWorkflows; otherwise fall back to registerAllToolsStatic. Dynamic mode remains using registerDiscoveryTools. Added logging of selected workflows.
Tool registry utilities
src/utils/tool-registry.ts
Added exported async function registerSelectedWorkflows(server, workflowNames): loads workflow groups, resolves tools for listed workflows, builds descriptors, and bulk registers tools; logs counts.

Sequence Diagram(s)

sequenceDiagram
  participant Env as Environment
  participant Proc as Process Startup
  participant Server as MCP Server
  participant Registry as Tool Registry

  Env->>Proc: XCODEBUILDMCP_DYNAMIC_TOOLS?
  alt Dynamic Tools = true
    Proc->>Registry: registerDiscoveryTools(Server)
  else Static Mode
    Env->>Proc: XCODEBUILDMCP_ENABLED_WORKFLOWS?
    alt Enabled Workflows set
      Proc->>Registry: registerSelectedWorkflows(Server, names[])
    else Not set
      Proc->>Registry: registerAllToolsStatic(Server)
    end
  end
Loading
sequenceDiagram
  participant Server as MCP Server
  participant ToolReg as tool-registry.registerSelectedWorkflows
  participant PluginReg as loadWorkflowGroups()

  Server->>ToolReg: registerSelectedWorkflows(names[])
  ToolReg->>PluginReg: loadWorkflowGroups()
  PluginReg-->>ToolReg: workflowGroups
  loop for each name in names[]
    ToolReg->>ToolReg: resolve workflow, build tool descriptors
  end
  ToolReg->>Server: registerTools(selectedTools)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

I thump my paws—select, not all!
A pick of flows, a lighter haul.
Static burrows, tidy, neat—
Only named trails meet my feet.
Dynamic winds? I’ll hop that too—
But for now, few carrots will do. 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
CHANGELOG.md (1)

3-6: Polish the entry: punctuation and capitalization for consistency.

Add a terminal period and capitalize “Sampling” to match README usage.

- - **Selective Workflow Loading**: New `XCODEBUILDMCP_ENABLED_WORKFLOWS` environment variable allows loading only specific workflow groups in static mode, reducing context window usage for clients that don't support MCP sampling
+ - **Selective Workflow Loading**: New `XCODEBUILDMCP_ENABLED_WORKFLOWS` environment variable allows loading only specific workflow groups in static mode, reducing context window usage for clients that don't support MCP Sampling.
src/utils/tool-registry.ts (1)

148-185: Harden selective loading: normalize inputs, warn on unknown workflows, and dedupe tool registrations.

Currently, unknown workflow names are silently ignored and duplicate tool names across workflows could be double-registered. Trim/normalize, dedupe workflow names, guard against duplicate tool names, and warn when nothing or unknown workflows are provided. This reduces confusion and avoids potential registration errors.

 export async function registerSelectedWorkflows(
   server: McpServer,
   workflowNames: string[],
 ): Promise<void> {
-  const { loadWorkflowGroups } = await import('../core/plugin-registry.js');
-  const workflowGroups = await loadWorkflowGroups();
-  const selectedTools = [];
+  const { loadWorkflowGroups } = await import('../core/plugin-registry.js');
+  const workflowGroups = await loadWorkflowGroups();
+  // Normalize and dedupe requested workflow names
+  const normalizedNames = workflowNames.map((n) => n.trim()).filter(Boolean);
+  const uniqueWorkflowNames = [...new Set(normalizedNames)];
+  const unknownWorkflows: string[] = [];
+  const selectedTools: Parameters<McpServer['registerTools']>[0] = [];
+  const seenToolNames = new Set<string>();
 
-  for (const workflowName of workflowNames) {
-    const workflow = workflowGroups.get(workflowName.trim());
-    if (workflow) {
-      for (const tool of workflow.tools) {
-        selectedTools.push({
-          name: tool.name,
-          config: {
-            description: tool.description ?? '',
-            inputSchema: tool.schema,
-          },
-          callback: (args: unknown): Promise<ToolResponse> =>
-            tool.handler(args as Record<string, unknown>),
-        });
-      }
-    }
-  }
+  for (const workflowName of uniqueWorkflowNames) {
+    const workflow = workflowGroups.get(workflowName);
+    if (!workflow) {
+      unknownWorkflows.push(workflowName);
+      continue;
+    }
+    for (const tool of workflow.tools) {
+      // Avoid double registration if the same tool appears in multiple workflows
+      if (seenToolNames.has(tool.name)) {
+        log('warn', `⚠️ Skipping duplicate tool registration: ${tool.name}`);
+        continue;
+      }
+      seenToolNames.add(tool.name);
+      selectedTools.push({
+        name: tool.name,
+        config: {
+          description: tool.description ?? '',
+          inputSchema: tool.schema,
+        },
+        callback: (args: unknown): Promise<ToolResponse> =>
+          tool.handler(args as Record<string, unknown>),
+      });
+    }
+  }
 
   if (selectedTools.length > 0) {
     server.registerTools(selectedTools);
   }
 
-  log(
-    'info',
-    `✅ Registered ${selectedTools.length} tools from workflows: ${workflowNames.join(', ')}`,
-  );
+  if (unknownWorkflows.length > 0) {
+    log('warn', `⚠️ Unknown workflows ignored: ${unknownWorkflows.join(', ')}`);
+  }
+  if (selectedTools.length === 0) {
+    log('warn', `⚠️ No tools registered for requested workflows: ${uniqueWorkflowNames.join(', ')}`);
+  } else {
+    log('info', `✅ Registered ${selectedTools.length} tools from workflows: ${uniqueWorkflowNames.join(', ')}`);
+  }
 }
README.md (2)

264-283: Tighten example parsing guidance and whitespace handling.

Consider clarifying that names are comma-separated and trimmed; unknown names are ignored. This aligns docs with implementation and reduces user confusion.

-For clients that don't support MCP Sampling but still want to reduce context window usage, you can selectively load only specific workflows using the `XCODEBUILDMCP_ENABLED_WORKFLOWS` environment variable:
+For clients that don't support MCP Sampling but still want to reduce context window usage, you can selectively load only specific workflows using the `XCODEBUILDMCP_ENABLED_WORKFLOWS` environment variable. Provide a comma-separated list; names are trimmed and matched against internal workflow keys. Unknown names are ignored:

285-301: Verify README workflow list vs generated plugin registry

Tried to extract workflow keys: src/core/plugin-registry.ts imports WORKFLOW_LOADERS and WORKFLOW_METADATA from ./generated-plugins.js, but a generated-plugins file is not present in the repo / source tree, so I could not confirm the README counts or that every listed workflow key exists.

Please check the following:

  • README.md (lines ~285–301) — hardcoded workflow keys + tool counts (needs attention).
  • src/core/plugin-registry.ts — imports the authoritative WORKFLOW_LOADERS / WORKFLOW_METADATA.
  • generated-plugins.js / generated-plugins.ts — apparently generated at build time and not committed; provide its path or ensure README is generated from it.

Suggested doc tweak (minimal):

-**Available Workflows:**
+**Available Workflows:**
+(Tool counts are approximate and may change between versions.)

Recommended actions:

  • Remove or make counts dynamic (generate from generated-plugins) or keep counts but add the above disclaimer.
  • If you want a full verification, please provide the generated-plugins file (or commit it / show its generated output) so I can compare the exact workflow keys against the README.
src/index.ts (1)

79-89: Parse the env list robustly and handle empty/whitespace-only values.

If the env var is set to an empty string or whitespace, the current code would proceed with an empty workflow name. Normalize inputs and fallback to full static registration if nothing valid remains.

-      // STATIC MODE: Check for selective workflows
-      const enabledWorkflows = process.env.XCODEBUILDMCP_ENABLED_WORKFLOWS;
-
-      if (enabledWorkflows) {
-        const workflowNames = enabledWorkflows.split(',');
-        log('info', `🚀 Initializing server with selected workflows: ${workflowNames.join(', ')}`);
-        await registerSelectedWorkflows(server, workflowNames);
-      } else {
-        log('info', '🚀 Initializing server in static tools mode...');
-        await registerAllToolsStatic(server);
-      }
+      // STATIC MODE: Check for selective workflows
+      const enabledWorkflows = process.env.XCODEBUILDMCP_ENABLED_WORKFLOWS;
+      if (typeof enabledWorkflows === 'string') {
+        const workflowNames = enabledWorkflows
+          .split(',')
+          .map((n) => n.trim())
+          .filter(Boolean);
+        if (workflowNames.length > 0) {
+          log('info', `🚀 Initializing server with selected workflows: ${workflowNames.join(', ')}`);
+          await registerSelectedWorkflows(server, workflowNames);
+        } else {
+          log('warn', '⚠️ XCODEBUILDMCP_ENABLED_WORKFLOWS provided but no valid workflow names found; falling back to static all-tools.');
+          log('info', '🚀 Initializing server in static tools mode...');
+          await registerAllToolsStatic(server);
+        }
+      } else {
+        log('info', '🚀 Initializing server in static tools mode...');
+        await registerAllToolsStatic(server);
+      }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 25d637b and 5fa466f.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • README.md (1 hunks)
  • src/index.ts (2 hunks)
  • src/utils/tool-registry.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/utils/tool-registry.ts (2)
src/core/plugin-registry.ts (1)
  • loadWorkflowGroups (24-66)
src/utils/logger.ts (1)
  • log (33-53)
src/index.ts (2)
src/utils/logger.ts (1)
  • log (33-53)
src/utils/tool-registry.ts (2)
  • registerSelectedWorkflows (151-184)
  • registerAllToolsStatic (189-212)
🪛 LanguageTool
CHANGELOG.md

[grammar] ~3-~3: There might be a mistake here.
Context: # Changelog ## [Unreleased] ### Added - Selective Workflow Loading: ...

(QB_NEW_EN)


[grammar] ~4-~4: There might be a mistake here.
Context: # Changelog ## [Unreleased] ### Added - Selective Workflow Loading: New `XCODE...

(QB_NEW_EN)

🔇 Additional comments (1)
src/index.ts (1)

37-41: Import looks correct and consistent with existing ESM style.

The new import of registerSelectedWorkflows aligns with other .js-suffixed ESM imports used across the file.

Copy link
Collaborator

@cameroncooke cameroncooke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR, thank you for your contribution!

@cameroncooke cameroncooke merged commit 4f50fc1 into getsentry:main Aug 15, 2025
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants