Skip to content

Group MCP tools by capability#2293

Open
GChaucer wants to merge 2 commits into
PostHog:mainfrom
GChaucer:fix/mcp-tool-groups
Open

Group MCP tools by capability#2293
GChaucer wants to merge 2 commits into
PostHog:mainfrom
GChaucer:fix/mcp-tool-groups

Conversation

@GChaucer
Copy link
Copy Markdown

Summary

  • Group MCP server tools into Read tools and Write / delete tools sections.
  • Classify clear read/write verbs from tool names, display names, and descriptions.
  • Default ambiguous tools to Write / delete tools for safer review.

Closes #2233

Testing

  • corepack pnpm --dir apps/code exec vitest run src/renderer/features/mcp-servers/hooks/mcpToolGroups.test.ts
  • corepack pnpm --dir apps/code typecheck
  • corepack pnpm exec biome check apps/code/src/renderer/features/mcp-servers/hooks/mcpToolGroups.ts apps/code/src/renderer/features/mcp-servers/hooks/mcpToolGroups.test.ts apps/code/src/renderer/features/mcp-servers/components/parts/ServerDetailView.tsx
  • git diff --check

Notes

  • Installed dependencies with lifecycle scripts disabled before verification.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/code/src/renderer/features/mcp-servers/hooks/mcpToolGroups.test.ts:25-37
**Prefer parameterised tests**

The first two `it` blocks each assert multiple cases as individual `expect` calls. When one assertion fails, the rest are skipped, hiding further failures. Prefer `it.each` so each case is its own named test. The same pattern applies to the write/delete block below.

### Issue 2 of 2
apps/code/src/renderer/features/mcp-servers/components/parts/ServerDetailView.tsx:433-456
**OnceAndOnlyOnce: duplicate handler**

The identical `onToolApprovalChange` callback is defined twice — once for each `ToolGroupSection`. Extract it to a `useCallback` (or a plain `const` before the return) so both sections share a single definition.

```suggestion
              ) : (
                <>
                  <ToolGroupSection
                    title="Read tools"
                    tools={groupedTools.read}
                    onToolApprovalChange={(toolName, approval_state) =>
                      setToolApproval({ toolName, approval_state })
                    }
                  />
                  <ToolGroupSection
                    title="Write / delete tools"
                    tools={groupedTools.write_delete}
                    onToolApprovalChange={(toolName, approval_state) =>
                      setToolApproval({ toolName, approval_state })
                    }
                  />
                </>
              )}
```

Reviews (1): Last reviewed commit: "Group MCP tools by capability" | Re-trigger Greptile

Comment on lines +25 to +37
it("classifies clear read verbs from tool names", () => {
expect(getMcpToolGroup(tool("get_ticket"))).toBe("read");
expect(getMcpToolGroup(tool("list_projects"))).toBe("read");
expect(getMcpToolGroup(tool("search_docs"))).toBe("read");
expect(getMcpToolGroup(tool("lookup_customer"))).toBe("read");
});

it("classifies clear write and delete verbs from tool names", () => {
expect(getMcpToolGroup(tool("create_ticket"))).toBe("write_delete");
expect(getMcpToolGroup(tool("delete_file"))).toBe("write_delete");
expect(getMcpToolGroup(tool("send_message"))).toBe("write_delete");
expect(getMcpToolGroup(tool("run_query"))).toBe("write_delete");
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Prefer parameterised tests

The first two it blocks each assert multiple cases as individual expect calls. When one assertion fails, the rest are skipped, hiding further failures. Prefer it.each so each case is its own named test. The same pattern applies to the write/delete block below.

Context Used: Do not attempt to comment on incorrect alphabetica... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/mcp-servers/hooks/mcpToolGroups.test.ts
Line: 25-37

Comment:
**Prefer parameterised tests**

The first two `it` blocks each assert multiple cases as individual `expect` calls. When one assertion fails, the rest are skipped, hiding further failures. Prefer `it.each` so each case is its own named test. The same pattern applies to the write/delete block below.

**Context Used:** Do not attempt to comment on incorrect alphabetica... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 433 to 456
) : (
filteredTools.map((tool) => (
<ToolRow
key={tool.tool_name}
tool={tool}
onChange={(approval_state) =>
<>
<ToolGroupSection
title="Read tools"
tools={groupedTools.read}
onToolApprovalChange={(toolName, approval_state) =>
setToolApproval({
toolName: tool.tool_name,
toolName,
approval_state,
})
}
/>
))
<ToolGroupSection
title="Write / delete tools"
tools={groupedTools.write_delete}
onToolApprovalChange={(toolName, approval_state) =>
setToolApproval({
toolName,
approval_state,
})
}
/>
</>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 OnceAndOnlyOnce: duplicate handler

The identical onToolApprovalChange callback is defined twice — once for each ToolGroupSection. Extract it to a useCallback (or a plain const before the return) so both sections share a single definition.

Suggested change
) : (
filteredTools.map((tool) => (
<ToolRow
key={tool.tool_name}
tool={tool}
onChange={(approval_state) =>
<>
<ToolGroupSection
title="Read tools"
tools={groupedTools.read}
onToolApprovalChange={(toolName, approval_state) =>
setToolApproval({
toolName: tool.tool_name,
toolName,
approval_state,
})
}
/>
))
<ToolGroupSection
title="Write / delete tools"
tools={groupedTools.write_delete}
onToolApprovalChange={(toolName, approval_state) =>
setToolApproval({
toolName,
approval_state,
})
}
/>
</>
)}
) : (
<>
<ToolGroupSection
title="Read tools"
tools={groupedTools.read}
onToolApprovalChange={(toolName, approval_state) =>
setToolApproval({ toolName, approval_state })
}
/>
<ToolGroupSection
title="Write / delete tools"
tools={groupedTools.write_delete}
onToolApprovalChange={(toolName, approval_state) =>
setToolApproval({ toolName, approval_state })
}
/>
</>
)}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/mcp-servers/components/parts/ServerDetailView.tsx
Line: 433-456

Comment:
**OnceAndOnlyOnce: duplicate handler**

The identical `onToolApprovalChange` callback is defined twice — once for each `ToolGroupSection`. Extract it to a `useCallback` (or a plain `const` before the return) so both sections share a single definition.

```suggestion
              ) : (
                <>
                  <ToolGroupSection
                    title="Read tools"
                    tools={groupedTools.read}
                    onToolApprovalChange={(toolName, approval_state) =>
                      setToolApproval({ toolName, approval_state })
                    }
                  />
                  <ToolGroupSection
                    title="Write / delete tools"
                    tools={groupedTools.write_delete}
                    onToolApprovalChange={(toolName, approval_state) =>
                      setToolApproval({ toolName, approval_state })
                    }
                  />
                </>
              )}
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is IMO the wrong way of going about it. MCP tools expose whether they actually are read only, destructive, etc. via tool annotations. We should use that instead: https://modelcontextprotocol.io/specification/2025-11-25/schema#toolannotations

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.

Group MCP tools by read and write/ delete

2 participants