nowo-tech / mcp-kit-bundle
Model Context Protocol (MCP) server for Symfony: stateless Streamable HTTP (JSON only, revisions 2026-07-28, 2025-11-25 and 2025-06-18), host-provided token authentication, a compiled tool registry with JSON Schema validation and an untrusted-content envelope for agent-facing tools.
Package info
github.com/nowo-tech/McpKitBundle
Type:symfony-bundle
pkg:composer/nowo-tech/mcp-kit-bundle
Requires
- php: >=8.2 <8.6
- opis/json-schema: ^2.4
- psr/clock: ^1.0
- psr/log: ^2.0 || ^3.0
- symfony/clock: ^7.4 || ^8.0
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/event-dispatcher: ^7.4 || ^8.0
- symfony/http-foundation: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/polyfill-mbstring: ^1.31
- symfony/routing: ^7.4 || ^8.0
- symfony/security-core: ^7.4 || ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- igor-php/igor-php: ^0.10.1
- nowo-tech/phpstan-frankenphp: ^1.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^11.5
- rector/rector: ^2.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/phpunit-bridge: ^7.4 || ^8.0
- symfony/security-bundle: ^7.4 || ^8.0
- symfony/yaml: ^7.4 || ^8.0
Suggests
- symfony/flex: Installs the recipe (config/packages/nowo_mcp_kit.yaml and the route import)
- symfony/security-bundle: Lets the endpoint check that the request went through a secured firewall (recommended)
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-09 18:20:37 UTC
README
⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
MCP Kit Bundle — a Model Context Protocol server endpoint for Symfony apps, so AI agents (Claude Code, Cursor, VS Code…) can call your tools with a personal token. Stateless Streamable HTTP with JSON answers only, protocol revisions 2026-07-28 (modern) and 2025-11-25 / 2025-06-18 (legacy) on one endpoint, authentication and authorization through your own hooks, a tool registry compiled at build time with JSON Schema validation of arguments and results, and an untrusted envelope that keeps content written by people apart from protocol text. The bundle knows no domain: you register the tools. Supports Symfony 7.4, 8.0 and 8.1 (CI: 7.4 and 8.1) · PHP 8.2+ (Symfony 8.x requires PHP 8.4+).
This bundle is FrankenPHP worker mode friendly.
Workers that do not reset the kernel between requests are supported too: services are readonly, the registry is compiled into the container, and per-request data lives on the request. See docs/FRANKENPHP-WORKER-AUDIT.md.
Features
- Streamable HTTP, stateless: one
POSTendpoint, JSON answers, no sessions, no SSE;Mcp-Session-Idis never issued. - Dual-era: modern per-request
_meta(2026-07-28) and the legacyinitializehandshake (2025-11-25, 2025-06-18) on the same endpoint, with the header checks (MCP-Protocol-Version,Mcp-Method,Mcp-Name) the spec requires. - Fail-closed pipeline:
Originallowlist (DNS rebinding), method, body size, bearer credential, token budget, media types, JSON-RPC shape, version and headers, in a fixed order. - Your tokens: an authenticator hook returns a principal per request; an authorizer hook decides which tools a token sees; a rate-limiter hook holds the budgets. No OAuth.
- Compiled tool registry: static tool definitions validated at container build (names, kinds, JSON Schema rules), explicit annotations, destructive tools hidden without the token's tick.
- Untrusted envelope: content written by people goes under
untrusted, behind a fixed notice, JSON-escaped, with invisible characters shown as escapes. - Limits and audit: body, depth, text, list and result caps; a write budget; an audit event per call with ids only.
Installation
composer require nowo-tech/mcp-kit-bundle
With Symfony Flex the recipe adds config/packages/nowo_mcp_kit.yaml and the route import. Without Flex, see docs/INSTALLATION.md.
Quick start
# config/packages/nowo_mcp_kit.yaml nowo_mcp_kit: enabled: true
See docs/USAGE.md for the hooks and the first tool.
Requirements
- PHP 8.2+ (
>=8.2 <8.6) - Symfony 7.4 or 8.x
- A stateless firewall in front of the endpoint that turns the bearer token into the security user (recommended:
symfony/security-bundle)
Configuration
Usage
See docs/USAGE.md.
Demo
demo/symfony8— Symfony 8.1 (FrankenPHP PHP 8.5, worker mode); host port 8219 by default.
The demo serves note tools (note_list, note_get, note_create, note_archive) and the demo://note/{id} template
with throwaway tokens, a seeded note full of injection text, and a conformance profile for the official MCP runner.
make -C demo up-symfony8 # http://localhost:8219 (client setup on the home page) make demo-smoke # boot, HTTP 200, down (REQ-TEST-011) make test-conformance # official MCP conformance runner (pinned), 2026-07-28 and 2025-11-25
Runtime mode is FRANKENPHP_MODE (worker default, or classic) — see docs/DEMO-FRANKENPHP.md.
Development
make up
make install
make test
make cs-check
make phpstan
make igor
make test-coverage-100
make release-check
Documentation
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- Architecture
- PSR evaluation (REQ-CS-007)
- Demo (FrankenPHP)
- FrankenPHP worker audit (kernel not reset)
- GitHub Actions CI requirements
Tests and coverage
- Tests: PHPUnit (PHP) — unit tests plus kernel integration tests (every pipeline step, both eras, tools, resources, worker mode); the official MCP conformance runner against the demo (required CI gate, per-check baseline)
- PHP: 100% (gate enforced in CI by
composer test-coverage-100, no exclusions) - TS/JS: N/A
- Python: N/A
License and author
MIT · Nowo.tech · Héctor Franco Aceituno
