Skip to content

How to create an inner decorator for tools? #1120

@BryanMakers

Description

@BryanMakers

Question

What I'm trying to achieve:

I'm creating a decorator that reuses elicitation logics. So I can reuse some code to write less code! 😄

What I have tried:

def simple_elicitation_acceptance(func):
    @wraps(func)
    async def wrapper(ctx: Context, *args, **kwargs):            
        if not ctx:
            raise ValueError("Context is required for elicitation acceptance.")
        
        result = await ctx.elicit(
            message=f"Confirm add a and b?", schema=SimpleConfirmation
        )
        
        match result:
            case AcceptedElicitation(data=data):
                if data.accepted:
                    return await func(*args, **kwargs)
                else:
                    return "Operation cancelled"
            case DeclinedElicitation():
                return "Operation declined"
            case CancelledElicitation():    
                return "Operation cancelled"
    return wrapper

then simply use it:

@mcp_app.tool(name="add")
@simple_elicitation_acceptance
async def add(a: int, b: int, ctx: Context) -> list:
    """
    add a and b
    """
    try:
        mcp_services: MCPServices = mcp_app.get_context().request_context.lifespan_context.some_fun_services
        res = some_fun_services.add(a, b)
        return res
    except Exception as e:
        raise Exception(f"Error adding: {e}")

My expected bahaviour:

I'm expecting my tool_call not to send a response until I've accepted the elicitation (via some input or event)

Actual behaviour:

Without me responding, the tool_call returns the following object and skips my input

meta=None content=[TextContent(type='text', text='Error executing tool add: Context is not available outside of a request', annotations=None, meta=None)] structuredContent=None isError=True

Additional Context

It actually works fine by just remove the decorator layer, but I really wanna make it a decorator so I can write less code!

Sorry if it was a noob question, or perhaps what I'm trying to achieve is not reasonable, or perhaps this sdk just doesn't yet support inner decorator for tools, but I've spent a lot of time on this so any answer is welcome haha!

Love the awesome work y'all are doing, thank you!

sorry made a couple edits to make my post reads a bit clearer

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Significant bug affecting many users, highly requested featurefeature requestRequest for a new feature that's not currently supportedquestionFurther information is requestedready for workEnough information for someone to start working on

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions