fix: accept both string and dict for body/params in n8n_api_call
All checks were successful
Build and Push n8n MCP Docker Image / build (push) Successful in 19s
All checks were successful
Build and Push n8n MCP Docker Image / build (push) Successful in 19s
Handle the case where MCP clients may pass JSON as either a string or dict object. Adds _normalize_json_param helper to handle both formats gracefully, preventing Pydantic validation errors.
This commit is contained in:
37
server.py
37
server.py
@@ -338,12 +338,34 @@ async def trigger_webhook(
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_json_param(value: str | dict[str, Any] | None) -> dict[str, Any]:
|
||||||
|
"""Normalize a parameter that can be either a JSON string or a dict.
|
||||||
|
|
||||||
|
This handles the case where MCP clients may pass either:
|
||||||
|
- A JSON string: '{"key": "value"}'
|
||||||
|
- A dict object: {"key": "value"}
|
||||||
|
"""
|
||||||
|
if value is None:
|
||||||
|
return {}
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return value
|
||||||
|
if isinstance(value, str):
|
||||||
|
if not value or value == "{}":
|
||||||
|
return {}
|
||||||
|
try:
|
||||||
|
parsed = json.loads(value)
|
||||||
|
return parsed if isinstance(parsed, dict) else {}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return {}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
@mcp.tool()
|
@mcp.tool()
|
||||||
async def n8n_api_call(
|
async def n8n_api_call(
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
method: str = "GET",
|
method: str = "GET",
|
||||||
params: str = "{}",
|
params: str | dict[str, Any] | None = None,
|
||||||
body: str = "{}",
|
body: str | dict[str, Any] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Execute a raw API call to n8n.
|
"""Execute a raw API call to n8n.
|
||||||
|
|
||||||
@@ -353,8 +375,8 @@ async def n8n_api_call(
|
|||||||
Args:
|
Args:
|
||||||
endpoint: API endpoint path (e.g., '/workflows', '/credentials')
|
endpoint: API endpoint path (e.g., '/workflows', '/credentials')
|
||||||
method: HTTP method (GET, POST, PUT, PATCH, DELETE)
|
method: HTTP method (GET, POST, PUT, PATCH, DELETE)
|
||||||
params: JSON string of query parameters (optional)
|
params: Query parameters as JSON string or dict (optional)
|
||||||
body: JSON string of request body for POST/PUT/PATCH (optional)
|
body: Request body as JSON string or dict for POST/PUT/PATCH (optional)
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
- Create workflow: n8n_api_call('/workflows', 'POST', body='{"name": "My Workflow", "nodes": [...], "connections": {...}}')
|
- Create workflow: n8n_api_call('/workflows', 'POST', body='{"name": "My Workflow", "nodes": [...], "connections": {...}}')
|
||||||
@@ -362,11 +384,8 @@ async def n8n_api_call(
|
|||||||
- List credentials: n8n_api_call('/credentials')
|
- List credentials: n8n_api_call('/credentials')
|
||||||
- Create tag: n8n_api_call('/tags', 'POST', body='{"name": "production"}')
|
- Create tag: n8n_api_call('/tags', 'POST', body='{"name": "production"}')
|
||||||
"""
|
"""
|
||||||
try:
|
params_dict = _normalize_json_param(params)
|
||||||
params_dict = json.loads(params) if params else {}
|
body_dict = _normalize_json_param(body)
|
||||||
body_dict = json.loads(body) if body else {}
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
return json.dumps({"error": True, "message": f"Invalid JSON: {e}"})
|
|
||||||
|
|
||||||
result = await client.request(
|
result = await client.request(
|
||||||
method=method,
|
method=method,
|
||||||
|
|||||||
Reference in New Issue
Block a user