Skip to content

Commit 7883cee

Browse files
feat: Initial commit
0 parents  commit 7883cee

File tree

78 files changed

+5176
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+5176
-0
lines changed

.github/workflows/changelog.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: "Update Changelog"
2+
3+
on:
4+
release:
5+
types: [released]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
update:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
with:
18+
ref: main
19+
20+
- name: Update Changelog
21+
uses: stefanzweifel/changelog-updater-action@v1
22+
with:
23+
latest-version: ${{ github.event.release.name }}
24+
release-notes: ${{ github.event.release.body }}
25+
26+
- name: Commit updated CHANGELOG
27+
uses: stefanzweifel/git-auto-commit-action@v5
28+
with:
29+
branch: main
30+
commit_message: Update CHANGELOG
31+
file_pattern: CHANGELOG.md

.gitignore

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Composer dependencies
2+
/vendor/
3+
/composer.lock
4+
5+
# PHPUnit
6+
.phpunit.result.cache
7+
8+
# PHP CS Fixer
9+
/.php-cs-fixer.cache
10+
/.php-cs-fixer.php
11+
12+
# Editor directories and files
13+
/.idea
14+
/.vscode
15+
*.sublime-project
16+
*.sublime-workspace
17+
18+
# Operating system files
19+
.DS_Store
20+
Thumbs.db
21+
22+
# Local environment files
23+
/.env
24+
/.env.backup
25+
/.env.local
26+
27+
# PHP CodeSniffer
28+
/.phpcs.xml
29+
/.phpcs.xml.dist
30+
/phpcs.xml
31+
/phpcs.xml.dist
32+
33+
# PHPStan
34+
/phpstan.neon
35+
/phpstan.neon.dist
36+
37+
# Local development tools
38+
/.php_cs
39+
/.php_cs.cache
40+
/.php_cs.dist
41+
/_ide_helper.php
42+
/.php-cs-fixer.php
43+
44+
# Build artifacts
45+
/build/
46+
/coverage/
47+
48+
# PHPUnit coverage reports
49+
/clover.xml
50+
/coverage.xml
51+
/coverage/
52+
53+
# Laravel generated files
54+
bootstrap/cache/
55+
.phpunit.result.cache
56+
57+
# Local Composer dependencies
58+
composer.phar
59+
60+
workbench
61+
playground
62+
63+
# Log files
64+
*.log
65+
66+
# Cache files
67+
cache

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Kyrian Obikwelu
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# PHP MCP Schema
2+
3+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/php-mcp/schema.svg?style=flat-square)](https://packagist.org/packages/php-mcp/schema)
4+
[![Total Downloads](https://img.shields.io/packagist/dt/php-mcp/schema.svg?style=flat-square)](https://packagist.org/packages/php-mcp/schema)
5+
[![License](https://img.shields.io/packagist/l/php-mcp/schema.svg?style=flat-square)](LICENSE)
6+
7+
This package provides PHP Data Transfer Objects (DTOs) and Enums for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) schema. It is intended to be used by PHP implementations of MCP servers and clients, ensuring type safety and consistency with the official specification.
8+
9+
Current MCP Schema Version: [**2025-03-26**](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-03-26/schema.ts)
10+
11+
## Installation
12+
13+
```bash
14+
composer require php-mcp/schema
15+
```
16+
17+
## Usage
18+
19+
This package contains PHP classes and enums that directly correspond to the types defined in the official MCP TypeScript schema (linked above). These can be used for:
20+
21+
* Type-hinting in your MCP server or client application logic.
22+
* Serializing PHP objects into arrays that match the MCP JSON structure before sending them over a transport.
23+
* Deserializing associative arrays (from decoded JSON) received from an MCP transport into strongly-typed PHP objects.
24+
25+
### DTO Features
26+
27+
Each Data Transfer Object (DTO) class typically provides:
28+
29+
* **Readonly Public Properties:** For immutability and direct access to data fields.
30+
* **Constructor:** For instantiating objects with all required properties and optional ones.
31+
* **Static `make(...): static` Method:** (For most DTOs) A convenient alternative factory method, often mirroring the constructor's signature, allowing for a fluent instantiation style.
32+
* **`toArray(): array` Method:** Converts the DTO instance into an associative array suitable for `json_encode()`. Optional properties with `null` values are typically omitted from the output array for cleaner JSON.
33+
* **Static `fromArray(array $data): static` Factory Method:** Constructs a DTO instance from an associative array (e.g., after `json_decode(..., true)`). This method usually includes validation for required fields.
34+
* **`JsonSerializable` Interface:** Most DTOs implement this, allowing them to be directly used with `json_encode()`.
35+
36+
See the `src/` directory for all available schema types, organized by their functional area within the Model Context Protocol.
37+
38+
## Contributing
39+
40+
Contributions are welcome! Please refer to the contributing guidelines of the main `php-mcp` project.
41+
42+
## License
43+
44+
MIT License. See [LICENSE](LICENSE) file.

composer.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "php-mcp/schema",
3+
"description": "PHP Data Transfer Objects (DTOs) and Enums for the Model Context Protocol (MCP) schema.",
4+
"type": "library",
5+
"license": "MIT",
6+
"autoload": {
7+
"psr-4": {
8+
"PhpMcp\\Schema\\": "src/"
9+
}
10+
},
11+
"authors": [
12+
{
13+
"name": "Kyrian Obikwelu",
14+
"email": "koshnawaza@gmail.com"
15+
}
16+
],
17+
"minimum-stability": "stable",
18+
"require": {
19+
"php": ">=8.1"
20+
}
21+
}

src/Annotations.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMcp\Schema;
6+
7+
use PhpMcp\Schema\Enum\Role;
8+
use JsonSerializable;
9+
10+
/**
11+
* Optional annotations for the client. The client can use annotations
12+
* to inform how objects are used or displayed.
13+
*/
14+
class Annotations implements JsonSerializable
15+
{
16+
/**
17+
* @param Role[]|null $audience Describes who the intended customer of this object or data is.
18+
*
19+
* It can include multiple entries to indicate content useful for multiple audiences (e.g., `[Role::User, Role::Assistant]`).
20+
*
21+
* @param float|null $priority Describes how important this data is for operating the server.
22+
*
23+
* A value of 1 means "most important," and indicates that the data is
24+
* effectively required, while 0 means "least important," and indicates that
25+
* the data is entirely optional.
26+
*/
27+
public function __construct(
28+
public readonly ?array $audience = null,
29+
public readonly ?float $priority = null
30+
) {
31+
if ($this->priority !== null && ($this->priority < 0 || $this->priority > 1)) {
32+
throw new \InvalidArgumentException("Annotation priority must be between 0 and 1.");
33+
}
34+
if ($this->audience !== null) {
35+
foreach ($this->audience as $role) {
36+
if (!($role instanceof Role)) {
37+
throw new \InvalidArgumentException("All audience members must be instances of Role enum.");
38+
}
39+
}
40+
}
41+
}
42+
43+
/**
44+
* @param Role[]|null $audience Describes who the intended customer of this object or data is.
45+
*
46+
* It can include multiple entries to indicate content useful for multiple audiences (e.g., `[Role::User, Role::Assistant]`).
47+
*
48+
* @param float|null $priority Describes how important this data is for operating the server.
49+
*
50+
* A value of 1 means "most important," and indicates that the data is
51+
* effectively required, while 0 means "least important," and indicates that
52+
* the data is entirely optional.
53+
*/
54+
public static function make(array $audience = null, float $priority = null): static
55+
{
56+
return new static($audience, $priority);
57+
}
58+
59+
public function toArray(): array
60+
{
61+
$data = [];
62+
if ($this->audience !== null) {
63+
$data['audience'] = array_map(fn (Role $r) => $r->value, $this->audience);
64+
}
65+
if ($this->priority !== null) {
66+
$data['priority'] = $this->priority;
67+
}
68+
return $data;
69+
}
70+
71+
public static function fromArray(array $data): static
72+
{
73+
$audience = null;
74+
if (isset($data['audience']) && is_array($data['audience'])) {
75+
$audience = array_map(fn (string $r) => Role::from($r), $data['audience']);
76+
}
77+
return new static(
78+
$audience,
79+
isset($data['priority']) ? (float)$data['priority'] : null
80+
);
81+
}
82+
83+
public function jsonSerialize(): array
84+
{
85+
return $this->toArray();
86+
}
87+
}

src/ClientCapabilities.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMcp\Schema;
6+
7+
use JsonSerializable;
8+
9+
/**
10+
* Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.
11+
*/
12+
class ClientCapabilities implements JsonSerializable
13+
{
14+
/**
15+
* Present if the client supports listing roots.
16+
* @var array{ listChanged: bool }|null
17+
*/
18+
public readonly ?array $roots;
19+
20+
/**
21+
* Present if the client supports sampling from an LLM.
22+
*/
23+
public readonly ?array $sampling;
24+
25+
/**
26+
* Experimental, non-standard capabilities that the client supports.
27+
*/
28+
public readonly ?array $experimental;
29+
30+
public function __construct(
31+
?bool $rootsListChanged = null,
32+
?bool $sampling = null,
33+
?array $experimental = null
34+
) {
35+
$this->roots = ($rootsListChanged !== null) ? ['listChanged' => $rootsListChanged] : null;
36+
$this->sampling = ($sampling === true) ? [] : $sampling;
37+
$this->experimental = $experimental;
38+
}
39+
40+
public static function make(?bool $rootsListChanged = null, ?bool $sampling = null, ?array $experimental = null): static
41+
{
42+
return new static($rootsListChanged, $sampling, $experimental);
43+
}
44+
45+
public function toArray(): array
46+
{
47+
$data = [];
48+
if ($this->roots !== null) {
49+
$data['roots'] = (object) $this->roots;
50+
}
51+
if ($this->sampling !== null) {
52+
$data['sampling'] = (object) $this->sampling;
53+
}
54+
if ($this->experimental !== null) {
55+
$data['experimental'] = $this->experimental;
56+
}
57+
return $data;
58+
}
59+
60+
public static function fromArray(array $data): static
61+
{
62+
$rootsListChanged = null;
63+
if (isset($data['roots'])) {
64+
if (is_array($data['roots']) && array_key_exists('listChanged', $data['roots'])) {
65+
$rootsListChanged = (bool) $data['roots']['listChanged'];
66+
} elseif (is_object($data['roots']) && property_exists($data['roots'], 'listChanged')) {
67+
$rootsListChanged = (bool) $data['roots']->listChanged;
68+
}
69+
}
70+
71+
$sampling = null;
72+
if (isset($data['sampling'])) {
73+
$sampling = true;
74+
}
75+
76+
return new static(
77+
$rootsListChanged,
78+
$sampling,
79+
$data['experimental'] ?? null
80+
);
81+
}
82+
83+
public function jsonSerialize(): array
84+
{
85+
return $this->toArray();
86+
}
87+
}

src/Constants.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMcp\Schema;
6+
7+
final class Constants
8+
{
9+
public const LATEST_PROTOCOL_VERSION = "2025-03-26";
10+
public const JSONRPC_VERSION = "2.0";
11+
12+
public const PARSE_ERROR = -32700;
13+
public const INVALID_REQUEST = -32600;
14+
public const METHOD_NOT_FOUND = -32601;
15+
public const INVALID_PARAMS = -32602;
16+
public const INTERNAL_ERROR = -32603;
17+
18+
public const SERVER_ERROR = -32000;
19+
private function __construct() {}
20+
}

0 commit comments

Comments
 (0)