Skip to content

Fix TypeError when MCP schema type is a list#4867

Merged
Soulter merged 3 commits intoAstrBotDevs:masterfrom
boushi1111:patch-1
Feb 5, 2026
Merged

Fix TypeError when MCP schema type is a list#4867
Soulter merged 3 commits intoAstrBotDevs:masterfrom
boushi1111:patch-1

Conversation

@boushi1111
Copy link
Contributor

@boushi1111 boushi1111 commented Feb 4, 2026

Fixes crash in Gemini native tools with VRChat MCP.

Modifications / 改动点

File Modified: astrbot/core/agent/tool.py

Fix: Added a check in convert_schema. If a parameter type is a list (e.g., ["string", "null"] returned by some MCP servers like vrchat-mcp), it now defaults to the first non-null type (e.g., "string") instead of crashing with TypeError.

Impact: Enables Gemini Native Tools to work with Node.js-based MCP servers.

Screenshots or Test Results / 运行截图或测试结果

Before Fix (Crash Log):

File "/AstrBot/astrbot/core/agent/tool.py", line 207, in convert_schema
if "type" in schema and schema["type"] in supported_types:
TypeError: unhashable type: 'list'

After Fix (Successful VRChat Query): User: 查询一下现在在线的vrc好友

[17:11:13] [Core] [INFO] [runners.tool_loop_agent_runner:333]: Agent 使用工具: ['vrchat_get_friends_list']
[17:11:13] [Core] [INFO] [runners.tool_loop_agent_runner:358]: 使用工具:vrchat_get_friends_list,参数:{'offline': False}
[17:11:19] [Core] [INFO] [respond.stage:168]: Prepare to send - [username]: 「哈?又要查?…

Checklist / 检查清单

  • 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
  • 👀 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

Summary by Sourcery

Bug Fixes:

  • 修复当 MCP 模式类型以列表形式提供时,在 convert_schema 中可能出现的 TypeError:通过将其规范化为列表中第一个非空类型来避免错误。
Original summary in English

Summary by Sourcery

Bug Fixes:

  • Prevent TypeError in convert_schema when MCP schema type is provided as a list by normalizing it to the first non-null type.

Fixes crash in Gemini native tools with VRChat MCP.
@auto-assign auto-assign bot requested review from Raven95676 and Soulter February 4, 2026 09:50
@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Feb 4, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - 我在这里给出了一些总体反馈:

  • 新增的逻辑会通过重写 schema['type'] 来修改传入的 schema 字典;建议在本地变量或浅拷贝上操作,这样复用原始 schema 的调用方就不会被副作用惊到。
  • schema['type'] 是一个仅包含不受支持类型(除了 "null")的列表时,next(...) 的回退逻辑会把它设置为 "string",但是后续的 supported_types 检查仍有可能跳过它;如果这是有意为之,建议加一段简短的注释,说明对“不受支持的 union 类型”期望的行为,以便后续维护者理解。
给 AI Agents 的提示词
Please address the comments from this code review:

## Overall Comments
- The new logic mutates the incoming `schema` dict by overwriting `schema['type']`; consider working on a local variable or shallow copy so callers that reuse the original schema aren’t surprised by side effects.
- When `schema['type']` is a list containing only unsupported types (other than `"null"`), the `next(...)` fallback will set it to `"string"` but the subsequent `supported_types` check may still skip it; if that’s intentional, a short comment clarifying the desired behavior for unsupported union types would help future maintainers.

Sourcery 对开源项目是免费的——如果你觉得我们的代码评审有帮助,欢迎分享 ✨
让我更有用!请对每条评论点 👍 或 👎,我会根据你的反馈改进后续的代码评审。
Original comment in English

Hey - I've left some high level feedback:

  • The new logic mutates the incoming schema dict by overwriting schema['type']; consider working on a local variable or shallow copy so callers that reuse the original schema aren’t surprised by side effects.
  • When schema['type'] is a list containing only unsupported types (other than "null"), the next(...) fallback will set it to "string" but the subsequent supported_types check may still skip it; if that’s intentional, a short comment clarifying the desired behavior for unsupported union types would help future maintainers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new logic mutates the incoming `schema` dict by overwriting `schema['type']`; consider working on a local variable or shallow copy so callers that reuse the original schema aren’t surprised by side effects.
- When `schema['type']` is a list containing only unsupported types (other than `"null"`), the `next(...)` fallback will set it to `"string"` but the subsequent `supported_types` check may still skip it; if that’s intentional, a short comment clarifying the desired behavior for unsupported union types would help future maintainers.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot bot added the area:core The bug / feature is about astrbot's core, backend label Feb 4, 2026
@dosubot dosubot bot added size:S This PR changes 10-29 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Feb 4, 2026
@Soulter
Copy link
Member

Soulter commented Feb 5, 2026

Is this bug due to the MCP Server itself being of a non-standard list type?

@boushi1111
Copy link
Contributor Author

Thanks for flagging this. I looked up the official documentation, and it explains exactly why this mismatch happens.

According to the Function calling with the Gemini API, the Schema object for function calling represents a "selected subset of the OpenAPI 3.0 schema object."

Crucially:

  1. Gemini's Requirement: The type field is defined strictly as an enum (e.g., STRING, INTEGER), meaning it accepts only a single value, not an array. To handle nulls, Google requires the separate nullable boolean field.
  2. MCP's Output: Many MCP servers (following standard JSON Schema) output type: ["string", "null"].

Conclusion:
Since AstrBot acts as the bridge, it must normalize the standard JSON Schema from MCP into the stricter OpenAPI subset required by Gemini.
My PR implements a fallback to convert the list type (e.g., ["string", "null"]) into a single supported type (e.g., "string") to prevent the crash.

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Feb 5, 2026
@Soulter Soulter merged commit d69592a into AstrBotDevs:master Feb 5, 2026
6 checks passed
LIghtJUNction added a commit that referenced this pull request Feb 5, 2026
* 默认host修改为::,同时新增两个环境变量DASHBOARD_HOST,DASHBOARD_ENABLE,和DASHBOARD_PORT对齐

* feat: systemd support (#4880)

* fix: pyright lint (#4874)

* feat: 将 MessageSession 的 platform_id 改为 init=False,实例化时无需传入

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 将 isinstance 检查改为元组、将默认模型值设为空字符串、将类型注解改为 Any 并导入

* refactor: 为 _serialize_job 增加返回类型注解 dict

* fix: 使用 cast 获取百度 AIP 的 msg 并对 psutil_addr 引入 type: ignore

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 引入 _AddrWithPort 协议并替换 conn.laddr 的 cast

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: 在构建 AstrBotMessage 时对 ctx.channel 可能为 None 进行兜底处理

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

---------

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: TypeError when MCP schema type is a list (#4867)

* Fix TypeError when MCP schema type is a list

Fixes crash in Gemini native tools with VRChat MCP.

* Refactor: avoid modifying schema in place per feedback

* Fix formatting and cleanup comments

* docs: update watashiwakoseinodesukara

Removed duplicate text and added a new image.

* 修复/跨平台一致性

* 琐事/类型标注和一些简单错误修正

* 修复/检查端口时候包含ipv6

* 修复/enable变量的赋值逻辑

---------

Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>
Co-authored-by: boushi1111 <95118141+boushi1111@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
united-pooh pushed a commit to united-pooh/AstrBot that referenced this pull request Feb 19, 2026
* Fix TypeError when MCP schema type is a list

Fixes crash in Gemini native tools with VRChat MCP.

* Refactor: avoid modifying schema in place per feedback

* Fix formatting and cleanup comments
miaoxutao123 pushed a commit to miaoxutao123/AstrBot that referenced this pull request Feb 28, 2026
* 默认host修改为::,同时新增两个环境变量DASHBOARD_HOST,DASHBOARD_ENABLE,和DASHBOARD_PORT对齐

* feat: systemd support (AstrBotDevs#4880)

* fix: pyright lint (AstrBotDevs#4874)

* feat: 将 MessageSession 的 platform_id 改为 init=False,实例化时无需传入

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 将 isinstance 检查改为元组、将默认模型值设为空字符串、将类型注解改为 Any 并导入

* refactor: 为 _serialize_job 增加返回类型注解 dict

* fix: 使用 cast 获取百度 AIP 的 msg 并对 psutil_addr 引入 type: ignore

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 引入 _AddrWithPort 协议并替换 conn.laddr 的 cast

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: 在构建 AstrBotMessage 时对 ctx.channel 可能为 None 进行兜底处理

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

---------

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: TypeError when MCP schema type is a list (AstrBotDevs#4867)

* Fix TypeError when MCP schema type is a list

Fixes crash in Gemini native tools with VRChat MCP.

* Refactor: avoid modifying schema in place per feedback

* Fix formatting and cleanup comments

* docs: update watashiwakoseinodesukara

Removed duplicate text and added a new image.

* 修复/跨平台一致性

* 琐事/类型标注和一些简单错误修正

* 修复/检查端口时候包含ipv6

* 修复/enable变量的赋值逻辑

---------

Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>
Co-authored-by: boushi1111 <95118141+boushi1111@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend lgtm This PR has been approved by a maintainer size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants