Skip to content

Add readme and license headers #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 29, 2025
Merged
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
96 changes: 96 additions & 0 deletions .doctor-rst.yaml
Original file line number Diff line number Diff line change
@@ -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: ~
51 changes: 46 additions & 5 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
@@ -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 changes: 26 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"require-dev": {
"php": ">=8.1",
"symfony/filesystem": "^6.4|^7.0",
"symfony/finder": "^6.4|^7.0"
"symfony/finder": "^6.4|^7.0",
"php-cs-fixer/shim": "^3.75"
}
}
121 changes: 14 additions & 107 deletions src/mcp-sdk/README.md
Original file line number Diff line number Diff line change
@@ -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
```

## Usage with Symfony

Server integration points for are tailored to Symfony Console and HttpFoundation (Laravel compatible).

### Console Command for STDIO Server

```php
namespace App\Command;

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;
}
}
composer require symfony/mcp-sdk
```

### Controller for Server-Sent Events Server
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.

```php
namespace App\Controller;
**This repository is a READ-ONLY sub-tree split**. See
https://github.com/symfony/ai to create issues or submit pull requests.

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;
## Resources

#[AsController]
#[Route('/mcp', name: 'mcp_')]
final readonly class McpController
{
public function __construct(
private Server $server,
private CachePoolStore $store,
private UrlGeneratorInterface $urlGenerator,
) {
}
- [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)

#[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
6 changes: 3 additions & 3 deletions src/mcp-sdk/composer.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -31,12 +31,12 @@
},
"autoload": {
"psr-4": {
"PhpLlm\\McpSdk\\": "src/"
"Symfony\\AI\\McpSdk\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"PhpLlm\\McpSdk\\Tests\\": "tests/"
"Symfony\\AI\\McpSdk\\Tests\\": "tests/"
}
}
}
Loading