brash-fountain-12853
02/18/2026, 1:07 AMtall-airline-16756
02/18/2026, 1:07 AMtall-airline-16756
02/18/2026, 1:07 AM@function_tool()
async def wrapped_mcp_tool(context: RunContext, dynamic_arg: str):
# inject fixed params here
full_params = {
"dynamic_arg": dynamic_arg,
"fixed_param1": "value1",
"fixed_param2": "value2"
}
# forward to MCP tool endpoint / client
return await mcp_client.call_tool("remote_tool_name", full_params)
When to choose which approach
• If you can edit the MCP server: add defaults there so all callers benefit.
• If you cannot edit the server or want per-agent customization: implement a client-side wrapper in your agent and always call the remote tool through that wrapper.
If you’d like, I can:
• Show a concrete wrapper example for your language (Python/TypeScript) and MCP client library.
• Help draft the server-side schema change if you control the MCP tool definition.
Which would you prefer — a client-side wrapper example in Python or TypeScript, or guidance for updating the MCP tool definition?
Sources: Tool definition and use | LiveKit Documentation | MCP Agent | LiveKit Documentation | Agent session | LiveKit Documentationbrash-fountain-12853
02/18/2026, 8:49 PMtall-airline-16756
02/18/2026, 8:50 PMmeta field from _make_function_tool. I don't have a code snippet or language context from you, so I'll explain the general purpose and common patterns, then ask a couple quick questions so I can give a precise example for your setup.
What meta is for (general)
• The meta field is a place to attach extra, developer-defined metadata about a function tool that doesn't belong in the function signature.
• Typical uses: include human-readable descriptions, UI hints, categories/tags, authorization scopes, telemetry keys, rate-limit hints, or information used by a wrapper that decides which tool to call.
• The LLM/runtime usually ignores meta when performing the call — it's for your agent/tooling to read and act on.
Common patterns for using meta
• UI/tooling: Show meta.title or <http://meta.help|meta.help> in a tool picker so users or moderators understand the tool purpose.
• Routing/authorization: Use meta.scopes or meta.role to check permissions before invoking the tool.
• Instrumentation: Store meta.telemetry_key to tag logs/metrics with which tool variant was used.
• Wrapping/augmentation: A wrapper reads meta to decide whether to inject fixed parameters, transform inputs, or enforce validation rules.
Examples (patterns you can adapt)
• Display/UX:
◦ meta = {"title": "Create user", "help": "Creates a new user in the system"}
◦ Agent UI renders title/help so operators see the intent before calling.
• Authorization:
◦ meta = {"required_scope": "user.create"}
◦ Before calling the tool, check the caller has user.create scope.
• Fixed-parameter injection:
◦ meta = {"inject": {"fixed_param1": "value1"}}
◦ Wrapper reads meta.inject and merges those into the call payload.
• Telemetry:
◦ meta = {"telemetry_key": "mcp:remote_tool_v2"}
◦ Logging/tracing attaches telemetry_key to all events for that tool.
How to read/use meta in your agent
• When you construct the function tool (via _make_function_tool), attach a meta object.
• When your agent enumerates or invokes tools, inspect the tool's meta field and implement the logic you need (UI presentation, permission checks, automatic parameter merging, logging, etc.).
• If using a wrapper, have the wrapper accept a tool descriptor and consult meta before forwarding the call.
Quick clarifying questions
1. Which language or SDK are you using (Python, TypeScript, other)?
2. Do you want an example that (a) displays meta in a UI, (b) uses meta to inject fixed parameters, or (c) enforces authorization/validation before calling?
3. Are you creating the tool locally, or consuming tools discovered from an MCP server?
Tell me your answers and I’ll provide a short, concrete code example tailored to your environment.brash-fountain-12853
02/18/2026, 8:57 PMmeta to inject fixed parameters,tall-airline-16756
02/18/2026, 8:57 PMmeta field from _make_function_tool to inject fixed parameters before calling an MCP tool. Below is a concise pattern you can adapt: it defines a wrapper tool with meta.inject containing fixed params, reads that metadata at call time, merges fixed + dynamic args, and forwards the combined payload to the MCP client.
Notes:
• Replace mcp_client.call_tool with whatever client method you use to call the remote MCP tool.
• This example assumes function tools are described by a Tool-like object returned from _make_function_tool (or equivalent), and that when the agent decides to call a tool, your wrapper has access to that tool descriptor including meta.
Example (Python)
from typing import Any, Dict
from dataclasses import dataclass
# Simplified tool descriptor used by your agent runtime
@dataclass
class ToolDescriptor:
name: str
func: Any # local callable for wrappers
meta: Dict[str, Any]
# Mock MCP client - replace with real client integration
class MCPClient:
async def call_tool(self, tool_name: str, params: Dict[str, Any]) -> Dict[str, Any]:
# perform remote call to MCP tool
# return a response dict
return {"tool": tool_name, "params": params}
mcp_client = MCPClient()
# Example: create a wrapper function tool using `_make_function_tool`-style metadata
def make_wrapped_tool(remote_tool_name: str, fixed_params: Dict[str, Any]) -> ToolDescriptor:
async def wrapper(**kwargs):
# read dynamic args (kwargs) and inject fixed params from meta
# the meta is attached to the descriptor so callers or tooling can inspect it
# In practice, this wrapper will be registered as the function to call.
# Compose the full set of params
full_params = {**fixed_params, **kwargs}
# Forward to MCP remote tool
return await mcp_client.call_tool(remote_tool_name, full_params)
# Attach metadata; consumer/wrapper can read meta['inject']
meta = {
"description": f"Wrapper for {remote_tool_name} that injects fixed params",
"inject": fixed_params
}
return ToolDescriptor(name=f"wrapped:{remote_tool_name}", func=wrapper, meta=meta)
# Example usage: define a wrapped tool that always injects two fixed params
wrapped_tool = make_wrapped_tool("remote_create_item", {"fixed_param1": "value1", "fixed_param2": 42})
# Agent runtime: when invoking the tool, use the descriptor's meta if needed
async def agent_invoke_tool(tool: ToolDescriptor, dynamic_args: Dict[str, Any]):
# Optionally, validate or log meta before calling
inject = tool.meta.get("inject", {})
# Merge to show intent (wrapper already injects them, but we can enforce here)
composed_args = {**inject, **dynamic_args}
# Call the tool's function (which itself forwards to MCP)
return await tool.func(**dynamic_args) # wrapper will merge again and call MCP
# Example call (in async context)
# await agent_invoke_tool(wrapped_tool, {"name": "my-item", "count": 3})
# Expected MCP call payload: {"fixed_param1":"value1","fixed_param2":42,"name":"my-item","count":3}
Key points and variations
• Keep injection logic in the wrapper so the LLM-facing tool signature contains only the dynamic parameters you want the model to provide.
• Store fixed params in meta.inject so other parts of your agent (UIs, permission checks, telemetry) can inspect them without executing the tool.
• Optionally, have the agent runtime merge meta.inject with dynamic args before calling the wrapper to enforce or audit injected values.
• If you control the MCP server, consider adding defaults server-side instead of injecting on the client; but use client-side wrappers when you cannot change the server.
If you want, I can:
• Convert this to a TypeScript example.
• Show a version where the agent enforces permission checks based on meta before invoking the wrapper.
Which would help next?