Skip to content

feat: add the ability to customize plugin tools and supports both form and JSON data formats.#267

Merged
zzcr merged 1 commit intodevfrom
zzc/feat-add-custom-tool-0105
Jan 5, 2026
Merged

feat: add the ability to customize plugin tools and supports both form and JSON data formats.#267
zzcr merged 1 commit intodevfrom
zzc/feat-add-custom-tool-0105

Conversation

@zzcr
Copy link
Member

@zzcr zzcr commented Jan 5, 2026

feat: 添加自定义插件工具的能力同时支持表单和json数据格式

Summary by CodeRabbit

  • New Features

    • MCP server creation now available with custom add button enabled by default.
    • Added public addMessage method for external message management.
    • New composable enabling programmatic MCP server management with batch and single addition modes.
  • Chores

    • Version bumps: next-remoter (0.0.10-beta.5), next-sdk (0.1.15-beta.5).
  • Changes

    • Record button in sidepanel temporarily disabled.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Walkthrough

The changes introduce a new composable for programmatically managing custom MCP servers, integrate it into the TinyRobotChat component with a new public API, add a toolChoice configuration option, bump package versions, and temporarily disable a UI action. These modifications enable users to add MCP servers dynamically in two modes: code-based batch import and form-based single server creation.

Changes

Cohort / File(s) Summary
Version Updates
packages/next-remoter/package.json, packages/next-sdk/package.json
Bump versions: next-remoter from 0.0.10-beta.4 to 0.0.10-beta.5; next-sdk from 0.1.15-beta.4 to 0.1.15-beta.5. No functional changes.
MCP Server Management Feature
packages/next-remoter/src/composable/useCustomMcpServer.ts
New composable providing handleCustomAdd(type: 'code' | 'form', data: any) for programmatic MCP server management. Supports batch JSON import (code mode) and structured form input (form mode) with JSON parsing, plugin normalization, agent insertion, PluginInfo construction, error handling, and loading indicators.
Component Integration
packages/next-remoter/src/components/tiny-robot-chat.vue
Enable custom add button on MCP server picker (:show-custom-add-button="true"), wire @plugin-create event to handleCustomAdd from new useCustomMcpServer composable, and expose new public method addMessage via defineExpose alongside existing handleClientDisconnected.
Configuration Addition
packages/next-remoter/src/composable/CustomAgentModelProvider.ts
Add toolChoice: 'auto' to chatStreamOptions configuration with documentation on tool invocation modes.
UI Temporary Disable
packages/next-wxt/entrypoints/sidepanel/App.vue
Comment out header-actions slot content (record button) with note indicating future re-enabling; functionality remains inactive until uncommented.

Sequence Diagram(s)

sequenceDiagram
    participant Component as TinyRobotChat Component
    participant Composable as useCustomMcpServer
    participant Agent as AgentModelProvider
    participant PluginStore as installedPlugins (Ref)
    participant UI as UI Feedback

    Component->>Composable: handleCustomAdd(type, data)
    alt type === 'code'
        Composable->>Composable: Parse JSON string
        Composable->>Composable: Extract MCP servers
        loop Each MCP Server
            Composable->>Agent: Add MCP server
            Composable->>PluginStore: Create & push PluginInfo
            Composable->>UI: Update success/failure count
        end
    else type === 'form'
        Composable->>Composable: Validate form data
        Composable->>Agent: Create & insert MCP server
        Composable->>Composable: Generate pluginId + tools
        Composable->>PluginStore: Push PluginInfo
        Composable->>UI: Show success toast
    end
    Composable->>Agent: Close all connections
    Composable->>Component: Return (Promise resolves)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A new composable hops into view,
Managing MCP servers—shiny and new!
Code or form, the choice is yours,
Adding servers through open doors.
With plugins dancing and buttons so bright,
The rabbit declares: oh what a sight!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the main changes: adding ability to customize plugin tools with support for both form and JSON data formats, as evidenced by the new useCustomMcpServer composable and UI updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zzc/feat-add-custom-tool-0105

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

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Fix all issues with AI Agents 🤖
In @packages/next-remoter/src/composable/useCustomMcpServer.ts:
- Around line 203-217: The destructured variable _headers from data is unused;
either remove it from the destructuring or wire it into the MCP server form
handling (e.g., propagate to the form state or include in the payload sent when
saving the server). Update the destructuring in useCustomMcpServer (remove
"headers: _headers") if you don't intend to support headers, or if you do,
ensure the headers value from data is validated and assigned to the form/model
fields and included in save/update logic where name, url, description,
thumbnail, and type (mcpType) are handled.
- Around line 229-233: The code unsafely casts mcpType into
'streamableHttp'|'sse' when building the mcpServer, which can let invalid values
(e.g. 'extension') slip through and miss required fields like sessionId; replace
the cast with explicit runtime validation of mcpType before constructing
mcpServer: check if mcpType === 'streamableHttp' || mcpType === 'sse' and build
McpServerConfig with those fields, otherwise handle other known kinds (e.g.
'extension') by including the required sessionId field or reject/throw/log an
error for unsupported values; reference mcpType, mcpServer and McpServerConfig
and ensure any branch produces a fully populated config.
🧹 Nitpick comments (2)
packages/next-remoter/src/composable/useCustomMcpServer.ts (2)

37-72: Consider adding URL validation for robustness.

The normalizeMcpConfig function handles type normalization well, but invalid URLs could pass through unchecked. Consider adding basic URL format validation to fail fast on misconfigured servers.

🔎 Suggested validation
 const normalizeMcpConfig = (config: any): McpServerConfig | null => {
   if (!config || typeof config !== 'object' || !config.url) {
     return null
   }
+
+  // Basic URL validation
+  try {
+    new URL(config.url)
+  } catch {
+    return null
+  }

   const { type, url, sessionId } = config

122-123: Consider defining proper type extension instead of @ts-ignore.

Using @ts-ignore to add originMcpConfig to PluginInfo suggests a type definition gap. If this is a common pattern, consider extending the PluginInfo type or creating a local interface.

🔎 Type extension example
// At the top of the file or in a shared types file
interface ExtendedPluginInfo extends PluginInfo {
  originMcpConfig?: McpServerConfig
}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e72a237 and 2c5623f.

📒 Files selected for processing (6)
  • packages/next-remoter/package.json
  • packages/next-remoter/src/components/tiny-robot-chat.vue
  • packages/next-remoter/src/composable/CustomAgentModelProvider.ts
  • packages/next-remoter/src/composable/useCustomMcpServer.ts
  • packages/next-sdk/package.json
  • packages/next-wxt/entrypoints/sidepanel/App.vue
🧰 Additional context used
🧬 Code graph analysis (1)
packages/next-remoter/src/composable/useCustomMcpServer.ts (3)
packages/next-sdk/agent/type.ts (1)
  • McpServerConfig (37-41)
packages/next-wxt/public/vendor/mcp-server.js (1)
  • sessionId (34-34)
packages/next-remoter/src/components/default-plugin-svg.ts (1)
  • defaultPluginSrc (19-19)
🔇 Additional comments (10)
packages/next-remoter/package.json (1)

3-3: LGTM!

Version bump to 0.0.10-beta.5 is appropriate for the new useCustomMcpServer composable feature.

packages/next-sdk/package.json (1)

3-3: LGTM!

Version bump aligns with the coordinated release of new features in the next-remoter package.

packages/next-wxt/entrypoints/sidepanel/App.vue (1)

224-230: Temporary UI disabling acknowledged.

The header-actions slot containing the custom add button is commented out pending screen recording feature completion. The custom add functionality is still available through TrMcpServerPicker with :show-custom-add-button="true" in tiny-robot-chat.vue.

packages/next-remoter/src/composable/CustomAgentModelProvider.ts (1)

488-491: LGTM!

Explicitly setting toolChoice: 'auto' with clear documentation of available options ('none', 'required') improves code clarity and makes the tool invocation behavior configurable and predictable.

packages/next-remoter/src/composable/useCustomMcpServer.ts (2)

9-31: LGTM!

The parseMcpConfigFromJson function has good error handling, validates the expected JSON structure, and provides clear error messages.


145-250: Functions are globally available—no imports needed.

showToast and showLoadingToast are auto-imported globally from vant/es via the unplugin-auto-import configuration (see packages/next-remoter/auto-imports.d.ts). These can be used without explicit imports in this file.

Likely an incorrect or invalid review comment.

packages/next-remoter/src/components/tiny-robot-chat.vue (4)

120-133: LGTM!

The TrMcpServerPicker is correctly configured with :show-custom-add-button="true" and the @plugin-create event is properly wired to handleCustomAdd from the new composable.


169-169: LGTM!

Import statement correctly added for the new useCustomMcpServer composable.


738-739: LGTM!

The composable is correctly initialized with all required dependencies: agent, installedPlugins, and defaultPluginSrc.


772-774: Good addition to the public API surface.

Exposing addMessage via defineExpose enables external consumers to programmatically add messages, which is useful for integration scenarios. The existing handleClientDisconnected exposure is maintained.

Comment on lines +203 to +217
const {
description,
headers: _headers,
name,
thumbnail,
type: mcpType,
url
} = data as {
description?: string
headers?: string | Record<string, string>
name?: string
thumbnail?: string | null
type?: string
url?: string
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unused variable _headers extracted but never used.

The headers field is destructured from data but is not utilized in the form processing logic. Either remove it or implement header support for MCP server configuration.

🔎 Proposed fix
       // 解构数据对象,headers 可能是字符串或对象
       const {
         description,
-        headers: _headers,
         name,
         thumbnail,
         type: mcpType,
         url
       } = data as {
         description?: string
-        headers?: string | Record<string, string>
         name?: string
         thumbnail?: string | null
         type?: string
         url?: string
       }
📝 Committable suggestion

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

Suggested change
const {
description,
headers: _headers,
name,
thumbnail,
type: mcpType,
url
} = data as {
description?: string
headers?: string | Record<string, string>
name?: string
thumbnail?: string | null
type?: string
url?: string
}
const {
description,
name,
thumbnail,
type: mcpType,
url
} = data as {
description?: string
name?: string
thumbnail?: string | null
type?: string
url?: string
}
🤖 Prompt for AI Agents
In @packages/next-remoter/src/composable/useCustomMcpServer.ts around lines
203-217, The destructured variable _headers from data is unused; either remove
it from the destructuring or wire it into the MCP server form handling (e.g.,
propagate to the form state or include in the payload sent when saving the
server). Update the destructuring in useCustomMcpServer (remove "headers:
_headers") if you don't intend to support headers, or if you do, ensure the
headers value from data is validated and assigned to the form/model fields and
included in save/update logic where name, url, description, thumbnail, and type
(mcpType) are handled.

Comment on lines +229 to +233
const mcpServer: McpServerConfig = {
type: mcpType as 'streamableHttp' | 'sse',
url,
useAISdkClient: true
} as McpServerConfig
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Type assertion could allow invalid mcpType values.

The cast mcpType as 'streamableHttp' | 'sse' doesn't validate the input. If mcpType is an unexpected value (e.g., 'extension'), it will be assigned to the config object without the required sessionId field.

🔎 Proposed validation
+      // Validate mcpType for form mode (only streamableHttp and sse are supported)
+      if (mcpType !== 'streamableHttp' && mcpType !== 'sse') {
+        showToast('添加工具失败:不支持的连接类型,仅支持 streamableHttp 或 sse')
+        return
+      }
+
       const mcpServer: McpServerConfig = {
-        type: mcpType as 'streamableHttp' | 'sse',
+        type: mcpType,
         url,
         useAISdkClient: true
-      } as McpServerConfig
+      }
📝 Committable suggestion

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

Suggested change
const mcpServer: McpServerConfig = {
type: mcpType as 'streamableHttp' | 'sse',
url,
useAISdkClient: true
} as McpServerConfig
// Validate mcpType for form mode (only streamableHttp and sse are supported)
if (mcpType !== 'streamableHttp' && mcpType !== 'sse') {
showToast('添加工具失败:不支持的连接类型,仅支持 streamableHttp 或 sse')
return
}
const mcpServer: McpServerConfig = {
type: mcpType,
url,
useAISdkClient: true
}
🤖 Prompt for AI Agents
In @packages/next-remoter/src/composable/useCustomMcpServer.ts around lines
229-233, The code unsafely casts mcpType into 'streamableHttp'|'sse' when
building the mcpServer, which can let invalid values (e.g. 'extension') slip
through and miss required fields like sessionId; replace the cast with explicit
runtime validation of mcpType before constructing mcpServer: check if mcpType
=== 'streamableHttp' || mcpType === 'sse' and build McpServerConfig with those
fields, otherwise handle other known kinds (e.g. 'extension') by including the
required sessionId field or reject/throw/log an error for unsupported values;
reference mcpType, mcpServer and McpServerConfig and ensure any branch produces
a fully populated config.

@zzcr zzcr merged commit f1fbcfe into dev Jan 5, 2026
3 checks passed
@kagol kagol deleted the zzc/feat-add-custom-tool-0105 branch January 8, 2026 08:20
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

Comments