-
Notifications
You must be signed in to change notification settings - Fork 712
[MCP] Tiny Agents in Python #3098
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
Co-authored-by: Julien Chaumond <[email protected]>
setup.py
Outdated
@@ -66,6 +66,7 @@ def get_version() -> str: | |||
|
|||
extras["mcp"] = [ | |||
"mcp>=1.8.0", | |||
"colorama", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(probably not worth the extra dependency if all you need are a few colors characters sequences)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be bullish to switch to Typer instead of argparse to be honest...
It has a much greater UX, easier to maintain, auto-completion out of the box, etc. It adds a dependency but only an optional one (on huggingface_hub[mcp]
)
Co-authored-by: Julien Chaumond <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks super cool already! 🔥
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! I'm pre-approving with some nits. Once we have SSE/HTTP servers implemented we should be on-par with the JS CLI to make some comms about it :)
(btw, is this a problem that we'll have two tiny-agents
CLIs conflicting? Hopefully not but 🤷)
else: | ||
raise KeyboardInterrupt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't know how to solve that but when I launch the CLI + wait for the tools to be loaded, I need to type 4 times on CTRL+C to exit and it exits with a ton of messages. Would be good to improve DX, either here or in a follow-up PR:
> tiny-agents run julien-c/local-coder
Fetching 2 files: 100%|███████████████████████████████████████████████████████| 2/2 [00:00<00:00, 64527.75it/s]
Agent loaded with 25 tools:
• browser_close
• browser_resize
• browser_console_messages
• browser_handle_dialog
• browser_file_upload
• browser_install
• browser_press_key
• browser_navigate
• browser_navigate_back
• browser_navigate_forward
• browser_network_requests
• browser_pdf_save
• browser_take_screenshot
• browser_snapshot
• browser_click
• browser_drag
• browser_hover
• browser_type
• browser_select_option
• browser_tab_list
• browser_tab_new
• browser_tab_select
• browser_tab_close
• browser_generate_playwright_test
• browser_wait_for
» ^CInterrupted – press Ctrl+C again to quit
^Cunhandled exception during asyncio.run() shutdown
task: <Task finished name='Task-1' coro=<run_agent() done, defined at /home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/cli.py:33> exception=ExceptionGroup('unhandled errors in a TaskGroup', [ProcessLookupError()])>
Traceback (most recent call last):
File "/home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/cli.py", line 63, in run_agent
async with Agent(
File "/home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/mcp_client.py", line 65, in __aexit__
await self.cleanup()
File "/home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/mcp_client.py", line 241, in cleanup
await self.exit_stack.aclose()
File "/usr/lib/python3.10/contextlib.py", line 656, in aclose
await self.__aexit__(None, None, None)
File "/usr/lib/python3.10/contextlib.py", line 714, in __aexit__
raise exc_details[1]
File "/usr/lib/python3.10/contextlib.py", line 697, in __aexit__
cb_suppress = await cb(*exc_details)
File "/usr/lib/python3.10/contextlib.py", line 206, in __aexit__
await anext(self.gen)
File "/home/wauplin/projects/huggingface_hub/.venv310/lib/python3.10/site-packages/mcp/client/stdio/__init__.py", line 170, in stdio_client
async with (
File "/home/wauplin/projects/huggingface_hub/.venv310/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 772, in __aexit__
raise BaseExceptionGroup(
exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
^C^CException ignored in: <module 'threading' from '/usr/lib/python3.10/threading.py'>
Traceback (most recent call last):
File "/usr/lib/python3.10/threading.py", line 1537, in _shutdown
atexit_call()
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 31, in _python_exit
t.join()
File "/usr/lib/python3.10/threading.py", line 1096, in join
self._wait_for_tstate_lock()
File "/usr/lib/python3.10/threading.py", line 1116, in _wait_for_tstate_lock
if lock.acquire(block, timeout):
KeyboardInterrupt:
(I do get similar output no matter when I exit but reporting this one is the most reproducible example)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as discussed in private, it's a bit complicated to "exit" properly an asyncio script in this context 😕 I pushed a better way to exit in f09b70a using os._exit()
but still, I believe it's not the best solution..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for looking into it. Let's do that and leave it for a later PR then...
I thought about it but i don't think so, given i doubt many people will install both globally. |
let's merge! 🔥 Screen.Recording.2025-05-21.at.19.36.22.mov |
(failing tests unrelated) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❗ 🔥 🚒
This is an early version of Tiny Agents (https://huggingface.co/blog/tiny-agents) in Python, inspired by @julien-c's work in JS: https://github.com/huggingface/huggingface.js/tree/main/packages/tiny-agents.
What's in the PR?
tiny-agents run
command (seesrc/huggingface_hub/inference/_mcp/cli.py
) that mirros the JS CLI and supports: a folder, a single agent.json, or a builtin agent name.src/huggingface_hub/inference/_mcp/tiny_agent.py
– very small orchestrator that keeps a history, enforces a max-turn limit, and plugs MCP tools into the LLM.What's missing?