Skip to content

Commit 0651021

Browse files
committed
Add watcher. Make as_mcp more flexible.
1 parent c21a2d7 commit 0651021

6 files changed

Lines changed: 535 additions & 59 deletions

File tree

docs/api/tools.mdx

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -579,11 +579,7 @@ as\_mcp
579579
-------
580580

581581
```python
582-
as_mcp(
583-
tools: Iterable[Tool[..., Any] | Callable[..., Any]],
584-
*,
585-
name: str = "Rigging Tools",
586-
) -> FastMCP
582+
as_mcp(*tools: Any, name: str = 'Rigging Tools') -> FastMCP
587583
```
588584

589585
Serves a collection of Rigging tools over the Model Context Protocol (MCP).
@@ -595,15 +591,16 @@ the conversion between Rigging's `Tool` objects and the MCP specification.
595591
**Parameters:**
596592

597593
* **`tools`**
598-
(`Iterable[Tool[..., Any] | Callable[..., Any]]`)
599-
–An iterable of `rigging.Tool` objects or raw Python functions
600-
to be exposed. If raw functions are passed, they will be
601-
converted to `Tool` objects automatically.
594+
(`Any`, default:
595+
`()`
596+
)
597+
–Any number of `rigging.Tool` objects, raw Python functions,
598+
or class instances with `@tool_method` methods.
602599
* **`name`**
603600
(`str`, default:
604601
`'Rigging Tools'`
605602
)
606-
–The name of the MCP server. This is used for identification
603+
–The name of the MCP server. This is used for identification.
607604

608605
Example
609606

@@ -618,7 +615,7 @@ def add_numbers(a: int, b: int) -> int:
618615
return a + b
619616

620617
if __name__ == "__main__":
621-
rg.as_mcp([add_numbers]).run(
618+
rg.as_mcp(add_numbers).run(
622619
transport="stdio"
623620
)
624621
```
@@ -627,8 +624,7 @@ if __name__ == "__main__":
627624
<Accordion title="Source code in rigging/tools/mcp.py" icon="code">
628625
```python
629626
def as_mcp(
630-
tools: t.Iterable[Tool[..., t.Any] | t.Callable[..., t.Any]],
631-
*,
627+
*tools: t.Any,
632628
name: str = "Rigging Tools",
633629
) -> "FastMCP":
634630
"""
@@ -639,10 +635,9 @@ def as_mcp(
639635
the conversion between Rigging's `Tool` objects and the MCP specification.
640636
641637
Args:
642-
tools: An iterable of `rigging.Tool` objects or raw Python functions
643-
to be exposed. If raw functions are passed, they will be
644-
converted to `Tool` objects automatically.
645-
name: The name of the MCP server. This is used for identification
638+
tools: Any number of `rigging.Tool` objects, raw Python functions,
639+
or class instances with `@tool_method` methods.
640+
name: The name of the MCP server. This is used for identification.
646641
647642
Example:
648643
~~~python
@@ -656,15 +651,32 @@ def as_mcp(
656651
return a + b
657652
658653
if __name__ == "__main__":
659-
rg.as_mcp([add_numbers]).run(
654+
rg.as_mcp(add_numbers).run(
660655
transport="stdio"
661656
)
662657
~~~
663658
"""
664-
rigging_tools = [t if isinstance(t, Tool) else Tool.from_callable(t) for t in tools]
659+
rigging_tools: list[Tool[..., t.Any]] = []
660+
for tool in flatten_list(list(tools)):
661+
interior_tools = [
662+
val
663+
for _, val in inspect.getmembers(
664+
tool,
665+
predicate=lambda x: isinstance(x, Tool),
666+
)
667+
]
668+
if interior_tools:
669+
rigging_tools.extend(interior_tools)
670+
elif not isinstance(tool, Tool):
671+
rigging_tools.append(Tool.from_callable(tool))
672+
else:
673+
rigging_tools.append(tool)
674+
665675
fastmcp_tools = [
666676
FastMCPTool.from_function(
667-
fn=_create_mcp_handler(tool.fn), name=tool.name, description=tool.description
677+
fn=_create_mcp_handler(tool.fn),
678+
name=tool.name,
679+
description=tool.description,
668680
)
669681
for tool in rigging_tools
670682
]

docs/api/util.mdx

Lines changed: 106 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -340,27 +340,117 @@ shorten\_string
340340

341341
```python
342342
shorten_string(
343-
content: str, max_length: int, *, sep: str = "..."
343+
text: str, max_length: int | None, *, sep: str = "..."
344344
) -> str
345345
```
346346

347-
Return a string at most max\_length characters long by removing the middle of the string.
347+
Return a string at most max\_length characters long by removing the middle.
348348

349349
<Accordion title="Source code in rigging/util.py" icon="code">
350350
```python
351-
def shorten_string(content: str, max_length: int, *, sep: str = "...") -> str:
351+
def shorten_string(text: str, max_length: int | None, *, sep: str = "...") -> str:
352352
"""
353-
Return a string at most max_length characters long by removing the middle of the string.
353+
Return a string at most max_length characters long by removing the middle.
354354
"""
355-
if len(content) <= max_length:
356-
return content
355+
if max_length is None or len(text) <= max_length:
356+
return text
357+
return shorten_text(text, max_chars=max_length, separator=sep)
358+
```
357359

358-
remaining = max_length - len(sep)
359-
if remaining <= 0:
360-
return sep
361360

362-
middle = remaining // 2
363-
return content[:middle] + sep + content[-middle:]
361+
</Accordion>
362+
363+
shorten\_text
364+
-------------
365+
366+
```python
367+
shorten_text(
368+
text: str,
369+
*,
370+
max_lines: int | None = None,
371+
max_chars: int | None = None,
372+
separator: str = "...",
373+
) -> str
374+
```
375+
376+
Shortens text to a maximum number of lines and/or characters by removing
377+
content from the middle.
378+
379+
Line shortening is applied first, followed by character shortening.
380+
381+
**Parameters:**
382+
383+
* **`text`**
384+
(`str`)
385+
–The string to shorten.
386+
* **`max_lines`**
387+
(`int | None`, default:
388+
`None`
389+
)
390+
–The maximum number of lines to allow.
391+
* **`max_chars`**
392+
(`int | None`, default:
393+
`None`
394+
)
395+
–The maximum number of characters to allow.
396+
* **`separator`**
397+
(`str`, default:
398+
`'...'`
399+
)
400+
–The separator to insert in the middle of the shortened text.
401+
402+
**Returns:**
403+
404+
* `str`
405+
–The shortened text
406+
407+
<Accordion title="Source code in rigging/util.py" icon="code">
408+
```python
409+
def shorten_text(
410+
text: str,
411+
*,
412+
max_lines: int | None = None,
413+
max_chars: int | None = None,
414+
separator: str = "...",
415+
) -> str:
416+
"""
417+
Shortens text to a maximum number of lines and/or characters by removing
418+
content from the middle.
419+
420+
Line shortening is applied first, followed by character shortening.
421+
422+
Args:
423+
text: The string to shorten.
424+
max_lines: The maximum number of lines to allow.
425+
max_chars: The maximum number of characters to allow.
426+
separator: The separator to insert in the middle of the shortened text.
427+
428+
Returns:
429+
The shortened text
430+
"""
431+
# 1 - line count first
432+
if max_lines is not None:
433+
lines = text.splitlines()
434+
if len(lines) > max_lines:
435+
remaining_lines = max_lines - 1 # leave space for the separator
436+
if remaining_lines <= 0:
437+
text = separator # if max_lines is 1, just use the separator
438+
else:
439+
half = remaining_lines // 2
440+
start_lines = lines[:half]
441+
end_lines = lines[-(remaining_lines - half) :]
442+
text = "\n".join([*start_lines, separator, *end_lines])
443+
444+
# 2 - character count
445+
if max_chars is not None and len(text) > max_chars:
446+
remaining_chars = max_chars - len(separator)
447+
if remaining_chars <= 0:
448+
text = separator
449+
else:
450+
half_chars = remaining_chars // 2
451+
text = text[:half_chars] + separator + text[-half_chars:]
452+
453+
return text
364454
```
365455

366456

@@ -413,26 +503,26 @@ truncate\_string
413503

414504
```python
415505
truncate_string(
416-
content: str, max_length: int, *, suf: str = "..."
506+
text: str, max_length: int, *, suf: str = "..."
417507
) -> str
418508
```
419509

420510
Return a string at most max\_length characters long by removing the end of the string.
421511

422512
<Accordion title="Source code in rigging/util.py" icon="code">
423513
```python
424-
def truncate_string(content: str, max_length: int, *, suf: str = "...") -> str:
514+
def truncate_string(text: str, max_length: int, *, suf: str = "...") -> str:
425515
"""
426516
Return a string at most max_length characters long by removing the end of the string.
427517
"""
428-
if len(content) <= max_length:
429-
return content
518+
if len(text) <= max_length:
519+
return text
430520

431521
remaining = max_length - len(suf)
432522
if remaining <= 0:
433523
return suf
434524

435-
return content[:remaining] + suf
525+
return text[:remaining] + suf
436526
```
437527

438528

0 commit comments

Comments
 (0)