ardanayatraa / laravel-mcp-hub
Application-owned Laravel source APIs and a scoped MCP Hub client.
Requires
- php: ^7.2.5 || ^8.0
- guzzlehttp/guzzle: ^7.15.2
- illuminate/console: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/contracts: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/database: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/http: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^11.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-28 16:32:31 UTC
README
Expose reviewed Laravel resources to an MCP Hub and call the Hub through a scoped server-side client. Applications retain control of business data, account identity, record ownership, and permissions.
Alpha release: 0.2.0-alpha.1. One package supports Laravel 5.8, 6, 7, 8, 9, 10, 11, 12 and 13. The package requires PHP 7.2.5 or later in the PHP 7/8 families; the framework and the application's other dependencies determine the effective PHP requirement.
| Laravel reference | PHP tested in CI |
|---|---|
| 5.8.38 | 7.2, 7.4 |
| 6.20.45 | 7.2 |
| 7.30.7 | 7.2 |
| 8.83.29 | 7.3 |
| 9.52.21 | 8.0, 8.2 |
| 10.50.4 | 8.1 |
| 11.45.0 | 8.2 |
| 12.64.0 | 8.2, 8.4 |
| 13.38.0 | 8.3, 8.4 |
The matrix checks reference patches for every supported major, not every historical patch or every possible PHP/framework combination. Use the latest compatible framework patch where possible. Future Laravel majors will be added after compatibility testing; support is not open-ended.
There are no business models registered by default.
Install
composer require ardanayatraa/laravel-mcp-hub:@alpha php artisan mcp-hub:install
No package version number is needed: Composer resolves a compatible release using the project's PHP and Laravel dependency constraints. The @alpha flag allows the current preview releases without changing the project's global minimum stability. It can be omitted once a compatible stable release is available. Composer package names require the vendor/package form.
Laravel discovers the provider automatically unless the application disables package discovery. The installer publishes config/mcp-hub.php only when it does not already exist. It does not overwrite application files, run application migrations, create a Hub account, grant data access, or rotate credentials.
Version 0.2 keeps the 0.1 configuration keys, contracts and source API. It uses Guzzle 7.15.2 or newer directly so older Laravel applications do not need Laravel's newer HTTP facade. An application pinned to Guzzle 6 must resolve that dependency before installation. No business model is mandatory.
Configure a connection
Provision the application in your Hub, then set these values in the application's environment or secret store:
MCP_HUB_APP_KEY=your_app MCP_HUB_ENVIRONMENT=production MCP_HUB_ENABLED=true MCP_HUB_URL=https://hub.example.com/mcp MCP_HUB_CLIENT_KEY= MCP_HUB_BASE_URL=https://app.example.com MCP_HUB_APP_TOKEN= MCP_HUB_DELEGATION_SECRET=
The client key authenticates Laravel to the Hub. The app token authenticates the Hub to Laravel. The delegation secret signs short-lived actor context; use at least 32 random characters for the app token and delegation secret. Keep all credentials server-side.
MCP_HUB_BASE_URL is the Laravel source URL, not the Hub URL. The Hub must be able to reach it, and its network/origin policy must permit the connection. Local HTTP Hub calls are accepted only for loopback addresses in Laravel's local/testing environments.
php artisan mcp-hub:connect --import-env php artisan mcp-hub:doctor php artisan mcp-hub:doctor --online --json
Import saves an encrypted copy under storage/app/mcp-hub/connection.enc using the application's encryption key. Existing environment values take precedence. Do not remove environment configuration expecting a complete provisioning workflow: one-time pairing and a database-backed settings screen are future work.
Register application-owned resources
The default config is intentionally empty:
'actor_resolver' => \McpHub\Laravel\Security\DenyActorResolver::class, 'models' => [],
The application implements two contracts:
- ActorResolver converts an authenticated user into an Actor and resolves signed user references back to a currently active account and tenant.
- ResourcePolicy authorizes each read and applies the application's complete ownership/tenant scope to an Eloquent query.
An example application registration could look like this:
'actor_resolver' => \App\Mcp\ActorResolver::class, 'models' => [ 'orders' => [ 'model' => \App\Models\Order::class, 'policy' => \App\Mcp\OrderPolicy::class, 'enabled' => true, 'read' => true, 'lookup' => 'title', 'fields' => [ 'title' => 'string', 'status' => 'string', 'total' => 'number', ], 'filters' => ['status' => ['paid', 'pending']], ], ],
These example classes belong to the installing application; the package does not provide or assume them. Model fields must be explicitly allowlisted. Hidden and sensitive field names are rejected. Pagination parameters limit and cursor are reserved and cannot be used as lookup or filter names.
You can replace Registry through the Laravel container to read your application's existing permission store. Register the Hub connector in source-managed mode so its tool catalog follows the current application manifest.
Source API
The default prefix is /api/ai/v1:
| Method | Path | Purpose |
|---|---|---|
| GET | /health | Service-authenticated health |
| GET | /capabilities | Application-managed Connector Contract 1.0 manifest |
| GET | /{resource}/list | Authorized, paginated records |
| GET | /{resource}/get | Exact lookup using the registered field |
| GET | /{resource}/count | Count within the same authorized scope |
All routes require the configured bearer app token. Reads additionally require a signed X-Hub-Assertion carrying the approved app key, audience, active user reference, tenant, expiry, and one-use jti.
Production needs a shared cache with atomic add for replay rejection. In-memory array/null caches are refused for actor verification outside local/testing. Source responses are marked no-store.
If the application already owns these routes, set routes.enabled to false and adapt its existing source registry and gateway rather than registering duplicate endpoints.
The generic alpha exposes reads only. Application-specific write proposals, confirmations, chat UI, report exports, provider credentials and business rules are outside this package.
Hub transport
$client = app(\McpHub\Laravel\HubClient::class); $catalog = $client->rpc('tools/list'); $delegation = app(\McpHub\Laravel\Security\Assertions::class)->delegate($user); $result = $client->rpc('tools/call', [ 'name' => 'your_app__orders__list', 'arguments' => ['limit' => 20], ], ['X-Hub-Delegation' => $delegation]);
The client supports tools/list and tools/call, bounded connect/read timeouts, JSON and SSE responses, response-ID checks, and sanitized errors. Its protocol metadata targets the current Hub transport; it is not a general-purpose client for arbitrary MCP servers.
Development
composer install
composer test
composer validate --strict
The default development install uses Laravel 12. The same Testbench suite runs across the matrix above with isolated SQLite databases. To reproduce a matrix row using its real PHP runtime:
php scripts/prepare-matrix.php 5.8 composer update --working-dir=.compat/5.8 --prefer-dist composer check-platform-reqs --working-dir=.compat/5.8 php .compat/5.8/vendor/bin/phpunit --bootstrap .compat/5.8/vendor/autoload.php
Historical frameworks include known upstream security advisories. Only the generated .compat development fixtures contain explicit advisory-ID exceptions from scripts/legacy-advisories.json. Exceptions allow resolution for testing and keep findings visible in audit output. CI stores the complete audit and dependency lock, and fails on unreviewed advisories. The published runtime manifest does not disable security blocking, change application settings, or ignore platform requirements. Connector compatibility does not restore security maintenance for old frameworks.
For an actual HTTP transport check, start the local Postman simulation:
postman simulation run postman/simulations/connector.sim.yaml --port 18130 --output ndjson
Set MCP_HUB_SIM_URL=http://127.0.0.1:18130/hub/mcp before running composer test. The mock validates the dummy caller and protocol metadata and models tools/list only; other calls return 501. A passing mock run is not a live Hub or model-completion test.
License
MIT. See LICENSE.