diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 00000000..ff15d7ff
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,35 @@
+name: Deploy Documentation
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.4'
+ coverage: "none"
+
+ - name: Install Composer
+ uses: "ramsey/composer-install@v3"
+
+ - name: Generate Documentation
+ run: make docs
+
+ - name: Deploy to gh-pages branch
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./.phpdoc/build
+ enable_jekyll: false
diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml
index cb769d43..90d85ad4 100644
--- a/.github/workflows/pipeline.yaml
+++ b/.github/workflows/pipeline.yaml
@@ -142,3 +142,6 @@ jobs:
- name: PHPStan
run: vendor/bin/phpstan analyse
+
+ - name: Documentation
+ run: make docs
diff --git a/.gitignore b/.gitignore
index 45c94f10..6dc5d9ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,7 @@ examples/**/sessions
tests/Conformance/results
tests/Conformance/sessions
tests/Conformance/logs/*.log
+
+# phpDocumentor
+.phpdoc/build/
+.phpdoc/cache/
diff --git a/.phpdoc/template/base.html.twig b/.phpdoc/template/base.html.twig
new file mode 100644
index 00000000..760f1652
--- /dev/null
+++ b/.phpdoc/template/base.html.twig
@@ -0,0 +1,13 @@
+{% extends 'layout.html.twig' %}
+
+{% set topMenu = {
+ "menu": [
+ { "name": "Guides", "url": "docs/index.html"},
+ { "name": "Specification", "url": "https://modelcontextprotocol.io/" }
+ ],
+ "social": [
+ { "iconClass": "fab fa-github", "url": "https://github.com/modelcontextprotocol/php-sdk"},
+ { "iconClass": "fab fa-discord", "url": "https://discord.gg/6CSzBmMkjX"}
+ ]
+}
+%}
diff --git a/.phpdoc/template/components/header-title.html.twig b/.phpdoc/template/components/header-title.html.twig
new file mode 100644
index 00000000..fe8d091f
--- /dev/null
+++ b/.phpdoc/template/components/header-title.html.twig
@@ -0,0 +1,10 @@
+
diff --git a/Makefile b/Makefile
index 3f62692d..5358de25 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: deps-stable deps-low cs phpstan tests unit-tests inspector-tests coverage ci ci-stable ci-lowest conformance-tests
+.PHONY: deps-stable deps-low cs phpstan tests unit-tests inspector-tests coverage ci ci-stable ci-lowest conformance-tests docs
deps-stable:
composer update --prefer-stable
@@ -36,3 +36,8 @@ ci: ci-stable
ci-stable: deps-stable cs phpstan tests
ci-lowest: deps-low cs phpstan tests
+
+docs:
+ vendor/bin/phpdoc
+ @grep -q 'No errors have been found' .phpdoc/build/reports/errors.html || \
+ (echo "Documentation errors found. See build/docs/reports/errors.html" && exit 1)
diff --git a/composer.json b/composer.json
index e0c2edbc..8803947c 100644
--- a/composer.json
+++ b/composer.json
@@ -36,7 +36,9 @@
"laminas/laminas-httphandlerrunner": "^2.12",
"nyholm/psr7": "^1.8",
"nyholm/psr7-server": "^1.1",
+ "phar-io/composer-distributor": "^1.0.2",
"php-cs-fixer/shim": "^3.91",
+ "phpdocumentor/shim": "^3",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^10.5",
"psr/simple-cache": "^2.0 || ^3.0",
@@ -69,7 +71,8 @@
},
"config": {
"allow-plugins": {
- "php-http/discovery": false
+ "php-http/discovery": false,
+ "phpdocumentor/shim": true
},
"sort-packages": true
}
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..5bfe45ea
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,7 @@
+# MCP PHP SDK Guides
+
+- [MCP Elements](mcp-elements.md) — Core capabilities (Tools, Resources, Resource Templates, and Prompts) with registration methods.
+- [Server Builder](server-builder.md) — Fluent builder class for creating and configuring MCP server instances.
+- [Transports](transports.md) — STDIO and HTTP transport implementations with guidance on choosing between them.
+- [Server-Client Communication](server-client-communication.md) — Methods for servers to communicate back to clients: sampling, logging, progress, and notifications.
+- [Examples](examples.md) — Example projects demonstrating attribute-based discovery, dependency injection, HTTP transport, and more.
diff --git a/docs/client-communication.md b/docs/server-client-communication.md
similarity index 100%
rename from docs/client-communication.md
rename to docs/server-client-communication.md
diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml
new file mode 100644
index 00000000..b209b815
--- /dev/null
+++ b/phpdoc.dist.xml
@@ -0,0 +1,44 @@
+
+
+ MCP PHP SDK
+
+
+
+
+ latest
+
+
+ src
+
+
+
+ vendor/**/*
+ tests/**/*
+
+
+ phpstan-type
+ phpstan-type-import
+ template
+ template-covariant
+ template-extends
+ template-implements
+ extends
+ implements
+
+
+
+
+ docs
+
+
+
+
+
+
+
+
diff --git a/src/JsonRpc/MessageFactory.php b/src/JsonRpc/MessageFactory.php
index 2ca446c2..1bb82db8 100644
--- a/src/JsonRpc/MessageFactory.php
+++ b/src/JsonRpc/MessageFactory.php
@@ -37,7 +37,7 @@ final class MessageFactory
/**
* Registry of all known message classes that have methods.
*
- * @var array>
+ * @var list|class-string>
*/
private const REGISTERED_MESSAGES = [
Schema\Notification\CancelledNotification::class,
@@ -68,7 +68,7 @@ final class MessageFactory
];
/**
- * @param array> $registeredMessages
+ * @param list|class-string> $registeredMessages
*/
public function __construct(
private readonly array $registeredMessages,
@@ -151,7 +151,7 @@ private function createMessage(array $data): MessageInterface
/**
* Finds the registered message class for a given method name.
*
- * @return class-string
+ * @return class-string|class-string
*
* @throws InvalidInputMessageException
*/
diff --git a/src/Server/Session/Psr16StoreSession.php b/src/Server/Session/Psr16StoreSession.php
index aacf0ffc..2f403f1a 100644
--- a/src/Server/Session/Psr16StoreSession.php
+++ b/src/Server/Session/Psr16StoreSession.php
@@ -17,12 +17,12 @@
use Symfony\Component\Uid\Uuid;
/**
- * @author luoyue <1569097443@qq.com>
- *
* PSR-16 compliant cache-based session store.
*
* This implementation uses any PSR-16 compliant cache as the storage backend
* for session data. Each session is stored with a prefixed key using the session ID.
+ *
+ * @author luoyue <1569097443@qq.com>
*/
class Psr16StoreSession implements SessionStoreInterface
{