mirror of
https://github.com/symfony/ai.git
synced 2026-03-23 23:42:18 +01:00
add readme and license headers
This commit is contained in:
96
.doctor-rst.yaml
Normal file
96
.doctor-rst.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
rules:
|
||||
american_english: ~
|
||||
argument_variable_must_match_type: ~
|
||||
avoid_repetetive_words: ~
|
||||
# be_kind_to_newcomers: ~
|
||||
blank_line_after_anchor: ~
|
||||
# blank_line_after_colon: ~
|
||||
blank_line_after_directive: ~
|
||||
# blank_line_after_filepath_in_code_block: ~
|
||||
# blank_line_after_filepath_in_php_code_block: ~
|
||||
# blank_line_after_filepath_in_twig_code_block: ~
|
||||
# blank_line_after_filepath_in_xml_code_block: ~
|
||||
# blank_line_after_filepath_in_yaml_code_block: ~
|
||||
blank_line_before_directive: ~
|
||||
# composer_dev_option_at_the_end: ~
|
||||
composer_dev_option_not_at_the_end: ~
|
||||
correct_code_block_directive_based_on_the_content: ~
|
||||
deprecated_directive_major_version:
|
||||
major_version: 2
|
||||
deprecated_directive_min_version:
|
||||
min_version: '2.0'
|
||||
deprecated_directive_should_have_version: ~
|
||||
ensure_bash_prompt_before_composer_command: ~
|
||||
ensure_exactly_one_space_before_directive_type: ~
|
||||
ensure_exactly_one_space_between_link_definition_and_link: ~
|
||||
ensure_link_definition_contains_valid_url: ~
|
||||
ensure_order_of_code_blocks_in_configuration_block: ~
|
||||
extend_abstract_admin: ~
|
||||
extend_abstract_controller: ~
|
||||
# extend_controller: ~
|
||||
extension_xlf_instead_of_xliff: ~
|
||||
# filename_uses_dashes_only: ~
|
||||
# filename_uses_underscores_only: ~
|
||||
final_admin_classes: ~
|
||||
final_admin_extension_classes: ~
|
||||
forbidden_directives:
|
||||
directives:
|
||||
- '.. index::'
|
||||
indention: ~
|
||||
kernel_instead_of_app_kernel: ~
|
||||
# line_length: ~
|
||||
lowercase_as_in_use_statements: ~
|
||||
max_blank_lines:
|
||||
max: 2
|
||||
max_colons: ~
|
||||
no_admin_yaml: ~
|
||||
no_app_bundle: ~
|
||||
no_app_console: ~
|
||||
# no_bash_prompt: ~
|
||||
no_blank_line_after_filepath_in_code_block: ~
|
||||
no_blank_line_after_filepath_in_php_code_block: ~
|
||||
no_blank_line_after_filepath_in_twig_code_block: ~
|
||||
no_blank_line_after_filepath_in_xml_code_block: ~
|
||||
no_blank_line_after_filepath_in_yaml_code_block: ~
|
||||
no_brackets_in_method_directive: ~
|
||||
no_composer_phar: ~
|
||||
no_composer_req: ~
|
||||
no_config_yaml: ~
|
||||
# no_contraction: ~
|
||||
no_directive_after_shorthand: ~
|
||||
no_explicit_use_of_code_block_php: ~
|
||||
no_inheritdoc_in_code_examples: ~
|
||||
no_merge_conflict: ~
|
||||
no_namespace_after_use_statements: ~
|
||||
no_php_open_tag_in_code_block_php_directive: ~
|
||||
# no_php_prefix_before_bin_console: ~
|
||||
# no_php_prefix_before_composer: ~
|
||||
# no_space_before_self_xml_closing_tag: ~
|
||||
only_backslashes_in_namespace_in_php_code_block: ~
|
||||
only_backslashes_in_use_statements_in_php_code_block: ~
|
||||
ordered_use_statements: ~
|
||||
# php_open_tag_in_code_block_php_directive: ~
|
||||
php_prefix_before_bin_console: ~
|
||||
replace_code_block_types: ~
|
||||
replacement: ~
|
||||
short_array_syntax: ~
|
||||
# space_before_self_xml_closing_tag: ~
|
||||
space_between_label_and_link_in_doc: ~
|
||||
space_between_label_and_link_in_ref: ~
|
||||
string_replacement: ~
|
||||
title_underline_length_must_match_title_length: ~
|
||||
typo: ~
|
||||
unused_links: ~
|
||||
use_deprecated_directive_instead_of_versionadded: ~
|
||||
use_https_xsd_urls: ~
|
||||
# use_named_constructor_without_new_keyword_rule: ~
|
||||
valid_inline_highlighted_namespaces: ~
|
||||
valid_use_statements: ~
|
||||
versionadded_directive_major_version:
|
||||
major_version: 2
|
||||
versionadded_directive_min_version:
|
||||
min_version: '2.0'
|
||||
versionadded_directive_should_have_version: ~
|
||||
yaml_instead_of_yml_suffix: ~
|
||||
yarn_dev_option_at_the_end: ~
|
||||
# yarn_dev_option_not_at_the_end: ~
|
||||
@@ -1,13 +1,54 @@
|
||||
<?php
|
||||
|
||||
$finder = (new PhpCsFixer\Finder())
|
||||
->in('src')
|
||||
->exclude(['var', 'vendor'])
|
||||
;
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (!file_exists(__DIR__.'/src')) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$fileHeaderParts = [
|
||||
<<<'EOF'
|
||||
This file is part of the Symfony package.
|
||||
|
||||
(c) Fabien Potencier <fabien@symfony.com>
|
||||
|
||||
EOF,
|
||||
<<<'EOF'
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
EOF,
|
||||
];
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
// @see https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/pull/7777
|
||||
->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
|
||||
->setRules([
|
||||
'@PHP71Migration' => true,
|
||||
'@PHPUnit75Migration:risky' => true,
|
||||
'@Symfony' => true,
|
||||
'@Symfony:risky' => true,
|
||||
'protected_to_private' => false,
|
||||
'declare_strict_types' => true,
|
||||
'header_comment' => [
|
||||
'header' => implode('', $fileHeaderParts),
|
||||
],
|
||||
])
|
||||
->setFinder($finder)
|
||||
->setRiskyAllowed(true)
|
||||
->setFinder(
|
||||
(new PhpCsFixer\Finder())
|
||||
->in(__DIR__.'/src')
|
||||
->append([__FILE__])
|
||||
->notPath('#/Fixtures/#')
|
||||
)
|
||||
->setCacheFile('.php-cs-fixer.cache')
|
||||
;
|
||||
|
||||
26
CONTRIBUTING.md
Normal file
26
CONTRIBUTING.md
Normal file
@@ -0,0 +1,26 @@
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Symfony is an open source, community-driven project.
|
||||
|
||||
If you'd like to contribute, please read the following documents:
|
||||
|
||||
* [Reviewing issues/pull requests][0]
|
||||
* [Reporting a Bug][1]
|
||||
* [Submitting a Patch][2]
|
||||
* [Symfony Core Team][3]
|
||||
* [Security Issues][4]
|
||||
* [Running Symfony Tests][5]
|
||||
* [Our Backwards Compatibility Promise][6]
|
||||
* [Coding Standards][7]
|
||||
* [Conventions][8]
|
||||
|
||||
[0]: https://symfony.com/doc/current/contributing/community/reviews.html
|
||||
[1]: https://symfony.com/doc/current/contributing/code/bugs.html
|
||||
[2]: https://symfony.com/doc/current/contributing/code/patches.html
|
||||
[3]: https://symfony.com/doc/current/contributing/code/core_team.html
|
||||
[4]: https://symfony.com/doc/current/contributing/code/security.html
|
||||
[5]: https://symfony.com/doc/current/contributing/code/tests.html
|
||||
[6]: https://symfony.com/doc/current/contributing/code/bc.html
|
||||
[7]: https://symfony.com/doc/current/contributing/code/standards.html
|
||||
[8]: https://symfony.com/doc/current/contributing/code/conventions.html
|
||||
20
README.md
Normal file
20
README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
<p align="center"><a href="https://symfony.com" target="_blank">
|
||||
<img src="https://symfony.com/logos/symfony_dynamic_01.svg" alt="Symfony Logo">
|
||||
</a></p>
|
||||
|
||||
<h3 align="center">
|
||||
Symfony AI
|
||||
</h3>
|
||||
|
||||
Symfony AI is a set of packages that integrate AI capabilities into PHP applications.
|
||||
|
||||
## Sponsor
|
||||
|
||||
Help Symfony by [sponsoring][2] its development!
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to Symfony AI! You can find the [contribution guide here](CONTRIBUTING.md).
|
||||
|
||||
[1]: https://symfony.com/backers
|
||||
[2]: https://symfony.com/sponsor
|
||||
@@ -1,119 +1,26 @@
|
||||
# Model Context Protocol PHP SDK [WIP]
|
||||
# Model Context Protocol PHP SDK
|
||||
|
||||
Model Context Protocol SDK for Client and Server applications in PHP.
|
||||
**Currently only support Tool Calls as Server via Server-Sent Events (SSE) and STDIO.**
|
||||
|
||||
See [Demo App](https://github.com/php-llm/mcp-demo) for a working example and [MCP Bundle](https://github.com/php-llm/mcp-bundle) for Symfony integration.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
composer require php-llm/mcp-sdk
|
||||
composer require symfony/mcp-sdk
|
||||
```
|
||||
|
||||
## Usage with Symfony
|
||||
This is a low level SDK that implements the [Model Context Protocol](https://modelcontextprotocol.io/)
|
||||
(MCP). The protocol is used by LLM model to build "plugins" and give them extra
|
||||
context. Example the logged in users' latest order.
|
||||
|
||||
Server integration points for are tailored to Symfony Console and HttpFoundation (Laravel compatible).
|
||||
**This repository is a READ-ONLY sub-tree split**. See
|
||||
https://github.com/symfony/ai to create issues or submit pull requests.
|
||||
|
||||
### Console Command for STDIO Server
|
||||
## Resources
|
||||
|
||||
```php
|
||||
namespace App\Command;
|
||||
- [Documentation](doc/index.rst)
|
||||
- [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)
|
||||
|
||||
use PhpLlm\McpSdk\Server;
|
||||
use PhpLlm\McpSdk\Server\Transport\Stdio\SymfonyConsoleTransport;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand('mcp', 'Starts an MCP server')]
|
||||
final class McpCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Server $server,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$this->server->connect(
|
||||
new SymfonyConsoleTransport($input, $output)
|
||||
);
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Controller for Server-Sent Events Server
|
||||
|
||||
```php
|
||||
namespace App\Controller;
|
||||
|
||||
use PhpLlm\McpSdk\Server;
|
||||
use PhpLlm\McpSdk\Server\Transport\Sse\Store\CachePoolStore;
|
||||
use PhpLlm\McpSdk\Server\Transport\Sse\StreamTransport;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
#[AsController]
|
||||
#[Route('/mcp', name: 'mcp_')]
|
||||
final readonly class McpController
|
||||
{
|
||||
public function __construct(
|
||||
private Server $server,
|
||||
private CachePoolStore $store,
|
||||
private UrlGeneratorInterface $urlGenerator,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/sse', name: 'sse', methods: ['GET'])]
|
||||
public function sse(): StreamedResponse
|
||||
{
|
||||
$id = Uuid::v4();
|
||||
$endpoint = $this->urlGenerator->generate('mcp_messages', ['id' => $id], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$transport = new StreamTransport($endpoint, $this->store, $id);
|
||||
|
||||
return new StreamedResponse(fn() => $this->server->connect($transport), headers: [
|
||||
'Content-Type' => 'text/event-stream',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'X-Accel-Buffering' => 'no',
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/messages/{id}', name: 'messages', methods: ['POST'])]
|
||||
public function messages(Request $request, Uuid $id): Response
|
||||
{
|
||||
$this->store->push($id, $request->getContent());
|
||||
|
||||
return new Response();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Exposing Tools
|
||||
|
||||
Under the hood the SDK uses [LLM Chain](https://github.com/php-llm/llm-chain)'s `ToolBox` to register, analyze and
|
||||
execute tools. In combination with its [Symfony Bundle](https://github.com/php-llm/llm-chain-bundle) you can expose
|
||||
tools with `#[AsTool]` attribute.
|
||||
|
||||
```php
|
||||
use PhpLlm\LlmChain\ToolBox\Attribute\AsTool;
|
||||
|
||||
#[AsTool('company_name', 'Provides the name of your company')]
|
||||
final class CompanyName
|
||||
{
|
||||
public function __invoke(): string
|
||||
{
|
||||
return 'ACME Corp.'
|
||||
}
|
||||
}
|
||||
```
|
||||
See [LLM Chain Documentation](https://github.com/php-llm/llm-chain?tab=readme-ov-file#tools) for more information.
|
||||
[1]: https://symfony.com/backers
|
||||
[3]: https://symfony.com/sponsor
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "php-llm/mcp-sdk",
|
||||
"name": "symfony/mcp-sdk",
|
||||
"type": "library",
|
||||
"description": "Model Context Protocol SDK for Client and Server applications in PHP",
|
||||
"license": "MIT",
|
||||
|
||||
32
src/mcp-sdk/doc/index.rst
Normal file
32
src/mcp-sdk/doc/index.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
Model Context Protocol SDK
|
||||
==========================
|
||||
|
||||
Symfony AI MCP SDK is the low level library that enables communication between
|
||||
a PHP application and an LLM model.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install the bundle using Composer:
|
||||
|
||||
.. code-block:: terminal
|
||||
|
||||
$ composer require symfony/mcp-sdk
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The `Model Context Protocol`_ is built on top of JSON-RPC. There two types of
|
||||
messages. A Notification and Request. The Notification is just a status update
|
||||
that something has happened. There is never a response to a Notification. A Request
|
||||
is a message that expects a response. There are 3 concepts that you may request.
|
||||
These are::
|
||||
|
||||
1. **Resources**: File-like data that can be read by clients (like API responses or file contents)
|
||||
1. **Tools**: Functions that can be called by the LLM (with user approval)
|
||||
1. **Prompts**: Pre-written templates that help users accomplish specific tasks
|
||||
|
||||
The SDK comes with NotificationHandlers and RequestHandlers which are expected
|
||||
to be wired up in your application.
|
||||
|
||||
.. _`Model Context Protocol`: https://modelcontextprotocol.io/
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
use Symfony\Component\Console as SymfonyConsole;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\PromptChain;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Prompt\MetadataInterface;
|
||||
@@ -18,7 +29,7 @@ class ExamplePrompt implements MetadataInterface, PromptGetterInterface
|
||||
$this->getDescription(),
|
||||
[new PromptGetResultMessages(
|
||||
'user',
|
||||
sprintf('Hello %s', $firstName ?? 'World')
|
||||
\sprintf('Hello %s', $firstName ?? 'World')
|
||||
)]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Resource\MetadataInterface;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Tool\MetadataInterface;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
interface CollectionInterface
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
interface IdentifierInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
interface MetadataInterface extends IdentifierInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
final readonly class PromptGet
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
final readonly class PromptGetResult
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
final readonly class PromptGetResultMessages
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Prompt;
|
||||
|
||||
use PhpLlm\McpSdk\Exception\PromptGetException;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Prompt\CollectionInterface;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Resource;
|
||||
|
||||
interface CollectionInterface
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Resource;
|
||||
|
||||
interface IdentifierInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Resource;
|
||||
|
||||
interface MetadataInterface extends IdentifierInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Resource;
|
||||
|
||||
final readonly class ResourceRead
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Resource;
|
||||
|
||||
final readonly class ResourceReadResult
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Resource;
|
||||
|
||||
use PhpLlm\McpSdk\Exception\ResourceNotFoundException;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Resource\CollectionInterface;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
interface CollectionInterface
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
interface IdentifierInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
interface MetadataInterface extends IdentifierInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
final readonly class ToolCall
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
final readonly class ToolCallResult
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
interface ToolCollectionInterface
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability\Tool;
|
||||
|
||||
use PhpLlm\McpSdk\Exception\ToolExecutionException;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Capability;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Tool\CollectionInterface;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
interface ExceptionInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
interface NotFoundExceptionInterface extends ExceptionInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Prompt\PromptGet;
|
||||
@@ -12,6 +21,6 @@ final class PromptGetException extends \RuntimeException implements ExceptionInt
|
||||
public readonly PromptGet $promptGet,
|
||||
?\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct(sprintf('Handling prompt "%s" failed with error: %s', $promptGet->name, $previous->getMessage()), previous: $previous);
|
||||
parent::__construct(\sprintf('Handling prompt "%s" failed with error: %s', $promptGet->name, $previous->getMessage()), previous: $previous);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Prompt\PromptGet;
|
||||
@@ -11,6 +20,6 @@ final class PromptNotFoundException extends \RuntimeException implements NotFoun
|
||||
public function __construct(
|
||||
public readonly PromptGet $promptGet,
|
||||
) {
|
||||
parent::__construct(sprintf('Resource not found for uri: "%s"', $promptGet->name));
|
||||
parent::__construct(\sprintf('Resource not found for uri: "%s"', $promptGet->name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Resource\ResourceRead;
|
||||
@@ -11,6 +20,6 @@ final class ResourceNotFoundException extends \RuntimeException implements NotFo
|
||||
public function __construct(
|
||||
public readonly ResourceRead $readRequest,
|
||||
) {
|
||||
parent::__construct(sprintf('Resource not found for uri: "%s"', $readRequest->uri));
|
||||
parent::__construct(\sprintf('Resource not found for uri: "%s"', $readRequest->uri));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Resource\ResourceRead;
|
||||
@@ -12,6 +21,6 @@ final class ResourceReadException extends \RuntimeException implements Exception
|
||||
public readonly ResourceRead $readRequest,
|
||||
?\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct(sprintf('Reading resource "%s" failed with error: %s', $readRequest->uri, $previous?->getMessage() ?? ''), previous: $previous);
|
||||
parent::__construct(\sprintf('Reading resource "%s" failed with error: %s', $readRequest->uri, $previous?->getMessage() ?? ''), previous: $previous);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Tool\ToolCall;
|
||||
@@ -12,6 +21,6 @@ final class ToolExecutionException extends \RuntimeException implements Exceptio
|
||||
public readonly ToolCall $toolCall,
|
||||
?\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct(sprintf('Execution of tool "%s" failed with error: %s', $toolCall->name, $previous?->getMessage() ?? ''), previous: $previous);
|
||||
parent::__construct(\sprintf('Execution of tool "%s" failed with error: %s', $toolCall->name, $previous?->getMessage() ?? ''), previous: $previous);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Exception;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Tool\ToolCall;
|
||||
@@ -11,6 +20,6 @@ final class ToolNotFoundException extends \RuntimeException implements NotFoundE
|
||||
public function __construct(
|
||||
public readonly ToolCall $toolCall,
|
||||
) {
|
||||
parent::__construct(sprintf('Tool not found for call: "%s"', $toolCall->name));
|
||||
parent::__construct(\sprintf('Tool not found for call: "%s"', $toolCall->name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Message;
|
||||
|
||||
final readonly class Error implements \JsonSerializable
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Message;
|
||||
|
||||
final class Factory
|
||||
{
|
||||
public function create(string $json): Request|Notification
|
||||
{
|
||||
$data = json_decode($json, true, flags: JSON_THROW_ON_ERROR);
|
||||
$data = json_decode($json, true, flags: \JSON_THROW_ON_ERROR);
|
||||
|
||||
if (!isset($data['method'])) {
|
||||
throw new \InvalidArgumentException('Invalid JSON-RPC request, missing method');
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Message;
|
||||
|
||||
final readonly class Notification implements \JsonSerializable, \Stringable
|
||||
@@ -40,6 +49,6 @@ final readonly class Notification implements \JsonSerializable, \Stringable
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('%s', $this->method);
|
||||
return \sprintf('%s', $this->method);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Message;
|
||||
|
||||
final class Request implements \JsonSerializable, \Stringable
|
||||
@@ -43,6 +52,6 @@ final class Request implements \JsonSerializable, \Stringable
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('%s: %s', $this->id, $this->method);
|
||||
return \sprintf('%s: %s', $this->id, $this->method);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Message;
|
||||
|
||||
final readonly class Response implements \JsonSerializable
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk;
|
||||
|
||||
use PhpLlm\McpSdk\Server\JsonRpcHandler;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Error;
|
||||
@@ -68,7 +77,7 @@ readonly class JsonRpcHandler
|
||||
} catch (\DomainException) {
|
||||
return null;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->logger->warning(sprintf('Failed to create response: %s', $e->getMessage()), ['exception' => $e]);
|
||||
$this->logger->warning(\sprintf('Failed to create response: %s', $e->getMessage()), ['exception' => $e]);
|
||||
|
||||
return $this->encodeResponse(Error::methodNotFound($message->id ?? 0, $e->getMessage()));
|
||||
}
|
||||
@@ -85,10 +94,10 @@ readonly class JsonRpcHandler
|
||||
$this->logger->info('Encoding response', ['response' => $response]);
|
||||
|
||||
if ($response instanceof Response && [] === $response->result) {
|
||||
return json_encode($response, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT);
|
||||
return json_encode($response, \JSON_THROW_ON_ERROR | \JSON_FORCE_OBJECT);
|
||||
}
|
||||
|
||||
return json_encode($response, JSON_THROW_ON_ERROR);
|
||||
return json_encode($response, \JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
private function handleNotification(Notification $notification): null
|
||||
@@ -99,7 +108,7 @@ readonly class JsonRpcHandler
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->warning(sprintf('No handler found for "%s".', $notification->method), ['notification' => $notification]);
|
||||
$this->logger->warning(\sprintf('No handler found for "%s".', $notification->method), ['notification' => $notification]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -112,6 +121,6 @@ readonly class JsonRpcHandler
|
||||
}
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('No handler found for method "%s".', $request->method));
|
||||
throw new \InvalidArgumentException(\sprintf('No handler found for method "%s".', $request->method));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\NotificationHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Notification;
|
||||
@@ -11,7 +20,7 @@ abstract class BaseNotificationHandler implements NotificationHandlerInterface
|
||||
{
|
||||
public function supports(Notification $message): bool
|
||||
{
|
||||
return $message->method === sprintf('notifications/%s', $this->supportedNotification());
|
||||
return $message->method === \sprintf('notifications/%s', $this->supportedNotification());
|
||||
}
|
||||
|
||||
abstract protected function supportedNotification(): string;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\NotificationHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Notification;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Notification;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Request;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Request;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Request;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Prompt\PromptGet;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Prompt\CollectionInterface;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Resource\CollectionInterface;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Resource\ResourceRead;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Tool\ToolCall;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\RequestHandler;
|
||||
|
||||
use PhpLlm\McpSdk\Capability\Tool\CollectionInterface;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Error;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\Transport\Sse\Store;
|
||||
|
||||
use PhpLlm\McpSdk\Server\Transport\Sse\StoreInterface;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\Transport\Sse;
|
||||
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\Transport\Sse;
|
||||
|
||||
use PhpLlm\McpSdk\Server\TransportInterface;
|
||||
@@ -44,9 +53,9 @@ final readonly class StreamTransport implements TransportInterface
|
||||
|
||||
private function flushEvent(string $event, string $data): void
|
||||
{
|
||||
echo sprintf('event: %s', $event).PHP_EOL;
|
||||
echo sprintf('data: %s', $data).PHP_EOL;
|
||||
echo PHP_EOL;
|
||||
echo \sprintf('event: %s', $event).\PHP_EOL;
|
||||
echo \sprintf('data: %s', $data).\PHP_EOL;
|
||||
echo \PHP_EOL;
|
||||
if (false !== ob_get_length()) {
|
||||
ob_flush();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server\Transport\Stdio;
|
||||
|
||||
use PhpLlm\McpSdk\Server\TransportInterface;
|
||||
@@ -33,14 +42,14 @@ final class SymfonyConsoleTransport implements TransportInterface
|
||||
|
||||
public function receive(): \Generator
|
||||
{
|
||||
$stream = $this->input instanceof StreamableInputInterface ? $this->input->getStream() ?? STDIN : STDIN;
|
||||
$stream = $this->input instanceof StreamableInputInterface ? $this->input->getStream() ?? \STDIN : \STDIN;
|
||||
$line = fgets($stream);
|
||||
if (false === $line) {
|
||||
return;
|
||||
}
|
||||
$this->buffer .= STDIN === $stream ? rtrim($line).PHP_EOL : $line;
|
||||
if (str_contains($this->buffer, PHP_EOL)) {
|
||||
$lines = explode(PHP_EOL, $this->buffer);
|
||||
$this->buffer .= \STDIN === $stream ? rtrim($line).\PHP_EOL : $line;
|
||||
if (str_contains($this->buffer, \PHP_EOL)) {
|
||||
$lines = explode(\PHP_EOL, $this->buffer);
|
||||
$this->buffer = array_pop($lines);
|
||||
|
||||
yield from $lines;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Server;
|
||||
|
||||
interface TransportInterface
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Tests\Message;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Error;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Tests\Message;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Factory;
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Tests\Message;
|
||||
|
||||
use PhpLlm\McpSdk\Message\Response;
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpLlm\McpSdk\Tests;
|
||||
|
||||
use PhpLlm\McpSdk\Server;
|
||||
|
||||
Reference in New Issue
Block a user