Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Exception/ClientRegistrationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Mcp\Exception;

final class ClientRegistrationException extends \RuntimeException implements ExceptionInterface
final class ClientRegistrationException extends RuntimeException
{
public function __construct(
string $message,
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/ElicitationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
*
* @author Johannes Wachter <johannes@sulu.io>
*/
final class ElicitationException extends \RuntimeException implements ExceptionInterface
final class ElicitationException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Exception/HandlerNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class HandlerNotFoundException extends \InvalidArgumentException implements NotFoundExceptionInterface
class HandlerNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface
{
}
2 changes: 1 addition & 1 deletion src/Exception/InvalidCursorException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class InvalidCursorException extends \InvalidArgumentException implements ExceptionInterface
final class InvalidCursorException extends InvalidArgumentException
{
public function __construct(
public readonly string $cursor,
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/InvalidInputMessageException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class InvalidInputMessageException extends \InvalidArgumentException implements ExceptionInterface
class InvalidInputMessageException extends InvalidArgumentException
{
private string|int|null $requestId = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*
* @author Christopher Hertel <mail@christopher-hertel.de>
*/
class MissingRequiredClientCapabilityException extends \RuntimeException implements ExceptionInterface
class MissingRequiredClientCapabilityException extends RuntimeException
{
public function __construct(
public readonly ClientCapabilities $requiredCapabilities,
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/PromptGetException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class PromptGetException extends \RuntimeException implements ExceptionInterface
final class PromptGetException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Exception/PromptNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class PromptNotFoundException extends \RuntimeException implements NotFoundExceptionInterface
final class PromptNotFoundException extends RuntimeException implements NotFoundExceptionInterface
{
public function __construct(
public readonly string $name,
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/RegistryException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use Mcp\Schema\JsonRpc\Error;

final class RegistryException extends \Exception implements ExceptionInterface
final class RegistryException extends Exception
{
public static function invalidParams(string $message = 'Invalid params', ?\Throwable $previous = null): self
{
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/ResourceNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class ResourceNotFoundException extends \RuntimeException implements NotFoundExceptionInterface
final class ResourceNotFoundException extends RuntimeException implements NotFoundExceptionInterface
{
public function __construct(
public readonly string $uri,
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/ResourceReadException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class ResourceReadException extends \RuntimeException implements ExceptionInterface
final class ResourceReadException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Exception/RootsException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
*
* @author Johannes Wachter <johannes@sulu.io>
*/
final class RootsException extends \RuntimeException implements ExceptionInterface
final class RootsException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Exception/RuntimeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
/**
* @author Christopher Hertel <mail@christopher-hertel.de>
*/
final class RuntimeException extends \RuntimeException implements ExceptionInterface
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
2 changes: 1 addition & 1 deletion src/Exception/SamplingException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
*
* @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/
final class SamplingException extends \RuntimeException implements ExceptionInterface
final class SamplingException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Exception/ToolCallException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class ToolCallException extends \RuntimeException implements ExceptionInterface
final class ToolCallException extends RuntimeException
{
}
2 changes: 1 addition & 1 deletion src/Exception/ToolNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
final class ToolNotFoundException extends \RuntimeException implements NotFoundExceptionInterface
final class ToolNotFoundException extends RuntimeException implements NotFoundExceptionInterface
{
public function __construct(
public readonly string $name,
Expand Down
2 changes: 2 additions & 0 deletions src/JsonRpc/MessageFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ private function createMessage(array $data): MessageInterface
$messageClass = $this->findMessageClassByMethod($data['method']);

return $messageClass::fromArray($data);
} catch (InvalidInputMessageException $e) {
throw $e;
} catch (InvalidArgumentException $e) {
throw new InvalidInputMessageException($e->getMessage(), 0, $e);
}
Expand Down
71 changes: 71 additions & 0 deletions tests/Unit/Exception/ExceptionHierarchyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/*
* This file is part of the official PHP MCP SDK.
*
* A collaboration between Symfony and the PHP Foundation.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Mcp\Tests\Unit\Exception;

use Mcp\Exception\BadMethodCallException;
use Mcp\Exception\Exception;
use Mcp\Exception\ExceptionInterface;
use Mcp\Exception\InvalidArgumentException;
use Mcp\Exception\LogicException;
use Mcp\Exception\RuntimeException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class ExceptionHierarchyTest extends TestCase
{
/**
* The SDK-level base classes every concrete exception must descend from,
* so that `catch (\Mcp\Exception\RuntimeException)` and friends work.
*/
private const BASE_CLASSES = [
Exception::class,
RuntimeException::class,
InvalidArgumentException::class,
LogicException::class,
BadMethodCallException::class,
];

#[DataProvider('provideConcreteExceptions')]
public function testExceptionExtendsAnMcpBaseClass(string $class): void
{
$this->assertTrue(
is_subclass_of($class, ExceptionInterface::class),
\sprintf('"%s" must implement "%s".', $class, ExceptionInterface::class),
);

foreach (self::BASE_CLASSES as $base) {
if (is_subclass_of($class, $base)) {
$this->addToAssertionCount(1);

return;
}
}

$this->fail(\sprintf('"%s" must extend one of the Mcp\Exception base classes, so it is catchable through them.', $class));
}

/**
* @return iterable<string, array{class-string}>
*/
public static function provideConcreteExceptions(): iterable
{
foreach (glob(\dirname(__DIR__, 3).'/src/Exception/*.php') ?: [] as $file) {
$class = 'Mcp\Exception\\'.basename($file, '.php');

if (!class_exists($class) || \in_array($class, self::BASE_CLASSES, true)) {
continue;
}

yield $class => [$class];
}
}
}
12 changes: 12 additions & 0 deletions tests/Unit/JsonRpc/MessageFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,18 @@ public function testMissingAllIdentifyingFields(): void
$this->assertStringContainsString('missing', $results[0]->getMessage());
}

public function testInvalidInputMessageExceptionIsNotReWrapped(): void
{
$missingMethod = $this->factory->create('{"jsonrpc": "2.0", "params": {}}');
$unknownMethod = $this->factory->create('{"jsonrpc": "2.0", "method": "unknown/method", "id": 1}');

foreach ([$missingMethod[0], $unknownMethod[0]] as $exception) {
$this->assertInstanceOf(InvalidInputMessageException::class, $exception);
$this->assertSame(InvalidInputMessageException::class, $exception::class);
$this->assertNull($exception->getPrevious());
}
}

public function testUnknownMethod(): void
{
$json = '{"jsonrpc": "2.0", "method": "unknown/method", "id": 1}';
Expand Down