Skip to content

Conversation

@CodeWithKyrian
Copy link
Contributor

@CodeWithKyrian CodeWithKyrian commented Jun 27, 2025

This PR implements comprehensive support for PHP callables as MCP server handlers, extending beyond the original class/method array format to support closures, static methods, and invokable classes.

What's New

Flexible Handler Types

  • Closures: function(string $input): string { return "processed: $input"; }
  • Class methods: [ClassName::class, 'methodName'] (resolved via container)
  • Static methods: [ClassName::class, 'staticMethod'] (called directly)
  • Invokable classes: InvokableClass::class (resolved via container, then __invoke())
  • Instance methods: [$instance, 'method'] (called directly on existing instance)

Smart Container Resolution

Updated handler resolution logic to properly distinguish between types that need container resolution vs. direct calls:

  1. String handlers (invokable classes) → Resolve from container first
  2. Array handlers → Check if class string vs. object instance
  3. Other callables → Call directly (closures, static methods, etc.)

Automatic Naming & Caching

  • Unique closure names: closure_tool_{spl_object_id} prevents collisions
  • Cache safety: Closures are never serialized (logged with warnings)
  • Backward compatibility: Existing array format handlers work unchanged

API Changes

Before

->withTool([EmailHandler::class, 'send'], 'send_email')
->withResource([ConfigHandler::class, 'get'], 'config://app')

After (all supported)

// Closures
->withTool(function(string $to, string $msg): string {
    return "Email sent to $to: $msg";
}, 'send_email')

// Static methods  
->withTool([EmailHandler::class, 'validateEmail'], 'validate')

// Invokable classes
->withTool(EmailSender::class, 'send_email') 

// Class methods (original - still works)
->withResource([ConfigHandler::class, 'get'], 'config://app')

Resolves #37

- Support closures, class methods, static methods, and invokable classes
- Reorder handler resolution logic to prioritize container resolution
- Add unique naming for closure handlers using spl_object_id()
- Prevent closure serialization in cache with validation warnings
- Update all registration methods to accept Closure|array|string
@CodeWithKyrian CodeWithKyrian merged commit 48f878f into main Jun 30, 2025
@CodeWithKyrian CodeWithKyrian deleted the feat/callable-handlers-support branch June 30, 2025 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Callbacks cannot handle Closures/Callables

2 participants