{"id":31704084,"url":"https://github.com/fblgit/bhanus","last_synced_at":"2026-03-10T06:31:00.170Z","repository":{"id":283974516,"uuid":"953446559","full_name":"fblgit/bhanus","owner":"fblgit","description":"MCP MultiAgentic Self-Evolving Hub for Local vLLM Function Calling Interception","archived":false,"fork":false,"pushed_at":"2025-03-23T16:52:27.000Z","size":53,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-08T22:50:03.525Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fblgit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-23T11:47:02.000Z","updated_at":"2025-04-07T04:41:02.000Z","dependencies_parsed_at":"2025-10-08T22:59:50.960Z","dependency_job_id":null,"html_url":"https://github.com/fblgit/bhanus","commit_stats":null,"previous_names":["fblgit/bhanus"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fblgit/bhanus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fblgit%2Fbhanus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fblgit%2Fbhanus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fblgit%2Fbhanus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fblgit%2Fbhanus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fblgit","download_url":"https://codeload.github.com/fblgit/bhanus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fblgit%2Fbhanus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30326891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-08T22:49:43.511Z","updated_at":"2026-03-10T06:31:00.127Z","avatar_url":"https://github.com/fblgit.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MCP-vLLM Integration Project\nA production-grade system integrating MCP with vLLM for efficient LLM inference and tool execution.\n\n## Setup\n1. Install dependencies: `pip install -r requirements.txt`\n2. Configure: Edit `config/config.yaml`\n\n\n## Current Progress:\n\n- [X] Inference Engine vLLM\n- [X] Template Engine\n- [X] MCP Client\n- [X] MCP Server\n- [X] Primitive Functions \u0026 Handlers\n- [X] Agent \u0026 Function Registration\n- [X] Prompt Templates\n- [ ] Parse Pipeline (WIP)\n- [ ] Ensure Agents \u0026 Functions Existence or Trigger Creation\n- [ ] E2E Flow (WIP `main.py`)\n- [ ] \n\n2025-03-23 11:50:26,023 - INFO - Starting MCP server...\n2025-03-23 11:50:26,026 - INFO - Initialized MCPServer on 127.0.0.1:6000 with registry function_registry.json\n2025-03-23 11:50:26,026 - INFO - Starting MCP server on 127.0.0.1:6000\n2025-03-23 11:50:26,026 - INFO - MCP server running on 127.0.0.1:6000\n2025-03-23 11:50:26,027 - INFO - Initializing core components...\n * Serving Flask app 'src.mcp_server.mcp_server'\n * Debug mode: off\n2025-03-23 11:50:26,033 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\n * Running on http://127.0.0.1:6000\n2025-03-23 11:50:26,033 - INFO - Press CTRL+C to quit\nINFO 03-23 11:50:28 llm_engine.py:226] Initializing an LLM engine (v0.6.1.dev238+ge2c6e0a82) with config: model='Qwen/Qwen2.5-1.5B-Instruct', speculative_config=None, tokenizer='Qwen/Qwen2.5-1.5B-Instruct', skip_tokenizer_init=False, tokenizer_mode=auto, revision=None, override_neuron_config=None, rope_scaling=None, rope_theta=None, tokenizer_revision=None, trust_remote_code=False, dtype=torch.bfloat16, max_seq_len=32768, download_dir=None, load_format=LoadFormat.AUTO, tensor_parallel_size=1, pipeline_parallel_size=1, disable_custom_all_reduce=False, quantization=None, enforce_eager=False, kv_cache_dtype=auto, quantization_param_path=None, device_config=cuda, decoding_config=DecodingConfig(guided_decoding_backend='outlines'), observability_config=ObservabilityConfig(otlp_traces_endpoint=None, collect_model_forward_time=False, collect_model_execute_time=False), seed=0, served_model_name=Qwen/Qwen2.5-1.5B-Instruct, use_v2_block_manager=False, num_scheduler_steps=1, multi_step_stream_outputs=False, enable_prefix_caching=False, use_async_output_proc=True, use_cached_outputs=False, mm_processor_kwargs=None)\nINFO 03-23 11:50:30 model_runner.py:1014] Starting to load model Qwen/Qwen2.5-1.5B-Instruct...\nINFO 03-23 11:50:31 weight_utils.py:242] Using model weights format ['*.safetensors']\nINFO 03-23 11:50:31 weight_utils.py:287] No model.safetensors.index.json found in remote.\nLoading safetensors checkpoint shards:   0% Completed | 0/1 [00:00\u003c?, ?it/s]\nLoading safetensors checkpoint shards: 100% Completed | 1/1 [00:00\u003c00:00,  2.14it/s]\nLoading safetensors checkpoint shards: 100% Completed | 1/1 [00:00\u003c00:00,  2.14it/s]\n\nINFO 03-23 11:50:32 model_runner.py:1025] Loading model weights took 2.8875 GB\nINFO 03-23 11:50:32 gpu_executor.py:122] # GPU blocks: 281784, # CPU blocks: 9362\nINFO 03-23 11:50:35 model_runner.py:1329] Capturing the model for CUDA graphs. This may lead to unexpected consequences if the model is not static. To run the model in eager mode, set 'enforce_eager=True' or use '--enforce-eager' in the CLI.\nINFO 03-23 11:50:35 model_runner.py:1333] CUDA graphs can take additional 1~3 GiB memory per GPU. If you are running out of memory, consider decreasing `gpu_memory_utilization` or enforcing eager mode. You can also reduce the `max_num_seqs` as needed to decrease memory usage.\nINFO 03-23 11:50:40 model_runner.py:1456] Graph capturing finished in 5 secs.\n2025-03-23 11:50:41,053 - INFO - Loaded model: Qwen/Qwen2.5-1.5B-Instruct with kwargs: {}\n2025-03-23 11:50:46,057 - INFO - 127.0.0.1 - - [23/Mar/2025 11:50:46] \"GET / HTTP/1.1\" 405 -\n2025-03-23 11:50:46,058 - INFO - Connected to MCP server at http://127.0.0.1:6000\n2025-03-23 11:50:46,058 - INFO - Defining and registering a new function...\n2025-03-23 11:50:46,060 - INFO - Loaded template 'define_function.jinja2' with expected_format '\\[\\[define_function\\(.*\\).*?\\]\\]' and description 'Define a new MCP function for registration'\n2025-03-23 11:50:46,060 - INFO - Generating with interception for prompt: '\n\n### System:\nTo define a new function for the MCP system, use the following syntax:\n\nExample 1: Code-Based Function\n- **Inputs**:\n  - `name`: \"get_current_time\"\n  - `description`: \"Retrieves the current system time\"\n  - `input`: `{}`\n  - `output`: \"string\"\n  - `type`: \"code\"\n- **Expected Output**:\n  ```\n  [[define_function(get_current_time) Retrieves the current system time]]\n  ```\n\nExample 2: Agent-Based Function\n- **Inputs**:\n  - `name`: \"tools_picker\"\n  - `description`: \"Selects relevant tools for a given task\"\n  - `input`: `{\"task\": \"string\"}`\n  - `output`: \"list\"\n  - `type`: \"agent\"\n- **Expected Output**:\n  ```\n  [[define_function(tools_picker) Selects relevant tools for a given task]]\n  ```\n\nExample 3: Function with Parameters\n- **Inputs**:\n  - `name`: \"search_from_api\"\n  - `description`: \"Searches an API for a query and returns results\"\n  - `input`: `{\"query\": \"string\", \"limit\": \"int\"}`\n  - `output`: \"dict\"\n  - `type`: \"code\"\n- **Expected Output**:\n  ```\n  [[define_function(search_from_api) Searches an API for a query and returns results]]\n  ```\n### Instruction:\nDefine a new function for the MCP system:\n\nWhere:\n- \"report_writer\" is the name of the function (e.g., \"report_writer\").\n- \"Writes a report from summarized content as an agent\" is a brief description of what the function does.\n\n### Response:\n'\n\nProcessed prompts: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00\u003c00:00, 13.89it/s, est. speed input: 5004.87 toks/s, output: 250.19 toks/s]\n2025-03-23 11:50:46,138 - INFO - Detected function definition: report_writer with {'description': 'Writes a report from summarized content as an agent', 'input': {}, 'output': 'string', 'type': 'agent'}\n2025-03-23 11:50:46,138 - INFO - Registering tool 'report_writer' with definition: {'name': 'report_writer', 'description': 'Writes a report from summarized content as an agent', 'input': {}, 'output': 'string', 'type': 'agent'}\n2025-03-23 11:50:46,141 - INFO - Registered tool: {'name': 'report_writer', 'description': 'Writes a report from summarized content as an agent', 'input': {}, 'output': 'string', 'type': 'agent'}\n2025-03-23 11:50:46,141 - INFO - 127.0.0.1 - - [23/Mar/2025 11:50:46] \"POST / HTTP/1.1\" 200 -\n2025-03-23 11:50:46,142 - INFO - Registered/updated function locally: report_writer with definition: {'name': 'report_writer', 'description': 'Writes a report from summarized content as an agent', 'input': {}, 'output': 'string', 'type': 'agent'}\n2025-03-23 11:50:46,142 - INFO - Successfully registered tool 'report_writer' on server and locally\n2025-03-23 11:50:46,142 - INFO - Registered/updated function locally: report_writer with definition: {'name': 'report_writer', 'description': 'Writes a report from summarized content as an agent', 'input': {}, 'output': 'string', 'type': 'agent'}\n2025-03-23 11:50:46,142 - INFO - Function registration result: '```\n[registered]report_writer[/registered]'\n2025-03-23 11:50:46,143 - INFO - Generating agent list with agent_factory...\n2025-03-23 11:50:46,143 - INFO - Loaded template 'agent_factory.jinja2' with expected_format 'Goal: .+\\\\nAgents: \\\\[.*\\\\]' and description 'Generate a list of collaborating agents for a given goal'\n2025-03-23 11:50:46,143 - INFO - Generating with interception for prompt: '\n\nYou are an AI assistant tasked with generating a list of expert agents that can collaborate to achieve a specific goal. The goal is provided, and you must output a list of agents that are best suited to work together on this task.\n\n**Instructions**:\n- Always start with the line: \"Goal: \u003ctask\u003e\"\n- Then, list the agents in the format: \"Agents: [agent1, agent2, ...]\"\n- Ensure the agents are relevant to the task and can collaborate effectively.\n\n**Examples**:\n\n1. **Input**: task = \"summarize code and write a report\"\n   **Output**:\n   Goal: summarize code and write a report\n   Agents: [code_analyzer, summarizer, report_writer]\n\n2. **Input**: task = \"plan a trip to Paris\"\n   **Output**:\n   Goal: plan a trip to Paris\n   Agents: [travel_planner, accommodation_finder, activity_suggestor]\n\n3. **Input**: task = \"debug a software application\"\n   **Output**:\n   Goal: debug a software application\n   Agents: [debugger, tester, log_analyzer]\n\n**Your Task**:\nGenerate the list of agents for the following goal:\n\nGoal: summarize code and write a report\nExisting Agents:\nAgents: ['\nProcessed prompts: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00\u003c00:00,  1.53it/s, est. speed input: 403.58 toks/s, output: 305.74 toks/s]\n2025-03-23 11:50:46,800 - INFO - Agent list: ['code_analyzer', 'summarizer', 'report_writer']\n2025-03-23 11:50:46,800 - INFO - Selecting tools with tools_picker...\n2025-03-23 11:50:46,801 - INFO - Loaded template 'tools_picker.jinja2' with expected_format 'Task: .+\\\\nSelected tools: \\\\[.*\\\\]' and description 'Select tools for a task'\n2025-03-23 11:50:46,802 - INFO - Requesting list of tools from MCP server at http://127.0.0.1:6000\n2025-03-23 11:50:46,803 - INFO - 127.0.0.1 - - [23/Mar/2025 11:50:46] \"POST / HTTP/1.1\" 200 -\n2025-03-23 11:50:46,804 - INFO - Generating with interception for prompt: '\n\n### System:\nYou are an AI assistant tasked with selecting the most relevant tools for a given task from a list of available tools. Your goal is to analyze the task and choose the tools that are necessary to accomplish it effectively.\n\n**Available Tools:**\n\n- **fetch_url**\n  - Description: Fetch content from a URL via GET request\n  - Input: {\"url\": \"string\"}\n  - Output: string\n  - Type: code\n\n- **fetch_text_url**\n  - Description: Fetch URL content and extract readable text using BeautifulSoup\n  - Input: {\"url\": \"string\"}\n  - Output: string\n  - Type: code\n\n- **fetch_links_url**\n  - Description: Fetch URL content and extract links with their text using BeautifulSoup\n  - Input: {\"url\": \"string\"}\n  - Output: dict\n  - Type: code\n\n- **pdf2text**\n  - Description: Convert a PDF file to text given its file path\n  - Input: {\"file_path\": \"string\"}\n  - Output: string\n- **fetch_file**\n  - Description: Fetch a file from a URL and store it temporarily, returning the file path\n  - Input: {\"url\": \"string\"}\n  - Output: string\n  - Type: code\n\n- **read_file**\n  - Description: Read contents of a file with optional chunking\n  - Input: {\"end\": \"int\", \"file_path\": \"string\", \"limit\": \"int\", \"start\": \"int\"}\n  - Output: string\n  - Type: code\n\n- **write_file**\n  - Description: Write content to a file and return its path, with optional file path override\n  - Input: {\"file_content\": \"string\", \"file_path\": \"string\"}\n  - Output: string\n  - Type: code\n\n- **run_snippet**\n  - Description: Run Python code from content in a separate thread and return file path and output\n  - Input: {\"code_content\": \"string\"}\n  - Output: dict\n  - Type: code\n\n- **google_search**\n  - Description: Perform a Google search and return results\n  - Input: {\"limit\": \"int\", \"query\": \"string\", \"start\": \"int\"}\n  - Output: dict\n  - Type: code\n\n- **calculator**\n  - Description: Evaluate a mathematical expression and return the result\n  - Input: {\"expression\": \"string\"}\n  - Output: float\n  - Type: code\n\n- **report_writer**\n  - Description: Writes a report from summarized content as an agent\n  - Input: {}\n  - Output: string\n  - Type: agent\n\n\n### Instruction:\n1. Review the task description provided.\n2. Examine the list of available tools, each with their name, description, input, output, and type.\n3. Select the tools that are most appropriate for the task. You may select multiple tools if needed.\n4. Output your selection in the following format:\n   ```\n   Task: \u003ctask description\u003e\n   Selected tools: [\u003ctool1\u003e, \u003ctool2\u003e, ...]\n   ```\n   - Replace `\u003ctask description\u003e` with the provided task.\n   - Replace `[\u003ctool1\u003e, \u003ctool2\u003e, ...]` with the names of the selected tools, enclosed in square brackets and separated by commas.\nBased on the task and available tools provided, generate the output in the specified format.\n**Task Description:**\nsummarize code and write a report\n\n### Response:\nTask: summarize code and write a report\nSelected tools: ['\n\nProcessed prompts: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00\u003c00:00, 27.16it/s, est. speed input: 20126.74 toks/s, output: 217.51 toks/s]\n2025-03-23 11:50:46,844 - INFO - Selected tools: ['run_snippet', 'report_writer', 'google_search']\n2025-03-23 11:50:46,844 - INFO - Executing scraping pipeline with dynamic tools...\n2025-03-23 11:50:46,844 - INFO - Initialized ScrapingPipeline with MCPClient and active engine\n2025-03-23 11:50:46,844 - INFO - Starting pipeline for goal: 'summarize code and write a report', max_urls: 2\n2025-03-23 11:50:46,844 - INFO - Requesting list of tools from MCP server at http://127.0.0.1:6000\n2025-03-23 11:50:46,845 - INFO - 127.0.0.1 - - [23/Mar/2025 11:50:46] \"POST / HTTP/1.1\" 200 -\n2025-03-23 11:50:46,846 - INFO - Invoking tool 'google_search' with params: {'query': 'summarize code and write a report'} and consent: True\n2025-03-23 11:50:46,848 - INFO - Invoking tool 'google_search' with params: {'consent': True, 'query': 'summarize code and write a report'}\n2025-03-23 11:50:47,563 - INFO - 127.0.0.1 - - [23/Mar/2025 11:50:47] \"POST / HTTP/1.1\" 200 -\n2025-03-23 11:50:47,564 - WARNING - Invalid URL format from 'google_search': {'results': [{'title': 'Highly Efficient Prompt for Summarizing — GPT-4 : r/ChatGPTPro', 'url': 'https://www.reddit.com/r/ChatGPTPro/comments/13n55w7/highly_efficient_prompt_for_summarizing_gpt4/'}, {'title': 'Overview of Copilot for Power BI - Power BI | Microsoft Learn', 'url': 'https://learn.microsoft.com/en-us/power-bi/create-reports/copilot-introduction'}, {'title': 'How to write a good Test Summary Report? | BrowserStack', 'url': 'https://www.browserstack.com/guide/how-to-write-test-summary-report'}, {'title': 'Create a grouped or summary report - Microsoft Support', 'url': 'https://support.microsoft.com/en-us/office/create-a-grouped-or-summary-report-f23301a1-3e0a-4243-9002-4a23ac0fdbf3'}, {'title': 'O*NET OnLine Help: Summary Report', 'url': 'https://www.onetonline.org/help/online/summary'}]}\n2025-03-23 11:50:47,564 - WARNING - No URLs found for goal\n2025-03-23 11:50:47,564 - WARNING - No summaries generated from the pipeline\n2025-03-23 11:50:47,564 - INFO - Processing summaries with registered report_writer...\n2025-03-23 11:50:47,564 - INFO - Requesting list of tools from MCP server at http://127.0.0.1:6000\n2025-03-23 11:50:47,566 - INFO - 127.0.0.1 - - [23/Mar/2025 11:50:47] \"POST / HTTP/1.1\" 200 -\n2025-03-23 11:50:47,567 - INFO - Loaded template 'report_writer.jinja2' with expected_format 'Report:.*' and description 'Generate a report from summaries'\n2025-03-23 11:50:47,567 - WARNING - Unsupported or unmatched expected_format: 'Report:.*' for output: '\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffblgit%2Fbhanus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffblgit%2Fbhanus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffblgit%2Fbhanus/lists"}