Skip to content

B-MCP: An Idea for an in browser implementation of the Model-Context-Protocol #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

MiguelsPizza
Copy link

@Yonom

I've been really interested in the work you are doing with allowing the model to call tools on the page. It got me thinking if the model context protocol could be implemented in browser where the website maintainer can define an "MCP server" which automatically gets picked up by the the model in the chat UI on load

This PR has a working implementation of this idea. It needs serious cleanup, but I think this idea has alot of potential.

let me walk you through it:

like a regular MCP server, the website owner runs this JS at some point (in this case it's before the react component mounts)

const myPageProvider = new McpWindowProvider(
  { name: "MyAwesomePageContext", version: "1.0.0" },
  { resources: true, tools: true, prompts: false }
);

myPageProvider.addResource(
  { uri: "page://title", name: "Page Title", mimeType: "text/plain" },
  async () => ({ contents: [{ uri: "page://title", text: document.title }] })
);

myPageProvider.addTool(
  {
      name: "showalert",
      description: "Shows an alert box with a custom message.",
      inputSchemaDef: { message: z.string().describe("The message to display in the alert.") },
      annotations: { openWorldHint: false } // Doesn't interact outside the page
  },
  async (args) => {
      try {
          alert(args.message);
          return { content: [{ type: 'text', text: `Alert shown with message: "${args.message}"` }] };
      } catch (e: any) {
          // alert() is unlikely to throw, but keeping the structure
          return { content: [{ type: 'text', text: `Error showing alert: ${e.message}` }], isError: true };
      }
  }
);

myPageProvider.exposeOnWindow(); // Exposes as window.mcp

Now that the mcp server has been exposed on the window as window.mcp the MCP client can pick it up. This is a bit redundant in the browser version but I'm trying my best to match the existing protocol. (you can check it out at CliendSDK.ts)

now we can use the client like this:

         const { serverInfo: sInfo, serverCapabilities: caps } = await clientInstance.connect();

I went ahead and created a client integration to Assistant-UI using the tool function exported by your lib:

basically what we are doing here is reading the tools from the browser mcp server, converting them to the assistant Ui tool format then registering them with the runtime (and some system prompt to tell the model how to use it)

        const assistantToolsList: AssistantTool[] = mcpClient.serverCapabilities?.tools
            ? mcpTools.map(mcpT => convertMcpToolToAssistantTool(mcpT, mcpClient))
            : [];

        const toolsForAssistant: Record<string, AssistantTool> = {};
        assistantToolsList.forEach(t => {
            toolsForAssistant[t.name] = t;
        });

        let systemInstructionsFromMcp = "";
        if (mcpClient.serverCapabilities?.resources && mcpResources.length > 0) {
             systemInstructionsFromMcp += "You can use the 'readResource' tool to get the content of these resources if needed, or I will provide them if I think they are relevant.\n";
        }

        const unregister = assistantRuntime.registerModelContextProvider({
            getModelContext: () => {
                let systemMessage = "";
                systemMessage += systemInstructionsFromMcp;

                console.log({toolsForAssistant})
                return {
                    system: systemMessage.trim() || "TOOLS:",
                    tools: toolsForAssistant,
                };
            },
        });
        

since this all happens in a hook we just create a context for it and wrap the chat ui in that context:

 <AssistantRuntimeProvider runtime={runtime}>
      <McpContextProviderComponent> {/* This provides the Tools to the runtime */}
        <SidebarProvider>
          <AppSidebar />
          <SidebarInset>
            <header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
              <SidebarTrigger />
              <Separator orientation="vertical" className="mr-2 h-4" />
              <Breadcrumb>
                <BreadcrumbList>
                  <BreadcrumbItem className="hidden md:block">
                    <BreadcrumbLink href="#">
                      Build Your Own ChatGPT UX
                    </BreadcrumbLink>
                  </BreadcrumbItem>
                  <BreadcrumbSeparator className="hidden md:block" />
                  <BreadcrumbItem>
                    <BreadcrumbPage>
                      Starter Template
                    </BreadcrumbPage>
                  </BreadcrumbItem>
                </BreadcrumbList>
              </Breadcrumb>
            </header>
            <Thread />...

Here is s demo of it working:

chrome-capture-2025-5-21

Copy link

coderabbitai bot commented May 22, 2025

Walkthrough

This update migrates the project from a Next.js-based React application to a Vite-powered React app with Cloudflare Workers integration. All Next.js-specific files, configuration, and API routes are removed, including layout, page, and assistant components. In their place, Vite configuration, an HTML entry point, and a new React app structure are introduced. The package dependencies are overhauled to support Vite, Tailwind CSS, Cloudflare Workers, and an MCP-Window protocol implementation. New TypeScript modules define and implement the MCP-Window protocol, including provider and client SDKs, type definitions, and React integration hooks. The project now uses modular TypeScript configuration files for app, node, and worker environments, and is configured for deployment with Cloudflare Wrangler. The README is rewritten to document the MCP-Window protocol and its usage.

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 30th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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

@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: 28

🔭 Outside diff range comments (1)
src/components/assistant-ui/tool-fallback.tsx (1)

20-22: ⚠️ Potential issue

Invert collapse toggle icons
The current logic shows an "up" icon when collapsed; it should show "down" to indicate expansion. Swap the icons:

- {isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
+ {isCollapsed ? <ChevronDownIcon /> : <ChevronUpIcon />}
🧹 Nitpick comments (33)
src/index.css (1)

1-1: Ensure Tailwind CSS directives are included
Importing @import "tailwindcss"; alone may not apply the required utility classes. Typically, your global CSS should include the Tailwind directives:

@tailwind base;
@tailwind components;
@tailwind utilities;

Alternatively, confirm that your Vite Tailwind plugin injects these automatically.

src/components/assistant-ui/tool-fallback.tsx (1)

15-15: Fix invalid Tailwind class for icon sizing
The lucide-react icons require h-4 w-4 rather than size-4. Update to:

- <CheckIcon className="size-4" />
+ <CheckIcon className="h-4 w-4" />
index.html (2)

7-7: Update the page title to reflect your application.

The current title "Vite + React + TS" is the default from Vite templates. Consider updating it to something specific to your MCP application, such as "MCP Browser Demo" or similar.

-    <title>Vite + React + TS</title>
+    <title>Model-Context-Protocol Browser Demo</title>

5-5: Consider updating the favicon.

The current favicon references the default Vite SVG. Consider replacing it with your own favicon that represents your application.

-    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+    <link rel="icon" type="image/svg+xml" href="/your-app-icon.svg" />
vite.config.ts (1)

1-17: Well-structured Vite configuration.

The Vite configuration looks good with appropriate plugins for React, Tailwind CSS, and Cloudflare. The path alias setup for "@" will make imports cleaner and more maintainable.

Consider adding environment-specific configurations if you have different needs for development and production:

export default defineConfig(({ mode }) => {
  const isDev = mode === 'development';
  
  return {
    plugins: [react(), tailwindcss(), cloudflare()],
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "./src"),
      },
    },
    // Environment-specific settings
    build: {
      sourcemap: isDev,
      // Add other environment-specific build options
    }
  };
});
src/components/app-sidebar.tsx (1)

37-41: Inconsistent blank line spacing

There are several inconsistent blank lines throughout the file (lines 37, 41, 54). Consider standardizing the spacing pattern for better readability.

      </SidebarContent>
-

      <SidebarRail />
      <SidebarFooter>
        <SidebarMenu>
-

          <SidebarMenuItem>
tsconfig.node.json (1)

30-30: Confirm vite.config.ts is the only file that needs Node.js config

The configuration only includes vite.config.ts. If you have other Node.js-specific files (like build scripts or ESLint config), consider including them as well.

🧰 Tools
🪛 Biome (1.9.4)

[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-31: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

worker/index.ts (1)

23-25: Remove unnecessary empty lines

There are multiple consecutive empty lines that should be cleaned up.

   if (c.env.NODE_ENV === 'development') {
     console.log(JSON.stringify({tools, frontendTools:frontendTools(tools) },null, 2))
   }
-
-  
-
   const result = streamText({
tsconfig.json (1)

18-19: Remove empty line in compilerOptions object

There's an unnecessary empty line that should be removed.

 	"compilerOptions": {
 		"types": [
 			"./worker-configuration.d.ts"
 		],
-		
 	}
tsconfig.app.json (1)

13-32: Consider adding comments explaining non-standard settings

Some of the configuration options like verbatimModuleSyntax and moduleDetection: "force" might not be familiar to all developers. Consider adding comments explaining their purpose.

     /* Bundler mode */
     "moduleResolution": "bundler",
     "allowImportingTsExtensions": true,
+    /* Preserves import statements exactly as written */
     "verbatimModuleSyntax": true,
+    /* Ensures all files are treated as modules */
     "moduleDetection": "force",
     "noEmit": true,
     "jsx": "react-jsx",
🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: JSON standard does not allow comments.

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: JSON standard does not allow comments.

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-32: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

src/Assistant.tsx (1)

19-21: Remove or implement the unused button.

This button has an empty onClick handler and doesn't seem to serve any purpose in the UI.

Either remove the button or implement its functionality:

-        <Button onClick={() => {
-          
-        }}>Hello </Button>
README.md (4)

190-190: Remove this placeholder comment before finalizing the README.

This note appears to be a reminder for development and should be removed before the final release.

-This README provides a good overview for someone wanting to understand or implement this in-window MCP variant. Remember to replace placeholders (like links to type definitions or SDK repositories) if you formalize this into actual files.

79-79: Fix the API Interface heading to remove redundancy.

The phrase "API Interface" is redundant as "API" already stands for "Application Programming Interface".

-## API Interface (`WindowMcpApi`)
+## API (`WindowMcpApi`)
🧰 Tools
🪛 LanguageTool

[style] ~79-~79: This phrase is redundant (‘I’ stands for ‘Interface’). Use simply “APIInterface”.
Context: ...re-list tools, re-read a resource). ## API Interface (WindowMcpApi) The window.mcp obje...

(ACRONYM_TAUTOLOGY)


161-161: Correct the "vice versa" spelling.

The expression "vice versa" should be written without a hyphen.

-Trust Model: MCP-Window typically operates within a same-origin or trusted-iframe context. The web page exposing window.mcp is implicitly trusted by the LLM client (or vice-versa, depending on how the components are loaded).
+Trust Model: MCP-Window typically operates within a same-origin or trusted-iframe context. The web page exposing window.mcp is implicitly trusted by the LLM client (or vice versa, depending on how the components are loaded).
🧰 Tools
🪛 LanguageTool

[grammar] ~161-~161: The expression “vice versa” is spelled without hyphens.
Context: ...mplicitly trusted by the LLM client (or vice-versa, depending on how the components are lo...

(VICE_VERSA)


83-101: The API interface definition is clear and helpful.

The TypeScript interface definition provides a good reference for implementers. Consider expanding the type definitions or linking directly to the implementation file.

Add a link to the actual implementation file:

(Refer to mcp-window-types.ts for detailed type definitions)
+For the complete implementation, see [mcp-window-types.ts](./src/window.MCP/mcp-window-types.ts).
src/winodw.MCP/mcp-tool-adapter.ts (3)

9-43: Enhance the schema conversion for better type coverage.

The mcpSchemaToZod function currently only handles basic types. Consider expanding it to support more complex types like arrays, objects, and enums.

            case 'boolean':
                fieldSchema = z.boolean();
                break;
            // Add more types like array, object, enum as needed
+           case 'array':
+               if (prop.items) {
+                   // Recursively handle array items
+                   const itemSchema = prop.items.type === 'object' 
+                       ? mcpSchemaToZod(prop.items)
+                       : z.any(); // Or handle primitive item types
+                   fieldSchema = z.array(itemSchema);
+               } else {
+                   fieldSchema = z.array(z.any());
+               }
+               break;
+           case 'integer':
+               fieldSchema = z.number().int();
+               break;
+           case 'null':
+               fieldSchema = z.null();
+               break;

59-67: Improve error handling for tool execution.

The current error handling concatenates all error text, but could be enhanced to provide more structured error information.

                if (result.isError) {
                    // Assistant UI might expect errors to be thrown or a specific error format
                    // For now, let's return the error content as a string.
                    const errorText = result.content
                        .filter(c => c.type === 'text' && c.text)
                        .map(c => c.text)
                        .join('\n');
-                   throw new Error(errorText || `MCP tool '${mcpTool.name}' reported an error.`);
+                   const error = new Error(errorText || `MCP tool '${mcpTool.name}' reported an error.`);
+                   // Add additional context to the error object
+                   (error as any).mcpToolName = mcpTool.name;
+                   (error as any).mcpToolError = true;
+                   (error as any).rawContent = result.content;
+                   throw error;
                }

46-56: Consider adding validation for the MCP tool schema.

The function assumes the MCP tool will have a valid schema, but additional validation could prevent runtime errors.

export function convertMcpToolToAssistantTool(
    mcpTool: McpTool,
    mcpClient: McpWindowClient // Pass the client to make the call
) {
+   // Validate mcpTool has required properties
+   if (!mcpTool.name) {
+       throw new Error('MCP tool must have a name');
+   }
+   
    const zodParams = mcpSchemaToZod(mcpTool.inputSchema);

    return assistantToolHelper({
        name: mcpTool.name, // Assistant UI expects name directly on the tool object
        description: mcpTool.description,
        parameters: zodParams,
src/main.tsx (4)

3-4: Duplicate global style imports may bloat bundle

Both ./globals.css and ./index.css are pulled in at start-up. If they each Tailwind-reset or contain overlapping rules you’ll pay twice in download & parse time, and risk order-dependent side-effects. Prefer a single root stylesheet (or import one from the other) to keep CSS deterministic.


15-19: Missing description field on resource

MCP Resource accepts an optional description. Supplying one makes the context far more helpful to the model:

-  { uri: "page://title", name: "Page Title", mimeType: "text/plain" },
+  { uri: "page://title",
+    name: "Page Title",
+    description: "The current document.title of the page.",
+    mimeType: "text/plain" },

21-28: Comment and implementation diverge

The comment says “tool to change the background color” but the tool actually triggers an alert. Either update the comment or the tool implementation to avoid confusion for maintainers and for the model’s self-documentation.


30-36: Blocking alert() hurts UX; prefer non-blocking UI

alert() pauses the JS thread and can feel jarring. Consider a non-blocking toast/snackbar component instead, or at least wrap the call in setTimeout to avoid stalling React renders. Example:

- alert(args.message);
+ setTimeout(() => window.alert(args.message), 0);  // minimal impact

Better would be a dedicated UI component.

src/winodw.MCP/useMcpContextProvider.tsx (3)

1-4: Remove unused imports to avoid dead-code warnings

tool, makeAssistantTool, and z are imported but never used (the only z usage is already imported on line 4). Drop them or use them; otherwise tsc/ESLint will complain and tree-shaking will carry the cost.


17-19: Avoid broad any; leverage generics for type safety

parameters: any and execute: (args: any) throw away the strong typing you already get from Zod. Consider:

interface AssistantTool<Params extends z.ZodTypeAny> {
  name: string;
  description?: string;
  parameters: Params;
  execute: (args: z.infer<Params>) => Promise<any>;
}

This will surface schema/implementation mismatches at compile time.


163-164: Remove leftover console.log before shipping

Debug logs inside the model-context provider will spam user consoles.

src/winodw.MCP/ClientSDK.ts (3)

1-1: File header name mismatch

The comment says mcp-window-client.ts but the file is ClientSDK.ts; keep them aligned to avoid confusion when grepping.


21-26: Constructor throws if provider is late-loaded – add retry or async connect

Many pages load scripts lazily. Failing immediately makes the client unusable. Consider deferring the lookup to connect() or retrying a few times before giving up:

-        if (!(window as any)[namespace]) {
-            throw new Error(`MCP Provider not found on window.${namespace}`);
-        }
-        this.provider = (window as any)[namespace] as WindowMcpApi;
+        const prov = (window as any)[namespace] as WindowMcpApi | undefined;
+        if (!prov) {
+            throw new Error(`MCP Provider not found on window.${namespace}. Call connect() after provider initialises.`);
+        }
+        this.provider = prov;

68-77: Event listener leaks on multiple clients

onNotification attaches directly to the provider but never checks for duplicate listeners; creating many clients can leak. Keep a Set of handlers or expose a dispose() to remove all listeners in one go.

src/winodw.MCP/serverSDK.ts (3)

24-27: Useless constructor – delete for cleaner code

The constructor neither adds logic nor alters initialisation; super() is injected automatically.
Removing it silences the Biome noUselessConstructor lint error and trims a few bytes.

-  constructor() {
-      super();
-  }
+
🧰 Tools
🪛 Biome (1.9.4)

[error] 25-27: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)


44-45: Generics wrongly reference ZodTypeDef without import and create very long Map value types

Besides the missing import, embedding the complete generic signature in the Map value
makes the line hard to read. Consider extracting helper interfaces:

interface ToolEntry extends Tool {
  handler: ToolHandler;
  inputValidator?: ZodSchema<any, ZodTypeDef, any>;
}
private tools = new Map<string, ToolEntry>();

Readability & DX both improve.


212-215: Global export without collision safety

Blindly assigning window[namespace] = this can overwrite an existing
window.mcp. Add a guard or console warning:

- (window as any)[namespace] = this;
+ if ((window as any)[namespace]) {
+   console.warn(`window.${namespace} already exists – overwriting.`);
+ }
+ (window as any)[namespace] = this;
src/winodw.MCP/mcp-window-types.ts (2)

55-60: Custom error class loses stack trace in some browsers

Invoking super(message) after assigning data prevents the correct
Error.captureStackTrace behaviour in V8 environments. Swap the order
and set this.name explicitly afterwards:

-  constructor(message: string, public data?: any) {
-    super(message);
-    this.name = "McpWindowError";
-  }
+  constructor(message: string, public data?: any) {
+    super(message);
+    this.name = 'McpWindowError';
+    if (Error.captureStackTrace) {
+      Error.captureStackTrace(this, McpWindowError);
+    }
+  }

321-340: Empty marker interfaces trigger Biome noEmptyInterface warnings

Interfaces with no members are equivalent to {}; use type aliases
to silence linter noise:

-export interface ResourceListChangedNotificationPayload {}
+export type ResourceListChangedNotificationPayload = {};

Repeat for the five other empty interfaces in this section.

🧰 Tools
🪛 Biome (1.9.4)

[error] 321-324: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 331-334: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 336-339: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7fc2c5c and 5c3c543.

⛔ Files ignored due to path filters (5)
  • app/favicon.ico is excluded by !**/*.ico
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • public/vite.svg is excluded by !**/*.svg
  • src/assets/Cloudflare_Logo.svg is excluded by !**/*.svg
  • src/assets/react.svg is excluded by !**/*.svg
📒 Files selected for processing (35)
  • .env.example (0 hunks)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • app/api/chat/route.ts (0 hunks)
  • app/assistant.tsx (0 hunks)
  • app/layout.tsx (0 hunks)
  • app/page.tsx (0 hunks)
  • eslint.config.js (1 hunks)
  • eslint.config.mjs (0 hunks)
  • index.html (1 hunks)
  • next.config.ts (0 hunks)
  • package.json (1 hunks)
  • postcss.config.mjs (0 hunks)
  • src/App.tsx (1 hunks)
  • src/Assistant.tsx (1 hunks)
  • src/components/app-sidebar.tsx (2 hunks)
  • src/components/assistant-ui/markdown-text.tsx (1 hunks)
  • src/components/assistant-ui/tool-fallback.tsx (1 hunks)
  • src/components/ui/sidebar.tsx (3 hunks)
  • src/index.css (1 hunks)
  • src/main.tsx (1 hunks)
  • src/vite-env.d.ts (1 hunks)
  • src/winodw.MCP/ClientSDK.ts (1 hunks)
  • src/winodw.MCP/McpContextProviderComponent.tsx (1 hunks)
  • src/winodw.MCP/mcp-tool-adapter.ts (1 hunks)
  • src/winodw.MCP/mcp-window-types.ts (1 hunks)
  • src/winodw.MCP/serverSDK.ts (1 hunks)
  • src/winodw.MCP/useMcpContextProvider.tsx (1 hunks)
  • tsconfig.app.json (1 hunks)
  • tsconfig.json (1 hunks)
  • tsconfig.node.json (1 hunks)
  • tsconfig.worker.json (1 hunks)
  • vite.config.ts (1 hunks)
  • worker/index.ts (1 hunks)
  • wrangler.jsonc (1 hunks)
💤 Files with no reviewable changes (8)
  • .env.example
  • eslint.config.mjs
  • next.config.ts
  • app/page.tsx
  • app/assistant.tsx
  • postcss.config.mjs
  • app/api/chat/route.ts
  • app/layout.tsx
🧰 Additional context used
🧬 Code Graph Analysis (6)
src/App.tsx (1)
src/Assistant.tsx (1)
  • Assistant (11-50)
src/winodw.MCP/McpContextProviderComponent.tsx (1)
src/winodw.MCP/useMcpContextProvider.tsx (1)
  • useMcpContextProvider (32-214)
src/winodw.MCP/mcp-tool-adapter.ts (2)
src/winodw.MCP/mcp-window-types.ts (3)
  • McpInputSchema (152-158)
  • CallToolParams (170-174)
  • CallToolResult (186-191)
src/winodw.MCP/ClientSDK.ts (1)
  • McpWindowClient (16-104)
src/main.tsx (1)
src/winodw.MCP/serverSDK.ts (1)
  • McpWindowProvider (39-216)
src/winodw.MCP/serverSDK.ts (1)
src/winodw.MCP/mcp-window-types.ts (12)
  • ReadResourceResult (86-89)
  • CallToolResult (186-191)
  • GetPromptResult (243-247)
  • WindowMcpApi (365-390)
  • ServerInfo (23-23)
  • ServerCapabilities (29-38)
  • Resource (63-71)
  • Tool (160-168)
  • Prompt (212-218)
  • ListResourcesResult (95-99)
  • ListToolsResult (197-201)
  • ListPromptsResult (253-257)
src/winodw.MCP/ClientSDK.ts (1)
src/winodw.MCP/mcp-window-types.ts (9)
  • WindowMcpApi (365-390)
  • ServerInfo (23-23)
  • ServerCapabilities (29-38)
  • ListResourcesResult (95-99)
  • ReadResourceResult (86-89)
  • ListToolsResult (197-201)
  • CallToolResult (186-191)
  • ListPromptsResult (253-257)
  • GetPromptResult (243-247)
🪛 Biome (1.9.4)
tsconfig.worker.json

[error] 6-6: Expected a property but instead found '}'.

Expected a property here.

(parse)

tsconfig.node.json

[error] 9-9: JSON standard does not allow comments.

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: JSON standard does not allow comments.

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 29-29: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-31: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

src/winodw.MCP/serverSDK.ts

[error] 25-27: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)

src/winodw.MCP/mcp-window-types.ts

[error] 124-126: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 133-135: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 276-278: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 321-324: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 331-334: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 336-339: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

tsconfig.app.json

[error] 13-13: JSON standard does not allow comments.

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: JSON standard does not allow comments.

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-32: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 33-33: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 34-34: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 34-34: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 34-36: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 36-37: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

🪛 LanguageTool
README.md

[uncategorized] ~37-~37: Loose punctuation mark.
Context: ...elements). * listResources(): Discover available resources. *...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~38-~38: Loose punctuation mark.
Context: ...ces. * readResource({ uri }): Get the content of a specific resource....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~40-~40: Loose punctuation mark.
Context: ...item to cart). * listTools(): Discover available tools. * `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~41-~41: Loose punctuation mark.
Context: ... * callTool({ name, arguments }): Execute a tool with given arguments. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~43-~43: Loose punctuation mark.
Context: ...e's context. * listPrompts(): Discover available prompt templates. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~44-~44: Loose punctuation mark.
Context: ... * getPrompt({ name, arguments }): Get the messages for a specific prompt,...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~48-~48: Loose punctuation mark.
Context: ...e, version). * getCapabilities(): Get the capabilities supported by the p...

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~79-~79: This phrase is redundant (‘I’ stands for ‘Interface’). Use simply “APIInterface”.
Context: ...re-list tools, re-read a resource). ## API Interface (WindowMcpApi) The window.mcp obje...

(ACRONYM_TAUTOLOGY)


[uncategorized] ~109-~109: Loose punctuation mark.
Context: ...and clients: * McpWindowProviderSDK: A helper library for web pages to easil...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~114-~114: Loose punctuation mark.
Context: ... notifications. * McpWindowClientSDK: A helper library for LLM UIs to: * ...

(UNLIKELY_OPENING_PUNCTUATION)


[grammar] ~161-~161: The expression “vice versa” is spelled without hyphens.
Context: ...mplicitly trusted by the LLM client (or vice-versa, depending on how the components are lo...

(VICE_VERSA)


[style] ~178-~178: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...: For list* methods if lists can become very large. Resource Subscriptions: More granular...

(EN_WEAK_ADJECTIVE)

🪛 markdownlint-cli2 (0.17.2)
README.md

68-68: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


69-69: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


70-70: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


71-71: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


110-110: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


111-111: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


112-112: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


113-113: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


115-115: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


116-116: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


117-117: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


121-121: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)


146-146: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

🔇 Additional comments (23)
.gitignore (1)

1-29: .gitignore covers expected files and directories
The ignore patterns correctly exclude logs, node_modules, Vite build outputs, local env files, editor metadata, and Wrangler artifacts.

src/vite-env.d.ts (1)

1-1: Add Vite environment type declarations
The reference to vite/client is necessary for recognizing Vite-specific globals and looks correct.

src/components/assistant-ui/tool-fallback.tsx (1)

1-1: Use import type for pure type imports
Explicitly marking ToolCallContentPartComponent as a type-only import is correct and ensures no runtime bundle overhead.

src/App.tsx (1)

1-8: New App root component is simple and correct
Rendering the Assistant component directly fits the restructured Vite app; ensure App is mounted in main.tsx and that React’s automatic JSX runtime is configured.

src/components/assistant-ui/markdown-text.tsx (1)

4-11: Clean import organization.

Import reorganization looks good. Properly marking type imports with the type keyword and removing the Next.js-specific "use client" directive aligns well with the migration to Vite.

src/components/ui/sidebar.tsx (2)

4-26: Improved import organization.

The reorganization of imports improves code readability by explicitly marking type imports and grouping related imports. The changes are purely organizational with no functional impact.


725-727: Proper code formatting.

Good cleanup by removing the trailing comma from the export list and adding a proper trailing newline at the end of the file.

wrangler.jsonc (1)

15-16: ⚠️ Potential issue

Invalid JSON trailing comma

There's a trailing comma after "enabled": true but no comma should be present since it's the last property in the object.

	"observability": {
		"enabled": true
-	}
+	},

Likely an incorrect or invalid review comment.

tsconfig.node.json (2)

1-31: Well-structured TypeScript configuration for Node.js environment

This configuration is properly set up for Node.js-specific files, with appropriate ES2022 target and ES2023 library support. The bundler mode settings and strict type checking options will help maintain code quality.

🧰 Tools
🪛 Biome (1.9.4)

[error] 9-9: JSON standard does not allow comments.

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: JSON standard does not allow comments.

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 29-29: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-31: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


20-20:

✅ Verification successful

Verify the erasableSyntaxOnly option compatibility

The erasableSyntaxOnly option is not commonly used and might be specific to newer TypeScript versions. Ensure it's compatible with your TypeScript version.


🌐 Web query:

What is the erasableSyntaxOnly option in TypeScript and which versions support it?

💡 Result:

The --erasableSyntaxOnly option in TypeScript, introduced in version 5.8, restricts the use of certain TypeScript features that cannot be easily removed without affecting runtime behavior. When enabled, TypeScript will raise errors for constructs such as:

  • enum declarations
  • namespace and module declarations with runtime code
  • Parameter properties in classes
  • Non-ECMAScript import = and export = assignments

This flag is particularly useful when working with environments like Node.js, which support running TypeScript files directly but only with syntax that can be erased to produce valid JavaScript. By enabling --erasableSyntaxOnly, developers can ensure their code is compatible with such environments by avoiding features that require transformation during the build process. (typescriptlang.org)

To use this option, include it in your tsconfig.json file under compilerOptions:

{
  "compilerOptions": {
    "erasableSyntaxOnly": true
  }
}

This setting will cause TypeScript to emit errors when encountering the restricted constructs mentioned above. (typescriptlang.org)

For more detailed information, refer to the official TypeScript documentation on the --erasableSyntaxOnly option. (typescriptlang.org)

Citations:


🏁 Script executed:

#!/bin/bash
set -e
# Extract the TypeScript version declared in package.json (dependencies or devDependencies)
if [ -f package.json ]; then
  jq -r '[.dependencies.typescript, .devDependencies.typescript] 
         | map(select(.!=null)) 
         | .[0] // "Not found"' package.json
else
  echo "package.json not found"
fi

Length of output: 185


erasableSyntaxOnly is supported in TS ≥ 5.8
Your project’s TypeScript version is ~5.8.3, so the "erasableSyntaxOnly": true setting in tsconfig.node.json is valid and requires no changes.

🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

tsconfig.json (1)

1-20: Well-structured project references for TypeScript compilation

The modular approach with separate configs for app, node, and worker environments is a good practice for a mixed-environment project.

tsconfig.app.json (2)

1-37: Well-configured TypeScript settings for React application

The configuration is properly set up for a React application with appropriate target, module resolution, and JSX settings.

🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: JSON standard does not allow comments.

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: JSON standard does not allow comments.

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 26-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 27-27: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-32: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 33-33: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 34-34: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 34-34: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 34-36: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 36-37: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


24-24: Verify the erasableSyntaxOnly option compatibility

Same as in tsconfig.node.json, this option is not commonly used. Ensure it's compatible with your TypeScript version and has the intended effect.

🧰 Tools
🪛 Biome (1.9.4)

[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

src/Assistant.tsx (2)

11-15: LGTM: Runtime initialization looks good.

The chat runtime is properly initialized with the correct API endpoint that will connect to the Cloudflare Worker.


17-18: Good implementation of the MCP context provider.

The McpContextProviderComponent is correctly positioned to provide MCP functionality to the entire assistant UI.

package.json (3)

7-12: LGTM: Build scripts are properly configured for Vite and Cloudflare.

The scripts for development, building, and deployment are well set up for the new architecture.


33-34:

✅ Verification successful

Verify React 19 compatibility with other dependencies.

You're using React 19, which is very recent. Ensure all dependencies are compatible with this version.


🌐 Web query:

Is React 19 compatible with @assistant-ui/react and @assistant-ui/react-ai-sdk?

💡 Result:

As of May 2025, React 19 is the latest stable release of React. The @assistant-ui/react library, which provides a customizable user interface for AI chat applications, has been updated to support React 19. The library's roadmap indicates that support for React 19 is included in the 2025 Q1 roadmap, along with support for Tailwind v4 and Next.js 19. (npmjs.com)

Similarly, the @assistant-ui/react-ai-sdk package, which integrates the Vercel AI SDK with @assistant-ui/react, has also been updated to support React 19. The latest version of this package was published on May 14, 2025, indicating ongoing maintenance and compatibility with recent React versions. (npmjs.com)

Therefore, both @assistant-ui/react and @assistant-ui/react-ai-sdk are compatible with React 19.

Citations:


React 19 Compatibility Confirmed

Both @assistant-ui/react and @assistant-ui/react-ai-sdk have official support for React 19 (per their May 2025 releases), so no additional changes are required.


15-39:

❓ Verification inconclusive

Review the dependency versions for potential vulnerabilities.

With the migration to Vite and new dependencies, it's important to check for any security vulnerabilities.


🏁 Script executed:

#!/bin/bash
# Check for vulnerable dependencies
npm audit --json | jq '.vulnerabilities'

Length of output: 394


Lockfile required before auditing dependencies

The audit failed because there’s no lockfile in the repo. To enable vulnerability checks:

  • Generate a lockfile in the project root:
    • For npm: npm install --package-lock-only
    • For Yarn: yarn install --frozen-lockfile
    • For pnpm: pnpm install --lockfile-only
  • Commit the new lockfile (package-lock.json, yarn.lock, or pnpm-lock.yaml)
  • Rerun the audit:
    • npm: npm audit --json | jq '.vulnerabilities'
    • Yarn: yarn audit
    • pnpm: pnpm audit

Once the lockfile is in place, verify there are no vulnerabilities introduced by the Vite migration or new dependencies.

README.md (2)

1-10: Excellent introduction to the MCP-Window protocol.

The overview provides a clear and concise explanation of what MCP-Window is, its purpose, and how it differs from standard MCP implementations. This helps readers quickly understand the key concept.


21-56: Well-structured explanation of key concepts.

The key concepts section does an excellent job of breaking down the MCP-Window components and their interactions. The categorization of features into resources, tools, and prompts makes the functionality clear.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~37-~37: Loose punctuation mark.
Context: ...elements). * listResources(): Discover available resources. *...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~38-~38: Loose punctuation mark.
Context: ...ces. * readResource({ uri }): Get the content of a specific resource....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~40-~40: Loose punctuation mark.
Context: ...item to cart). * listTools(): Discover available tools. * `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~41-~41: Loose punctuation mark.
Context: ... * callTool({ name, arguments }): Execute a tool with given arguments. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~43-~43: Loose punctuation mark.
Context: ...e's context. * listPrompts(): Discover available prompt templates. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~44-~44: Loose punctuation mark.
Context: ... * getPrompt({ name, arguments }): Get the messages for a specific prompt,...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~48-~48: Loose punctuation mark.
Context: ...e, version). * getCapabilities(): Get the capabilities supported by the p...

(UNLIKELY_OPENING_PUNCTUATION)

src/winodw.MCP/mcp-tool-adapter.ts (1)

74-87: LGTM: The result processing logic is well-structured.

The code correctly prioritizes structured content first, then text content, and finally falls back to the raw content. This provides a flexible way to handle various tool response formats.

src/main.tsx (1)

42-46: Unchecked root element may crash in SSR / tests

document.getElementById('root')! asserts presence. In SSR or unit tests the element might be missing, throwing immediately. Fail gracefully:

-const container = document.getElementById('root')!;
-createRoot(container).render(
+const container = document.getElementById('root');
+if (container) {
+  createRoot(container).render(
     /* … */
-)
+  );
+} else {
+  console.error("Root element #root not found – React app not mounted.");
+}
src/winodw.MCP/serverSDK.ts (1)

1-1: Directory name winodw.MCP looks like a typo

winodwwindow. Renaming avoids future import confusions.

Comment on lines 4 to 6
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo",
"types": ["./worker-configuration.d.ts", "vite/client"],
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix JSON syntax error: remove trailing comma.

There's a syntax error in your JSON configuration. JSON doesn't allow trailing commas before closing brackets, which will cause parsing errors.

Apply this diff to fix the issue:

  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.worker.tsbuildinfo",
-    "types": ["./worker-configuration.d.ts", "vite/client"],
+    "types": ["./worker-configuration.d.ts", "vite/client"]
  },
🧰 Tools
🪛 Biome (1.9.4)

[error] 6-6: Expected a property but instead found '}'.

Expected a property here.

(parse)

🤖 Prompt for AI Agents
In tsconfig.worker.json around lines 4 to 6, there is a trailing comma after the
last item in the "types" array, which is invalid JSON syntax. Remove the
trailing comma after "vite/client" to fix the JSON parsing error.

@@ -0,0 +1,6 @@
import useMcpContextProvider from "./useMcpContextProvider";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Directory name contains typo

There's a typo in the directory name: "winodw.MCP" should be "window.MCP"

This typo appears to be in the directory structure itself, not just the import path. Ensure all references to this directory are updated if you rename it.

🤖 Prompt for AI Agents
In src/winodw.MCP/McpContextProviderComponent.tsx at line 1, the directory name
"winodw.MCP" contains a typo and should be corrected to "window.MCP". Rename the
directory from "winodw.MCP" to "window.MCP" in the file system and update all
import paths and references accordingly to reflect this corrected directory
name.

Comment on lines 1 to 6
import useMcpContextProvider from "./useMcpContextProvider";

export default function McpContextProviderComponent({ children, mcpClientNamespace }: { children: React.ReactNode, mcpClientNamespace?: string}) {
useMcpContextProvider(mcpClientNamespace);
return <>{children}</>;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Component needs to handle hook return values

The component calls useMcpContextProvider but doesn't use any of the return values like isLoading, error, or other MCP context data. This means errors or loading states aren't handled at this level.

Consider exposing the MCP context to consumers by either:

  1. Creating a React Context and providing the values to children:
- import useMcpContextProvider from "./useMcpContextProvider";
+ import React, { createContext, useContext } from "react";
+ import useMcpContextProvider, { McpContext } from "./useMcpContextProvider";

+ export const McpContext = createContext<McpContext | null>(null);
+ export const useMcp = () => useContext(McpContext);

export default function McpContextProviderComponent({ children, mcpClientNamespace }: { children: React.ReactNode, mcpClientNamespace?: string}) {
-    useMcpContextProvider(mcpClientNamespace);
-    return <>{children}</>;
+    const mcpContext = useMcpContextProvider(mcpClientNamespace);
+    return (
+        <McpContext.Provider value={mcpContext}>
+            {mcpContext.error ? (
+                <div>Error connecting to MCP: {mcpContext.error.message}</div>
+            ) : mcpContext.isLoading ? (
+                <div>Loading MCP resources...</div>
+            ) : (
+                <>{children}</>
+            )}
+        </McpContext.Provider>
+    );
 }
  1. Or at minimum, handle loading and error states:
export default function McpContextProviderComponent({ children, mcpClientNamespace }: { children: React.ReactNode, mcpClientNamespace?: string}) {
-    useMcpContextProvider(mcpClientNamespace);
+    const { isLoading, error } = useMcpContextProvider(mcpClientNamespace);
+    
+    if (error) {
+        return <div>Error connecting to MCP: {error.message}</div>;
+    }
+    
+    if (isLoading) {
+        return <div>Loading MCP resources...</div>;
+    }
     
     return <>{children}</>;
 }
🤖 Prompt for AI Agents
In src/winodw.MCP/McpContextProviderComponent.tsx lines 1 to 6, the component
calls the useMcpContextProvider hook but does not handle or expose its return
values such as isLoading or error. To fix this, modify the component to either
create a React Context that provides these values to its children or at minimum,
add conditional rendering to handle loading and error states before rendering
children. This ensures that consumers of the component can access MCP context
data and that loading or error states are properly managed.

Comment on lines 43 to 53
<SidebarMenuButton size="lg">
<a href="https://github.com/assistant-ui/assistant-ui" target="_blank" className="flex items-center gap-2">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Github className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">GitHub</span>
<span className="">View Source</span>
</div>
</Link>
</a>
</SidebarMenuButton>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add security attributes to GitHub link

Same issue as with the other external link. The GitHub link should include rel="noopener noreferrer" for security.

<SidebarMenuButton size="lg">
-  <a href="/assistant-ui/assistant-ui" target="_blank" className="flex items-center gap-2">
+  <a href="/assistant-ui/assistant-ui" target="_blank" rel="noopener noreferrer" className="flex items-center gap-2">
    <div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
      <Github className="size-4" />
    </div>
    <div className="flex flex-col gap-0.5 leading-none">
      <span className="font-semibold">GitHub</span>
      <span className="">View Source</span>
    </div>
  </a>
</SidebarMenuButton>
📝 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
<SidebarMenuButton size="lg">
<a href="https://github.com/assistant-ui/assistant-ui" target="_blank" className="flex items-center gap-2">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Github className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">GitHub</span>
<span className="">View Source</span>
</div>
</Link>
</a>
</SidebarMenuButton>
<SidebarMenuButton size="lg">
<a
href="https://github.com/assistant-ui/assistant-ui"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2"
>
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Github className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">GitHub</span>
<span className="">View Source</span>
</div>
</a>
</SidebarMenuButton>
🤖 Prompt for AI Agents
In src/components/app-sidebar.tsx between lines 43 and 53, the GitHub external
link is missing the security attributes rel="noopener noreferrer". Add these
attributes to the <a> tag to prevent security vulnerabilities related to opening
links in a new tab.

Comment on lines 21 to 30
<SidebarMenuButton size="lg">
<a href="https://assistant-ui.com" target="_blank" className="flex items-center gap-2">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<MessagesSquare className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">assistant-ui</span>
</div>
</Link>
</a>
</SidebarMenuButton>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add security attributes to external links

External links using target="_blank" should include rel="noopener noreferrer" to prevent potential security vulnerabilities.

<SidebarMenuButton size="lg">
-   <a href="https://assistant-ui.com" target="_blank" className="flex items-center gap-2">
+   <a href="https://assistant-ui.com" target="_blank" rel="noopener noreferrer" className="flex items-center gap-2">
      <div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
        <MessagesSquare className="size-4" />
      </div>
      <div className="flex flex-col gap-0.5 leading-none">
        <span className="font-semibold">assistant-ui</span>
      </div>
    </a>
  </SidebarMenuButton>
📝 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
<SidebarMenuButton size="lg">
<a href="https://assistant-ui.com" target="_blank" className="flex items-center gap-2">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<MessagesSquare className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">assistant-ui</span>
</div>
</Link>
</a>
</SidebarMenuButton>
<SidebarMenuButton size="lg">
<a
href="https://assistant-ui.com"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2"
>
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<MessagesSquare className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">assistant-ui</span>
</div>
</a>
</SidebarMenuButton>
🤖 Prompt for AI Agents
In src/components/app-sidebar.tsx around lines 21 to 30, the external link with
target="_blank" is missing the security attributes rel="noopener noreferrer".
Add rel="noopener noreferrer" to the <a> tag to prevent potential security
vulnerabilities related to opening links in a new tab.

Comment on lines 30 to 35
dispatchMcpEvent(type: McpEvent, payload?: any) {
const event = new CustomEvent<McpNotification>("mcpNotification", {
detail: { type, payload },
});
this.dispatchEvent(event);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

McpEvent / McpNotification types are undefined

dispatchMcpEvent generically parameterises CustomEvent with McpNotification, and the
first argument is typed as McpEvent, yet neither is exported from
mcp-window-types.ts. This causes unresolved-identifier errors.

Fix options:

-import type { …, McpEvent, McpNotification, … } from './mcp-window-types.ts';
+import type { McpNotificationDetail as McpNotification, /* alias */ } 
+  from './mcp-window-types.ts';
+type McpEvent = McpNotification['type'];

or formally export those aliases from the types file.
Without this, the provider cannot compile.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/winodw.MCP/serverSDK.ts around lines 30 to 35, the types McpEvent and
McpNotification used in dispatchMcpEvent are not defined or imported, causing
unresolved identifier errors. To fix this, locate the mcp-window-types.ts file
and ensure that McpEvent and McpNotification types are properly exported from
there. Then, import these types into serverSDK.ts so they can be referenced
without errors.

Comment on lines 104 to 122
private zodToMcpSchema(schema: ZodSchema<any, ZodTypeDef, any>): ToolInputSchema {
// Basic Zod to JSON Schema-like conversion (can be made more robust)
if (schema instanceof z.ZodObject) {
const properties: ToolInputSchema['properties'] = {};
const shape = schema.shape as Record<string, ZodSchema<any, ZodTypeDef, any>>;
for (const key in shape) {
const fieldSchema = shape[key];
let type = 'any';
if (fieldSchema instanceof z.ZodString) type = 'string';
else if (fieldSchema instanceof z.ZodNumber) type = 'number';
else if (fieldSchema instanceof z.ZodBoolean) type = 'boolean';
else if (fieldSchema instanceof z.ZodArray) type = 'array';
else if (fieldSchema instanceof z.ZodObject) type = 'object';
properties[key] = { type, description: fieldSchema.description };
}
return { type: 'object', properties, required: Object.keys(shape) /* simplistic */ };
}
return { type: 'object', properties: {} };
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

zodToMcpSchema treats every property as required

required: Object.keys(shape) marks all keys mandatory, ignoring Zod’s
.optional(). Tools that rely on optional arguments will mis-validate.

Either:

  1. Inspect fieldSchema.isOptional() (available in Zod ≥3.22) or
  2. Use schema.safeParse({}) heuristics to collect required keys.

Example patch:

 const required: string[] = [];
 for (const key in shape) {
   const fieldSchema = shape[key];
+  if (!(fieldSchema.isOptional?.() ?? false)) {
+    required.push(key);
+  }
   …
 }
-return { type: 'object', properties, required: Object.keys(shape) };
+return { type: 'object', properties, required };

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/winodw.MCP/serverSDK.ts lines 104 to 122, the zodToMcpSchema method
incorrectly marks all properties as required by setting required to all keys in
the schema shape, ignoring optional fields. To fix this, update the code to
check each fieldSchema for optionality using fieldSchema.isOptional() and only
include keys that are not optional in the required array. This ensures the
generated schema correctly reflects which properties are mandatory and which are
optional.

Comment on lines 73 to 85
addTool<T extends z.ZodRawShape>(
tool: Omit<Tool, 'inputSchema'> & { inputSchemaDef?: T, inputSchema?: ToolInputSchema },
handler: (args: z.infer<z.ZodObject<T>>) => Promise<CallToolResult>
): void {
if (!this.capabilities.tools) throw new Error("Tool capability not enabled.");
let validator;
if (tool.inputSchemaDef) {
validator = z.object(tool.inputSchemaDef);
}
this.tools.set(tool.name, {
...tool,
inputSchema: tool.inputSchema || (tool.inputSchemaDef ? this.zodToMcpSchema(validator!) : { type: 'object', properties: {} }),
handler: async (params) => {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

ToolInputSchema is not declared anywhere

The generic overload refers to ToolInputSchema, but only McpInputSchema
exists in the shared types module. Rename to the exported type or add an alias:

- tool: Omit<Tool, 'inputSchema'> & { inputSchemaDef?: T, inputSchema?: ToolInputSchema },
+ tool: Omit<Tool, 'inputSchema'> & { inputSchemaDef?: T, inputSchema?: McpInputSchema },

This is a hard compile failure.

📝 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
addTool<T extends z.ZodRawShape>(
tool: Omit<Tool, 'inputSchema'> & { inputSchemaDef?: T, inputSchema?: ToolInputSchema },
handler: (args: z.infer<z.ZodObject<T>>) => Promise<CallToolResult>
): void {
if (!this.capabilities.tools) throw new Error("Tool capability not enabled.");
let validator;
if (tool.inputSchemaDef) {
validator = z.object(tool.inputSchemaDef);
}
this.tools.set(tool.name, {
...tool,
inputSchema: tool.inputSchema || (tool.inputSchemaDef ? this.zodToMcpSchema(validator!) : { type: 'object', properties: {} }),
handler: async (params) => {
addTool<T extends z.ZodRawShape>(
tool: Omit<Tool, 'inputSchema'> & { inputSchemaDef?: T, inputSchema?: McpInputSchema },
handler: (args: z.infer<z.ZodObject<T>>) => Promise<CallToolResult>
): void {
if (!this.capabilities.tools) throw new Error("Tool capability not enabled.");
let validator;
if (tool.inputSchemaDef) {
validator = z.object(tool.inputSchemaDef);
}
this.tools.set(tool.name, {
...tool,
inputSchema: tool.inputSchema || (tool.inputSchemaDef ? this.zodToMcpSchema(validator!) : { type: 'object', properties: {} }),
handler: async (params) => {
🤖 Prompt for AI Agents
In src/winodw.MCP/serverSDK.ts between lines 73 and 85, the type ToolInputSchema
used in the addTool method is not declared anywhere, causing a compile error.
Replace ToolInputSchema with the correct exported type McpInputSchema from the
shared types module or create an alias for ToolInputSchema that points to
McpInputSchema. This will resolve the type reference and fix the compilation
failure.

Comment on lines 152 to 158
export interface McpInputSchema {
type: "object";
properties?: { [key: string]: { type: string; description?: string; [key: string]: any } };
required?: string[];
// passthrough
[key: string]: any;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Export ToolInputSchema alias for SDK compatibility

serverSDK.ts expects ToolInputSchema, but only McpInputSchema is
defined. Provide a simple alias to keep both names working:

 export interface McpInputSchema {
   …
 }
+
+// Back-compat alias – remove once all call-sites migrate.
+export type ToolInputSchema = McpInputSchema;
📝 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
export interface McpInputSchema {
type: "object";
properties?: { [key: string]: { type: string; description?: string; [key: string]: any } };
required?: string[];
// passthrough
[key: string]: any;
}
export interface McpInputSchema {
type: "object";
properties?: { [key: string]: { type: string; description?: string; [key: string]: any } };
required?: string[];
// passthrough
[key: string]: any;
}
// Back-compat alias – remove once all call-sites migrate.
export type ToolInputSchema = McpInputSchema;
🤖 Prompt for AI Agents
In src/winodw.MCP/mcp-window-types.ts around lines 152 to 158, the interface
McpInputSchema is defined but the SDK expects an alias named ToolInputSchema.
Add an export statement that creates a type alias ToolInputSchema for
McpInputSchema to maintain compatibility with serverSDK.ts without changing the
existing interface.

Comment on lines 349 to 360
export type McpNotificationDetail =
| ({ type: "resourcesListChanged" } & ResourceListChangedNotificationPayload)
| ({ type: "resourceUpdated" } & ResourceUpdatedNotificationPayload)
| ({ type: "toolsListChanged" } & ToolListChangedNotificationPayload)
| ({ type: "promptsListChanged" } & PromptListChangedNotificationPayload)
| ({ type: "loggingMessage" } & LoggingMessageNotificationPayload); // Renamed from "notifications/message"

// The CustomEvent detail type
export interface McpNotificationEventDetail {
type: McpNotificationDetail['type']; // The specific notification type
payload?: Omit<McpNotificationDetail, 'type'>; // The payload for that type
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add canonical McpEvent / McpNotification type exports

The provider dispatches events with type plus payload. Supplying
formal aliases eases consumption and fixes missing-type errors noted
in serverSDK.ts.

 export type McpNotificationDetail =
   …
   | ({ type: "loggingMessage" } & LoggingMessageNotificationPayload); // Renamed from "notifications/message"

+// Convenience aliases -------------------------------------------------
+export type McpEvent = McpNotificationDetail['type'];
+export type McpNotification = McpNotificationDetail;
🤖 Prompt for AI Agents
In src/winodw.MCP/mcp-window-types.ts around lines 349 to 360, add explicit type
aliases named McpEvent and McpNotification that represent the union of event
types with their payloads, matching the dispatched event structure. This will
provide canonical exports for these types, making it easier to consume them
elsewhere and resolving missing-type errors in serverSDK.ts. Define McpEvent and
McpNotification as unions of objects containing the type and corresponding
payload, aligning with the existing McpNotificationDetail and
McpNotificationEventDetail structures.

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.

1 participant