Skip to content

Conversation

underhill-gb
Copy link

Hi ! I'm a new contributor and have been a fan of PageAssist for a while.

I was particularly excited about the possibility of adding support for MCP Server Tools, so I decided to have a crack at it myself. While I was at it, I also noticed a performance issue with the UI and went ahead and fixed that too. I'm submitting this with the hope that it's a useful foundation for the project to build upon.


Feature: MCP Server Tools (Ollama / Streamable HTTP)

This adds the ability for the chat to use tools from an MCP Server via Ollama's 'tools' parameter.

The key user-facing improvement is the clear visual feedback during a chatbot/agent lifecycle. As shown in the screenshot below, tool execution is rendered as a distinct phase of the model's process: Thinking... -> Executing -> Thinking... , and then the final synthesized answer, making the whole sequence transparent and easy to follow.

Screenshot 2025-07-25 181421 Screenshot 2025-07-25 180923

I'm really happy with how this turned out. I'm sure the underlying logic could be improved, but after a pretty tough merge, I'm a bit exhausted! My main goal was to get a working version submitted that the community could refine / build upon.


Code Health: Optimized UI Rendering

While debugging the MCP feature, I noticed that the Sidebar and other UI elements were re-rendering on every single chunk of an LLM response. This issue didn't cause any noticeable visual artifacts or lag, but it does create unnecessary rendering cycles and makes debugging noisier. This fix eliminates those redundant renders, leading to a more efficient and maintainable component tree.

A number of changes were required, so I wanted to document them here.

The fix was applied in three layers to prevent functions from being re-created on every render:

  1. Sidebar.tsx was wrapped in React.memo so it can skip re-rendering when its props haven't changed.
  2. Parent components (Layout.tsx, Sidepanel\Chat\header.tsx) were updated to use useCallback. This ensures the functions passed as props are the same instance on each render, which is necessary for React.memo to work effectively.
  3. The root cause was addressed by memoizing the functions returned from the useMessage.tsx and useMessageOption.tsx hooks. This ensures that components receive the same function instances on each render, which prevents unnecessary re-renders from propagating down the component tree.

I'm happy to share what I've done and will do my best to address any feedback as my time permits. Please feel free to take this code and edit or build upon it directly.

Thanks for creating PageAssist and for considering my contribution!

Copy link

socket-security bot commented Jul 25, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License

View full report

@n4ze3m
Copy link
Owner

n4ze3m commented Jul 26, 2025

Wow, this is a huge feature! :) I'll test and merge it. Thank you for the contribution!

n4ze3m and others added 3 commits July 27, 2025 20:23
I noticed the Sidebar was re-rendering on every single text chunk from the LLM. This was making the UI feel a bit sluggish and was spamming the console, which made debugging a pain.

A cascade of unnecessary re-renders occurred because parent components were creating 'new' functions for props like onClose and clearChat on every render.

Here's how I approached the issue:

1. Added React.memo to Sidebar.tsx, enabling it to ignore prop changes that aren't actually different.

2. Stabilized the parents Layout.tsx and Chat\Header.tsx by wrapping the functions being passed down ('onClose', etc.) in 'useCallback'; stopping them from being treated as 'new' on every render.

3. Updated the custom hooks, useMessage and useMessageOption, wrapping all of their returned functions in useCallback or useMemo; ensuring they too provide stable/consistent functions to any components that use them.

After these changes the Sidebar should only update when it actually needs to, making the app feel a bit faster and the console much cleaner.
@underhill-gb
Copy link
Author

underhill-gb commented Jul 28, 2025

Hi @n4ze3m Thanks for the encouraging feedback on this PR!

I've just finished resolving the latest merge conflicts and pushed the changes. It was a great learning experience, especially with a file as complex as useMessage.tsx.

As I'm still new to the project's codebase, my only concern is that if the branch happens to fall out of sync again, I might struggle to repeat such a complex merge correctly.

With that in mind, any guidance you could offer on the next steps or a potential timeline for review would be incredibly helpful.

No pressure at all, and thanks again for your time and for maintaining this great project!

@n4ze3m
Copy link
Owner

n4ze3m commented Jul 29, 2025

Hey, thanks for resolving the conflict! :) I'll push a few UI-related changes to his branch.
Yeah, useMessage.tsx is getting a bit large , in the coming version, I'll refactor it like useMessageOption for better readability.

@n4ze3m n4ze3m changed the base branch from main to mcp August 16, 2025 12:38
@bsget
Copy link

bsget commented Sep 30, 2025

Is there any update on if this is planned to be integrated into PageAssist? If you need additional resources to work on it I'm happy to help resolve any issues/conflicts.

@n4ze3m
Copy link
Owner

n4ze3m commented Sep 30, 2025

It has been merged into another branch named 'mcp.' I've been busy, which is why I haven't added the breaking change yet. I'll look into it and add support. I know it's a really great feature for Page Assist

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.

3 participants