Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .docs/stdio-terminal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .docs/stdio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .docs/streamable-terminal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .docs/streamable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# EditorConfig is awesome: http://EditorConfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = tab
tab_width = 4

[*.{json,yaml,yml,md}]
indent_style = space
indent_size = 2
10 changes: 10 additions & 0 deletions .github/.kodiak.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version = 1

[merge]
automerge_label = "automerge"
blacklist_title_regex = "^WIP.*"
blacklist_labels = ["WIP"]
method = "rebase"
delete_branch_on_merge = true
notify_on_conflict = true
optimistic_updates = false
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: daily
labels:
- "dependencies"
- "automerge"
18 changes: 18 additions & 0 deletions .github/workflows/codesniffer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: "Codesniffer"

on:
pull_request:
workflow_dispatch:

push:
branches: ["*"]

schedule:
- cron: "0 8 * * 1"

jobs:
codesniffer:
name: "Codesniffer"
uses: contributte/.github/.github/workflows/codesniffer.yml@master
with:
php: "8.4"
19 changes: 19 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "Coverage"

on:
pull_request:
workflow_dispatch:

push:
branches: ["*"]

schedule:
- cron: "0 8 * * 1"

jobs:
coverage:
name: "Nette Tester"
uses: contributte/.github/.github/workflows/nette-tester-coverage-v2.yml@master
with:
php: "8.4"
make: "init coverage"
19 changes: 19 additions & 0 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "Phpstan"

on:
pull_request:
workflow_dispatch:

push:
branches: ["*"]

schedule:
- cron: "0 8 * * 1"

jobs:
phpstan:
name: "Phpstan"
uses: contributte/.github/.github/workflows/phpstan.yml@master
with:
php: "8.4"
make: "init phpstan"
26 changes: 26 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: "Nette Tester"

on:
pull_request:
workflow_dispatch:

push:
branches: [ "*" ]

schedule:
- cron: "0 8 * * 1"

jobs:
test85:
name: "Nette Tester"
uses: contributte/.github/.github/workflows/nette-tester.yml@master
with:
php: "8.5"
make: "init tests"

test84:
name: "Nette Tester"
uses: contributte/.github/.github/workflows/nette-tester.yml@master
with:
php: "8.4"
make: "init tests"
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# IDE
.idea

# Composer
/vendor

# Nette
/var/
/config/local.neon

# Docker
/.data
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Contributte

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
88 changes: 88 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
############################################################
# PROJECT ##################################################
############################################################
.PHONY: project
project: install setup

.PHONY: init
init:
cp config/local.neon.example config/local.neon

.PHONY: install
install:
composer install

.PHONY: setup
setup:
mkdir -p var/tmp var/log
chmod 0777 var/tmp var/log

.PHONY: clean
clean:
find var/tmp -mindepth 1 ! -name '.gitignore' -type f,d -exec rm -rf {} +
find var/log -mindepth 1 ! -name '.gitignore' -type f,d -exec rm -rf {} +

############################################################
# DEVELOPMENT ##############################################
############################################################
.PHONY: qa
qa: cs phpstan

.PHONY: cs
cs:
vendor/bin/codesniffer app tests

.PHONY: csf
csf:
vendor/bin/codefixer app tests

.PHONY: phpstan
phpstan:
vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=512M

.PHONY: tests
tests:
vendor/bin/tester -s -p php --colors 1 -C tests

.PHONY: coverage
coverage:
vendor/bin/tester -s -p phpdbg --colors 1 -C --coverage ./coverage.xml --coverage-src ./app tests

.PHONY: dev
dev:
NETTE_DEBUG=1 NETTE_ENV=dev php -S 0.0.0.0:8080 -t www

.PHONY: build
build:
echo "OK"

############################################################
# MCP ######################################################
############################################################
.PHONY: inspector
inspector: mcp-inspect ## Alias for mcp-inspect

.PHONY: mcp-inspect
mcp-inspect: ## Run MCP inspector
npx @modelcontextprotocol/inspector

.PHONY: mcp-stdio
mcp-stdio: ## Run MCP inspector for stdio server
npx @modelcontextprotocol/inspector php bin/console mcp:server

############################################################
# DOCKER ###################################################
############################################################
.PHONY: docker-up
docker-up:
docker compose up

############################################################
# DEPLOYMENT ###############################################
############################################################
.PHONY: deploy
deploy:
$(MAKE) clean
$(MAKE) project
$(MAKE) build
$(MAKE) clean
98 changes: 98 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
![](https://heatbadger.now.sh/github/readme/contributte/mcp-skeleton/)

<p align=center>
<a href="https://github.com/contributte/mcp-skeleton/actions"><img src="https://badgen.net/github/checks/contributte/mcp-skeleton/master"></a>
<a href="https://coveralls.io/r/contributte/mcp-skeleton"><img src="https://badgen.net/coveralls/c/github/contributte/mcp-skeleton"></a>
<a href="https://packagist.org/packages/contributte/mcp-skeleton"><img src="https://badgen.net/packagist/dm/contributte/mcp-skeleton"></a>
<a href="https://packagist.org/packages/contributte/mcp-skeleton"><img src="https://badgen.net/packagist/v/contributte/mcp-skeleton"></a>
</p>
<p align=center>
<a href="https://packagist.org/packages/contributte/mcp-skeleton"><img src="https://badgen.net/packagist/php/contributte/mcp-skeleton"></a>
<a href="https://github.com/contributte/mcp-skeleton"><img src="https://badgen.net/github/license/contributte/mcp-skeleton"></a>
<a href="https://bit.ly/ctteg"><img src="https://badgen.net/badge/support/gitter/cyan"></a>
<a href="https://bit.ly/cttfo"><img src="https://badgen.net/badge/support/forum/yellow"></a>
<a href="https://contributte.org/partners.html"><img src="https://badgen.net/badge/sponsor/donations/F96854"></a>
</p>

<p align=center>
Website 🚀 <a href="https://contributte.org">contributte.org</a> | Contact 👨🏻‍💻 <a href="https://f3l1x.io">f3l1x.io</a> | Twitter 🐦 <a href="https://twitter.com/contributte">@contributte</a>
</p>

-----

# MCP Skeleton

Example project demonstrating integration of **Model Context Protocol (MCP)** for **Nette Framework** using `contributte/mcp`.

The MCP integration is based on the upstream documentation: [contributte/mcp docs](https://github.com/contributte/mcp/tree/master/.docs).

![](https://github.assets.f3l1x.io/contributte-mcp-project1.gif)

## Requirements

- PHP 8.4+
- Composer
- Node.js (only for MCP inspector via `npx`)

## Installation

```bash
composer install
```

## Usage

This skeleton registers a single MCP server named `default` and uses **attribute auto-discovery** from `app/Domain/Mcp`.

**Capabilities:**

- Tools:
- `calculator_add`
- `calculator_multiply`
- Resources:
- `app://config`
- `file://readme`
- Resource templates:
- `app://users/{id}`
- Prompts:
- `code_review`
- `explain_code`

### Streamable HTTP server

1. Start inspector: `make inspector`
2. Open the inspector in your browser and connect to `http://localhost:8080/mcp`.

#### Manual

1. Start inspector: `make inspector` (or `make mcp-stdio` to auto-run the STDIO server)
2. Open the inspector in your browser and do work.

## Screenshots

### STDIO

![STDIO - terminal output](.docs/stdio-terminal.png)

![MCP Inspector - STDIO resources](.docs/stdio.png)

### Streamable HTTP

![Streamable HTTP - terminal output](.docs/streamable-terminal.png)

![MCP Inspector - Streamable HTTP tools](.docs/streamable.png)


## Development

See [how to contribute](https://contributte.org/contributing.html) to this package.

This package is currently maintaining by these authors.

<a href="https://github.com/f3l1x">
<img width="80" height="80" src="https://avatars2.githubusercontent.com/u/538058?v=3&s=80">
</a>

-----

Consider to [support](https://contributte.org/partners.html) **contributte** development team. Also thank you for using this project.
28 changes: 28 additions & 0 deletions app/Bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types = 1);

namespace App;

use Contributte\Bootstrap\ExtraConfigurator;
use Contributte\Nella\Boot\Bootloader;
use Contributte\Nella\Boot\Preset\NellaPreset;
use Nette\Application\Application;

final class Bootstrap
{

public static function boot(): ExtraConfigurator
{
return Bootloader::create()
->use(NellaPreset::create(__DIR__))
->boot();
}

public static function run(): void
{
self::boot()
->createContainer()
->getByType(Application::class)
->run();
}

}
22 changes: 22 additions & 0 deletions app/Domain/Mcp/CalculatorTool.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php declare(strict_types = 1);

namespace App\Domain\Mcp;

use Mcp\Capability\Attribute\McpTool;

final class CalculatorTool
{
#[McpTool(name: 'calculator_add', description: 'Add two numbers')]
public function add(int $a, int $b): int
{
return $a + $b;
}

#[McpTool(name: 'calculator_multiply', description: 'Multiply two numbers')]
public function multiply(int $a, int $b): int
{
return $a * $b;
}
}


Loading
Loading