Skip to content

Commit 48aa2ca

Browse files
authored
Merge pull request #63 from wouterken/fix/escape_double_quotes_in_compiled_tool_descriptions
Escape double quotes inside compiled code description strings
2 parents c9bfadf + 4704c7d commit 48aa2ca

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

nerve/tools/mcp/compiler.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ async def create_function_body(client: Client, mcp_tool: Tool) -> tuple[str, dic
9191
for name, arg_props in mcp_tool.inputSchema.get("properties", {}).items():
9292
# print(name, arg_props)
9393
args_def, arg_type = _get_python_type(name, arg_props)
94-
arg = {"name": name, "type": _stringify_type(arg_type), "description": arg_props.get("description", "")}
94+
arg = {
95+
"name": name,
96+
"type": _stringify_type(arg_type),
97+
"description": arg_props.get("description", "").replace('\\', '\\\\').replace('"', '\\"'),
98+
}
9599

96100
if args_def:
97101
type_defs.update(args_def)

nerve/tools/mcp/compiler_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,29 @@ async def process_data(user: Annotated[user_0, "User information"], settings: An
200200
'''.strip(),
201201
func_body,
202202
)
203+
204+
async def test_create_function_body_double_quotes_inside_description(self) -> None:
205+
client = MagicMock(spec=Client)
206+
207+
mock_tool = Tool(
208+
name="test_state_tool",
209+
description="A tool to test default string handling.",
210+
inputSchema={
211+
"type": "object",
212+
"properties": {
213+
"state": {
214+
"type": "string",
215+
"description": "The state of the \"entity\".",
216+
"default": "open", # This default value could be misinterpreted as the 'open' function.
217+
},
218+
},
219+
},
220+
)
221+
222+
func_body, type_defs = await create_function_body(client, mock_tool)
223+
224+
# Default value to be correctly quoted as a string literal: 'open'
225+
self.assertIn(
226+
"""async def test_state_tool(state: Annotated[str, "The state of the \\\"entity\\\"."] = 'open') -> Any:""",
227+
func_body,
228+
)

0 commit comments

Comments
 (0)