Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
46.15% covered (danger)
46.15%
12 / 26
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PhpMyFaqMcpServer
46.15% covered (danger)
46.15%
12 / 26
75.00% covered (warning)
75.00%
3 / 4
8.90
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 runConsole
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getServerInfo
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createServerInfo
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * phpMyFAQ MCP Server
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2025 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2025-08-16
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Service\McpServer;
21
22use phpMyFAQ\Configuration;
23use phpMyFAQ\Faq;
24use phpMyFAQ\Language;
25use phpMyFAQ\Search;
26use phpMyFAQ\System;
27use Symfony\Component\Console\Input\InputInterface;
28use Symfony\Component\Console\Output\OutputInterface;
29
30/**
31 * Class PhpMyFaqMcpServer
32 *
33 * Main MCP server class for phpMyFAQ that sets up and runs the Model Context Protocol server
34 * with FAQ search capabilities. This allows LLM models to query the phpMyFAQ knowledge base
35 * through the MCP protocol.
36 */
37class PhpMyFaqMcpServer implements McpServerRuntimeInterface
38{
39    private McpServerRuntimeInterface $runtime;
40
41    private const string MCP_SERVER_NAME = 'phpMyFAQ MCP Server';
42
43    public function __construct(
44        private readonly Configuration $configuration,
45        Language $language,
46        private readonly Search $search,
47        private readonly Faq $faq,
48        ?McpServerRuntimeInterface $runtime = null,
49    ) {
50        $detectionEnabled = (bool) $this->configuration->get(item: 'main.languageDetection');
51        $configLang = (string) $this->configuration->get(item: 'main.language');
52        $detectionEnabled
53            ? $language->setLanguageWithDetection($configLang)
54            : $language->setLanguageFromConfiguration($configLang);
55
56        $this->configuration->setLanguage($language);
57        $this->runtime = $runtime ?? new McpSdkRuntime(
58            new FaqSearchTool($this->configuration, $this->search, $this->faq),
59            $this->createServerInfo(),
60        );
61    }
62
63    /**
64     * Run the MCP server with console transport
65     */
66    public function runConsole(InputInterface $input, OutputInterface $output): void
67    {
68        $this->runtime->runConsole($input, $output);
69    }
70
71    /**
72     * Get server information for debugging
73     */
74    public function getServerInfo(): array
75    {
76        return $this->runtime->getServerInfo();
77    }
78
79    /**
80     * @return array<string, mixed>
81     */
82    private function createServerInfo(): array
83    {
84        return [
85            'name' => self::MCP_SERVER_NAME,
86            'version' => System::getMcpServerVersion(),
87            'description' => 'Model Context Protocol server for phpMyFAQ installations',
88            'capabilities' => [
89                'tools' => true,
90            ],
91            'tools' => [
92                [
93                    'name' => 'faq_search',
94                    'description' => 'Search through phpMyFAQ installations',
95                ],
96            ],
97        ];
98    }
99}