Skip to content

Commit f38519c

Browse files
authored
Merge pull request modelcontextprotocol#15 from major/main
Fix place_first_triggers_second_order with nested JSON
2 parents 2d2c20e + ef655a9 commit f38519c

File tree

3 files changed

+35
-5
lines changed

3 files changed

+35
-5
lines changed

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,23 @@ info/
4747

4848
# Environment files
4949
.env
50+
51+
# Python
52+
__pycache__/
53+
*.py[cod]
54+
*$py.class
55+
*.so
56+
.Python
57+
.venv
58+
venv/
59+
ENV/
60+
env/
61+
*.egg
62+
*.egg-info/
63+
dist/
64+
build/
65+
.pytest_cache/
66+
.coverage
67+
htmlcov/
68+
.mypy_cache/
69+
.ruff_cache/

src/schwab_mcp/tools/orders.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Annotated, Any, cast
44

5+
import copy
56
import datetime
67
from mcp.server.fastmcp import FastMCP
78
from schwab.orders.common import first_triggers_second as trigger_builder
@@ -464,11 +465,10 @@ async def place_first_triggers_second_order(
464465
context: SchwabServerContext = ctx.request_context.lifespan_context
465466
client = context.orders
466467

467-
trigger_order_spec = (
468-
first_order_spec.copy()
469-
) # Avoid modifying the original input dict
468+
# Use deep copy to avoid any reference issues with nested structures
469+
trigger_order_spec = copy.deepcopy(first_order_spec)
470470
trigger_order_spec["orderStrategyType"] = "TRIGGER"
471-
trigger_order_spec["childOrderStrategies"] = [second_order_spec]
471+
trigger_order_spec["childOrderStrategies"] = [copy.deepcopy(second_order_spec)]
472472

473473
# Place the order
474474
return await call(

src/schwab_mcp/tools/utils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,17 @@ async def call(func: Callable[..., Awaitable[Any]], *args: Any, **kwargs: Any) -
1414
response = await func(*args, **kwargs)
1515
response.raise_for_status()
1616

17-
if getattr(response, "status_code", None) == 204:
17+
# Handle responses with no content
18+
# 204 No Content: explicit no-content response
19+
# 201 Created: order placement endpoints return empty body with Location header
20+
status_code = getattr(response, "status_code", None)
21+
if status_code in (201, 204):
22+
return None
23+
24+
# Check if response has content before trying to parse JSON
25+
# Some endpoints (like place_order) return empty bodies even with 2xx status
26+
content = getattr(response, "content", b"")
27+
if not content or len(content) == 0:
1828
return None
1929

2030
try:

0 commit comments

Comments
 (0)