Download the PHP package mnapoli/backoffice-mcp without Composer

On this page you can find all versions of the php package mnapoli/backoffice-mcp. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package backoffice-mcp

Back-office MCP

Let an AI agent read your Laravel application's database through a strict, read-only whitelist of Eloquent models.

It is meant for internal tools: an admin server for you, a support server for your support team… Each server exposes three tools: schema, query and count. It is built on laravel/mcp and spatie/laravel-query-builder.

Anything absent from the whitelist is unreachable. A column that is not listed is never selected nor returned, and a filter, sort, relation or resource that is not listed is rejected rather than silently ignored.

Installation

Declaring a server

Create one class per audience, and declare what it can read:

Soft-deleted rows are excluded unless the agent asks for them with trashed.

The model's own $hidden, $visible and $appends are ignored: the whitelist alone decides what a row contains.

Tell the agent what the server is for with $description, for example which application this is and which repository holds its code:

It comes before the generic instructions on using the tools, which also tell the agent to explore the application's code to understand the data. Override $instructions to replace those entirely.

Exposing it

Publish the configuration file:

Then declare your servers in config/backoffice-mcp.php. Each one is behind a bearer token, or behind a login with the user accounts of your application.

Behind a token

Each server has its own bearer token. When the token is empty, the route is not registered at all: the URL answers 404, so a server stays off in every environment until you set its token there.

Generate a token with openssl rand -hex 32, then connect a client:

Behind a login (OAuth)

Claude (web, desktop and mobile), ChatGPT and most MCP clients connect with OAuth: you add the URL of the server, log in to your application in the browser, and approve the client. Only the users who pass the gate of the server can connect.

Define the gate in a service provider, it receives the logged-in user:

The gate is checked on every request, so a user who loses the right loses access immediately, whatever tokens their clients hold. The gate is required: without one, every user of your application could read the server.

OAuth runs on Laravel Passport:

  1. Install it:

    Your user model needs neither Passport's HasApiTokens trait nor an api guard, so Passport can live alongside Sanctum. Users are those of the guard that Passport logs them in with, web unless you set passport.guard. In production, give Passport its keys with the PASSPORT_PRIVATE_KEY and PASSPORT_PUBLIC_KEY environment variables.

  2. Publish the consent screen, adapt it to your application's layout and styles, and tell Passport to use it in a service provider:

    Passport's access tokens last a year by default. MCP clients refresh theirs, so a shorter lifetime costs nothing and limits what a leaked token is worth: Passport::tokensExpireIn(now()->addHour()).

  3. Any MCP client can register itself and ask your users for access, under any name. By default it can then send them back anywhere after the consent screen, with the code that gets it a token. Limit that to the clients you use, in config/mcp.php (php artisan vendor:publish --tag=mcp-config):

Users who are not logged in are sent to your login route, then back to the consent screen. To connect:

Turn OAuth off for an environment with 'oauth' => (bool) env('SUPPORT_MCP_OAUTH'): the route is then not registered, as with an empty token.

Throttling and logging

Requests are throttled to 60 per minute per server, and per IP address or, behind OAuth, per user (requests_per_minute to change it). Every tool call is logged with Log::info(), with the user_id behind OAuth.

Limits

Each server can override its limits:

Property Default
defaultLimit 25 Rows returned when the agent does not say.
maxLimit 200 Rows returned at most. Pagination is offset-based, and every sort ends on the primary key so that pages are stable.
maxIncludedRows 25 Related rows loaded per row for an included relation (the most recent ones). Use counts to count them all.
maxTotalIncludedRows 10 000 Related rows one request may load in total (rows × relations × related rows). A request over it is refused, saying which limit to lower.
maxResponseBytes 100 000 JSON size of one page of rows. A page over it is trimmed to what fits and comes back with next_offset and a suggested_limit. The default keeps a response to what an agent can afford to read.
queryTimeout 8 Seconds all the queries of one request may run, divided between them. 0 turns it off. MySQL, MariaDB and PostgreSQL only.

On AWS Lambda behind API Gateway, keep maxResponseBytes under about 1 MB: the response is encoded several times on its way out (structured content, text content, then the Lambda payload), and API Gateway caps it at 6 MB.

What is deliberately missing

There is no GROUP BY and no raw SQL. The agent aggregates with the count tool, or with the counts argument of query for a per-row relation count.

Writes are not supported.

Testing your whitelist

Tools can be called in tests on your own server:

AdminMcpServer::tool(SchemaTool::class) returns the whole whitelist, with the database type of each column. Use it to check that every whitelisted column exists in your schema.

Contributing

The tests run on SQLite. To run them against a real server, which is the only way to test the query timeout, set DB_CONNECTION (mysql, mariadb or pgsql) and DB_PORT, DB_USERNAME, DB_PASSWORD, DB_DATABASE.


All versions of backoffice-mcp with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
illuminate/database Version ^12.0|^13.0
illuminate/http Version ^12.0|^13.0
illuminate/routing Version ^12.0|^13.0
illuminate/support Version ^12.0|^13.0
laravel/mcp Version ^0.9
spatie/laravel-query-builder Version ^7.3
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package mnapoli/backoffice-mcp contains the following files

Loading the files please wait ...