Replace ToolRegistration DTO and array plugin definitions with typed PluginDefinitionInterface objects
## Description Replace the `ToolRegistration` DTO and the array-based plugin definitions used across `mcp_server` with typed `PluginDefinitionInterface` objects produced directly by attribute discovery and derivers. Today plugin metadata flows through the codebase in two parallel shapes: the array plugin definition produced by Drupal's discovery layer, and a `ToolRegistration` DTO that `ToolPluginBase::getRegistration()` re-builds by re-reading the same array. The DTO duplicates the definition, hides which fields the SDK actually consumes, and exists only for tools — the other four plugin types (`ResourceProvider`, `ResourceTemplateProvider`, `Notification`, `PromptArgumentCompletionProvider`) read the same array shape inline through `$this->pluginDefinition['key']` lookups. The goal is to introduce one typed `*Definition` class per attribute, have each attribute extend its definition class so `AttributeBase::get()` returns the typed object verbatim, and migrate every consumer (plugin bases, plugin managers, factory, deriver, tests) to read typed properties. The `ToolRegistration` DTO, `ToolPluginInterface::getRegistration()`, `ToolPluginManager::getRegistrations()` and `ToolPluginManager::getTool()` are deleted in favour of a single `getDefinitions(): iterable<TypedDefinition>` flow. The unused `configEntity` field on `ToolRegistration` (no production consumers; only asserted in `ToolApiRegistrationTest`) is dropped entirely; derivative metadata is preserved on the typed definition as scalar fields (`mcpToolConfigId`, `toolId`). The full plan lives at `.ai/task-manager/plans/39--typed-plugin-definitions/plan-39--typed-plugin-definitions.md`. ## Acceptance Criteria - [ ] The `ToolRegistration` class is deleted; `grep -r 'ToolRegistration' web/modules/contrib/mcp_server/` returns no production-code matches. - [ ] `ToolPluginInterface::getRegistration()`, `ToolPluginManager::getRegistrations()` and `ToolPluginManager::getTool()` are deleted with no callers remaining. - [ ] Each of the five attributes (`Tool`, `ResourceProvider`, `ResourceTemplateProvider`, `Notification`, `PromptArgumentCompletionProvider`) extends a typed `*Definition` class implementing `Drupal\Component\Plugin\Definition\PluginDefinitionInterface`. - [ ] `getDefinitions()` on every plugin manager returns instances of those typed classes (verified by a kernel smoke test per manager). - [ ] No plugin base in `src/Plugin/*Base.php` reads from `$this->pluginDefinition[...]` array keys; all reads use typed property access. - [ ] `McpToolConfigDeriver` emits typed `ToolDefinition` clones (via an immutable `withDerivative(...)` helper) instead of associative arrays, and `ToolApi::execute()` reads `$this->pluginDefinition->toolId` instead of an array key. - [ ] `McpServerFactory::registerTools()` iterates `$toolPluginManager->getDefinitions()`, validates names locally (MCP NameValidator pattern + duplicate-name guard), and calls `Builder::addTool()` with typed-definition properties. - [ ] `ToolApiRegistrationTest` asserts on the typed definition (`$definition->mcpToolConfigId`, `$definition->toolId`, `$definition->inputSchema['properties']['message']`) instead of `$registration->configEntity`. - [ ] `vendor/bin/phpstan analyse web/modules/contrib/mcp_server/` passes at the configured level with no new errors. - [ ] Full PHPUnit suite (`tests/`, `modules/mcp_server_tool_bridge/tests/`, `modules/mcp_server_oauth/tests/`) passes; `vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/contrib/mcp_server/` reports no style regressions. - [ ] Documentation is updated: `references/tools/index.md`, `AGENTS.md` and `references/sdk/index.md` describe the typed-definition contract; mentions of `ToolRegistration` and `getRegistration()` are removed. ## Additional Context This issue layers on top of #3585862 (collapse SDK-dispatch shim so plugins are the SDK's `RuntimeToolHandlerInterface`) and the single-tool-per-plugin assumption. It is a straight refactor with no backwards-compatibility layer — the module is unreleased per `AGENTS.md`. Note: this is distinct from #3585867 (a bug in `ToolAutocompleteController` treating `ToolDefinition` as an array) and from the deferred items tracked in #3585865, though all three move the codebase toward the same end state of typed plugin definitions throughout. Caches are a low risk: typed definitions are `final readonly` with scalar/array properties and `TranslatableMarkup` (already serialised today by attribute discovery). Out of scope: `McpPromptConfig` entity, resource provider config storage, and the `mcp_server_oauth` per-tool OAuth metadata flow (independent of the DTO).
issue