abstract-toolserver 0.0.44__tar.gz → 0.0.45__tar.gz

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.
Files changed (86) hide show
  1. {abstract_toolserver-0.0.44/src/abstract_toolserver.egg-info → abstract_toolserver-0.0.45}/PKG-INFO +1 -1
  2. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/setup.py +1 -1
  3. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/app.py +7 -0
  4. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/catalog.py +39 -29
  5. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/mcp.py +21 -15
  6. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/seat.py +1 -2
  7. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45/src/abstract_toolserver.egg-info}/PKG-INFO +1 -1
  8. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_catalog_start.py +1 -1
  9. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/LICENSE +0 -0
  10. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/README.md +0 -0
  11. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/pyproject.toml +0 -0
  12. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/setup.cfg +0 -0
  13. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/__init__.py +0 -0
  14. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/__main__.py +0 -0
  15. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/assess.py +0 -0
  16. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/board_format.py +0 -0
  17. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/browser.py +0 -0
  18. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/canvas.py +0 -0
  19. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/channels.py +0 -0
  20. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/claudeauth.py +0 -0
  21. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/claudedirs.py +0 -0
  22. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/cli.py +0 -0
  23. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/client.py +0 -0
  24. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/clients.py +0 -0
  25. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/comms.py +0 -0
  26. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/conversation_archive.py +0 -0
  27. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/db.py +0 -0
  28. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/discovery.py +0 -0
  29. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/events.py +0 -0
  30. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/exchanges.py +0 -0
  31. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/gates.py +0 -0
  32. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/grid.py +0 -0
  33. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/handoff.py +0 -0
  34. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/image.py +0 -0
  35. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/instructions.py +0 -0
  36. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/issues.py +0 -0
  37. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/ledgers.py +0 -0
  38. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/loci.py +0 -0
  39. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/messages.py +0 -0
  40. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/metrics.py +0 -0
  41. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/pkg_versions.py +0 -0
  42. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/prompt.py +0 -0
  43. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/provider.py +0 -0
  44. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/reuse_gate.py +0 -0
  45. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/rolling.py +0 -0
  46. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/rolling_reduce.py +0 -0
  47. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/routes/__init__.py +0 -0
  48. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/sessions.py +0 -0
  49. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/todo.py +0 -0
  50. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/tools.py +0 -0
  51. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/uitools.py +0 -0
  52. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/vl.py +0 -0
  53. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/vmgui.py +0 -0
  54. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/vmhosts.py +0 -0
  55. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/vmpage.py +0 -0
  56. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver/vmpool.py +0 -0
  57. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver.egg-info/SOURCES.txt +0 -0
  58. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver.egg-info/dependency_links.txt +0 -0
  59. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver.egg-info/entry_points.txt +0 -0
  60. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver.egg-info/requires.txt +0 -0
  61. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/src/abstract_toolserver.egg-info/top_level.txt +0 -0
  62. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_auth.py +0 -0
  63. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_board_format.py +0 -0
  64. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_channels.py +0 -0
  65. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_client.py +0 -0
  66. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_comms.py +0 -0
  67. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_comms_claim.py +0 -0
  68. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_comms_claim_live.py +0 -0
  69. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_db_query_errors.py +0 -0
  70. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_discovery.py +0 -0
  71. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_exchanges_ledgers.py +0 -0
  72. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_gate_ufw_apply.py +0 -0
  73. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_handoff.py +0 -0
  74. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_instructions.py +0 -0
  75. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_issues.py +0 -0
  76. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_mcp_governor.py +0 -0
  77. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_mct_archive.py +0 -0
  78. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_metrics.py +0 -0
  79. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_rolling_reduce.py +0 -0
  80. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_sessions.py +0 -0
  81. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_todo_id_prefix.py +0 -0
  82. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_ui_tools.py +0 -0
  83. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_vmgui.py +0 -0
  84. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_vmgui_live.py +0 -0
  85. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_vmhosts.py +0 -0
  86. {abstract_toolserver-0.0.44 → abstract_toolserver-0.0.45}/tests/test_vms_page.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstract_toolserver
3
- Version: 0.0.44
3
+ Version: 0.0.45
4
4
  Summary: The abstract_* ecosystem exposed as an API-callable AI toolset: functions become self-describing Flask endpoints with /endpoints discovery and ?help.
5
5
  Home-page: https://github.com/AbstractEndeavors/abstract-toolserver
6
6
  Author: putkoff
@@ -7,7 +7,7 @@ SERVER = ['abstract_flask', 'abstract_utilities']
7
7
 
8
8
  setuptools.setup(
9
9
  name='abstract_toolserver',
10
- version='0.0.44',
10
+ version='0.0.45',
11
11
  author='putkoff',
12
12
  author_email='partners@abstractendeavors.com',
13
13
  description="The abstract_* ecosystem exposed as an API-callable AI toolset: functions become self-describing Flask endpoints with /endpoints discovery and ?help.",
@@ -67,6 +67,13 @@ def _install_operator_gate(app):
67
67
  "instance": ident.get("instance", ""),
68
68
  "version": ident.get("version") or _discovery.package_version()})
69
69
 
70
+ @app.route("/handoff/<session_id>", methods=["GET"])
71
+ def _handoff_get(session_id):
72
+ # the canonical dereference of a handoff pointer: /toolserver/handoff/{id}
73
+ from .seat import session_resume
74
+ doc = session_resume(session_id)
75
+ return jsonify({"result": doc})
76
+
70
77
  @app.before_request
71
78
  def _require_operator_token():
72
79
  if request.method == "OPTIONS":
@@ -5,7 +5,7 @@ Two consumers share everything here:
5
5
 
6
6
  * the ``ts`` toolset (POST /ts/categories, /ts/list, /ts/call) — served by the
7
7
  same register_categories machinery as every other tool, so the public names
8
- are ts_categories / ts_list / ts_call.
8
+ are toolserver_categories / toolserver_list / toolserver_call.
9
9
  * POST /mcp — the MCP Streamable-HTTP JSON-RPC transport (routes/__init__.py).
10
10
 
11
11
  The catalog is the UNION of
@@ -25,7 +25,8 @@ import json
25
25
 
26
26
  from . import clients
27
27
 
28
- _META_CATEGORY = "ts"
28
+ _META_CATEGORY = "toolserver"
29
+ _META_CATEGORY_ALIAS = "ts" # pre-rename routes /ts/*, still served
29
30
  _DELEGATE_MARK = "[delegated " # proxy docstrings start "[delegated → <base>] ..."
30
31
 
31
32
  # Curated one-liners for the known categories (fallback = first few tool names).
@@ -210,9 +211,9 @@ def _short(name, category):
210
211
  # ══════════════════════════════════════════════════════════
211
212
  # ts_* tool functions (registered under TOOLSETS["ts"])
212
213
  # ══════════════════════════════════════════════════════════
213
- def ts_categories():
214
+ def toolserver_categories():
214
215
  """List every tool category (local + online clients) with a tool count and a
215
- short summary. Call this first, then ts_list(category), then ts_call(name)."""
216
+ short summary. Call this first, then toolserver_list(category), then toolserver_call(name)."""
216
217
  local = _local_tools()
217
218
  cats = {} # cat -> set(names)
218
219
  for name, (cat, _route, _func) in local.items():
@@ -229,7 +230,7 @@ def ts_categories():
229
230
  return out
230
231
 
231
232
 
232
- def ts_list(category=None):
233
+ def toolserver_list(category=None):
233
234
  """Start here, or list exact tools in one category.
234
235
 
235
236
  With no category, returns a guided category index and copyable next-call
@@ -239,13 +240,13 @@ def ts_list(category=None):
239
240
  """
240
241
  category = str(category or "").strip().strip("/").lower()
241
242
  if not category:
242
- categories = ts_categories()
243
+ categories = toolserver_categories()
243
244
  return {
244
245
  "start_here": True,
245
246
  "workflow": [
246
247
  "Choose a category from categories below.",
247
- "Call ts_list again with that category to get exact tool schemas.",
248
- "Call ts_call with a returned full tool name and an arguments object.",
248
+ "Call toolserver_list again with that category to get exact tool schemas.",
249
+ "Call toolserver_call with a returned full tool name and an arguments object.",
249
250
  ],
250
251
  "categories": categories,
251
252
  "examples": {
@@ -259,7 +260,7 @@ def ts_list(category=None):
259
260
  "arguments": {"path": "tools/toolserver"},
260
261
  },
261
262
  },
262
- "naming": "ts_call name = <category>_<route>; use names exactly as returned",
263
+ "naming": "toolserver_call name = <category>_<route>; use names exactly as returned",
263
264
  }
264
265
  tools, seen = [], set()
265
266
  for name, (cat, _route, func) in sorted(_local_tools().items()):
@@ -277,26 +278,26 @@ def ts_list(category=None):
277
278
  seen.add(name)
278
279
  if not tools:
279
280
  return {"category": category, "count": 0, "tools": [],
280
- "error": f"unknown or empty category: {category}", "hint": "ts_categories"}
281
+ "error": f"unknown or empty category: {category}", "hint": "toolserver_categories"}
281
282
  return {
282
283
  "category": category,
283
284
  "count": len(tools),
284
285
  "tools": tools,
285
- "next": {"tool": "ts_call", "shape": {"name": "<tool name above>",
286
+ "next": {"tool": "toolserver_call", "shape": {"name": "<tool name above>",
286
287
  "arguments": "<object matching its parameters>"}},
287
288
  }
288
289
 
289
290
 
290
- def ts_call(name=None, arguments=None, client=None, tags=None):
291
+ def toolserver_call(name=None, arguments=None, client=None, tags=None):
291
292
  """Invoke a tool by full name (e.g. 'fs_read_file', 'ui_capture'). Args:
292
- name, arguments (object of the tool's params, from ts_list), optional client
293
+ name, arguments (object of the tool's params, from toolserver_list), optional client
293
294
  (route a client-provided tool to a specific client id/name) and tags (pick an
294
295
  online client matching these tags). Local tools run in-process with the same
295
296
  argument coercion and result shape a direct POST to the tool's endpoint gives;
296
297
  client tools route to an online provider. Unknown name -> error as data."""
297
298
  name = str(name or "").strip()
298
299
  if not name:
299
- return {"error": "name is required", "hint": "ts_categories → ts_list"}
300
+ return {"error": "name is required", "hint": "toolserver_categories → toolserver_list"}
300
301
  arguments = arguments if isinstance(arguments, dict) else {}
301
302
  local = _local_tools()
302
303
  if name in local and not client:
@@ -305,7 +306,7 @@ def ts_call(name=None, arguments=None, client=None, tags=None):
305
306
  return func(*args, **kwargs) # raw value; exceptions propagate to the endpoint
306
307
  # client-provided (or an explicit client override)
307
308
  if name not in local and name not in _client_index() and not client:
308
- return {"error": f"unknown tool: {name}", "hint": "ts_categories → ts_list"}
309
+ return {"error": f"unknown tool: {name}", "hint": "toolserver_categories → toolserver_list"}
309
310
  return clients.dispatch(name, _coerce_args(arguments), client=client, tags=tags)
310
311
 
311
312
 
@@ -317,24 +318,29 @@ def _prune(func, coerced):
317
318
  return (), coerced
318
319
 
319
320
 
321
+ # pre-rename import aliases (tests, external callers)
322
+ ts_categories, ts_list, ts_call = toolserver_categories, toolserver_list, toolserver_call
323
+
324
+
320
325
  def get_toolset():
321
- return {_META_CATEGORY: {"categories": ts_categories, "list": ts_list, "call": ts_call}}
326
+ routes = {"categories": toolserver_categories, "list": toolserver_list, "call": toolserver_call}
327
+ return {_META_CATEGORY: routes, _META_CATEGORY_ALIAS: dict(routes)}
322
328
 
323
329
 
324
330
  # ══════════════════════════════════════════════════════════
325
331
  # MCP Streamable-HTTP (JSON-RPC 2.0 over POST /mcp)
326
332
  # ══════════════════════════════════════════════════════════
327
333
  _META_TOOL_SCHEMAS = [
328
- {"name": "ts_categories",
334
+ {"name": "toolserver_categories",
329
335
  "description": "List toolserver tool categories (local + online clients) with counts. "
330
- "Call this first, then ts_list.",
336
+ "Call this first, then toolserver_list.",
331
337
  "inputSchema": {"type": "object", "properties": {}}},
332
- {"name": "ts_list",
338
+ {"name": "toolserver_list",
333
339
  "description": "List the tools in one category, with each tool's parameters. "
334
- "Arg: category (from ts_categories).",
340
+ "Arg: category (from toolserver_categories).",
335
341
  "inputSchema": {"type": "object", "properties": {"category": {"type": "string"}},
336
342
  "required": ["category"]}},
337
- {"name": "ts_call",
343
+ {"name": "toolserver_call",
338
344
  "description": "Invoke a toolserver tool by full name. Args: name, arguments "
339
345
  "(object of the tool's params), optional client (id/name) and tags "
340
346
  "(list) to route a client-provided tool to a specific online client.",
@@ -346,6 +352,9 @@ _META_TOOL_SCHEMAS = [
346
352
  "required": ["name"]}},
347
353
  ]
348
354
  _META_NAMES = {t["name"] for t in _META_TOOL_SCHEMAS}
355
+ _META_NAME_ALIASES = {"ts_categories": "toolserver_categories", "ts_list": "toolserver_list",
356
+ "ts_call": "toolserver_call"} # pre-rename names, still accepted
357
+ _META_NAMES |= set(_META_NAME_ALIASES)
349
358
 
350
359
 
351
360
  def _server_version():
@@ -384,22 +393,23 @@ def _as_text(result):
384
393
 
385
394
  def mcp_tools_call(name, arguments):
386
395
  """(result_obj, is_error) for an MCP tools/call. Handles the three meta tools
387
- by name and, in flat mode, any tool by its full name (via ts_call)."""
396
+ by name and, in flat mode, any tool by its full name (via toolserver_call)."""
388
397
  name = str(name or "")
398
+ name = _META_NAME_ALIASES.get(name, name)
389
399
  arguments = arguments if isinstance(arguments, dict) else {}
390
400
  try:
391
- if name == "ts_categories":
392
- return ts_categories(), False
393
- if name == "ts_list":
394
- r = ts_list(category=arguments.get("category"))
401
+ if name == "toolserver_categories":
402
+ return toolserver_categories(), False
403
+ if name == "toolserver_list":
404
+ r = toolserver_list(category=arguments.get("category"))
395
405
  return r, bool(r.get("error"))
396
- if name == "ts_call":
397
- r = ts_call(name=arguments.get("name"),
406
+ if name == "toolserver_call":
407
+ r = toolserver_call(name=arguments.get("name"),
398
408
  arguments=arguments.get("arguments") or {},
399
409
  client=arguments.get("client"), tags=arguments.get("tags"))
400
410
  return r, bool(isinstance(r, dict) and "error" in r)
401
411
  # flat-mode: name is the tool itself
402
- r = ts_call(name=name, arguments=arguments)
412
+ r = toolserver_call(name=name, arguments=arguments)
403
413
  return r, bool(isinstance(r, dict) and "error" in r)
404
414
  except Exception as e: # noqa: BLE001 — tool raised → MCP isError
405
415
  return {"error": str(e)}, True
@@ -449,25 +449,25 @@ def load_tools():
449
449
  # ── categorical mode ────────────────────────────────────────────────────────
450
450
  # Flat mode exposes all ~146 endpoints as distinct tools — every schema rides in
451
451
  # the prompt EVERY turn (~5k tok) whether used or not. Categorical mode exposes 3
452
- # meta-tools and lets the model discover on demand: ts_categories → ts_list(cat)
453
- # → ts_call(name), cutting the standing toolset cost to a few hundred tokens.
452
+ # meta-tools and lets the model discover on demand: toolserver_categories → toolserver_list(cat)
453
+ # → toolserver_call(name), cutting the standing toolset cost to a few hundred tokens.
454
454
  # Enable with AC_MCP_MODE=categorical. (Schemas come from the same cached
455
- # discovery, so ts_list is instant.)
455
+ # discovery, so toolserver_list is instant.)
456
456
  CATEGORICAL = os.environ.get("AC_MCP_MODE", "flat").lower() in ("cat", "categorical", "category")
457
457
 
458
458
  META_TOOLS = [
459
- {"name": "ts_categories",
459
+ {"name": "toolserver_categories",
460
460
  "description": "List abstract_toolserver tool categories (e.g. web, vm, vmpool, ui, "
461
- "todo, fs, seat, session, db) with counts. Call this first, then ts_list.",
461
+ "todo, fs, seat, session, db) with counts. Call this first, then toolserver_list.",
462
462
  "inputSchema": {"type": "object", "properties": {}}},
463
- {"name": "ts_list",
463
+ {"name": "toolserver_list",
464
464
  "description": "List the toolserver tools in one category, with each tool's parameters. "
465
- "Args: category (from ts_categories).",
465
+ "Args: category (from toolserver_categories).",
466
466
  "inputSchema": {"type": "object", "properties": {"category": {"type": "string"}},
467
467
  "required": ["category"]}},
468
- {"name": "ts_call",
468
+ {"name": "toolserver_call",
469
469
  "description": "Invoke a toolserver tool by full name (e.g. 'fs_read_file'). Args: name, "
470
- "arguments (object of the tool's params, from ts_list).",
470
+ "arguments (object of the tool's params, from toolserver_list).",
471
471
  "inputSchema": {"type": "object",
472
472
  "properties": {"name": {"type": "string"}, "arguments": {"type": "object"}},
473
473
  "required": ["name"]}},
@@ -500,17 +500,22 @@ def _categories(tools):
500
500
  return [{"category": k, "tools": n} for k, n in sorted(c.items())]
501
501
 
502
502
 
503
+ _META_ALIASES = {"ts_categories": "toolserver_categories", "ts_list": "toolserver_list",
504
+ "ts_call": "toolserver_call"} # pre-rename names, still accepted
505
+
506
+
503
507
  def _handle_meta(name, args, tools, url_by_name):
504
508
  """(out, is_error) for a categorical meta-tool call."""
505
- if name == "ts_categories":
509
+ name = _META_ALIASES.get(name, name)
510
+ if name == "toolserver_categories":
506
511
  return _categories(tools), False
507
- if name == "ts_list":
512
+ if name == "toolserver_list":
508
513
  cat = str(args.get("category", "")).strip().strip("/").lower()
509
514
  sel = [t for t in tools if _category_of(t) == cat]
510
515
  listing = [{"name": t["name"], "description": t.get("description", ""),
511
516
  "inputSchema": t.get("inputSchema", {})} for t in sel]
512
517
  return {"category": cat, "count": len(listing), "tools": listing}, (not sel)
513
- if name == "ts_call":
518
+ if name == "toolserver_call":
514
519
  target = args.get("name")
515
520
  call_args = _coerce(args.get("arguments") or {})
516
521
  url = url_by_name.get(target)
@@ -697,14 +702,15 @@ def serve_mcp():
697
702
  "text": json.dumps(out, indent=2, default=str)}],
698
703
  "isError": bool(is_err)})
699
704
  continue
700
- if CATEGORICAL and name in ("ts_categories", "ts_list", "ts_call"):
705
+ if CATEGORICAL and name in ("toolserver_categories", "toolserver_list", "toolserver_call",
706
+ "ts_categories", "ts_list", "ts_call"):
701
707
  try:
702
708
  out, is_err = _handle_meta(name, args, tools_cache, url_by_name)
703
709
  except Exception as e:
704
710
  out, is_err = {"error": str(e)}, True
705
- gov_tool = str(args.get("name") or "") if name == "ts_call" else name
711
+ gov_tool = str(args.get("name") or "") if name in ("toolserver_call", "ts_call") else name
706
712
  text = govern_result(json.dumps(out, indent=2, default=str), gov_tool,
707
- args.get("arguments") if name == "ts_call" else args)
713
+ args.get("arguments") if name in ("toolserver_call", "ts_call") else args)
708
714
  _result(id_, {"content": [{"type": "text", "text": text}],
709
715
  "isError": bool(is_err)})
710
716
  continue
@@ -387,9 +387,8 @@ def session_resume(session_id):
387
387
 
388
388
 
389
389
  def get_toolset():
390
- # seat_rollover (the phase gate) is UNMOUNTED for now (operator 2026-10-01):
391
- # the serve owns rolls; the session chain endpoints below are the contract.
392
390
  return {"seat": {"report": seat_report, "state": seat_state,
391
+ "rollover": seat_rollover,
393
392
  "session_register": session_register,
394
393
  "session_handoff": session_handoff,
395
394
  "session_resume": session_resume}}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstract_toolserver
3
- Version: 0.0.44
3
+ Version: 0.0.45
4
4
  Summary: The abstract_* ecosystem exposed as an API-callable AI toolset: functions become self-describing Flask endpoints with /endpoints discovery and ?help.
5
5
  Home-page: https://github.com/AbstractEndeavors/abstract-toolserver
6
6
  Author: putkoff
@@ -21,5 +21,5 @@ def test_ts_list_without_category_is_a_guided_start():
21
21
  def test_ts_list_category_includes_next_call_shape():
22
22
  result = ts_list("channel")
23
23
  assert result["tools"]
24
- assert result["next"]["tool"] == "ts_call"
24
+ assert result["next"]["tool"] == "toolserver_call"
25
25
  assert result["next"]["shape"]["name"] == "<tool name above>"