eulerian-marketing-platform 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ This package provides a Model Context Protocol (MCP) server that enables
4
4
  AI assistants to interact with Eulerian Marketing Platform APIs.
5
5
  """
6
6
 
7
- __version__ = "0.2.3"
7
+ __version__ = "0.2.5"
8
8
  __author__ = "Eulerian Technologies"
9
9
  __all__ = []
10
10
 
@@ -74,12 +74,13 @@ def forward_request(request_data: dict) -> dict:
74
74
  request_data: The JSON-RPC request to forward
75
75
 
76
76
  Returns:
77
- The JSON-RPC response from the remote server
77
+ The JSON-RPC response from the remote server, or None for notifications
78
78
  """
79
79
  timeout = float(os.environ.get("EMP_TIMEOUT", "300"))
80
80
 
81
81
  request_id = request_data.get("id")
82
82
  method = request_data.get("method")
83
+ is_notification = request_id is None
83
84
 
84
85
  logger.info(f">>> REQUEST: {method} (id: {request_id})")
85
86
  logger.debug(f" Full request: {json.dumps(request_data)[:200]}...")
@@ -100,10 +101,30 @@ def forward_request(request_data: dict) -> dict:
100
101
 
101
102
  logger.info(f"<<< RESPONSE: HTTP {response.status_code}")
102
103
 
104
+ # Handle HTTP 204 No Content (proper response for notifications)
105
+ if response.status_code == 204:
106
+ logger.info(" HTTP 204 No Content - notification acknowledged")
107
+ # For notifications, this is expected and correct
108
+ if is_notification:
109
+ logger.info(" Notification processed - no response sent")
110
+ return None
111
+ else:
112
+ # For regular requests, 204 is unusual but we'll treat it as success with empty result
113
+ return {
114
+ "jsonrpc": "2.0",
115
+ "id": request_id,
116
+ "result": None
117
+ }
118
+
103
119
  if response.status_code != 200:
104
120
  error_msg = f"HTTP {response.status_code}: {response.reason_phrase}"
105
121
  logger.error(f" Error: {response.text[:200]}")
106
122
 
123
+ # For notifications, don't return error responses
124
+ if is_notification:
125
+ logger.info(" Notification error - no response sent")
126
+ return None
127
+
107
128
  return {
108
129
  "jsonrpc": "2.0",
109
130
  "id": request_id,
@@ -113,11 +134,17 @@ def forward_request(request_data: dict) -> dict:
113
134
  }
114
135
  }
115
136
 
116
- # Parse response
137
+ # Parse response (only for HTTP 200 responses)
117
138
  try:
118
139
  response_data = response.json()
119
140
  logger.debug(f" Response: {json.dumps(response_data)[:200]}...")
120
141
 
142
+ # For notifications, we should not send back any response, regardless of what the remote server returns
143
+ if is_notification:
144
+ logger.info(f" Notification received response from server: {json.dumps(response_data)}")
145
+ logger.info(" Notification processed - no response sent")
146
+ return None
147
+
121
148
  # Validate JSON-RPC response
122
149
  if "jsonrpc" not in response_data:
123
150
  logger.warning(" WARNING: Missing 'jsonrpc' field")
@@ -131,6 +158,12 @@ def forward_request(request_data: dict) -> dict:
131
158
 
132
159
  except json.JSONDecodeError as e:
133
160
  logger.error(f" ERROR: Invalid JSON - {e}")
161
+
162
+ # For notifications, don't return error responses
163
+ if is_notification:
164
+ logger.info(" Notification JSON error - no response sent")
165
+ return None
166
+
134
167
  return {
135
168
  "jsonrpc": "2.0",
136
169
  "id": request_id,
@@ -142,6 +175,12 @@ def forward_request(request_data: dict) -> dict:
142
175
 
143
176
  except httpx.TimeoutException:
144
177
  logger.error("ERROR: Request timeout")
178
+
179
+ # For notifications, don't return error responses
180
+ if is_notification:
181
+ logger.info(" Notification timeout - no response sent")
182
+ return None
183
+
145
184
  return {
146
185
  "jsonrpc": "2.0",
147
186
  "id": request_id,
@@ -153,6 +192,12 @@ def forward_request(request_data: dict) -> dict:
153
192
 
154
193
  except httpx.RequestError as e:
155
194
  logger.error(f"ERROR: Request failed - {str(e)}")
195
+
196
+ # For notifications, don't return error responses
197
+ if is_notification:
198
+ logger.info(" Notification request error - no response sent")
199
+ return None
200
+
156
201
  return {
157
202
  "jsonrpc": "2.0",
158
203
  "id": request_id,
@@ -166,6 +211,12 @@ def forward_request(request_data: dict) -> dict:
166
211
  logger.error(f"ERROR: Unexpected error - {str(e)}")
167
212
  import traceback
168
213
  logger.error(f"Traceback: {traceback.format_exc()}")
214
+
215
+ # For notifications, don't return error responses
216
+ if is_notification:
217
+ logger.info(" Notification unexpected error - no response sent")
218
+ return None
219
+
169
220
  return {
170
221
  "jsonrpc": "2.0",
171
222
  "id": request_id,
@@ -216,14 +267,15 @@ def main() -> None:
216
267
  # Forward to remote server
217
268
  response_data = forward_request(request_data)
218
269
 
219
- # JSON-RPC notifications MUST NOT be answered
220
- if "id" in request_data and request_data["id"] is not None:
270
+ # Only send response for non-notifications (when response_data is not None)
271
+ if response_data is not None:
221
272
  response_json = json.dumps(response_data)
222
273
  print(response_json, flush=True)
223
274
  sys.stdout.flush()
224
275
  logger.info(" Response forwarded [OK]")
225
276
  else:
226
- logger.info(" Notification forwarded (no response sent)")
277
+ logger.info(" Notification processed (no response sent)")
278
+
227
279
  except json.JSONDecodeError as e:
228
280
  logger.error(f"ERROR: Invalid JSON in request - {e}")
229
281
  logger.error(f" Problematic line: {line[:200]}")
@@ -279,4 +331,3 @@ def main() -> None:
279
331
 
280
332
  if __name__ == "__main__":
281
333
  main()
282
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eulerian-marketing-platform
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: MCP server for Eulerian Marketing Platform - enables AI assistants to interact with Eulerian's marketing analytics and campaign management APIs
5
5
  Author-email: Eulerian Technologies <mathieu@eulerian.com>
6
6
  License: MIT
@@ -385,6 +385,9 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
385
385
 
386
386
  ## Changelog
387
387
 
388
+ ### 0.2.3
389
+ - fixes disconnection issue with notifications
390
+
388
391
  ### 0.2.0
389
392
  - Move to full Proxy mode
390
393
  - Remove instructions for uvx deployment
@@ -0,0 +1,8 @@
1
+ eulerian_marketing_platform/__init__.py,sha256=Vy3v2bzqOBm-2QuGgb87QkLjojhqRDvzRTeNPqVMaOE,428
2
+ eulerian_marketing_platform/server.py,sha256=3Iz8fZCug6DnvI1pd3o5Ilbvcu61Zb9KpnLXYjZs0Yk,12119
3
+ eulerian_marketing_platform-0.2.5.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
+ eulerian_marketing_platform-0.2.5.dist-info/METADATA,sha256=lmDkaF4qVTcsHgM3Yw20d7xCjPRw8M-eVlD1eerYkTU,12169
5
+ eulerian_marketing_platform-0.2.5.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
+ eulerian_marketing_platform-0.2.5.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
+ eulerian_marketing_platform-0.2.5.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
+ eulerian_marketing_platform-0.2.5.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- eulerian_marketing_platform/__init__.py,sha256=O0u23icj5NMvBhcwSNHDYh5L2yN-K64g9fS1nQ9s8l0,428
2
- eulerian_marketing_platform/server.py,sha256=xE1SiUUivym38KenUAblKVaKzXLZh5gnkPCY4c665wg,9891
3
- eulerian_marketing_platform-0.2.3.dist-info/LICENSE,sha256=eIqBqE_fRsqQJ8F-2v0e-8WzZqdshsCqnzmqLAWrNHU,1078
4
- eulerian_marketing_platform-0.2.3.dist-info/METADATA,sha256=JAVCiUo1zTO3F9fTjyYDE5hi9MgpPY2EhlmGQxirzKU,12111
5
- eulerian_marketing_platform-0.2.3.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
6
- eulerian_marketing_platform-0.2.3.dist-info/entry_points.txt,sha256=rrPZptATSS9PUtH9gzCYq0WuP6eahkF-DkdUP1FaYfk,88
7
- eulerian_marketing_platform-0.2.3.dist-info/top_level.txt,sha256=nidh3T6fw-mLjUqZwQ8AiMScS4usuH0WXW4ZgG4HYCo,28
8
- eulerian_marketing_platform-0.2.3.dist-info/RECORD,,