Add API documentation generation with phpDocumentor (#184)
* Add API documentation generation with phpDocumentor - Add phpDocumentor configuration and `docs` Makefile target - Generate docs during CI to catch errors before releases - Set up GitHub Pages with Jekyll for hosting generated docs - Add GitHub Actions workflow to deploy docs to GitHub Pages on releases 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix phpDocumentor errors in type annotations Change class-string union types to use phpDocumentor-compatible syntax and reorder docblock tags so class descriptions precede `@author` tags. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix CI: pin phar-io/composer-distributor ^1.0.2 phar-io/composer-distributor 1.0.0 has a bug where it uses the wrong package version when determining the phpDocumentor download URL, causing CI to fail with 404 errors when using --prefer-lowest. Version 1.0.2 fixes this issue. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Integrate markdown guides into phpDocumentor output Configure phpDocumentor to generate both API documentation and user guides in a single unified site. This replaces the previous Jekyll-based approach where API docs were copied into the docs folder. - Add `<guide>` configuration to `phpdoc.dist.xml` - Create custom template with "Guides" navigation link - Replace `docs/index.html` redirect with `docs/index.md` guide index - Update workflow to publish `build/docs` directly without Jekyll - Track `.phpdoc/template/` while still ignoring `.phpdoc/cache/` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fine-tuning for path, config, and layout --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
This commit is contained in:
parent
2fe982505f
commit
940eb90872
12 changed files with 131 additions and 7 deletions
35
.github/workflows/docs.yml
vendored
Normal file
35
.github/workflows/docs.yml
vendored
Normal file
|
|
@ -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
|
||||||
3
.github/workflows/pipeline.yaml
vendored
3
.github/workflows/pipeline.yaml
vendored
|
|
@ -142,3 +142,6 @@ jobs:
|
||||||
|
|
||||||
- name: PHPStan
|
- name: PHPStan
|
||||||
run: vendor/bin/phpstan analyse
|
run: vendor/bin/phpstan analyse
|
||||||
|
|
||||||
|
- name: Documentation
|
||||||
|
run: make docs
|
||||||
|
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -9,3 +9,7 @@ examples/**/sessions
|
||||||
tests/Conformance/results
|
tests/Conformance/results
|
||||||
tests/Conformance/sessions
|
tests/Conformance/sessions
|
||||||
tests/Conformance/logs/*.log
|
tests/Conformance/logs/*.log
|
||||||
|
|
||||||
|
# phpDocumentor
|
||||||
|
.phpdoc/build/
|
||||||
|
.phpdoc/cache/
|
||||||
|
|
|
||||||
13
.phpdoc/template/base.html.twig
Normal file
13
.phpdoc/template/base.html.twig
Normal file
|
|
@ -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"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
%}
|
||||||
10
.phpdoc/template/components/header-title.html.twig
Normal file
10
.phpdoc/template/components/header-title.html.twig
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<h1 class="phpdocumentor-title">
|
||||||
|
<a href="{{ path('/docs/index.html') }}" class="phpdocumentor-title__link">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 195 195" fill="none">
|
||||||
|
<path d="M25 97.8528L92.8823 29.9706C102.255 20.598 117.451 20.598 126.823 29.9706V29.9706C136.196 39.3431 136.196 54.5391 126.823 63.9117L75.5581 115.177" stroke="black" stroke-width="12" stroke-linecap="round"/>
|
||||||
|
<path d="M76.2653 114.47L126.823 63.9117C136.196 54.5391 151.392 54.5391 160.765 63.9117L161.118 64.2652C170.491 73.6378 170.491 88.8338 161.118 98.2063L99.7248 159.6C96.6006 162.724 96.6006 167.789 99.7248 170.913L112.331 183.52" stroke="black" stroke-width="12" stroke-linecap="round"/>
|
||||||
|
<path d="M109.853 46.9411L59.6482 97.1457C50.2757 106.518 50.2757 121.714 59.6482 131.087V131.087C69.0208 140.459 84.2168 140.459 93.5894 131.087L143.794 80.8822" stroke="black" stroke-width="12" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
<span style="margin-left: 0.25em;">{{ project.name }}</span>
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
7
Makefile
7
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:
|
deps-stable:
|
||||||
composer update --prefer-stable
|
composer update --prefer-stable
|
||||||
|
|
@ -36,3 +36,8 @@ ci: ci-stable
|
||||||
ci-stable: deps-stable cs phpstan tests
|
ci-stable: deps-stable cs phpstan tests
|
||||||
|
|
||||||
ci-lowest: deps-low 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)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,9 @@
|
||||||
"laminas/laminas-httphandlerrunner": "^2.12",
|
"laminas/laminas-httphandlerrunner": "^2.12",
|
||||||
"nyholm/psr7": "^1.8",
|
"nyholm/psr7": "^1.8",
|
||||||
"nyholm/psr7-server": "^1.1",
|
"nyholm/psr7-server": "^1.1",
|
||||||
|
"phar-io/composer-distributor": "^1.0.2",
|
||||||
"php-cs-fixer/shim": "^3.91",
|
"php-cs-fixer/shim": "^3.91",
|
||||||
|
"phpdocumentor/shim": "^3",
|
||||||
"phpstan/phpstan": "^2.1",
|
"phpstan/phpstan": "^2.1",
|
||||||
"phpunit/phpunit": "^10.5",
|
"phpunit/phpunit": "^10.5",
|
||||||
"psr/simple-cache": "^2.0 || ^3.0",
|
"psr/simple-cache": "^2.0 || ^3.0",
|
||||||
|
|
@ -69,7 +71,8 @@
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
"php-http/discovery": false
|
"php-http/discovery": false,
|
||||||
|
"phpdocumentor/shim": true
|
||||||
},
|
},
|
||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
docs/index.md
Normal file
7
docs/index.md
Normal file
|
|
@ -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.
|
||||||
78
docs/server-client-communication.md
Normal file
78
docs/server-client-communication.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Client Communication
|
||||||
|
|
||||||
|
MCP supports various ways a server can communicate back to a server on top of the main request-response flow.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [ClientGateway](#client-gateway)
|
||||||
|
- [Sampling](#sampling)
|
||||||
|
- [Logging](#logging)
|
||||||
|
- [Notification](#notification)
|
||||||
|
- [Progress](#progress)
|
||||||
|
|
||||||
|
## ClientGateway
|
||||||
|
|
||||||
|
Every communication back to client is handled using the `Mcp\Server\ClientGateway` and its dedicated methods per
|
||||||
|
operation. To use the `ClientGateway` in your code, you need to use method argument injection for `RequestContext`.
|
||||||
|
|
||||||
|
Every reference of a MCP element, that translates to an actual method call, can just add an type-hinted argument for the
|
||||||
|
`RequestContext` and the SDK will take care to include the gateway in the arguments of the method call:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Mcp\Capability\Attribute\McpTool;
|
||||||
|
use Mcp\Server\RequestContext;
|
||||||
|
|
||||||
|
class MyService
|
||||||
|
{
|
||||||
|
#[McpTool('my_tool', 'My Tool Description')]
|
||||||
|
public function myTool(RequestContext $context): string
|
||||||
|
{
|
||||||
|
$context->getClientGateway()->log(...);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sampling
|
||||||
|
|
||||||
|
With [sampling](https://modelcontextprotocol.io/specification/2025-06-18/client/sampling) servers can request clients to
|
||||||
|
execute "completions" or "generations" with a language model for them:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$result = $clientGateway->sample('Roses are red, violets are', 350, 90, ['temperature' => 0.5]);
|
||||||
|
```
|
||||||
|
|
||||||
|
The `sample` method accepts four arguments:
|
||||||
|
|
||||||
|
1. `message`, which is **required** and accepts a string, an instance of `Content` or an array of `SampleMessage` instances.
|
||||||
|
2. `maxTokens`, which defaults to `1000`
|
||||||
|
3. `timeout` in seconds, which defaults to `120`
|
||||||
|
4. `options` which might include `system_prompt`, `preferences` for model choice, `includeContext`, `temperature`, `stopSequences` and `metadata`
|
||||||
|
|
||||||
|
[Find more details to sampling payload in the specification.](https://modelcontextprotocol.io/specification/2025-06-18/client/sampling#protocol-messages)
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
The [Logging](https://modelcontextprotocol.io/specification/2025-06-18/server/utilities/logging) utility enables servers
|
||||||
|
to send structured log messages as notifcation to clients:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Mcp\Schema\Enum\LoggingLevel;
|
||||||
|
|
||||||
|
$clientGateway->log(LoggingLevel::Warning, 'The end is near.');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Progress
|
||||||
|
|
||||||
|
With a [Progress](https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/progress#progress)
|
||||||
|
notification a server can update a client while an operation is ongoing:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$clientGateway->progress(4.2, 10, 'Downloading needed images.');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notification
|
||||||
|
|
||||||
|
Lastly, the server can push all kind of notifications, that implement the `Mcp\Schema\JsonRpc\Notification` interface
|
||||||
|
to the client to:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$clientGateway->notify($yourNotification);
|
||||||
|
```
|
||||||
44
phpdoc.dist.xml
Normal file
44
phpdoc.dist.xml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<phpdocumentor
|
||||||
|
configVersion="3"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="https://www.phpdoc.org"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://docs.phpdoc.org/latest/phpdoc.xsd"
|
||||||
|
>
|
||||||
|
<title>MCP PHP SDK</title>
|
||||||
|
<paths>
|
||||||
|
<output>.phpdoc/build</output>
|
||||||
|
</paths>
|
||||||
|
<version number="latest">
|
||||||
|
<folder>latest</folder>
|
||||||
|
<api ignore-packages="true">
|
||||||
|
<source dsn=".">
|
||||||
|
<path>src</path>
|
||||||
|
</source>
|
||||||
|
<output>api</output>
|
||||||
|
<ignore>
|
||||||
|
<path>vendor/**/*</path>
|
||||||
|
<path>tests/**/*</path>
|
||||||
|
</ignore>
|
||||||
|
<ignore-tags>
|
||||||
|
<ignore-tag>phpstan-type</ignore-tag>
|
||||||
|
<ignore-tag>phpstan-type-import</ignore-tag>
|
||||||
|
<ignore-tag>template</ignore-tag>
|
||||||
|
<ignore-tag>template-covariant</ignore-tag>
|
||||||
|
<ignore-tag>template-extends</ignore-tag>
|
||||||
|
<ignore-tag>template-implements</ignore-tag>
|
||||||
|
<ignore-tag>extends</ignore-tag>
|
||||||
|
<ignore-tag>implements</ignore-tag>
|
||||||
|
</ignore-tags>
|
||||||
|
</api>
|
||||||
|
<guide format="md">
|
||||||
|
<source dsn=".">
|
||||||
|
<path>docs</path>
|
||||||
|
</source>
|
||||||
|
<output>/</output>
|
||||||
|
</guide>
|
||||||
|
</version>
|
||||||
|
<setting name="guides.enabled" value="true"/>
|
||||||
|
<setting name="graphs.enabled" value="false"/>
|
||||||
|
<setting name="template.color" value="black"/>
|
||||||
|
</phpdocumentor>
|
||||||
|
|
@ -37,7 +37,7 @@ final class MessageFactory
|
||||||
/**
|
/**
|
||||||
* Registry of all known message classes that have methods.
|
* Registry of all known message classes that have methods.
|
||||||
*
|
*
|
||||||
* @var array<int, class-string<Request|Notification>>
|
* @var list<class-string<Request>|class-string<Notification>>
|
||||||
*/
|
*/
|
||||||
private const REGISTERED_MESSAGES = [
|
private const REGISTERED_MESSAGES = [
|
||||||
Schema\Notification\CancelledNotification::class,
|
Schema\Notification\CancelledNotification::class,
|
||||||
|
|
@ -68,7 +68,7 @@ final class MessageFactory
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int, class-string<Request|Notification>> $registeredMessages
|
* @param list<class-string<Request>|class-string<Notification>> $registeredMessages
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly array $registeredMessages,
|
private readonly array $registeredMessages,
|
||||||
|
|
@ -151,7 +151,7 @@ final class MessageFactory
|
||||||
/**
|
/**
|
||||||
* Finds the registered message class for a given method name.
|
* Finds the registered message class for a given method name.
|
||||||
*
|
*
|
||||||
* @return class-string<Request|Notification>
|
* @return class-string<Request>|class-string<Notification>
|
||||||
*
|
*
|
||||||
* @throws InvalidInputMessageException
|
* @throws InvalidInputMessageException
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,12 @@ use Psr\SimpleCache\CacheInterface;
|
||||||
use Symfony\Component\Uid\Uuid;
|
use Symfony\Component\Uid\Uuid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author luoyue <1569097443@qq.com>
|
|
||||||
*
|
|
||||||
* PSR-16 compliant cache-based session store.
|
* PSR-16 compliant cache-based session store.
|
||||||
*
|
*
|
||||||
* This implementation uses any PSR-16 compliant cache as the storage backend
|
* 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.
|
* for session data. Each session is stored with a prefixed key using the session ID.
|
||||||
|
*
|
||||||
|
* @author luoyue <1569097443@qq.com>
|
||||||
*/
|
*/
|
||||||
class Psr16StoreSession implements SessionStoreInterface
|
class Psr16StoreSession implements SessionStoreInterface
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue