Skip to main content
Glama
jaksa-v
by jaksa-v

mcp-lab

Eine Laravel-App, die dazu dient, jeden Teil von Laravel MCP zu erzwingen. Fake-Helpdesk. Fake-Firma. Wirf sie weg, wenn du fertig bist.

Dies ist die Standardreferenz dafür, wie MCP in Laravel funktioniert und wie dieses Repo es verwendet.

Dies ist ein Fitnessstudio, kein Produkt. Wenn du dich dabei ertappst, eine Schriftart auszuwählen oder eine Abrechnungsseite zu erfinden, hör auf.

Wie Laravel MCP funktioniert

Model Context Protocol ist JSON-RPC. Ein KI-Host listet auf, was dein Server bereitstellt, und ruft es dann auf. Cursor und Inspector sind die Hosts, um die es in diesem Repo geht. Laravel MCP, laravel/mcp 0.9.x hier, ist der Wrapper.

Du erfindest kein Protokoll. Du schreibst PHP-Klassen und registrierst sie.

Server

Ein Server ist eine Klasse, die Laravel\Mcp\Server erweitert. Es ist ein Katalog von Tools, Ressourcen und Prompts.

#[Name('Northwind Tickets')]
#[Version('0.0.1')]
#[Instructions('...')]
class TicketsServer extends Server
{
    protected array $tools = [/* ... */];
    protected array $resources = [/* ... */];
    protected array $prompts = [/* ... */];
}

#[Name], #[Version], #[Instructions] und #[Icon] sind Metadaten, die der Host dem Modell zeigt. Instructions sind der System-Prompt für diesen Server. Halte sie kurz und operativ.

Erstelle einen mit php artisan make:mcp-server. Registriere ihn in routes/ai.php. Laravel lädt diese Datei selbst. Füge sie nicht zu bootstrap/app.php hinzu.

Lokal vs. Web

Dieselbe Serverklasse. Zwei Wege hinein.

Mcp::local('tickets', TicketsServer::class);
Mcp::web('/mcp/tickets', TicketsServer::class)->middleware(['auth:api', 'throttle:mcp']);

Lokal ist stdio. Der Host führt php artisan mcp:start tickets als untergeordneten Prozess aus. Das ist die tägliche Cursor-Schleife. Keine HTTP-Sitzung, keine Cookies, kein Passport.

Web ist HTTP JSON-RPC unter diesem Pfad. Inspector und Remote-Hosts verwenden es. Middleware wird angewendet, und hier lebt OAuth.

Wickle routes/ai.php nicht in die web-Middleware-Gruppe ein. CSRF blockiert Inspector.

Tools, Ressourcen und Prompts

Ein Server kann Tools, Ressourcen und Prompts bereitstellen. Generiere sie mit make:mcp-tool, make:mcp-resource und make:mcp-prompt. Füge dann die Klasse zu den Server-Arrays hinzu. Eine nicht registrierte Klasse tut nichts.

Tools sind Aktionen. Das Modell ruft sie mit Argumenten auf. schema() ist das JSON-Schema, das der Host bewirbt. handle(Request $request) erledigt die Arbeit. $request->validate() ist gewöhnliche Laravel-Validierung. Schreibe Nachrichten, auf die ein Modell reagieren kann, wie Gib mir die Ticket-ID, z. B. 12., nicht Das Feld ticket_id ist erforderlich.

Ressourcen sind lesbare Dokumente unter einer URI. Eine statische URI verwendet #[Uri('desk://playbook')]. Vorlagen implementieren HasUriTemplate und lesen Variablen mit $request->get('id'). Der MIME-Typ verwendet #[MimeType]. Der Host kann sie auflisten und lesen, ohne ein Tool aufzurufen.

Prompts sind wiederverwendbare Nachrichtenvorlagen. arguments() deklariert, was der Host sammeln soll. handle() gibt Nachrichten zurück, normalerweise eine Assistentenanweisung plus eine Benutzernachricht, die echte Daten enthält. Das Modell schreibt dann daraus.

Konstruktor-Injektion von Repositories. Führe keine Abfragen in der Tool-Klasse durch. handle() kann auch Laravel-Dienste per Typ-Hint einbinden.

Antworten

handle() gibt eine Laravel\Mcp\Response, eine Antwort-Factory, ein Array von Antworten oder einen Generator zurück.

Form

Wie

Text

Response::text('...')

Fehler

Response::error('Permission denied.')

Strukturiertes JSON

Response::structured($payload) plus outputSchema()

Mehrere Textblöcke

Response::make([Response::text(...), Response::text(...)])

Ressourcenlink

Response::resourceLink(uri:, name:, mimeType:, title:)

Blob von der Festplatte

Response::fromStorage('badge.png')

HTML-App

Response::view('mcp.queue-app', [...])

Fortschritt

yield Response::notification('processing/progress', [...]) aus einem Generator

Response::structured darf nicht leer sein und gibt eine Factory zurück. Um strukturiertes JSON mit Ressourcenlinks zu mischen, baue beide und füge die Nutzlast mit withStructuredContent hinzu. Das macht list_tickets.

Die Klasse $meta ist Metadaten auf dem Tool selbst. ->withMeta([...]) ist Metadaten auf einer einzelnen Antwort. create_ticket hat das erste. get_ticket hat das zweite.

Annotationen

Hinweise für den Host. Sie erzwingen nichts in PHP. Policies tun das immer noch.

Attribut

Bedeutung hier

#[IsReadOnly]

Schreibt nicht

#[IsIdempotent]

Sicher zu wiederholen

#[IsDestructive]

Löscht oder zerstört Zustand

#[IsOpenWorld]

Kann die Außenwelt berühren. who_is_on_call trägt dies, obwohl die Rotation gefälscht ist

#[Priority], #[Audience], #[LastModified]

Ressourcen-Hinweise

#[RendersApp]

Dieses Tool öffnet eine MCP-App

shouldRegister(Request $request): bool verbirgt ein Tool, eine Ressource oder einen Prompt aus der Liste. Wenn der Host dennoch versucht, ein verstecktes aufzurufen, gibt der Server not-found zurück. Verwende es für Rollen-Gates. delete_ticket ist nur für Admins. Überprüfe trotzdem $request->user()->can(...) innerhalb von handle(). Auflisten und Ausführen sind verschiedene Türen.

Autorisierung

$request->user() ist der angemeldete Benutzer, wie in einem Controller. Rufe $user->can('update', $ticket) auf und gib Response::error('Permission denied.') zurück. Erfinde kein zweites Auth-System.

Lokale Server haben keine HTTP-Sitzung. Der Ticket-Server dieser App meldet sich in boot() als Sam an, wenn Auth leer ist. Webserver erhalten den Benutzer von Passport.

Der MCP-Client

Laravel kann auch einen MCP-Server aufrufen. Benannte Clients leben in einem Service-Provider.

Mcp::registerClient('directory', fn () => Client::local('php', [
    'artisan', 'mcp:start', 'directory',
]));

Dann macht Ticket-Code Mcp::client('directory')->callTool('get_person', ['id' => $id]) oder ->readResource('directory://people/'.$id).

Client::local startet einen Prozess. Client::web($url) ist HTTP. Gleiche-App-HTTP gegen php artisan serve verklemmt, weil dieser Prozess single-threaded ist. Verwende local für Aufrufe innerhalb derselben App.

MCP-Apps

Eine AppResource gibt ein eigenständiges HTML-Dokument unter einer ui://-URI zurück. Ein Tool, das mit #[RendersApp(resource: QueueApp::class)] markiert ist, teilt einem fähigen Host mit, dieses HTML abzurufen und in einen sandboxed iframe zu legen.

Die Blade-Ansicht verwendet <x-mcp::app>. Diese Komponente liefert das Client-SDK. Im iframe gibt dir createMcpApp app.callServerTool(...). Vite und React gelten nicht. Tailwind und Alpine kommen von #[AppMeta(libraries: [Library::Tailwind, Library::Alpine])].

Visibility::App verbirgt ein Tool vor dem Modell, sodass nur der iframe es aufrufen kann. get_queue_data ist dieses Tool.

Cursor listet diese Tools auf. Es rendert den iframe nicht. Pest ist, wie du weißt, dass die Klassen funktionieren.

Auth im Web

Die Laravel-Dokumentation bietet Sanctum und Passport. Sanctum ist ein Bearer-Token. Passport ist OAuth 2.1, was das Protokoll spezifiziert.

Diese App verwendet Passport. Mcp::oauthRoutes() registriert Discovery und dynamische Client-Registrierung. Web-Routen verwenden auth:api. Laravel MCP bewirbt einen einzelnen mcp:use-Scope. Veröffentliche mcp-views und weise Passport::authorizationView auf resources/views/mcp/authorize.blade.php zu. Lass diese Blade-Datei in Ruhe.

Testen

Inspector ist zum Herumstochern. Pest ist, wie du weißt, dass Policies halten.

TicketsServer::actingAs($sam)
    ->tool(ListTicketsTool::class, ['status' => 'open'])
    ->assertOk()
    ->assertSee('...');

TicketsServer::resource(TicketResource::class, ['id' => $ticket->id]);
TicketsServer::prompt(DraftReplyPrompt::class, ['ticket_id' => $ticket->id, 'tone' => 'curt']);

Vorlagenressourcen nehmen die URI-Variablen als zweites Argument. Der Helfer erweitert desk://tickets/{id}.

assertSee liest nur Text und strukturierte Daten. Ressourcenlinks und _meta liegen auf der rohen JSON-RPC-Nutzlast. Die mcpRpc() und mcpToolContent() dieses Repos in tests/Helpers.php lesen das. Generator-Tools verwenden assertSentNotification und assertNotificationCount. Das Endergebnis enthält immer noch die Text-Nutzlasten.

Web-Auth ist ein HTTP-Test. POST /mcp/tickets mit mcpTicketsCall(). Nicht authentifizierte Anfragen müssen 401 sein, keine Login-Weiterleitung.

Was dieses Repo ist

Northwind Support. Eine Laravel-13-App, PHP 8.4, SQLite. Inertia und React sind nur die Dump-Seite. Der Agent ist der Schreibpfad.

Zwei MCP-Server, jeweils zweimal registriert, lokal und web.

routes/ai.php

Mcp::local('directory', DirectoryServer::class);
Mcp::local('tickets', TicketsServer::class);

Mcp::oauthRoutes();

Mcp::web('/mcp/directory', DirectoryServer::class)
    ->middleware(['auth:api', 'throttle:mcp']);

Mcp::web('/mcp/tickets', TicketsServer::class)
    ->middleware(['auth:api', 'throttle:mcp']);

DirectoryServer ist schreibgeschützt für Personen und Teams. TicketsServer ist das Helpdesk. Ticket-Tools dürfen User oder Team nicht über Eloquent abfragen. Sie schlagen Personen über den benannten directory-Client nach, get_person und directory://people/{id}. Deshalb gibt es zwei Server. Wenn du User::find() aus einem Ticket-Tool machst, hast du den Punkt übersprungen.

Abfragen leben in DirectoryRepository und TicketRepository. Tools injizieren diese.

Domäne

Drei Rollen auf users.role.

Rolle

Was sie können

requester

Tickets öffnen, eigene kommentieren, öffentliche Wissensdatenbank lesen

agent

Jedes Ticket sehen, zuweisen, kommentieren, Status ändern, interne Wissensdatenbank lesen

admin

Alles, was ein Agent kann, plus Tickets löschen und den Wochenrückblick-Prompt

Policies sind gewöhnliche Laravel-Policies. TicketPolicy deckt view, update, comment und delete ab. ArticlePolicy verbirgt interne Artikel vor Requesters. Personal ist Role::isStaff(), Agent oder Admin.

Login-Benutzer kommen aus LabSeeder. Passwort für alle ist password.

E-Mail

Rolle

ada@northwind.test

requester

sam@northwind.test

agent

root@northwind.test

admin

email_verified_at ist gesetzt. Fortify hat Verifizierung aktiviert. User implementiert MustVerifyEmail nicht, also wirst du nicht blockiert.

Jonah Hale, jonah@northwind.test, ist der Bereitschafts-Agent.

Tabellen

Halte sie klein. Wenn eine Spalte nicht von einem Tool benötigt wird, ist sie nicht da.

users. Starter-Kit-Spalten plus role (requester\|agent\|admin), team_id nullable, title, on_call.

teams. name, slug. Support, Billing, Warehouse.

tickets. subject, body, status (open\|pending\|closed), priority (low\|normal\|high\|urgent), requester_id, assignee_id nullable, team_id nullable.

comments. ticket_id, user_id, body.

articles. slug, title, body, visibility (public\|internal). Vier Zeilen. Öffentliche sind Rückerstattungen und Versand. Interne sind Eskalation und Rückerstattungsmissbrauch.

LabSeeder läuft von DatabaseSeeder. Es ist idempotent genug, um nach migrate:fresh erneut ausgeführt zu werden. Zwanzig Tickets, dreißig Kommentare, acht Personen, ein PNG unter storage/app/badge.png.

DirectoryServer

Schreibgeschützt. Die Anweisungen sagen das. Name Northwind Directory, Version 0.0.1, türkisfarbenes Symbol.

Tools

Tool

Was es tut

search_people

Suche nach Name, E-Mail oder Titel. Optionaler Team-Slug. Strukturierte { people } mit outputSchema. #[IsReadOnly] und #[IsIdempotent]

get_person

Einzelne Benutzer-ID nachschlagen. Benutzerdefinierte Validierungsmeldungen. Strukturiertes { person }

list_teams

Keine Pflichtargumente. Zwei Textblöcke, zuerst Namen, dann Slugs

who_is_on_call

Gibt den on_call-Benutzer zurück. #[IsOpenWorld] auf einer Fake-Rota, damit die Annotation verwendet wird

Ressourcen

URI

Was es tut

directory://org

Statisches Markdown. #[MimeType], #[Priority(0.9)], #[Audience(Role::Assistant)]

directory://people/{id}

Personendossier. HasUriTemplate, $request->get('id')

directory://teams/{slug}

Team-Dossier. Zweites Template, damit das erste kein Einzelfall ist

directory://on-call

Wer Bereitschaft hat. #[LastModified]

directory://badge

Kleines PNG über Response::fromStorage('badge.png')

Hier gibt es keine Prompts. Sie gehören auf den Ticket-Server, wo sie etwas zu sagen haben.

TicketsServer

Name Northwind Tickets, Version 0.0.1, dunkles Icon.

boot() meldet sich als sam@northwind.test an, wenn niemand authentifiziert ist. Lokales Cursor hat keine HTTP-Session. Ohne dies würde jedes Tool You must be signed in. sagen. Web-Anfragen haben bereits einen Passport-Benutzer, daher kehrt boot() früh zurück.

Tools

Tool

Was es tut

list_tickets

Listet Tickets, die der Benutzer sehen kann. Status- und Prioritätsfilter. Strukturierte Ausgabe plus desk://tickets/{id}-Ressourcenlinks

get_ticket

Ein Ticket. Namen von Bearbeiter und Anfragendem kommen von directory://people/{id}. withMeta(['source' => 'eloquent'])

create_ticket

Öffnet ein Ticket. Die Klasse $meta hat version und author

add_comment

Fügt nach der comment-Policy-Prüfung einen Kommentar hinzu

assign_ticket

#[IsIdempotent]. Löst die Person mit Mcp::client('directory')->callTool('get_person', ...) auf

set_status

Setzt open, pending oder closed. Das ist auch Schließen und Wiederöffnen

delete_ticket

#[IsDestructive]. shouldRegister ist nur für Admins true

close_stale_tickets

Schließt jedes open-Ticket, das älter als N Tage ist. Gibt dabei processing/progress aus

search_kb

Durchsucht Artikel, die der aktuelle Benutzer sehen kann. Strukturierte { articles } mit desk://kb/{slug}

show_queue

Modell-sichtbar. #[RendersApp(resource: QueueApp::class)]

get_queue_data

Gleiche App, visibility: [Visibility::App]. Das iframe aktualisiert, ohne dem Modell ein zweites Listentool zu geben

list_tickets kann TicketResource::uri() nicht für Links verwenden. Diese Methode gibt das Template desk://tickets/{id} zurück. Links müssen die erweiterte Zeichenkette sein.

assign_ticket und get_ticket weigern sich, User anzufassen. Wenn der Directory-Client abgekoppelt ist, schlägt die Zuweisung fehl. Pest beweist das.

Prompts

Prompt

Was es tut

draft_reply

Nimmt ticket_id und tone. Lädt das Ticket. Assistenten-Nachricht plus eine Benutzernachricht, die den echten Betreff enthält

triage_ticket

Nimmt ticket_id. Validiert mit einer nützlichen Fehlerzeichenkette

weekly_review

Zusammenfassung offener Tickets. shouldRegister ist für Anfragende false

Ressourcen

URI

Was es tut

desk://playbook

Statisches Markdown, hohe Priorität. Wie man triagiert

desk://queue

Markdown-Liste offener Tickets, die der aktuelle Benutzer sehen kann

desk://tickets/{id}

Markdown-Dossier mit Kommentaren

desk://kb/{slug}

Ein Artikel. Fehlende und verbotene Slugs geben denselben Fehler zurück

desk://kb/escalation

Nur für Mitarbeiter: Liste des internen Eskalationsartikels

ui:// QueueApp

Interaktives Queue-iframe

desk://queue ist Markdown. QueueApp ist das iframe. Verwechsle sie nicht.

QueueApp

QueueApp erweitert AppResource. Blade unter resources/views/mcp/queue-app.blade.php. Alpine innerhalb von <x-mcp::app>. Aktualisierung ruft get_queue_data über app.callServerTool auf.

Dies ist keine Inertia-Seite. Schreibe sie nicht in React um.

Wenn der Host keine MCP-Apps rendern kann, sind die Klassen und Pest-Tests immer noch der Beweis.

Auth und die Webserver

Sowohl /mcp/tickets als auch /mcp/directory verwenden auth:api und throttle:mcp. Der mcp-Limiter ist 60 pro Minute in AppServiceProvider, schlüsselbasiert auf Benutzer-ID oder IP.

User implementiert OAuthenticatable und verwendet Passport HasApiTokens. Das Fehlen des Interfaces ist der übliche Passport-Setup-Fehler.

Eine nicht authentifizierte POST-Anfrage gibt 401 mit WWW-Authenticate zurück, das auf die geschützte Ressourcen-Metadaten dieses Pfads verweist. Discovery deckt sowohl /mcp/tickets als auch /mcp/directory ab. Dynamische Registrierung ist POST /oauth/register. Ein Zugriffstoken funktioniert auf beiden Servern.

Der Genehmigungs- und Ablehnungsbildschirm ist resources/views/mcp/authorize.blade.php. Lass ihn in Ruhe.

Dashboard

Fortify und Inertia kommen aus dem Starter-Kit. Ersetze sie nicht.

/dashboard ist zwei Tabellen. Tickets zeigen id, Betreff, Status, Priorität, Anfragenden und Bearbeiter. Personen zeigen id, Name, Rolle, Team und Bereitschaft. Wayfinder benennt die Route. DashboardController übergibt Inertia-Props. Keine Formulare, die Tickets erstellen.

Beweis, dass ein Schreib-Tool funktioniert hat, durch Aktualisieren von /dashboard. Führe composer run dev aus, wenn du dich um die React-Seite kümmerst.

Passport-Autorisierung und das QueueApp-iframe bleiben Blade. Das Paket besitzt diese.

Wie du damit sprichst

Cursor, lokal. .cursor/mcp.json startet beide Server aus dem Projektstamm.

{
    "mcpServers": {
        "northwind-tickets": {
            "command": "php",
            "args": ["artisan", "mcp:start", "tickets"]
        },
        "northwind-directory": {
            "command": "php",
            "args": ["artisan", "mcp:start", "directory"]
        }
    }
}

Tickets ist die tägliche Schleife. Du brauchst directory in Cursor nicht für die Client-Arbeit. Der Ticket-Server-Prozess startet es.

Lokale Tickets laufen als Sam. Um Ada oder Root zu sehen, verwende Pest actingAs oder den Webserver mit ihrem Token.

Inspector. php artisan mcp:inspector tickets und php artisan mcp:inspector mcp/tickets. Verwende dies, wenn ein Tool nichts tut und du das rohe Ergebnis brauchst. Web-Inspector benötigt ein Passport-Bearer-Token. Die Inspector-UI ist auf :6274, diese App ist auf :8000. CORS für mcp/*, oauth/* und .well-known/* lebt in config/cors.php. Ohne diese Pfade geben die Discovery-GETs 200 zurück und der Browser verwirft sie trotzdem.

Dashboard. Beweis, dass die Schreib-Tools Eloquent treffen.

Pest. php artisan test --compact tests/Feature/Mcp.

Rufe nicht Client::web('http://127.0.0.1:8000/mcp/directory') aus einem Ticket-Tool auf, während artisan serve der einzige PHP-Prozess ist. Es wird hängen bleiben. composer run dev ändert das nicht. Ein zweiter PHP-Server auf :8001 plus Client::web ist ein optionales späteres Experiment, nicht der Standard.

Dieses Repo testen

Feature-Tests leben in tests/Feature/Mcp. TestCase bindet den directory-Client immer neu an InProcessDirectoryTransport, damit SQLite :memory: sichtbar ist. Ein Test in DirectoryClientTest verwendet den echten stdio-Client, um Tools aufzulisten. Der Unplugged-Client-Test zeigt den benannten Client auf php -r 'exit(1);'.

Helfer in tests/Helpers.php:

  • mcpRpc($response) für das rohe JSON-RPC-Array

  • mcpToolContent($response) für die Ergebnis-Inhaltsliste

  • mcpTicketsCall($name, $arguments) für einen tools/call-HTTP-Body

Um zu behaupten, dass ein Tool versteckt ist, TicketsServer::actingAs($user) und dann (new TicketsServer(new FakeTransporter))->createContext()->tools(). Rufe nicht handle() auf einem versteckten Tool auf und erwarte einen Policy-Fehler. Das Aufrufen ist ein JSON-RPC-Fehler „nicht gefunden“.

Lies Annotationen aus $tool->annotations(), nicht aus toArray()['annotations']. Tool::toArray() typisiert dieses Feld als array|object. Ressourcen-toArray() lässt Annotationen aus.

Friere Zeit mit Carbon::setTestNow ein. Ohne pest-plugin-phpstan ist $this TestCall und $this->travelTo typprüft nicht.

Importiere Pest\Laravel\postJson und Pest\Laravel\withToken. Rufe sie nicht auf $this auf.

Was die Suite abdeckt:

  • Anfragender kann nicht zuweisen oder löschen

  • Agent kann zuweisen, nicht löschen

  • Admin kann löschen

  • delete_ticket fehlt, wenn als Sam agiert, vorhanden für Root

  • Interne Eskalationsressource vor Ada verborgen

  • search_kb verbirgt interne Artikel vor Anfragenden

  • weekly_review nur für Mitarbeiter

  • assign_ticket schlägt fehl, wenn der Directory-Client die Person nicht finden kann

  • Validierungsfehler sind Sätze

  • close_stale_tickets gibt Fortschrittsbenachrichtigungen aus

  • OAuth-Discovery, Registrierung, Autorisierungs-Blade, PKCE, dann ein Tool-Aufruf auf beiden Webservern

Starter-Kit-Fortify-Tests bleiben. Schreibe sie nicht um, um MCP zu beweisen.

Dateilayout

app/
  Enums/Role.php Status.php Priority.php Visibility.php
  Models/User.php Team.php Ticket.php Comment.php Article.php
  Policies/TicketPolicy.php ArticlePolicy.php
  Repositories/DirectoryRepository.php TicketRepository.php ArticleRepository.php
  Http/Controllers/DashboardController.php
  Mcp/
    Servers/DirectoryServer.php TicketsServer.php
    Tools/          (15 tools)
    Resources/      (11 resources, including QueueApp)
    Prompts/        (3 prompts)
routes/ai.php
resources/js/pages/dashboard.tsx
resources/views/mcp/authorize.blade.php
resources/views/mcp/queue-app.blade.php
database/seeders/LabSeeder.php
tests/Feature/Mcp/
tests/Helpers.php
tests/Support/InProcessDirectoryTransport.php
.ai/rules/          (settled decisions for the next agent)

Stehende Fallen

Diese sind bereits in .ai/rules. Sie gehören auch hierher, weil sie leicht wieder zu brechen sind.

  • Ticket-Tools sprechen mit DirectoryServer über Client::local. Tests überschreiben das mit dem In-Process-Transport.

  • Frage User oder Team nicht aus assign_ticket oder get_ticket ab. Verschiebe diese Suche nicht in TicketRepository.

  • PHPDoc-Verzeichnis $resources als class-string<Server\Resource>. Pint schreibt class-string<Resource> in den PHP-Typ resource klein.

  • ai.php bleibt außerhalb der Web-Middleware-Gruppe.

  • QueueApp ist ui://. desk://queue ist Markdown.

  • KB-Artikel gehen durch ArticleRepository. Fehlende und verbotene desk://kb/{slug}-Lesezugriffe verwenden denselben Fehler.

Dokumentation

-
license - not tested
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.

  • Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jaksa-v/mcp-lab'

If you have feedback or need assistance with the MCP directory API, please join our Discord server