Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mcp Kit Laravel Package

heihallo/mcp-kit

A Laravel toolkit for building Model Context Protocol servers, helping you expose tools, resources, and prompts to AI clients with clean, framework-native APIs and minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Read the source before you install. At zero stars and zero dependents you are the entire QA function for this package. Budget an hour to skim src/, config/, and database/migrations/ before it touches a real app. Nothing below should be taken as verified API surface — treat class and command names as shapes to confirm against the repo.

Minimal path:

  1. composer require heihallo/mcp-kit (pin an exact version, not ^).
  2. Publish config and migrations: php artisan vendor:publish --tag=mcp-kit-config and --tag=mcp-kit-migrations, then php artisan migrate.
  3. Register the service provider if it isn't auto-discovered, and check php artisan route:list | grep -i mcp to see what endpoint you now expose.
  4. Find the capability registry — the place where tools are declared. In packages like this it's usually a config array, an attribute on tool classes, or a register() call in a service provider. This file is your allowlist and the single most important thing to read.
  5. Issue a token for yourself: php artisan mcp-kit:token {user} or equivalent.

First use case, deliberately boring: expose exactly one read-only capability — "look up an order by ID" — delegating to an existing Action or query you already trust. Issue a personal token, point an MCP client (Claude Desktop, Cursor, or mcp-inspector) at the endpoint, and confirm three things:

  • the tool appears in the client's tool list,
  • a call returns real data,
  • a row lands in the audit table with your user ID attached.

If the audit row is missing, stop and fix that before adding any write capability. Audit is the feature you cannot retrofit.

The second thing to wire is a write capability in preview/confirm mode, because that's the package's actual differentiator and where the integration risk lives.

Implementation Patterns

Wrap, don't reimplement. Every tool should be a thin adapter over an Action/Service class the rest of your app already uses. The moment a tool contains its own validation or query logic, you have two code paths that will drift and only one of them is covered by your existing tests. Aim for tools that are ~15 lines: validate input, call the Action, shape the response.

Catalogue as opt-in allowlist. Resist any auto-discovery of "public methods" the package might offer. An explicit registry means every new agent capability is a reviewable one-line diff in a PR, which is exactly the review gate you want for anything that can mutate data.

Per-person tokens, per-device scoping. Tokens should map to a real users row, never to the application itself, and ideally to a user_id + device_label + expires_at triple. Practical flow:

  • token issued from an authenticated settings page, shown once,
  • token carries a scope set that narrows the user's normal permissions (never widens them),
  • offboarding is a revokeAllForUser() call in the same listener that deactivates the account,
  • rotate on a schedule; short TTLs with refresh beat long-lived secrets in a laptop's JSON config.

Authorization stays in Laravel. Route tool-level access through Gate::forUser($tokenUser)->allows(...) against policies you already maintain, rather than a parallel ACL in the package's config. The access middleware should be the enforcement point; the config should only decide which ability name a tool maps to.

Preview/confirm as a two-phase protocol. The pattern that works:

preview_refund(order_id, amount)
  -> { diff: "...", confirm_token: "abc", expires_at: "..." }

apply_refund(confirm_token)
  -> executes, or 409 if expired/replayed/args changed

Rules that matter: bind the confirm token to the exact argument payload (hash it in), make it single-use, give it a short TTL (2–5 minutes), and make the effect idempotent anyway. The preview response should render the human-readable consequence — "refund $40.00 to Jane Doe, order #1234" — because that string is what the person in the chat window actually approves. If the model can summarize it lossily, the confirmation is theatre.

Audit as a first-class record. Log user_id, token_id, tool_name, hash of arguments, outcome, latency, and request correlation ID. Two decisions to make up front: redact argument values that can contain PII or secrets (log the hash, not the body, for anything touching auth or payment data), and decide whether the audit write shares a transaction with the mutation. For writes, it usually should — an unlogged refund is worse than a failed one.

Ground rules as data, not prose scattered in prompts. Keep them in a versioned config file: what's off-limits, when to escalate to a human, which environments the agent should refuse to touch. Coarse policy survives model changes; per-tool usage documentation inside the rules block just burns context.

Memory: namespaced, bounded, untrusted. Key by user_id, cap entry count and total bytes, add TTL, and expose an explicit forget tool. On read, treat memory as untrusted input — it's user-influenced text re-entering the model's context, so don't let it carry instructions that override ground rules.

Onboarding as a tool. A what_can_i_do capability that returns the caller's permitted tools plus a one-line description and a docs link replaces a lot of Slack questions and gives new staff a self-serve map on day one.

Long operations: return a job ID and a check_status tool instead of holding the MCP call open. Clients time out, and a timed-out write with unknown outcome is the worst possible state.

Gotchas and Tips

You are the maintainer. Zero dependents means no Stack Overflow answers, no blog posts, no one else hitting the bug first. Pin the version in composer.json, keep a fork or a patch set ready, and assume you'll own fixes. Write an integration test per tool now, while the surface is small.

Tokens end up in plaintext on disk. MCP client configs are JSON files in home directories, frequently synced to cloud drives and occasionally committed. Scope them narrowly, expire them, and consider a per-device token so a single leak is a single revocation.

The confirm token gets lost between turns. Agents truncate context, clients restart, users interleave questions. Design so a lost token degrades gracefully: the agent can re-run preview, and the error message says exactly that. Don't make confirm tokens so opaque that recovery requires a human with database access.

Replay and TOCTOU. A confirm token that isn't bound to its argument hash lets a caller preview a $5 refund and confirm a $500 one. Bind it. Single-use it. And re-check authorization at confirm time, not just at preview — roles change mid-conversation more often than you'd think.

Stale permission caches. If tool lists or scopes are cached per token, a revoked role can keep working until TTL expiry. Either keep authorization checks uncached (cheap, hits Gate) or bust the cache in the same place you mutate roles.

Tool-count bloat degrades selection quality. Fifteen tools with overlapping descriptions is measurably worse than five crisp ones. Group related reads into one parameterized tool, and prune anything unused after a month — the audit log tells you exactly which tools nobody calls.

Input schemas are a public contract. Once a colleague's saved prompt or a client-side workflow depends on a parameter name, renaming it silently breaks them. Additive changes only; deprecate with a version bump.

Audit table growth and PII. Estimate volume before launch — an active user can generate hundreds of rows a day. Set a retention window at creation time rather than discovering the problem at 10M rows, and never let audit logging become the reason a SELECT on user data gets slow.

Debugging: you want the raw JSON-RPC frames when a tool "isn't being called." Add a debug log channel behind an env flag that dumps request/response bodies with token values redacted, and verify the endpoint with mcp-inspector outside your chat client — it removes the client from the variable set and shows you the exact schema the model is being given.

Local development: seed a dev token via a seeder, never commit a real one, and point the client at your herd/valet host. Confirm the package doesn't register its routes in production by default — if it does, that's your first patch.

Extension points worth checking in source: the middleware stack order (access before audit, or audit before access — you want the denial logged too), whether the audit middleware sees the tool name before or after resolution, and whether memory/onboarding are swappable via container bindings. If they're hardcoded, prefer composing around them rather than forking.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle