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
|
||||
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/sessions
|
||||
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:
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
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.
|
||||
*
|
||||
* @var array<int, class-string<Request|Notification>>
|
||||
* @var list<class-string<Request>|class-string<Notification>>
|
||||
*/
|
||||
private const REGISTERED_MESSAGES = [
|
||||
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(
|
||||
private readonly array $registeredMessages,
|
||||
|
|
@ -151,7 +151,7 @@ final class MessageFactory
|
|||
/**
|
||||
* Finds the registered message class for a given method name.
|
||||
*
|
||||
* @return class-string<Request|Notification>
|
||||
* @return class-string<Request>|class-string<Notification>
|
||||
*
|
||||
* @throws InvalidInputMessageException
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ use Psr\SimpleCache\CacheInterface;
|
|||
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
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue