plotext-plus 1.0.8__py3-none-any.whl → 1.0.9__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.
- plotext_plus/mcp_server.py +210 -15
- {plotext_plus-1.0.8.dist-info → plotext_plus-1.0.9.dist-info}/METADATA +1 -1
- {plotext_plus-1.0.8.dist-info → plotext_plus-1.0.9.dist-info}/RECORD +6 -6
- {plotext_plus-1.0.8.dist-info → plotext_plus-1.0.9.dist-info}/WHEEL +0 -0
- {plotext_plus-1.0.8.dist-info → plotext_plus-1.0.9.dist-info}/entry_points.txt +0 -0
- {plotext_plus-1.0.8.dist-info → plotext_plus-1.0.9.dist-info}/licenses/LICENSE +0 -0
plotext_plus/mcp_server.py
CHANGED
|
@@ -71,11 +71,15 @@ async def scatter_plot(x: List[Union[int, float]], y: List[Union[int, float]],
|
|
|
71
71
|
Returns:
|
|
72
72
|
The rendered plot as text
|
|
73
73
|
"""
|
|
74
|
+
# Convert string inputs to float
|
|
75
|
+
x_numeric = [float(val) if isinstance(val, str) else val for val in x]
|
|
76
|
+
y_numeric = [float(val) if isinstance(val, str) else val for val in y]
|
|
77
|
+
|
|
74
78
|
plotting.clear_figure()
|
|
75
79
|
if title:
|
|
76
80
|
plotting.title(title)
|
|
77
81
|
|
|
78
|
-
_, output = _capture_plot_output(plotting.scatter,
|
|
82
|
+
_, output = _capture_plot_output(plotting.scatter, x_numeric, y_numeric, marker=marker, color=color)
|
|
79
83
|
_, show_output = _capture_plot_output(plotting.show)
|
|
80
84
|
|
|
81
85
|
return output + show_output
|
|
@@ -95,14 +99,41 @@ async def line_plot(x: List[Union[int, float]], y: List[Union[int, float]],
|
|
|
95
99
|
Returns:
|
|
96
100
|
The rendered plot as text
|
|
97
101
|
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
plotting.title(title)
|
|
102
|
+
import sys
|
|
103
|
+
print(f"DEBUG: line_plot called with x={x}, y={y}, title={title}", file=sys.stderr)
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
# Convert string inputs to float
|
|
106
|
+
try:
|
|
107
|
+
x_numeric = [float(val) if isinstance(val, str) else val for val in x]
|
|
108
|
+
y_numeric = [float(val) if isinstance(val, str) else val for val in y]
|
|
109
|
+
print(f"DEBUG: Converted to x_numeric={x_numeric}, y_numeric={y_numeric}", file=sys.stderr)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
print(f"DEBUG: Error converting inputs: {e}", file=sys.stderr)
|
|
112
|
+
raise
|
|
104
113
|
|
|
105
|
-
|
|
114
|
+
try:
|
|
115
|
+
plotting.clear_figure()
|
|
116
|
+
print("DEBUG: Cleared figure", file=sys.stderr)
|
|
117
|
+
|
|
118
|
+
if title:
|
|
119
|
+
plotting.title(title)
|
|
120
|
+
print(f"DEBUG: Set title: {title}", file=sys.stderr)
|
|
121
|
+
|
|
122
|
+
_, output = _capture_plot_output(plotting.plot, x_numeric, y_numeric, color=color)
|
|
123
|
+
print(f"DEBUG: Generated plot output, length: {len(output)}", file=sys.stderr)
|
|
124
|
+
|
|
125
|
+
_, show_output = _capture_plot_output(plotting.show)
|
|
126
|
+
print(f"DEBUG: Generated show output, length: {len(show_output)}", file=sys.stderr)
|
|
127
|
+
|
|
128
|
+
result = output + show_output
|
|
129
|
+
print(f"DEBUG: Returning result, total length: {len(result)}", file=sys.stderr)
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
except Exception as e:
|
|
133
|
+
print(f"DEBUG: Error during plotting: {e}", file=sys.stderr)
|
|
134
|
+
import traceback
|
|
135
|
+
traceback.print_exc(file=sys.stderr)
|
|
136
|
+
raise
|
|
106
137
|
|
|
107
138
|
|
|
108
139
|
@tool
|
|
@@ -119,11 +150,14 @@ async def bar_chart(labels: List[str], values: List[Union[int, float]],
|
|
|
119
150
|
Returns:
|
|
120
151
|
The rendered plot as text
|
|
121
152
|
"""
|
|
153
|
+
# Convert string inputs to float
|
|
154
|
+
values_numeric = [float(val) if isinstance(val, str) else val for val in values]
|
|
155
|
+
|
|
122
156
|
plotting.clear_figure()
|
|
123
157
|
if title:
|
|
124
158
|
plotting.title(title)
|
|
125
159
|
|
|
126
|
-
_, output = _capture_plot_output(plotting.bar, labels,
|
|
160
|
+
_, output = _capture_plot_output(plotting.bar, labels, values_numeric, color=color)
|
|
127
161
|
_, show_output = _capture_plot_output(plotting.show)
|
|
128
162
|
|
|
129
163
|
return output + show_output
|
|
@@ -212,7 +246,11 @@ async def quick_scatter(x: List[Union[int, float]], y: List[Union[int, float]],
|
|
|
212
246
|
Returns:
|
|
213
247
|
The rendered chart as text
|
|
214
248
|
"""
|
|
215
|
-
|
|
249
|
+
# Convert string inputs to float
|
|
250
|
+
x_numeric = [float(val) if isinstance(val, str) else val for val in x]
|
|
251
|
+
y_numeric = [float(val) if isinstance(val, str) else val for val in y]
|
|
252
|
+
|
|
253
|
+
_, output = _capture_plot_output(charts.quick_scatter, x_numeric, y_numeric, title=title, theme=theme_name)
|
|
216
254
|
return output
|
|
217
255
|
|
|
218
256
|
|
|
@@ -230,7 +268,11 @@ async def quick_line(x: List[Union[int, float]], y: List[Union[int, float]],
|
|
|
230
268
|
Returns:
|
|
231
269
|
The rendered chart as text
|
|
232
270
|
"""
|
|
233
|
-
|
|
271
|
+
# Convert string inputs to float
|
|
272
|
+
x_numeric = [float(val) if isinstance(val, str) else val for val in x]
|
|
273
|
+
y_numeric = [float(val) if isinstance(val, str) else val for val in y]
|
|
274
|
+
|
|
275
|
+
_, output = _capture_plot_output(charts.quick_line, x_numeric, y_numeric, title=title, theme=theme_name)
|
|
234
276
|
return output
|
|
235
277
|
|
|
236
278
|
|
|
@@ -248,7 +290,10 @@ async def quick_bar(labels: List[str], values: List[Union[int, float]],
|
|
|
248
290
|
Returns:
|
|
249
291
|
The rendered chart as text
|
|
250
292
|
"""
|
|
251
|
-
|
|
293
|
+
# Convert string inputs to float
|
|
294
|
+
values_numeric = [float(val) if isinstance(val, str) else val for val in values]
|
|
295
|
+
|
|
296
|
+
_, output = _capture_plot_output(charts.quick_bar, labels, values_numeric, title=title, theme=theme_name)
|
|
252
297
|
return output
|
|
253
298
|
|
|
254
299
|
|
|
@@ -274,7 +319,10 @@ async def quick_pie(labels: List[str], values: List[Union[int, float]],
|
|
|
274
319
|
Returns:
|
|
275
320
|
The rendered pie chart as text
|
|
276
321
|
"""
|
|
277
|
-
|
|
322
|
+
# Convert string inputs to float
|
|
323
|
+
values_numeric = [float(val) if isinstance(val, str) else val for val in values]
|
|
324
|
+
|
|
325
|
+
_, output = _capture_plot_output(charts.quick_pie, labels, values_numeric, colors=colors,
|
|
278
326
|
title=title, show_values=show_values,
|
|
279
327
|
show_percentages=show_percentages,
|
|
280
328
|
show_values_on_slices=show_values_on_slices,
|
|
@@ -303,7 +351,10 @@ async def quick_donut(labels: List[str], values: List[Union[int, float]],
|
|
|
303
351
|
Returns:
|
|
304
352
|
The rendered doughnut chart as text
|
|
305
353
|
"""
|
|
306
|
-
|
|
354
|
+
# Convert string inputs to float
|
|
355
|
+
values_numeric = [float(val) if isinstance(val, str) else val for val in values]
|
|
356
|
+
|
|
357
|
+
_, output = _capture_plot_output(charts.quick_donut, labels, values_numeric, colors=colors,
|
|
307
358
|
title=title, show_values=show_values,
|
|
308
359
|
show_percentages=show_percentages,
|
|
309
360
|
show_values_on_slices=show_values_on_slices,
|
|
@@ -803,8 +854,152 @@ async def quick_donut_convenience_prompt() -> str:
|
|
|
803
854
|
# Main server entry point
|
|
804
855
|
def start_server():
|
|
805
856
|
"""Start the MCP server."""
|
|
806
|
-
|
|
807
|
-
|
|
857
|
+
import sys
|
|
858
|
+
import os
|
|
859
|
+
|
|
860
|
+
# Check if we're being run in STDIO mode (by MCP CLI)
|
|
861
|
+
# Force HTTP mode if MCP_HTTP_MODE is set, otherwise detect based on stdin
|
|
862
|
+
force_http = os.getenv('MCP_HTTP_MODE', '').lower() == 'true'
|
|
863
|
+
force_stdio = os.getenv('MCP_STDIO_MODE', '').lower() == 'true'
|
|
864
|
+
|
|
865
|
+
if force_http:
|
|
866
|
+
is_stdio_mode = False
|
|
867
|
+
elif force_stdio:
|
|
868
|
+
is_stdio_mode = True
|
|
869
|
+
else:
|
|
870
|
+
# Auto-detect: STDIO mode when stdin is not a terminal (pipes/redirects)
|
|
871
|
+
is_stdio_mode = not sys.stdin.isatty()
|
|
872
|
+
|
|
873
|
+
if is_stdio_mode:
|
|
874
|
+
# STDIO mode for MCP CLI - simple JSON-RPC implementation
|
|
875
|
+
import json
|
|
876
|
+
import asyncio
|
|
877
|
+
|
|
878
|
+
async def handle_stdio():
|
|
879
|
+
try:
|
|
880
|
+
for line in sys.stdin:
|
|
881
|
+
if not line.strip():
|
|
882
|
+
continue
|
|
883
|
+
|
|
884
|
+
try:
|
|
885
|
+
request = json.loads(line)
|
|
886
|
+
method = request.get('method')
|
|
887
|
+
request_id = request.get('id')
|
|
888
|
+
|
|
889
|
+
if method == 'initialize':
|
|
890
|
+
response = {
|
|
891
|
+
"jsonrpc": "2.0",
|
|
892
|
+
"id": request_id,
|
|
893
|
+
"result": {
|
|
894
|
+
"protocolVersion": "2024-11-05",
|
|
895
|
+
"capabilities": {
|
|
896
|
+
"tools": {},
|
|
897
|
+
"prompts": {},
|
|
898
|
+
"resources": {}
|
|
899
|
+
},
|
|
900
|
+
"serverInfo": {
|
|
901
|
+
"name": "Plotext Plus MCP Server",
|
|
902
|
+
"version": "1.0.0"
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
elif method == 'tools/list':
|
|
907
|
+
response = {
|
|
908
|
+
"jsonrpc": "2.0",
|
|
909
|
+
"id": request_id,
|
|
910
|
+
"result": {
|
|
911
|
+
"tools": [
|
|
912
|
+
{
|
|
913
|
+
"name": "line_plot",
|
|
914
|
+
"description": "Create a line plot with given x and y data points",
|
|
915
|
+
"inputSchema": {
|
|
916
|
+
"type": "object",
|
|
917
|
+
"properties": {
|
|
918
|
+
"x": {"type": "array", "items": {"type": "number"}},
|
|
919
|
+
"y": {"type": "array", "items": {"type": "number"}},
|
|
920
|
+
"title": {"type": "string"}
|
|
921
|
+
},
|
|
922
|
+
"required": ["x", "y"]
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
]
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
elif method == 'tools/call':
|
|
929
|
+
tool_name = request['params']['name']
|
|
930
|
+
arguments = request['params']['arguments']
|
|
931
|
+
|
|
932
|
+
if tool_name == 'line_plot':
|
|
933
|
+
try:
|
|
934
|
+
result = await line_plot(**arguments)
|
|
935
|
+
response = {
|
|
936
|
+
"jsonrpc": "2.0",
|
|
937
|
+
"id": request_id,
|
|
938
|
+
"result": {
|
|
939
|
+
"content": [
|
|
940
|
+
{
|
|
941
|
+
"type": "text",
|
|
942
|
+
"text": result
|
|
943
|
+
}
|
|
944
|
+
]
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
except Exception as e:
|
|
948
|
+
response = {
|
|
949
|
+
"jsonrpc": "2.0",
|
|
950
|
+
"id": request_id,
|
|
951
|
+
"error": {
|
|
952
|
+
"code": -32000,
|
|
953
|
+
"message": str(e)
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
else:
|
|
957
|
+
response = {
|
|
958
|
+
"jsonrpc": "2.0",
|
|
959
|
+
"id": request_id,
|
|
960
|
+
"error": {
|
|
961
|
+
"code": -32601,
|
|
962
|
+
"message": f"Unknown tool: {tool_name}"
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
else:
|
|
966
|
+
response = {
|
|
967
|
+
"jsonrpc": "2.0",
|
|
968
|
+
"id": request_id,
|
|
969
|
+
"error": {
|
|
970
|
+
"code": -32601,
|
|
971
|
+
"message": f"Unknown method: {method}"
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
print(json.dumps(response), flush=True)
|
|
976
|
+
|
|
977
|
+
except Exception as e:
|
|
978
|
+
error_response = {
|
|
979
|
+
"jsonrpc": "2.0",
|
|
980
|
+
"id": request.get('id') if 'request' in locals() else None,
|
|
981
|
+
"error": {
|
|
982
|
+
"code": -32700,
|
|
983
|
+
"message": f"Parse error: {str(e)}"
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
print(json.dumps(error_response), flush=True)
|
|
987
|
+
|
|
988
|
+
except Exception as e:
|
|
989
|
+
print(f"STDIO handler error: {e}", file=sys.stderr)
|
|
990
|
+
|
|
991
|
+
asyncio.run(handle_stdio())
|
|
992
|
+
else:
|
|
993
|
+
# HTTP server mode (default)
|
|
994
|
+
print("Starting Plotext Plus MCP Server...")
|
|
995
|
+
from chuk_mcp_server import ChukMCPServer
|
|
996
|
+
server = ChukMCPServer(
|
|
997
|
+
name="Plotext Plus MCP Server",
|
|
998
|
+
version="1.0.0",
|
|
999
|
+
prompts=True, # Enable prompts capability
|
|
1000
|
+
logging=True # Enable logging capability for MCP clients
|
|
1001
|
+
)
|
|
1002
|
+
server.run()
|
|
808
1003
|
|
|
809
1004
|
|
|
810
1005
|
if __name__ == "__main__":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plotext_plus
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.9
|
|
4
4
|
Summary: Modern terminal plotting library with enhanced visual features, themes, and AI integration
|
|
5
5
|
Project-URL: Homepage, https://github.com/ccmitchellusa/plotext_plus
|
|
6
6
|
Project-URL: Repository, https://github.com/ccmitchellusa/plotext_plus.git
|
|
@@ -20,14 +20,14 @@ plotext_plus/api.py,sha256=56xYn9uzkMe88iELbanRQ-12bC8Rvv2Jk0BX45Fk8zY,28424
|
|
|
20
20
|
plotext_plus/charts.py,sha256=VfL0keEo02TPwjUZ6eNFx2q2qOTpiVoq_igL5rGE-gY,1315
|
|
21
21
|
plotext_plus/core.py,sha256=k6g2dYuHFcNevLJM0elkYupz7fC8Qqk_vLEyrXu2V3I,20668
|
|
22
22
|
plotext_plus/mcp_cli.py,sha256=otZaP1tolvAL2vx84TVNiTlFdJyDx1cMIMcbhqsSna8,2651
|
|
23
|
-
plotext_plus/mcp_server.py,sha256=
|
|
23
|
+
plotext_plus/mcp_server.py,sha256=cL-6CL3nQ53LbC3ZReC77_zxFrRVA8UgqQEqNRakaXI,37130
|
|
24
24
|
plotext_plus/plotext_cli.py,sha256=o3JmSNc7Ify4C6Wkva8x8QRh-pLeiD3VArc3E78xlVU,17677
|
|
25
25
|
plotext_plus/plotting.py,sha256=7YUISs2Aolqo-lMEX8amGfMNOSFV9zcSqlrEMwVK2RM,2063
|
|
26
26
|
plotext_plus/themes.py,sha256=xX6XqL2U-7MQmv-k1HU-UTSZRbTfv9op5_4ZRXm435g,725
|
|
27
27
|
plotext_plus/utilities.py,sha256=scdPDGf6po2rvEL5DX7y1pY41uxlCXTVVIo0w5qA8JE,1170
|
|
28
28
|
plotext_plus/utils.py,sha256=NFEupN17WY2Xk4EgDY-On_1J3MOvwNBYubnt6Rg8QW4,15387
|
|
29
|
-
plotext_plus-1.0.
|
|
30
|
-
plotext_plus-1.0.
|
|
31
|
-
plotext_plus-1.0.
|
|
32
|
-
plotext_plus-1.0.
|
|
33
|
-
plotext_plus-1.0.
|
|
29
|
+
plotext_plus-1.0.9.dist-info/METADATA,sha256=mMcu8ukY6WNT9L86-ROTSG9-PVhxTi2ENtP2owMLtmE,11355
|
|
30
|
+
plotext_plus-1.0.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
31
|
+
plotext_plus-1.0.9.dist-info/entry_points.txt,sha256=XocAh2z8hTGtuQL1zEcGTulrgfZ2g5UMyHSV-JOSNN8,103
|
|
32
|
+
plotext_plus-1.0.9.dist-info/licenses/LICENSE,sha256=MkgUiRFwIvXwUVDEPy11uIULq7pGDHpIulD4KulsjnM,1150
|
|
33
|
+
plotext_plus-1.0.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|