Skip to content

Comments

Mi MCP tools improvements#1535

Merged
gigara merged 18 commits intomainfrom
mi-mcp-tools
Feb 23, 2026
Merged

Mi MCP tools improvements#1535
gigara merged 18 commits intomainfrom
mi-mcp-tools

Conversation

@kaumini
Copy link
Contributor

@kaumini kaumini commented Feb 23, 2026

Purpose

MCP tools improvements

  • Implement diagram on connection click for tools
  • Group mcp tools with same connection
  • Adding mcp tools (with plus click) with previous connection should show already selected tools
  • Submit mcp tool descriptions
  • Render ai connector icon for mcp diagram and panel

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

UI Component Development

Specify the reason if following are not followed.

  • Added reusable UI components to the ui-toolkit. Follow the intructions when adding the componenent.
  • Use ui-toolkit components wherever possible. Run npm run storybook from the root directory to view current components.
  • Matches with the native VSCode look and feel.

Manage Icons

Specify the reason if following are not followed.

  • Added Icons to the font-wso2-vscode. Follow the instructions.

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Summary by CodeRabbit

  • New Features

    • MCP tool selection now includes document and range context for more accurate results.
    • Selections preserve full tool objects (UI shows names); select-all/deselect-all and counts updated.
    • Connector nodes consolidate MCP tools that share a connection and show "Tool Operation" / "MCP Tools" labels.
    • "Add MCP Tools" option gated by AI mediator version (minimum required).
  • Chores

    • Adjusted tools list maximum height offset for improved layout.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds document URI and range to the MCP tools RPC and client call; migrates MCP selection model from string[] to McpTool[] with derived selectedToolNames; deduplicates MCP tools by mcpConnection in visitors; and updates connector rendering and connection-opening flows to be MCP-aware.

Changes

Cohort / File(s) Summary
RPC Types & Syntax Tree
workspaces/mi/mi-core/src/rpc-types/mi-diagram/types.ts, workspaces/mi/syntax-tree/src/syntax-tree-interfaces.ts
McpToolsRequest now includes documentUri and range; McpToolsResponse may include selectedTools; Tool interface gains mcpConnection?: string and mcpToolNames?: string[].
Language Client
workspaces/mi/mi-extension/src/lang-client/ExtendedLanguageClient.ts
getMcpTools RPC payload expanded to serialize and send documentUri and range along with connectionName.
Tool Selection UI
workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx, workspaces/mi/mi-diagram/src/components/Form/FormGenerator.tsx
Selection API moved from string[] to McpTool[]; components accept documentUri and range; response selectedTools mapped to McpTool[]; derive selectedToolNames: Set<string> for display/validation; select-all, modals and lists updated to use McpTool objects and name-set for UI.
Connector & Node Rendering
workspaces/mi/mi-diagram/src/components/nodes/BaseNodeModel.ts, workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx
Treat tool nodes as connectors where appropriate; use 'ai' connectorName for MCP tools; make icon, header, description and connection-open flows MCP-aware and surface mcpToolNames in UI.
Visitors / Layout & Positioning
workspaces/mi/mi-diagram/src/visitors/NodeFactoryVisitor.ts, workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts, workspaces/mi/mi-diagram/src/visitors/SizingVisitor.ts
Filter MCP tools to a deduplicated list (first tool per unique mcpConnection) while keeping non-MCP tools; populate mcpToolNames for MCP tools; sizing/positioning iterate over filtered list.
Side Panel / Mediators
workspaces/mi/mi-diagram/src/components/sidePanel/mediators/List.tsx
Add isAIMediatorVersionValid() helper and gate "Add MCP Tools" card behind minimum AI mediator version check.
Constants
workspaces/mi/mi-diagram/src/resources/constants.ts
Incremented MCP_TOOLS_LIST_MAX_HEIGHT_OFFSET from 470 to 480.

Sequence Diagram(s)

sequenceDiagram
  participant UI as Form / MCPtoolsSelection
  participant Client as ExtendedLanguageClient
  participant Server as Language Server
  participant Diagram as Diagram Components

  UI->>Client: getMcpTools({ connectionName, documentUri, range })
  Client->>Server: RPC request (connectionName, documentUri, range)
  Server-->>Client: McpToolsResponse (McpTool[] + optional selectedTools)
  Client-->>UI: resolved McpTool[] (mapped)
  UI->>UI: derive selectedToolNames (Set<string>) and update selection state
  UI->>Diagram: re-render nodes/connectors (use mcpToolNames / MCP-aware flows)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

Possibly related PRs

  • Add MCP tools support #1436 — Prior MCP tools work that introduced initial getMcpTools RPC and UI plumbing; this PR extends payload and migrates selection model.

Suggested reviewers

  • hevayo
  • gigara

Poem

🐇 I hopped through code and threaded a range,
URIs in paw, deduped tools by their change,
Names gathered in sets, selections now true,
Connectors now listen, and open for you,
A tiny rabbit cheer for diagrams anew ✨

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete, providing only a high-level Purpose section listing objectives but omitting critical content in Goals, Approach, UI changes, testing, security, and documentation sections required by the template. Complete the missing sections: Goals, Approach (with UI/visual documentation), UI Component Development verification, Release note, Documentation links, Automation tests, Security checks, and Test environment details.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Mi MCP tools improvements' is vague and generic, using the term 'improvements' without conveying specific details about the primary changes in the changeset. Use a more specific title that captures the main focus, such as 'Group MCP tools by connection and add connection context to requests' or 'Implement MCP tool grouping and diagram enhancements'.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mi-mcp-tools

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx (1)

362-423: ⚠️ Potential issue | 🟡 Minor

Use Tool.mcpConnection for MCP connection label/icon.

The label/icon currently rely on connectorNode.mcpConnection, which can be undefined when MCP connection data lives on the Tool. This can leave the connection label blank for MCP tools.

🧩 Suggested fix
-    const connectorNode = ((node.stNode as Tool).mediator ?? node.stNode) as Connector;
+    const toolNode = node.stNode as Tool;
+    const connectorNode = (toolNode.mediator ?? node.stNode) as Connector;
     const tooltip = hasDiagnotics ? node.getDiagnostics().map(diagnostic => diagnostic.message).join("\n") : undefined;
-    const isMCPTool = (node.stNode as Tool).isMcpTool;
+    const isMCPTool = toolNode.isMcpTool;
+    const connectionLabel = isMCPTool ? toolNode.mcpConnection : connectorNode.configKey;
...
-            {(connectorNode.configKey || isMCPTool )  &&
+            {(connectionLabel || isMCPTool )  &&
                 <S.CircleContainer
...
-                            {connectorNode.mcpConnection && <g transform="translate(68,7)">
+                            {isMCPTool && connectionLabel && <g transform="translate(68,7)">
                                 <foreignObject width="25" height="25">
                                     <S.IconContainer>{getMediatorIconsFromFont('mcp')}</S.IconContainer>
                                 </foreignObject>
                             </g>}
...
             {(connectorNode.configKey || isMCPTool) &&
                 <S.ConnectionContainer>
                     <S.ConnectionText>
-                        {connectorNode.configKey || connectorNode.mcpConnection}
+                        {connectionLabel}
                     </S.ConnectionText>
                 </S.ConnectionContainer>}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx`
around lines 362 - 423, The connector label/icon uses
connectorNode.mcpConnection but MCP tools may store the data on the Tool object;
update usages to fall back to Tool.mcpConnection when
connectorNode.mcpConnection is falsy. Specifically, in the JSX blocks that
render the icon and the connection label (references:
connectorNode.mcpConnection, getMediatorIconsFromFont('mcp'), and the
ConnectionText that renders connectorNode.configKey ||
connectorNode.mcpConnection), change the expression to use
connectorNode.mcpConnection || Tool.mcpConnection (or an equivalent accessor
from props/context that provides the Tool) so the icon and text render for MCP
tools. Ensure the tooltip/conditional checks (connectorNode.configKey ||
isMCPTool) still gate rendering.
workspaces/mi/mi-diagram/src/components/Form/FormGenerator.tsx (2)

1281-1302: ⚠️ Potential issue | 🟠 Major

documentUri and range may be undefined but McpToolsSelection expects non-optional values.

In FormGeneratorProps, both documentUri and range are optional (documentUri?: string, range?: Range), but McpToolsSelectionProps declares them as required (documentUri: string, range: Range). The mcpToolsSelection case has no guard to ensure they're defined before rendering.

This means undefined can be passed to McpToolsSelection, which then forwards them to the RPC call at line 472/474 of McpToolsSelection.tsx, potentially causing a runtime error.

Proposed fix: guard the render
         case 'mcpToolsSelection':
+            if (!documentUri || !range) {
+                return null;
+            }
             const selectedToolsSet = new Set<string>(
                 Array.isArray(selectedMcpTools) ? selectedMcpTools : []
             );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/mi/mi-diagram/src/components/Form/FormGenerator.tsx` around lines
1281 - 1302, The mcpToolsSelection branch in FormGenerator (case
'mcpToolsSelection') can pass undefined documentUri/range to McpToolsSelection
(props documentUri: string, range: Range); add a guard that checks
FormGenerator's documentUri and range are defined before returning
McpToolsSelection and otherwise render a safe fallback (e.g., null or a
validation message) or disable the control; ensure the check happens before
creating selectedToolsSet and before rendering so McpToolsSelection never
receives undefined values.

1282-1301: ⚠️ Potential issue | 🟠 Major

selectedToolsSet is constructed incorrectly — McpTool[] objects are passed to new Set<string>().

After this PR, mcpToolsSelection stores McpTool[] (objects with name and description). useWatch on line 243 returns these objects. Passing them to new Set<string>() produces a Set of "[object Object]" strings, not tool names. The selectedTools prop becomes unusable for any .has(toolName) check.

This is currently masked because McpToolsSelection internally computes selectedToolNames from getValues rather than using the selectedTools prop. However, if the component is fixed to use the prop (per the earlier comment), this will break.

Proposed fix: map to tool names
         case 'mcpToolsSelection':
             const selectedToolsSet = new Set<string>(
-                Array.isArray(selectedMcpTools) ? selectedMcpTools : []
+                Array.isArray(selectedMcpTools)
+                    ? selectedMcpTools.map((tool: any) => typeof tool === 'string' ? tool : tool.name)
+                    : []
             );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/mi/mi-diagram/src/components/Form/FormGenerator.tsx` around lines
1282 - 1301, The selectedToolsSet is being built from selectedMcpTools (which
now contains McpTool objects) but is passed to new Set<string>() without mapping
to names, producing "[object Object]" entries; update the construction of
selectedToolsSet (used where selectedMcpTools is referenced and passed into the
McpToolsSelection component) to map selectedMcpTools to their name strings
(e.g., Array.isArray(selectedMcpTools) ? selectedMcpTools.map(t => t.name) : [])
before creating the Set so selectedTools prop is a Set of tool names that
.has(toolName) checks will work as intended.
workspaces/mi/mi-core/src/rpc-types/mi-diagram/types.ts (1)

2108-2126: ⚠️ Potential issue | 🟡 Minor

Remove the unused McpToolsWithDescription interface.

The McpToolsWithDescription interface (lines 2123-2126) is not imported or used anywhere in the codebase. Since it duplicates the McpTool interface concept with only a minor difference (required vs. optional description field), and is not referenced anywhere, it should be removed as dead code.

The McpToolsRequest, McpToolsResponse, and changes to add documentUri, range, and selectedTools are otherwise consistent with the PR objectives.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/mi/mi-core/src/rpc-types/mi-diagram/types.ts` around lines 2108 -
2126, Remove the dead interface McpToolsWithDescription by deleting its
declaration (the interface named McpToolsWithDescription) from the file; ensure
no other code references it (search for McpToolsWithDescription) and rely on the
existing McpToolsResponse/McpToolsRequest types instead so you don't introduce
any new type changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`:
- Around line 443-451: The memo for selectedToolNames currently depends on
getValues('mcpToolsSelection') which is non-reactive and causes
incorrect/ineffective memoization; replace this by deriving the Set from the
reactive selectedTools prop passed by the parent (or subscribe directly with
useWatch using the component's _control) and memoize on that reactive value
instead — update the selectedToolNames computation to map the incoming
selectedTools (or the useWatch result) to a Set of tool.name, and remove
getValues from the dependency array so the displayed selection actually follows
form changes.

In `@workspaces/mi/mi-diagram/src/visitors/NodeFactoryVisitor.ts`:
- Around line 732-759: The filter for toolsWithUniqueConnections currently
excludes MCP tools lacking mcpConnection (tool.mcpConnection falsy) which hides
legacy/new tools; change the filter so missing mcpConnection is treated as a
unique connection (i.e., if connectionName is null/undefined, return true to
include that MCP tool), and keep the rest of the dedup logic the same; also
ensure the grouping logic that builds toolNode.mcpToolNames and the calls to
createNodeAndLinks (in this file) remains compatible, and mirror this fallback
behavior in PositionVisitor and SizingVisitor so layout/positioning treat
missing mcpConnection as its own unique group.

---

Outside diff comments:
In `@workspaces/mi/mi-core/src/rpc-types/mi-diagram/types.ts`:
- Around line 2108-2126: Remove the dead interface McpToolsWithDescription by
deleting its declaration (the interface named McpToolsWithDescription) from the
file; ensure no other code references it (search for McpToolsWithDescription)
and rely on the existing McpToolsResponse/McpToolsRequest types instead so you
don't introduce any new type changes.

In `@workspaces/mi/mi-diagram/src/components/Form/FormGenerator.tsx`:
- Around line 1281-1302: The mcpToolsSelection branch in FormGenerator (case
'mcpToolsSelection') can pass undefined documentUri/range to McpToolsSelection
(props documentUri: string, range: Range); add a guard that checks
FormGenerator's documentUri and range are defined before returning
McpToolsSelection and otherwise render a safe fallback (e.g., null or a
validation message) or disable the control; ensure the check happens before
creating selectedToolsSet and before rendering so McpToolsSelection never
receives undefined values.
- Around line 1282-1301: The selectedToolsSet is being built from
selectedMcpTools (which now contains McpTool objects) but is passed to new
Set<string>() without mapping to names, producing "[object Object]" entries;
update the construction of selectedToolsSet (used where selectedMcpTools is
referenced and passed into the McpToolsSelection component) to map
selectedMcpTools to their name strings (e.g., Array.isArray(selectedMcpTools) ?
selectedMcpTools.map(t => t.name) : []) before creating the Set so selectedTools
prop is a Set of tool names that .has(toolName) checks will work as intended.

In
`@workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx`:
- Around line 362-423: The connector label/icon uses connectorNode.mcpConnection
but MCP tools may store the data on the Tool object; update usages to fall back
to Tool.mcpConnection when connectorNode.mcpConnection is falsy. Specifically,
in the JSX blocks that render the icon and the connection label (references:
connectorNode.mcpConnection, getMediatorIconsFromFont('mcp'), and the
ConnectionText that renders connectorNode.configKey ||
connectorNode.mcpConnection), change the expression to use
connectorNode.mcpConnection || Tool.mcpConnection (or an equivalent accessor
from props/context that provides the Tool) so the icon and text render for MCP
tools. Ensure the tooltip/conditional checks (connectorNode.configKey ||
isMCPTool) still gate rendering.

---

Duplicate comments:
In `@workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts`:
- Around line 533-549: The filter for toolsWithUniqueConnections in
PositionVisitor excludes MCP tools that have no mcpConnection (returning false),
which drops valid tools; update the filter so non-MCP tools remain included, and
MCP tools without a connection are also included (only MCP tools with a defined
mcpConnection should be deduplicated by checking firstIndex). Locate the
toolsList.filter block in PositionVisitor (the toolsWithUniqueConnections
variable) and change the connectionName check from "if (!connectionName) {
return false; }" to include those tools (e.g., "if (!connectionName) { return
true; }" or equivalent logic) so only MCP tools with a connection are subject to
the findIndex uniqueness filter.

In `@workspaces/mi/mi-diagram/src/visitors/SizingVisitor.ts`:
- Around line 606-633: The filter for toolsWithUniqueConnections currently
excludes MCP tools that lack an mcpConnection (returns false) which drops them
unintentionally; update the filter inside SizingVisitor.ts so that: if
!isMcpTool return true as before, but if isMcpTool and the tool has no
mcpConnection also return true (treat them like non-MCP), and only apply the
"firstIndex" uniqueness check when a connectionName exists; reference the
toolsWithUniqueConnections filter, toolsList, Tool, isMcpTool, and mcpConnection
(and mirror the same fix you applied in NodeFactoryVisitor).

Comment on lines +732 to 759
const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
const isMcpTool = tool.isMcpTool;
if (!isMcpTool) {
return true; // Include all non-MCP tools
}
// For MCP tools, only include the first one with each unique connection name
const connectionName = tool.mcpConnection;
if (!connectionName) {
return false;
}
const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
return index === firstIndex;
});

for (let i = 0; i < toolsWithUniqueConnections.length; i++) {
const toolNode = toolsWithUniqueConnections[i];
const isMCPTool = toolNode.isMcpTool;
if (isMCPTool) {
if (toolNode.mcpConnection) {
toolNode.mcpToolNames = toolsList
.filter((t: Tool) => t.mcpConnection === toolNode.mcpConnection)
.map((t: Tool) => t.name);
}
this.createNodeAndLinks({ node: toolNode, name: toolNode.tag, type: NodeTypes.CONNECTOR_NODE, dontLink: true });
continue;
}
if(toolNode.mediator == undefined) {
if (toolNode.mediator == undefined) {
continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid hiding MCP tools without a connection.

The filter excludes MCP tools when mcpConnection is missing, which can make newly added/legacy tools disappear from the diagram. Consider keeping such tools visible (treat missing connection as unique), and mirror the fallback in PositionVisitor and SizingVisitor for consistent layout.

🔧 Suggested adjustment
-                    const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
-                        const isMcpTool = tool.isMcpTool;
-                        if (!isMcpTool) {
-                            return true; // Include all non-MCP tools
-                        }
-                        // For MCP tools, only include the first one with each unique connection name
-                        const connectionName = tool.mcpConnection;
-                        if (!connectionName) {
-                            return false;
-                        }
-                        const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
-                        return index === firstIndex;
-                    });
+                    const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
+                        const isMcpTool = tool.isMcpTool;
+                        if (!isMcpTool) {
+                            return true; // Include all non-MCP tools
+                        }
+                        // For MCP tools, only include the first one with each unique connection name.
+                        // If there's no connection yet, keep the tool visible.
+                        const connectionName = tool.mcpConnection;
+                        if (!connectionName) {
+                            return true;
+                        }
+                        const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
+                        return index === firstIndex;
+                    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
const isMcpTool = tool.isMcpTool;
if (!isMcpTool) {
return true; // Include all non-MCP tools
}
// For MCP tools, only include the first one with each unique connection name
const connectionName = tool.mcpConnection;
if (!connectionName) {
return false;
}
const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
return index === firstIndex;
});
for (let i = 0; i < toolsWithUniqueConnections.length; i++) {
const toolNode = toolsWithUniqueConnections[i];
const isMCPTool = toolNode.isMcpTool;
if (isMCPTool) {
if (toolNode.mcpConnection) {
toolNode.mcpToolNames = toolsList
.filter((t: Tool) => t.mcpConnection === toolNode.mcpConnection)
.map((t: Tool) => t.name);
}
this.createNodeAndLinks({ node: toolNode, name: toolNode.tag, type: NodeTypes.CONNECTOR_NODE, dontLink: true });
continue;
}
if(toolNode.mediator == undefined) {
if (toolNode.mediator == undefined) {
continue;
const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
const isMcpTool = tool.isMcpTool;
if (!isMcpTool) {
return true; // Include all non-MCP tools
}
// For MCP tools, only include the first one with each unique connection name.
// If there's no connection yet, keep the tool visible.
const connectionName = tool.mcpConnection;
if (!connectionName) {
return true;
}
const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
return index === firstIndex;
});
for (let i = 0; i < toolsWithUniqueConnections.length; i++) {
const toolNode = toolsWithUniqueConnections[i];
const isMCPTool = toolNode.isMcpTool;
if (isMCPTool) {
if (toolNode.mcpConnection) {
toolNode.mcpToolNames = toolsList
.filter((t: Tool) => t.mcpConnection === toolNode.mcpConnection)
.map((t: Tool) => t.name);
}
this.createNodeAndLinks({ node: toolNode, name: toolNode.tag, type: NodeTypes.CONNECTOR_NODE, dontLink: true });
continue;
}
if (toolNode.mediator == undefined) {
continue;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/mi/mi-diagram/src/visitors/NodeFactoryVisitor.ts` around lines 732
- 759, The filter for toolsWithUniqueConnections currently excludes MCP tools
lacking mcpConnection (tool.mcpConnection falsy) which hides legacy/new tools;
change the filter so missing mcpConnection is treated as a unique connection
(i.e., if connectionName is null/undefined, return true to include that MCP
tool), and keep the rest of the dedup logic the same; also ensure the grouping
logic that builds toolNode.mcpToolNames and the calls to createNodeAndLinks (in
this file) remains compatible, and mirror this fallback behavior in
PositionVisitor and SizingVisitor so layout/positioning treat missing
mcpConnection as its own unique group.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request implements improvements to MCP (Model Context Protocol) tools functionality in the MI (Micro Integrator) diagram and visualization components. The changes focus on improving user experience when working with MCP tools, including better grouping, selection management, and visual representation.

Changes:

  • Extended Tool interface to include MCP-specific metadata (connection name and tool names)
  • Modified MCP tools request/response to include document context and selected tools
  • Implemented grouping of MCP tools by connection in diagram visualization
  • Changed MCP tool selection from string arrays to full tool objects with descriptions
  • Updated connector icons to use AI connector icon for MCP tools

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
workspaces/mi/syntax-tree/src/syntax-tree-interfaces.ts Added mcpConnection and mcpToolNames properties to Tool interface
workspaces/mi/mi-extension/src/lang-client/ExtendedLanguageClient.ts Updated getMcpTools request to include documentUri and range parameters
workspaces/mi/mi-diagram/src/visitors/SizingVisitor.ts Implemented filtering to show only unique MCP connection nodes in diagram sizing
workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts Applied same unique connection filtering for MCP tools positioning
workspaces/mi/mi-diagram/src/visitors/NodeFactoryVisitor.ts Grouped MCP tools by connection and populated mcpToolNames array
workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx Updated to fetch AI connector icon for MCP tools and display grouped tool names
workspaces/mi/mi-diagram/src/components/nodes/BaseNodeModel.ts Added handling for tool tag and MCP tools in connector operations
workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx Changed selection management from string[] to McpTool[] objects with pre-selection support
workspaces/mi/mi-diagram/src/components/Form/FormGenerator.tsx Passed documentUri and range to McpToolsSelection component
workspaces/mi/mi-core/src/rpc-types/mi-diagram/types.ts Extended McpToolsRequest and McpToolsResponse with additional fields
workspaces/mi/mi-diagram/src/resources/constants.ts Adjusted MCP tools list max height offset

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +606 to +618
const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
const isMcpTool = tool.isMcpTool;
if (!isMcpTool) {
return true; // Include all non-MCP tools
}
// For MCP tools, only include the first one with each unique connection name
const connectionName = tool.mcpConnection;
if (!connectionName) {
return false;
}
const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
return index === firstIndex;
});
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The filtering logic for tools with unique connections is duplicated across three visitor files (SizingVisitor, PositionVisitor, and NodeFactoryVisitor). Consider extracting this into a shared utility function to improve maintainability and ensure consistency. This would make it easier to maintain and modify this logic in the future.

Copilot uses AI. Check for mistakes.
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.

🧹 Nitpick comments (3)
workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx (2)

517-520: documentUri and range are missing from the fetchMcpTools effect's dependency array.

fetchMcpTools closes over both documentUri and range, which are used in the getMcpTools RPC call to retrieve previously-selected tools for the current document position. React docs recommend that the dependency array includes all values from component scope that change over time and are used by the effect; "otherwise, your code will reference stale values from previous renders."

If documentUri or range changes (e.g., the user edits nodes before opening the tool selector, shifting its range) while selectedConnection stays the same, the effect won't re-fire and fetchMcpTools won't be called with the updated context. For this PR's core feature ("show already-selected tools"), that means stale pre-selections could be loaded.

♻️ Proposed fix
 useEffect(() => {
     // Retrieve mcp tools when selected connection changes
     fetchMcpTools();
-}, [rpcClient, selectedConnection]);
+}, [rpcClient, selectedConnection, documentUri, range]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`
around lines 517 - 520, The useEffect that calls fetchMcpTools is missing
documentUri and range in its dependency array, so it can close over stale values
used by getMcpTools; update the dependency array for the effect in
McpToolsSelection (the useEffect that currently lists [rpcClient,
selectedConnection]) to include documentUri and range (or include fetchMcpTools
if you memoize it) so the effect re-runs when the document URI or selection
range changes and the fetched pre-selections are correct.

608-622: Redundant {fetchMcpTools && (...)} guard — fetchMcpTools is always truthy.

fetchMcpTools is a function defined unconditionally in the component body; it is never null or undefined. The check at line 610 is always true and can be simplified.

♻️ Proposed fix
-                        {fetchMcpTools && (
-                            <div style={{ padding: '0 12px 12px 12px', display: 'flex', alignItems: 'center' }}>
+                            <div style={{ padding: '0 12px 12px 12px', display: 'flex', alignItems: 'center' }}>
                                 <Button
                                     onClick={fetchMcpTools}
                                     disabled={loading}
                                     appearance="secondary"
                                 >
                                     <Codicon name="refresh" sx={{ marginRight: '6px' }} iconSx={{ width: 18, height: 18, fontSize: 18 }} />
                                     Retry
                                 </Button>
-                            </div>
-                        )}
+                            </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`
around lines 608 - 622, Remove the redundant conditional guard around the retry
button: the fetchMcpTools function is defined unconditionally in the
MCPtoolsSelection component, so replace the "{fetchMcpTools && (...)}" block
with the button markup rendered directly. Locate the JSX block that currently
uses the fetchMcpTools guard (the div containing the Button which calls
fetchMcpTools) and render it unconditionally, keeping the onClick,
disabled={loading}, appearance, and Codicon props intact.
workspaces/mi/mi-diagram/src/components/sidePanel/mediators/List.tsx (1)

301-312: Latent bug in version comparison: missing major-version lower-bound guard.

The algorithm correctly returns true when version[0] > minVersion[0] (line 308), but immediately jumps to comparing version[1] without first checking version[0] < minVersion[0]. When minVersion is [0, 2, 1] this is harmless (major is always ≥ 0), but if minVersion is ever bumped to e.g. [1, 2, 1], a version like [0, 3, 0] would incorrectly return true at line 309.

A loop-based or explicit three-way comparison avoids the issue entirely:

♻️ Proposed fix — general semver three-way comparison
-    // Compare major.minor.patch
-    if (version[0] > minVersion[0]) return true;
-    if (version[1] > minVersion[1]) return true;
-    if (version[1] < minVersion[1]) return false;
-    return version[2] >= minVersion[2];
+    // Compare major.minor.patch (each component in order)
+    for (let i = 0; i < minVersion.length; i++) {
+        if ((version[i] ?? 0) > minVersion[i]) return true;
+        if ((version[i] ?? 0) < minVersion[i]) return false;
+    }
+    return true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/mi/mi-diagram/src/components/sidePanel/mediators/List.tsx` around
lines 301 - 312, The version check in isAIMediatorVersionValid incorrectly skips
a lower-bound check for the major version; update isAIMediatorVersionValid to
perform a proper three-way semver comparison between the parsed version (from
allMediators.AI.version) and minVersion (currently [0,2,1]) — either by first
returning false if version[0] < minVersion[0], returning true if version[0] >
minVersion[0], and only then comparing minor/patch, or by implementing a loop
that compares each component in order and returns accordingly; ensure you handle
missing parts (e.g., undefined) when mapping to Number.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`:
- Around line 517-520: The useEffect that calls fetchMcpTools is missing
documentUri and range in its dependency array, so it can close over stale values
used by getMcpTools; update the dependency array for the effect in
McpToolsSelection (the useEffect that currently lists [rpcClient,
selectedConnection]) to include documentUri and range (or include fetchMcpTools
if you memoize it) so the effect re-runs when the document URI or selection
range changes and the fetched pre-selections are correct.
- Around line 608-622: Remove the redundant conditional guard around the retry
button: the fetchMcpTools function is defined unconditionally in the
MCPtoolsSelection component, so replace the "{fetchMcpTools && (...)}" block
with the button markup rendered directly. Locate the JSX block that currently
uses the fetchMcpTools guard (the div containing the Button which calls
fetchMcpTools) and render it unconditionally, keeping the onClick,
disabled={loading}, appearance, and Codicon props intact.

In `@workspaces/mi/mi-diagram/src/components/sidePanel/mediators/List.tsx`:
- Around line 301-312: The version check in isAIMediatorVersionValid incorrectly
skips a lower-bound check for the major version; update isAIMediatorVersionValid
to perform a proper three-way semver comparison between the parsed version (from
allMediators.AI.version) and minVersion (currently [0,2,1]) — either by first
returning false if version[0] < minVersion[0], returning true if version[0] >
minVersion[0], and only then comparing minor/patch, or by implementing a loop
that compares each component in order and returns accordingly; ensure you handle
missing parts (e.g., undefined) when mapping to Number.
ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4be49e9 and 44d982c.

📒 Files selected for processing (2)
  • workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx
  • workspaces/mi/mi-diagram/src/components/sidePanel/mediators/List.tsx

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx (1)

608-622: ⚠️ Potential issue | 🟡 Minor

{fetchMcpTools && ...} is always truthy — dead conditional.

fetchMcpTools is a locally defined function and can never be falsy. The guard provides no protection and can be removed.

♻️ Proposed fix
-                        {fetchMcpTools && (
-                            <div style={{ padding: '0 12px 12px 12px', display: 'flex', alignItems: 'center' }}>
-                                <Button
-                                    onClick={fetchMcpTools}
-                                    disabled={loading}
-                                    appearance="secondary"
-                                >
-                                    <Codicon name="refresh" sx={{ marginRight: '6px' }} iconSx={{ width: 18, height: 18, fontSize: 18 }} />
-                                    Retry
-                                </Button>
-                            </div>
-                        )}
+                        <div style={{ padding: '0 12px 12px 12px', display: 'flex', alignItems: 'center' }}>
+                            <Button
+                                onClick={fetchMcpTools}
+                                disabled={loading}
+                                appearance="secondary"
+                            >
+                                <Codicon name="refresh" sx={{ marginRight: '6px' }} iconSx={{ width: 18, height: 18, fontSize: 18 }} />
+                                Retry
+                            </Button>
+                        </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`
around lines 608 - 622, The conditional guard `{fetchMcpTools && (...)}` is dead
because `fetchMcpTools` is a locally defined function and always truthy; remove
the guard and render the Retry button block unconditionally (the div containing
Button/Codicon/Retry) so the UI isn't wrapped in an unnecessary check, or if the
original intent was to only render when an external prop exists, rename or
change `fetchMcpTools` to the optional prop (e.g., `onFetchMcpTools`) and check
that instead; update references to `fetchMcpTools`/`onFetchMcpTools` in the
`McpToolsSelection` component accordingly.
workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx (1)

375-420: ⚠️ Potential issue | 🟠 Major

Fix incorrect source for MCP connection value at lines 381 and 418.

When isMCPTool is true, connectorNode is set to (node.stNode as Tool).mediator (a Connector instance). However, the actual mcpConnection value lives on the Tool object itself, not on its mediator. This causes two issues:

  1. Line 381 — the condition connectorNode.mcpConnection checks the wrong object and should use isMCPTool instead (when true, the MCP icon should render).
  2. Line 418 — the expression connectorNode.configKey || connectorNode.mcpConnection doesn't properly handle the MCP case; for MCP tools, the value should come from (node.stNode as Tool).mcpConnection as shown in the correct pattern at line 254.
🐛 Proposed fixes
-            {connectorNode.mcpConnection && <g transform="translate(68,7)">
+            {isMCPTool && <g transform="translate(68,7)">
                 <foreignObject width="25" height="25">
                     <S.IconContainer>{getMediatorIconsFromFont('mcp')}</S.IconContainer>
                 </foreignObject>
             </g>}
-                        {connectorNode.configKey || connectorNode.mcpConnection}
+                        {isMCPTool ? (node.stNode as Tool).mcpConnection : connectorNode.configKey}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx`
around lines 375 - 420, The MCP rendering and value lookup use the mediator
(connectorNode) instead of the Tool when isMCPTool is true; change the icon
condition to check isMCPTool (not connectorNode.mcpConnection) so the MCP icon
renders for tools, and change the displayed text expression to use
connectorNode.configKey || (isMCPTool ? (node.stNode as Tool).mcpConnection :
connectorNode.mcpConnection) so MCP tools pull mcpConnection from the Tool
instance rather than from connectorNode; update both places where
connectorNode.mcpConnection is currently referenced (the icon render block using
getMediatorIconsFromFont('mcp') and the ConnectionText expression) to use the
corrected checks/lookup.
🧹 Nitpick comments (1)
workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx (1)

423-436: selectedTools prop is destructured but never consumed — misleading API surface.

The selectedTools: Set<string> prop is assigned a default and destructured, but selectedToolNames derived from useWatch is used throughout the component for all rendering and logic. Any value passed in via selectedTools is silently ignored, which will mislead callers.

Consider removing selectedTools from McpToolsSelectionProps if the component's selection state is wholly owned by the form via mcpToolsSelection, or document clearly that the prop is deprecated/unused.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`
around lines 423 - 436, The prop selectedTools is destructured in
McpToolsSelection but never used (the component reads selection from useWatch
via selectedToolNames/mcpToolsSelection), so remove selectedTools from the
McpToolsSelectionProps type and from the McpToolsSelection parameter list (and
any default value assignment) to avoid a misleading API surface; alternatively,
if you intend to allow external initialization, wire selectedTools into the form
state by setting the form default or calling setValue('mcpToolsSelection',
Array.from(selectedTools)) inside McpToolsSelection (keep only one
approach—prefer removing the unused prop if the form fully owns selection).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx`:
- Around line 257-259: The handler in ConnectorNodeWidget currently returns
silently when no match is found for connectionName in
connectionData.connections, leaving users with no feedback; update the code that
checks `if (!connection) { return; }` (in the click/connection handler in
ConnectorNodeWidget) to surface an explicit user-visible error (for example call
the app's notification/toast API, set a local error state that briefly
highlights the connector, or log a clear warning) and include the missing
`connectionName` in the message; ensure you still guard against null but replace
the silent return with a user-facing action so misconfigured MCP connections are
obvious.

---

Outside diff comments:
In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`:
- Around line 608-622: The conditional guard `{fetchMcpTools && (...)}` is dead
because `fetchMcpTools` is a locally defined function and always truthy; remove
the guard and render the Retry button block unconditionally (the div containing
Button/Codicon/Retry) so the UI isn't wrapped in an unnecessary check, or if the
original intent was to only render when an external prop exists, rename or
change `fetchMcpTools` to the optional prop (e.g., `onFetchMcpTools`) and check
that instead; update references to `fetchMcpTools`/`onFetchMcpTools` in the
`McpToolsSelection` component accordingly.

In
`@workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx`:
- Around line 375-420: The MCP rendering and value lookup use the mediator
(connectorNode) instead of the Tool when isMCPTool is true; change the icon
condition to check isMCPTool (not connectorNode.mcpConnection) so the MCP icon
renders for tools, and change the displayed text expression to use
connectorNode.configKey || (isMCPTool ? (node.stNode as Tool).mcpConnection :
connectorNode.mcpConnection) so MCP tools pull mcpConnection from the Tool
instance rather than from connectorNode; update both places where
connectorNode.mcpConnection is currently referenced (the icon render block using
getMediatorIconsFromFont('mcp') and the ConnectionText expression) to use the
corrected checks/lookup.

---

Nitpick comments:
In
`@workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx`:
- Around line 423-436: The prop selectedTools is destructured in
McpToolsSelection but never used (the component reads selection from useWatch
via selectedToolNames/mcpToolsSelection), so remove selectedTools from the
McpToolsSelectionProps type and from the McpToolsSelection parameter list (and
any default value assignment) to avoid a misleading API surface; alternatively,
if you intend to allow external initialization, wire selectedTools into the form
state by setting the form default or calling setValue('mcpToolsSelection',
Array.from(selectedTools)) inside McpToolsSelection (keep only one
approach—prefer removing the unused prop if the form fully owns selection).
ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 44d982c and da9aaed.

📒 Files selected for processing (2)
  • workspaces/mi/mi-diagram/src/components/Form/MCPtoolsSelection/McpToolsSelection.tsx
  • workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx

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.

🧹 Nitpick comments (1)
workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts (1)

533-545: findIndex inside filter is O(n²); prefer a Set for seen connections.

toolsList.findIndex(...) is called once per MCP tool in the filter callback, making the whole block O(n²). While tool counts are small today, the intent (first-occurrence deduplication) is more clearly expressed with a Set.

♻️ O(1) deduplication with a Set
-                    const toolsWithUniqueConnections = toolsList.filter((tool: Tool, index: number) => {
-                        const isMcpTool = tool.isMcpTool;
-                        if (!isMcpTool) {
-                            return true; // Include all non-MCP tools
-                        }
-                        // For MCP tools, only include the first one with each unique connection name
-                        const connectionName = tool.mcpConnection;
-                        if (!connectionName) {
-                            return false;
-                        }
-                        const firstIndex = toolsList.findIndex((t: Tool) => t.mcpConnection === connectionName);
-                        return index === firstIndex;
-                    });
+                    const seenMcpConnections = new Set<string>();
+                    const toolsWithUniqueConnections = toolsList.filter((tool: Tool) => {
+                        if (!tool.isMcpTool) {
+                            return true; // Include all non-MCP tools
+                        }
+                        // For MCP tools, only include the first one with each unique connection name
+                        const connectionName = tool.mcpConnection;
+                        if (!connectionName) {
+                            return false;
+                        }
+                        if (seenMcpConnections.has(connectionName)) {
+                            return false;
+                        }
+                        seenMcpConnections.add(connectionName);
+                        return true;
+                    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts` around lines 533 -
545, The current filter for toolsWithUniqueConnections is O(n²) because it calls
toolsList.findIndex inside the callback; replace that logic by using a Set to
track seen mcpConnection values: iterate/filter toolsList, include all non-MCP
tools (tool.isMcpTool false), and for MCP tools check if tool.mcpConnection is
falsy (skip) or not in the Set (add it and include) otherwise skip; update
references to Tool, toolsList, tool.isMcpTool, and tool.mcpConnection
accordingly to preserve the “first-occurrence” semantics while making the
operation O(n).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts`:
- Around line 533-545: The current filter for toolsWithUniqueConnections is
O(n²) because it calls toolsList.findIndex inside the callback; replace that
logic by using a Set to track seen mcpConnection values: iterate/filter
toolsList, include all non-MCP tools (tool.isMcpTool false), and for MCP tools
check if tool.mcpConnection is falsy (skip) or not in the Set (add it and
include) otherwise skip; update references to Tool, toolsList, tool.isMcpTool,
and tool.mcpConnection accordingly to preserve the “first-occurrence” semantics
while making the operation O(n).
ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da9aaed and 05f1110.

📒 Files selected for processing (2)
  • workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx
  • workspaces/mi/mi-diagram/src/visitors/PositionVisitor.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • workspaces/mi/mi-diagram/src/components/nodes/ConnectorNode/ConnectorNodeWidget.tsx

Copy link
Contributor

@gigara gigara left a comment

Choose a reason for hiding this comment

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

LGTM. Add a test case in a separate PR to cover the new flow.

@gigara gigara merged commit e4ce6e5 into main Feb 23, 2026
31 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants