[Server] Fix: standardize error handling across handlers with MCP specificatio… (#124)

* fix: standardize error handling across handlers with MCP specification compliance

* Update mcp-elements.md

Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>

* docs: clarify error handling behavior for all element types

* docs: remove unnecessary whitespace in mcp-elements.md

* fix: simplify exception signatures to accept simple messages

* refactor: use specific exceptions in examples for better error handling

* feat: throw exceptions from reference provider instead of returning null

---------

Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
This commit is contained in:
Kyrian Obikwelu 2025-10-30 17:30:58 +01:00 • committed by GitHub
commit ca18caf29d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 278 additions and 185 deletions

View file

@ -23,6 +23,9 @@ use Mcp\Event\ResourceListChangedEvent;
use Mcp\Event\ResourceTemplateListChangedEvent;
use Mcp\Event\ToolListChangedEvent;
use Mcp\Exception\InvalidCursorException;
use Mcp\Exception\PromptNotFoundException;
use Mcp\Exception\ResourceNotFoundException;
use Mcp\Exception\ToolNotFoundException;
use Mcp\Schema\Page;
use Mcp\Schema\Prompt;
use Mcp\Schema\Resource;
@ -209,43 +212,41 @@ final class Registry implements ReferenceProviderInterface, ReferenceRegistryInt
}
}
public function getTool(string $name): ?ToolReference
public function getTool(string $name): ToolReference
{
return $this->tools[$name] ?? null;
return $this->tools[$name] ?? throw new ToolNotFoundException($name);
}
public function getResource(
string $uri,
bool $includeTemplates = true,
): ResourceReference|ResourceTemplateReference|null {
): ResourceReference|ResourceTemplateReference {
$registration = $this->resources[$uri] ?? null;
if ($registration) {
return $registration;
}
if (!$includeTemplates) {
return null;
}
foreach ($this->resourceTemplates as $template) {
if ($template->matches($uri)) {
return $template;
if ($includeTemplates) {
foreach ($this->resourceTemplates as $template) {
if ($template->matches($uri)) {
return $template;
}
}
}
$this->logger->debug('No resource matched URI.', ['uri' => $uri]);
return null;
throw new ResourceNotFoundException($uri);
}
public function getResourceTemplate(string $uriTemplate): ?ResourceTemplateReference
public function getResourceTemplate(string $uriTemplate): ResourceTemplateReference
{
return $this->resourceTemplates[$uriTemplate] ?? null;
return $this->resourceTemplates[$uriTemplate] ?? throw new ResourceNotFoundException($uriTemplate);
}
public function getPrompt(string $name): ?PromptReference
public function getPrompt(string $name): PromptReference
{
return $this->prompts[$name] ?? null;
return $this->prompts[$name] ?? throw new PromptNotFoundException($name);
}
public function getTools(?int $limit = null, ?string $cursor = null): Page

View file

@ -11,6 +11,9 @@
namespace Mcp\Capability\Registry;
use Mcp\Exception\PromptNotFoundException;
use Mcp\Exception\ResourceNotFoundException;
use Mcp\Exception\ToolNotFoundException;
use Mcp\Schema\Page;
/**
@ -23,23 +26,31 @@ interface ReferenceProviderInterface
{
/**
* Gets a tool reference by name.
*
* @throws ToolNotFoundException
*/
public function getTool(string $name): ?ToolReference;
public function getTool(string $name): ToolReference;
/**
* Gets a resource reference by URI (includes template matching if enabled).
*
* @throws ResourceNotFoundException
*/
public function getResource(string $uri, bool $includeTemplates = true): ResourceReference|ResourceTemplateReference|null;
public function getResource(string $uri, bool $includeTemplates = true): ResourceReference|ResourceTemplateReference;
/**
* Gets a resource template reference by URI template.
*
* @throws ResourceNotFoundException
*/
public function getResourceTemplate(string $uriTemplate): ?ResourceTemplateReference;
public function getResourceTemplate(string $uriTemplate): ResourceTemplateReference;
/**
* Gets a prompt reference by name.
*
* @throws PromptNotFoundException
*/
public function getPrompt(string $name): ?PromptReference;
public function getPrompt(string $name): PromptReference;
/**
* Gets all registered tools.