Skip to content
Closed
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
1 change: 0 additions & 1 deletion .phpstan/ForbidNativeExceptionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ final class ForbidNativeExceptionRule implements Rule
'Symfony\\AI\\Agent' => 'Symfony\\AI\\Agent\\Exception\\',
'Symfony\\AI\\Platform' => 'Symfony\\AI\\Platform\\Exception\\',
'Symfony\\AI\\Store' => 'Symfony\\AI\\Store\\Exception\\',
'Symfony\\AI\\McpSdk' => 'Symfony\\AI\\McpSdk\\Exception\\',
'Symfony\\AI\\AiBundle' => 'Symfony\\AI\\AiBundle\\Exception\\',
'Symfony\\AI\\McpBundle' => 'Symfony\\AI\\McpBundle\\Exception\\',
];
Expand Down
5 changes: 2 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ This is the Symfony AI monorepo containing multiple components and bundles that
- **Platform** (`src/platform/`): Unified interface to AI platforms (OpenAI, Anthropic, Azure, Gemini, VertexAI, etc.)
- **Agent** (`src/agent/`): Framework for building AI agents that interact with users and perform tasks
- **Store** (`src/store/`): Data storage abstraction with indexing and retrieval for vector databases
- **MCP SDK** (`src/mcp-sdk/`): SDK for Model Context Protocol enabling agent-tool communication

### Integration Bundles
- **AI Bundle** (`src/ai-bundle/`): Symfony integration for Platform, Store, and Agent components
- **MCP Bundle** (`src/mcp-bundle/`): Symfony integration for MCP SDK
- **MCP Bundle** (`src/mcp-bundle/`): Symfony integration for official MCP SDK

### Supporting Directories
- **Examples** (`examples/`): Standalone examples demonstrating component usage across different AI platforms
Expand Down Expand Up @@ -92,7 +91,7 @@ symfony server:start
Components are designed to work independently but have these relationships:
- Agent depends on Platform for AI communication
- AI Bundle integrates Platform, Agent, and Store
- MCP Bundle provides MCP SDK integration
- MCP Bundle provides official MCP SDK integration
- Store is standalone but often used with Agent for RAG applications

## Testing Architecture
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ Symfony AI consists of several lower and higher level **components** and the res
* **[Platform](src/platform/README.md)**: A unified interface to various AI platforms like OpenAI, Anthropic, Azure, Gemini, VertexAI, and more.
* **[Agent](src/agent/README.md)**: Framework for building AI agents that can interact with users and perform tasks.
* **[Store](src/store/README.md)**: Data storage abstraction with indexing and retrieval for AI applications.
* **[MCP SDK](src/mcp-sdk/README.md)**: SDK for [Model Context Protocol](https://modelcontextprotocol.io) enabling communication between AI agents and tools.
* **Bundles**
* **[AI Bundle](src/ai-bundle/README.md)**: Symfony integration for AI Platform, Store and Agent components.
* **[MCP Bundle](src/mcp-bundle/README.md)**: Symfony integration for MCP SDK, allowing them to act as MCP servers or clients.
* **[MCP Bundle](src/mcp-bundle/README.md)**: Symfony integration for official [mcp/sdk](https://github.com/modelcontextprotocol/php-sdk), allowing them to act as MCP servers or clients.

## Examples & Demo

Expand All @@ -42,3 +41,4 @@ For testing multi-modal features, the repository contains binary media content,
* `tests/Fixture/image.jpg`: Chris F., Creative Commons, see [pexels.com](https://www.pexels.com/photo/blauer-und-gruner-elefant-mit-licht-1680755/)
* `tests/Fixture/audio.mp3`: davidbain, Creative Commons, see [freesound.org](https://freesound.org/people/davidbain/sounds/136777/)
* `tests/Fixture/document.pdf`: Chem8240ja, Public Domain, see [Wikipedia](https://en.m.wikipedia.org/wiki/File:Re_example.pdf)

43 changes: 16 additions & 27 deletions demo/src/MCP/Tools/CurrentTimeTool.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,27 @@

namespace App\MCP\Tools;

use Symfony\AI\McpSdk\Capability\Tool\MetadataInterface;
use Symfony\AI\McpSdk\Capability\Tool\ToolAnnotationsInterface;
use Symfony\AI\McpSdk\Capability\Tool\ToolCall;
use Symfony\AI\McpSdk\Capability\Tool\ToolCallResult;
use Symfony\AI\McpSdk\Capability\Tool\ToolExecutorInterface;
use Mcp\Capability\Tool\IdentifierInterface;
use Mcp\Capability\Tool\MetadataInterface;
use Mcp\Capability\Tool\ToolExecutorInterface;
use Mcp\Schema\Content\TextContent;
use Mcp\Schema\Request\CallToolRequest;
use Mcp\Schema\Result\CallToolResult;

/**
* @author Tom Hart <tom.hart.221@gmail.com>
*/
class CurrentTimeTool implements MetadataInterface, ToolExecutorInterface
final class CurrentTimeTool implements IdentifierInterface, MetadataInterface, ToolExecutorInterface
{
public function call(ToolCall $input): ToolCallResult
public function call(CallToolRequest $request): CallToolResult
{
$format = $input->arguments['format'] ?? 'Y-m-d H:i:s';
$format = $request->arguments['format'] ?? 'Y-m-d H:i:s';

return new ToolCallResult(
(new \DateTime('now', new \DateTimeZone('UTC')))->format($format)
);
$timeString = (new \DateTime('now', new \DateTimeZone('UTC')))->format($format);

return new CallToolResult([
new TextContent($timeString),
]);
}

public function getName(): string
Expand All @@ -52,22 +55,8 @@ public function getInputSchema(): array
'default' => 'Y-m-d H:i:s',
],
],
'required' => ['format'],
'required' => [],
];
}

public function getOutputSchema(): ?array
{
return null;
}

public function getTitle(): ?string
{
return null;
}

public function getAnnotations(): ?ToolAnnotationsInterface
{
return null;
}
}

5 changes: 3 additions & 2 deletions src/mcp-bundle/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# MCP Bundle

Symfony integration bundle for [Model Context Protocol](https://modelcontextprotocol.io/) using the Symfony AI
MCP SDK [symfony/mcp-sdk](https://github.com/symfony/mcp-sdk).
Symfony integration bundle for [Model Context Protocol](https://modelcontextprotocol.io/) using the official
MCP SDK [mcp/sdk](https://github.com/modelcontextprotocol/php-sdk).

**Currently only supports tools as server via Server-Sent Events (SSE) and STDIO.**

Expand All @@ -25,3 +25,4 @@ https://github.com/symfony/ai to create issues or submit pull requests.
- [Report issues](https://github.com/symfony/ai/issues) and
[send Pull Requests](https://github.com/symfony/ai/pulls)
in the [main Symfony AI repository](https://github.com/symfony/ai)

4 changes: 2 additions & 2 deletions src/mcp-bundle/composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "symfony/mcp-bundle",
"type": "symfony-bundle",
"description": "Symfony integration bundle for Model Context Protocol (via symfony/mcp-sdk)",
"description": "Symfony integration bundle for Model Context Protocol (via mcp/sdk)",
"license": "MIT",
"authors": [
{
Expand All @@ -16,7 +16,7 @@
"symfony/framework-bundle": "^6.4 || ^7.0",
"symfony/http-foundation": "^6.4 || ^7.0",
"symfony/http-kernel": "^6.4 || ^7.0",
"symfony/mcp-sdk": "@dev",
"mcp/sdk": "dev-main",
"symfony/routing": "^6.4 || ^7.0"
},
"require-dev": {
Expand Down
32 changes: 32 additions & 0 deletions src/mcp-bundle/config/options.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@
->scalarNode('app')->defaultValue('app')->end()
->scalarNode('version')->defaultValue('0.0.1')->end()
->scalarNode('page_size')->defaultValue(20)->end()
->arrayNode('discovery')
->children()
->booleanNode('enabled')->defaultTrue()->end()
->arrayNode('directories')
->scalarPrototype()->end()
->defaultValue(['src'])
->end()
->arrayNode('exclude')
->scalarPrototype()->end()
->defaultValue(['vendor', 'var', 'tests'])
->end()
->end()
->end()
// ->arrayNode('servers')
// ->useAttributeAsKey('name')
// ->arrayPrototype()
Expand Down Expand Up @@ -55,6 +68,25 @@
// ->end()
// ->end()
// ->end()
->arrayNode('server_capabilities')
->addDefaultsIfNotSet()
->children()
->booleanNode('tools')->defaultTrue()->end()
->booleanNode('tools_list_changed')->defaultNull()->end()
->booleanNode('resources')->defaultNull()->end()
->booleanNode('resources_subscribe')->defaultFalse()->end()
->booleanNode('resources_list_changed')->defaultNull()->end()
->booleanNode('prompts')->defaultNull()->end()
->booleanNode('prompts_list_changed')->defaultNull()->end()
->booleanNode('logging')->defaultFalse()->end()
->booleanNode('completions')->defaultTrue()->end()
->arrayNode('experimental')
->useAttributeAsKey('name')
->variablePrototype()->end()
->defaultValue([])
->end()
->end()
->end()
->arrayNode('client_transports')
->children()
->booleanNode('stdio')->defaultFalse()->end()
Expand Down
80 changes: 38 additions & 42 deletions src/mcp-bundle/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,67 +11,63 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Symfony\AI\McpSdk\Capability\ToolChain;
use Symfony\AI\McpSdk\Message\Factory;
use Symfony\AI\McpSdk\Server;
use Symfony\AI\McpSdk\Server\JsonRpcHandler;
use Symfony\AI\McpSdk\Server\NotificationHandler\InitializedHandler;
use Symfony\AI\McpSdk\Server\RequestHandler\InitializeHandler;
use Symfony\AI\McpSdk\Server\RequestHandler\PingHandler;
use Symfony\AI\McpSdk\Server\RequestHandler\ToolCallHandler;
use Symfony\AI\McpSdk\Server\RequestHandler\ToolListHandler;
use Symfony\AI\McpSdk\Server\Transport\Sse\Store\CachePoolStore;
use Mcp\JsonRpc\Handler;
use Mcp\JsonRpc\MessageFactory;
use Mcp\Schema\Implementation;
use Mcp\Server;
use Mcp\Server\Transport\Sse\Store\CachePoolStore;
use Symfony\AI\McpBundle\Registry\SymfonyRegistry;
use Symfony\AI\McpBundle\Registry\SymfonyRegistryFactory;

return static function (ContainerConfigurator $container): void {
$container->services()
->set('mcp.server.notification_handler.initialized', InitializedHandler::class)
->args([])
->tag('mcp.server.notification_handler')
->set('mcp.server.request_handler.initialize', InitializeHandler::class)
// Registry factory for configuring discovery
->set('mcp.registry.factory', SymfonyRegistryFactory::class)
->args([
param('mcp.app'),
param('mcp.version'),
])
->tag('mcp.server.request_handler')
->set('mcp.server.request_handler.ping', PingHandler::class)
->args([])
->tag('mcp.server.request_handler')
->set('mcp.server.request_handler.tool_call', ToolCallHandler::class)
->args([
service('mcp.tool_executor'),
param('kernel.project_dir'),
param('mcp.discovery.enabled'),
param('mcp.discovery.directories'),
param('mcp.discovery.exclude'),
param('mcp.server_capabilities'),
service('logger')->ignoreOnInvalid(),
])
->tag('mcp.server.request_handler')
->set('mcp.server.request_handler.tool_list', ToolListHandler::class)

// Core Registry for managing tools, prompts, and resources
->set('mcp.registry', SymfonyRegistry::class)
->factory([service('mcp.registry.factory'), 'create'])

// Implementation info for the server
->set('mcp.implementation', Implementation::class)
->args([
service('mcp.tool_collection'),
param('mcp.page_size'),
param('mcp.app'),
param('mcp.version'),
])
->tag('mcp.server.request_handler')

->set('mcp.message_factory', Factory::class)
->args([])
->set('mcp.server.json_rpc', JsonRpcHandler::class)
// Message Factory
->set('mcp.message_factory', MessageFactory::class)
->factory([MessageFactory::class, 'make'])

// JSON-RPC Handler with all request and notification handlers
->set('mcp.json_rpc_handler', Handler::class)
->factory([Handler::class, 'make'])
->args([
service('mcp.message_factory'),
tagged_iterator('mcp.server.request_handler'),
tagged_iterator('mcp.server.notification_handler'),
service('mcp.registry'),
service('mcp.implementation'),
service('logger')->ignoreOnInvalid(),
])

// Main MCP Server
->set('mcp.server', Server::class)
->args([
service('mcp.server.json_rpc'),
service('mcp.json_rpc_handler'),
service('logger')->ignoreOnInvalid(),
])
->alias(Server::class, 'mcp.server')

// SSE Store for Server-Sent Events transport
->set('mcp.server.sse.store.cache_pool', CachePoolStore::class)
->args([
service('cache.app'),
])
->set('mcp.tool_chain', ToolChain::class)
->args([
tagged_iterator('mcp.tool'),
])
->alias('mcp.tool_executor', 'mcp.tool_chain')
->alias('mcp.tool_collection', 'mcp.tool_chain')
;
};
4 changes: 2 additions & 2 deletions src/mcp-bundle/doc/index.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MCP Bundle
==========

Symfony integration bundle for `Model Context Protocol`_ using the Symfony AI MCP SDK `symfony/mcp-sdk`_.
Symfony integration bundle for `Model Context Protocol`_ using the external MCP SDK `mcp/sdk`_.

**Currently only supports tools as server via Server-Sent Events (SSE) and STDIO.**

Expand Down Expand Up @@ -64,7 +64,7 @@ Configuration
url: 'http://localhost:8000/sse' # URL to SSE endpoint of MCP server

.. _`Model Context Protocol`: https://modelcontextprotocol.io/
.. _`symfony/mcp-sdk`: https://github.com/symfony/mcp-sdk
.. _`mcp/sdk`: https://github.com/modelcontextprotocol/php-sdk
.. _`Claude Desktop`: https://claude.ai/download
.. _`MCP Server List`: https://modelcontextprotocol.io/examples
.. _`AI Bundle`: https://github.com/symfony/ai-bundle
6 changes: 3 additions & 3 deletions src/mcp-bundle/src/Command/McpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

namespace Symfony\AI\McpBundle\Command;

use Symfony\AI\McpSdk\Server;
use Symfony\AI\McpSdk\Server\Transport\Stdio\SymfonyConsoleTransport;
use Mcp\Server;
use Mcp\Server\Transport\StdioTransport;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -30,7 +30,7 @@ public function __construct(
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->server->connect(
new SymfonyConsoleTransport($input, $output)
new StdioTransport(\STDIN, \STDOUT)
);

return Command::SUCCESS;
Expand Down
6 changes: 3 additions & 3 deletions src/mcp-bundle/src/Controller/McpController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

namespace Symfony\AI\McpBundle\Controller;

use Symfony\AI\McpSdk\Server;
use Symfony\AI\McpSdk\Server\Transport\Sse\Store\CachePoolStore;
use Symfony\AI\McpSdk\Server\Transport\Sse\StreamTransport;
use Mcp\Server;
use Mcp\Server\Transport\Sse\Store\CachePoolStore;
use Mcp\Server\Transport\Sse\StreamTransport;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
Expand Down
Loading
Loading