loadbench-mcp 0.1.0__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.
load_solver/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
load_solver/server.py
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Load solver — an MCP server that does the structural math LLMs get wrong.
|
|
3
|
+
|
|
4
|
+
Three tools:
|
|
5
|
+
- check_tipping : will a set of weights tip over its support footprint?
|
|
6
|
+
- solve_supports : how much load does each leg / bracket carry?
|
|
7
|
+
- beam_check : will this beam / shelf hold the load? (stress + deflection)
|
|
8
|
+
|
|
9
|
+
Run locally: uv run server.py
|
|
10
|
+
Test the math: python test_physics.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import Literal
|
|
14
|
+
import math
|
|
15
|
+
import numpy as np
|
|
16
|
+
from mcp.server.fastmcp import FastMCP
|
|
17
|
+
|
|
18
|
+
mcp = FastMCP("load-solver")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ----------------------------------------------------------------------------
|
|
22
|
+
# Geometry / physics helpers (plain functions, unit-tested in test_physics.py)
|
|
23
|
+
# ----------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
def _centroid(points):
|
|
26
|
+
"""Mass-weighted centre of mass of [{x, y, mass}, ...]. Returns (cx, cy, total_mass)."""
|
|
27
|
+
total = sum(p["mass"] for p in points)
|
|
28
|
+
if total <= 0:
|
|
29
|
+
raise ValueError("total mass must be positive")
|
|
30
|
+
cx = sum(p["mass"] * p["x"] for p in points) / total
|
|
31
|
+
cy = sum(p["mass"] * p["y"] for p in points) / total
|
|
32
|
+
return cx, cy, total
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _point_in_polygon(px, py, poly):
|
|
36
|
+
"""Ray-casting test. poly = [{x, y}, ...] in order. Works for any simple polygon."""
|
|
37
|
+
inside = False
|
|
38
|
+
n = len(poly)
|
|
39
|
+
j = n - 1
|
|
40
|
+
for i in range(n):
|
|
41
|
+
xi, yi = poly[i]["x"], poly[i]["y"]
|
|
42
|
+
xj, yj = poly[j]["x"], poly[j]["y"]
|
|
43
|
+
if ((yi > py) != (yj > py)) and (px < (xj - xi) * (py - yi) / (yj - yi) + xi):
|
|
44
|
+
inside = not inside
|
|
45
|
+
j = i
|
|
46
|
+
return inside
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _dist_point_segment(px, py, ax, ay, bx, by):
|
|
50
|
+
"""Shortest distance from P to segment AB, plus the nearest point on AB."""
|
|
51
|
+
dx, dy = bx - ax, by - ay
|
|
52
|
+
if dx == 0 and dy == 0:
|
|
53
|
+
t = 0.0
|
|
54
|
+
else:
|
|
55
|
+
t = ((px - ax) * dx + (py - ay) * dy) / (dx * dx + dy * dy)
|
|
56
|
+
t = max(0.0, min(1.0, t))
|
|
57
|
+
nx, ny = ax + t * dx, ay + t * dy
|
|
58
|
+
return math.hypot(px - nx, py - ny), nx, ny
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _nearest_boundary(px, py, poly):
|
|
62
|
+
"""Min distance from P to the polygon boundary, and the nearest boundary point."""
|
|
63
|
+
best = (float("inf"), 0.0, 0.0)
|
|
64
|
+
n = len(poly)
|
|
65
|
+
for i in range(n):
|
|
66
|
+
a, b = poly[i], poly[(i + 1) % n]
|
|
67
|
+
d, nx, ny = _dist_point_segment(px, py, a["x"], a["y"], b["x"], b["y"])
|
|
68
|
+
if d < best[0]:
|
|
69
|
+
best = (d, nx, ny)
|
|
70
|
+
return best
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# ----------------------------------------------------------------------------
|
|
74
|
+
# Tool 1 — tip-over check
|
|
75
|
+
# ----------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
@mcp.tool()
|
|
78
|
+
def check_tipping(masses: list[dict], base_polygon: list[dict]) -> dict:
|
|
79
|
+
"""Check whether a collection of weights will tip over its support footprint.
|
|
80
|
+
|
|
81
|
+
Computes the centre of mass and tests whether its vertical projection falls
|
|
82
|
+
inside the support base (the polygon where the object touches the ground).
|
|
83
|
+
If it falls outside, the object tips. Use this for shelving, stacked loads,
|
|
84
|
+
machinery on legs, vehicles, or anything that could topple.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
masses: list of point masses, each {"x": metres, "y": metres, "mass": kg}.
|
|
88
|
+
x/y are top-down (plan-view) positions. Height does not affect whether
|
|
89
|
+
it tips on level ground, only the horizontal centre of mass does.
|
|
90
|
+
base_polygon: the support footprint as ordered vertices [{"x", "y"}, ...]
|
|
91
|
+
in metres (e.g. the four feet of a shelf, or the contact outline).
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
center_of_mass, is_stable (bool), tipping_margin_m (positive = inside the
|
|
95
|
+
base with this much clearance; negative = already outside / tipping),
|
|
96
|
+
tipping_direction (unit vector toward the closest base edge), and a short
|
|
97
|
+
human-readable explanation.
|
|
98
|
+
"""
|
|
99
|
+
if len(base_polygon) < 3:
|
|
100
|
+
raise ValueError("base_polygon needs at least 3 vertices")
|
|
101
|
+
cx, cy, total = _centroid(masses)
|
|
102
|
+
inside = _point_in_polygon(cx, cy, base_polygon)
|
|
103
|
+
dist, nx, ny = _nearest_boundary(cx, cy, base_polygon)
|
|
104
|
+
margin = dist if inside else -dist
|
|
105
|
+
# unit vector from CoM toward the nearest edge (the weak / tip direction)
|
|
106
|
+
vx, vy = nx - cx, ny - cy
|
|
107
|
+
norm = math.hypot(vx, vy) or 1.0
|
|
108
|
+
direction = {"x": round(vx / norm, 4), "y": round(vy / norm, 4)}
|
|
109
|
+
if inside:
|
|
110
|
+
explanation = (
|
|
111
|
+
f"Stable. Centre of mass is inside the support base with "
|
|
112
|
+
f"{margin:.3f} m of clearance to the nearest edge."
|
|
113
|
+
)
|
|
114
|
+
else:
|
|
115
|
+
explanation = (
|
|
116
|
+
f"Tips over. Centre of mass falls {abs(margin):.3f} m outside the "
|
|
117
|
+
f"support base; it will topple toward the indicated direction."
|
|
118
|
+
)
|
|
119
|
+
return {
|
|
120
|
+
"center_of_mass": {"x": round(cx, 4), "y": round(cy, 4)},
|
|
121
|
+
"total_mass_kg": round(total, 4),
|
|
122
|
+
"is_stable": inside,
|
|
123
|
+
"tipping_margin_m": round(margin, 4),
|
|
124
|
+
"tipping_direction": direction,
|
|
125
|
+
"explanation": explanation,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# ----------------------------------------------------------------------------
|
|
130
|
+
# Tool 2 — support reaction forces
|
|
131
|
+
# ----------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
@mcp.tool()
|
|
134
|
+
def solve_supports(
|
|
135
|
+
supports: list[dict],
|
|
136
|
+
loads: list[dict],
|
|
137
|
+
self_weight_n: float = 0.0,
|
|
138
|
+
) -> dict:
|
|
139
|
+
"""Compute how much vertical force each support (leg, bracket, foot) carries.
|
|
140
|
+
|
|
141
|
+
Models a rigid object resting on point supports of equal stiffness and solves
|
|
142
|
+
static equilibrium so the reactions balance every applied load in force and
|
|
143
|
+
moment. Handles any number of supports. Flags supports that exceed their rated
|
|
144
|
+
capacity, and supports with a negative reaction (the object is lifting off /
|
|
145
|
+
would tip rather than rest evenly).
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
supports: [{"id": str, "x": m, "y": m, "capacity_n": N (optional)}].
|
|
149
|
+
loads: downward point loads [{"x": m, "y": m, "magnitude_n": N}].
|
|
150
|
+
self_weight_n: optional self-weight of the object (N), applied at the
|
|
151
|
+
centroid of the supports.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
per-support reaction forces, over-capacity / lift-off flags, total load,
|
|
155
|
+
max utilisation, any warnings, and a short explanation.
|
|
156
|
+
"""
|
|
157
|
+
if len(supports) == 0:
|
|
158
|
+
raise ValueError("need at least one support")
|
|
159
|
+
|
|
160
|
+
warnings = []
|
|
161
|
+
|
|
162
|
+
# total load and its resultant position (centroid of the loads)
|
|
163
|
+
total = self_weight_n + sum(l["magnitude_n"] for l in loads)
|
|
164
|
+
if total <= 0:
|
|
165
|
+
raise ValueError("total load must be positive")
|
|
166
|
+
|
|
167
|
+
sx = sum(s["x"] for s in supports) / len(supports)
|
|
168
|
+
sy = sum(s["y"] for s in supports) / len(supports)
|
|
169
|
+
mx = self_weight_n * sx + sum(l["magnitude_n"] * l["x"] for l in loads)
|
|
170
|
+
my = self_weight_n * sy + sum(l["magnitude_n"] * l["y"] for l in loads)
|
|
171
|
+
|
|
172
|
+
xs = np.array([s["x"] for s in supports], dtype=float)
|
|
173
|
+
ys = np.array([s["y"] for s in supports], dtype=float)
|
|
174
|
+
n = len(supports)
|
|
175
|
+
|
|
176
|
+
# Reaction model: R_i = a + b*x_i + c*y_i (deflection plane of a rigid body
|
|
177
|
+
# on equal-stiffness supports). Solve the 3 equilibrium equations for a,b,c.
|
|
178
|
+
A = np.array([
|
|
179
|
+
[n, xs.sum(), ys.sum()],
|
|
180
|
+
[xs.sum(), (xs * xs).sum(), (xs * ys).sum()],
|
|
181
|
+
[ys.sum(), (xs * ys).sum(), (ys * ys).sum()],
|
|
182
|
+
])
|
|
183
|
+
rhs = np.array([total, mx, my])
|
|
184
|
+
|
|
185
|
+
if n < 3 or np.linalg.matrix_rank(A) < 3:
|
|
186
|
+
warnings.append(
|
|
187
|
+
"Supports are fewer than 3 or nearly collinear; the distribution is "
|
|
188
|
+
"approximate. Use 3+ non-collinear supports for a unique solution."
|
|
189
|
+
)
|
|
190
|
+
coeffs, *_ = np.linalg.lstsq(A, rhs, rcond=None)
|
|
191
|
+
else:
|
|
192
|
+
coeffs = np.linalg.solve(A, rhs)
|
|
193
|
+
|
|
194
|
+
a, b, c = coeffs
|
|
195
|
+
reactions = a + b * xs + c * ys
|
|
196
|
+
|
|
197
|
+
out = []
|
|
198
|
+
max_util = 0.0
|
|
199
|
+
for s, r in zip(supports, reactions):
|
|
200
|
+
force = float(r)
|
|
201
|
+
cap = s.get("capacity_n")
|
|
202
|
+
over = bool(cap is not None and force > cap)
|
|
203
|
+
util = (force / cap) if cap else None
|
|
204
|
+
if util is not None:
|
|
205
|
+
max_util = max(max_util, util)
|
|
206
|
+
if force < 0:
|
|
207
|
+
warnings.append(
|
|
208
|
+
f"Support '{s.get('id', '?')}' has a negative reaction "
|
|
209
|
+
f"({force:.1f} N) — it is lifting off; the object is unstable here."
|
|
210
|
+
)
|
|
211
|
+
out.append({
|
|
212
|
+
"id": s.get("id", "?"),
|
|
213
|
+
"force_n": round(force, 2),
|
|
214
|
+
"over_capacity": over,
|
|
215
|
+
"utilization": round(util, 3) if util is not None else None,
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
explanation = (
|
|
219
|
+
f"Total load {total:.1f} N distributed across {n} support(s). "
|
|
220
|
+
+ ("Some supports are overloaded or lifting off — see flags." if warnings
|
|
221
|
+
else "All reactions are positive and within capacity.")
|
|
222
|
+
)
|
|
223
|
+
return {
|
|
224
|
+
"reactions": out,
|
|
225
|
+
"total_load_n": round(total, 2),
|
|
226
|
+
"max_utilization": round(max_util, 3) if max_util else None,
|
|
227
|
+
"warnings": warnings,
|
|
228
|
+
"explanation": explanation,
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# ----------------------------------------------------------------------------
|
|
233
|
+
# Tool 3 — beam / shelf check
|
|
234
|
+
# ----------------------------------------------------------------------------
|
|
235
|
+
|
|
236
|
+
@mcp.tool()
|
|
237
|
+
def beam_check(
|
|
238
|
+
span_m: float,
|
|
239
|
+
support_type: Literal["simply_supported", "cantilever"],
|
|
240
|
+
load_type: Literal["point", "udl"],
|
|
241
|
+
magnitude_n: float,
|
|
242
|
+
e_pa: float,
|
|
243
|
+
allowable_stress_pa: float,
|
|
244
|
+
section_modulus_m3: float | None = None,
|
|
245
|
+
inertia_m4: float | None = None,
|
|
246
|
+
width_m: float | None = None,
|
|
247
|
+
height_m: float | None = None,
|
|
248
|
+
deflection_limit_ratio: float | None = None,
|
|
249
|
+
) -> dict:
|
|
250
|
+
"""Check whether a beam or shelf holds a load: bending stress and deflection.
|
|
251
|
+
|
|
252
|
+
Closed-form Euler–Bernoulli check. "point" puts the whole load at the centre
|
|
253
|
+
(simply supported) or the free end (cantilever); "udl" spreads magnitude_n
|
|
254
|
+
evenly along the span. Give the section either directly (section_modulus_m3
|
|
255
|
+
and inertia_m4) OR as a solid rectangle (width_m and height_m).
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
span_m: clear span / length, metres.
|
|
259
|
+
support_type: "simply_supported" (held both ends) or "cantilever" (one end).
|
|
260
|
+
load_type: "point" or "udl" (uniformly distributed).
|
|
261
|
+
magnitude_n: total load in newtons (1 kg ≈ 9.81 N).
|
|
262
|
+
e_pa: Young's modulus of the material, pascals (steel ≈ 2.0e11, pine ≈ 9e9).
|
|
263
|
+
allowable_stress_pa: allowable bending stress of the material, pascals.
|
|
264
|
+
section_modulus_m3: Z, if known. Else give width_m and height_m.
|
|
265
|
+
inertia_m4: I, if known. Else give width_m and height_m.
|
|
266
|
+
width_m, height_m: for a solid rectangle, used to compute Z and I.
|
|
267
|
+
deflection_limit_ratio: optional, e.g. 250 means limit deflection to span/250.
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
max_moment_nm, max_stress_pa, max_deflection_m, stress utilisation,
|
|
271
|
+
pass/fail, governing check, and a short explanation.
|
|
272
|
+
"""
|
|
273
|
+
if width_m and height_m:
|
|
274
|
+
section_modulus_m3 = width_m * height_m ** 2 / 6.0
|
|
275
|
+
inertia_m4 = width_m * height_m ** 3 / 12.0
|
|
276
|
+
if not section_modulus_m3 or not inertia_m4:
|
|
277
|
+
raise ValueError("provide section_modulus_m3 + inertia_m4, or width_m + height_m")
|
|
278
|
+
|
|
279
|
+
L, P, E, I, Z = span_m, magnitude_n, e_pa, inertia_m4, section_modulus_m3
|
|
280
|
+
|
|
281
|
+
if support_type == "simply_supported":
|
|
282
|
+
if load_type == "point":
|
|
283
|
+
m_max = P * L / 4.0
|
|
284
|
+
defl = P * L ** 3 / (48.0 * E * I)
|
|
285
|
+
else:
|
|
286
|
+
m_max = P * L / 8.0
|
|
287
|
+
defl = 5.0 * P * L ** 3 / (384.0 * E * I)
|
|
288
|
+
else: # cantilever
|
|
289
|
+
if load_type == "point":
|
|
290
|
+
m_max = P * L
|
|
291
|
+
defl = P * L ** 3 / (3.0 * E * I)
|
|
292
|
+
else:
|
|
293
|
+
m_max = P * L / 2.0
|
|
294
|
+
defl = P * L ** 3 / (8.0 * E * I)
|
|
295
|
+
|
|
296
|
+
stress = m_max / Z
|
|
297
|
+
stress_util = stress / allowable_stress_pa
|
|
298
|
+
stress_ok = stress <= allowable_stress_pa
|
|
299
|
+
|
|
300
|
+
defl_ok = True
|
|
301
|
+
defl_util = None
|
|
302
|
+
if deflection_limit_ratio:
|
|
303
|
+
limit = L / deflection_limit_ratio
|
|
304
|
+
defl_util = defl / limit
|
|
305
|
+
defl_ok = defl <= limit
|
|
306
|
+
|
|
307
|
+
passes = stress_ok and defl_ok
|
|
308
|
+
if not stress_ok:
|
|
309
|
+
governing = "bending stress"
|
|
310
|
+
elif not defl_ok:
|
|
311
|
+
governing = "deflection"
|
|
312
|
+
else:
|
|
313
|
+
governing = "stress" if (defl_util is None or stress_util >= defl_util) else "deflection"
|
|
314
|
+
|
|
315
|
+
explanation = (
|
|
316
|
+
f"{'PASS' if passes else 'FAIL'}: peak stress {stress/1e6:.1f} MPa vs "
|
|
317
|
+
f"{allowable_stress_pa/1e6:.1f} MPa allowable "
|
|
318
|
+
f"({stress_util*100:.0f}% used), deflection {defl*1000:.1f} mm."
|
|
319
|
+
)
|
|
320
|
+
return {
|
|
321
|
+
"max_moment_nm": round(m_max, 2),
|
|
322
|
+
"max_stress_pa": round(stress, 1),
|
|
323
|
+
"max_deflection_m": round(defl, 6),
|
|
324
|
+
"stress_utilization": round(stress_util, 3),
|
|
325
|
+
"deflection_utilization": round(defl_util, 3) if defl_util is not None else None,
|
|
326
|
+
"passes": passes,
|
|
327
|
+
"governing_check": governing,
|
|
328
|
+
"explanation": explanation,
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def main():
|
|
333
|
+
"""Console entry point: run the MCP server over stdio."""
|
|
334
|
+
mcp.run()
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
if __name__ == "__main__":
|
|
338
|
+
main()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: loadbench-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for structural load & stability math: tipping, support reactions, beam checks.
|
|
5
|
+
Project-URL: Homepage, https://github.com/jeongho54/loadbench-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/jeongho54/loadbench-mcp
|
|
7
|
+
Author: jeongho54
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: beam,engineering,mcp,model-context-protocol,statics,structural,tipping
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Requires-Dist: mcp<2,>=1.27
|
|
17
|
+
Requires-Dist: numpy>=1.26
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
<!-- mcp-name: io.github.jeongho54/loadbench -->
|
|
21
|
+
|
|
22
|
+
# loadbench-mcp
|
|
23
|
+
|
|
24
|
+
An MCP server that does the structural load & stability math language models get
|
|
25
|
+
wrong. AI assistants call it instead of guessing.
|
|
26
|
+
|
|
27
|
+
| Tool | Question it answers |
|
|
28
|
+
|------|---------------------|
|
|
29
|
+
| `check_tipping` | Will these weights topple over their footprint? |
|
|
30
|
+
| `solve_supports` | How much load does each leg / bracket carry? |
|
|
31
|
+
| `beam_check` | Will this beam or shelf hold the load? (stress + deflection) |
|
|
32
|
+
|
|
33
|
+
All math is verified against hand-computed answers (`tests/test_physics.py`).
|
|
34
|
+
|
|
35
|
+
## Install & run
|
|
36
|
+
|
|
37
|
+
Once published to PyPI, any MCP client can launch it with no install step:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
uvx loadbench-mcp
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or install it:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
pip install loadbench-mcp
|
|
47
|
+
loadbench-mcp
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Use it in Claude Desktop
|
|
51
|
+
|
|
52
|
+
Add to your `claude_desktop_config.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"loadbench": {
|
|
58
|
+
"command": "uvx",
|
|
59
|
+
"args": ["loadbench-mcp"]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Restart Claude Desktop, then ask things like *"A 2 m pine shelf on two brackets
|
|
66
|
+
0.3 m from each end — will it hold 40 kg in the middle?"*
|
|
67
|
+
|
|
68
|
+
## Local development
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
uv run --with mcp --with numpy python -m load_solver.server # run from source
|
|
72
|
+
python -m pytest tests # verify the math
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Inputs are SI units (metres, kilograms, newtons; 1 kg ≈ 9.81 N). Tool docstrings
|
|
76
|
+
carry the full argument details, which the model reads automatically.
|
|
77
|
+
|
|
78
|
+
> Estimates for planning, not certified engineering. For loads where a failure
|
|
79
|
+
> could cause injury or real damage, have a qualified engineer check the result.
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
load_solver/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
|
|
2
|
+
load_solver/server.py,sha256=rLHUur0ZJ2QftSHO1TwrR43xkhqY28IuqrPznZb4dlA,12922
|
|
3
|
+
loadbench_mcp-0.1.0.dist-info/METADATA,sha256=0HTJgh3poeO4IzPyLV8yw-9G5heKMErgv7afGQ9Bzzc,2368
|
|
4
|
+
loadbench_mcp-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
5
|
+
loadbench_mcp-0.1.0.dist-info/entry_points.txt,sha256=c7ADSkgt4pl4B9JBJOVb5A_9uZF7pM2SBfvi8z6PCD4,58
|
|
6
|
+
loadbench_mcp-0.1.0.dist-info/RECORD,,
|