How to inject extra fixed parameters in MCP tool c...
# ask-ai
b
How to inject extra fixed parameters in MCP tool call?
t
Thanks for reaching out, Maxence. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about injecting extra fixed parameters when making an MCP tool call. Short answer • You cannot inject fixed parameters directly into an MCP tool at the point the LLM invokes it. MCP tools’ schemas and defaults are defined on the MCP server. • You can accomplish the same outcome by either (A) defining defaults on the MCP server-side tool, or (B) wrapping the MCP tool call on the agent/client side so the fixed parameters are always included. Options and how to implement each 1) Define fixed/default parameters on the MCP server • Add the fixed parameters as defaults in the tool’s schema or implementation on the MCP server. Calls from agents that omit those fields will then use the server-side defaults. • Use this when you control the MCP server/tool definition and want the fixed values enforced for all clients. 2) Wrap the MCP tool on the agent/client side (recommended when you can’t change the MCP server) • Create a local function/tool in your agent that accepts only the dynamic arguments the LLM should supply. • Inside that wrapper, merge the dynamic arguments with your fixed parameters, then forward the composed payload to the MCP tool (via the MCP client or HTTP call). • This keeps the LLM-facing tool signature clean while ensuring fixed parameters are always included. Example pattern (Python-like pseudocode)
Copy code
@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 Documentation
b
How can I use the meta field from _make_function_tool
t
Thanks — you're asking how to use the
meta
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.
b
Python example that uses
meta
to inject fixed parameters,
t
Thanks — you want a Python example showing how to use the
meta
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)
Copy code
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?