forked from core/php-mcp
feat: MCP domain as native endpoint with OpenBrain support
The mcp.* domain now serves both the human-readable portal AND the
functional API. Agents POST to /tools/call with an API key, browsers
get the HTML docs as a fallback. No separate api.* bridge needed.
- Add POST /tools/call, GET /resources/{uri} routes to mcp domain
- Add JSON server list/detail routes (servers.json, servers/{id}.json)
- Add OpenBrain icon to landing, index, and show views
- Replace all api.* domain references with mcp.* (request()->getSchemeAndHttpHost())
- Rewrite connect.blade.php as HTTP-only documentation
- Update ApiExplorer base URL to use current mcp domain
- Remove stdio/Docker configuration from all views
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
92faed247e
commit
0653c82148
8 changed files with 159 additions and 124 deletions
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Core\Mcp\Middleware\McpApiKeyAuth;
|
||||
use Core\Mcp\Middleware\McpAuthenticate;
|
||||
use Mod\Api\Controllers\McpApiController;
|
||||
use Core\Website\Mcp\Controllers\McpRegistryController;
|
||||
|
||||
/*
|
||||
|
|
@ -9,8 +11,8 @@ use Core\Website\Mcp\Controllers\McpRegistryController;
|
|||
| MCP Portal Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Public routes for the MCP server registry and documentation portal.
|
||||
| These routes serve both human-readable docs and machine-readable JSON.
|
||||
| The MCP domain IS the endpoint. Agents hit /tools/call and /resources/*
|
||||
| with an API key; browsers get the human-readable fallback (HTML docs).
|
||||
|
|
||||
| Domain is set via config('mcp.domain') — the app Boot may override
|
||||
| this with a wildcard for multi-domain support.
|
||||
|
|
@ -18,27 +20,36 @@ use Core\Website\Mcp\Controllers\McpRegistryController;
|
|||
*/
|
||||
|
||||
Route::domain(config('mcp.domain'))->name('mcp.')->group(function () {
|
||||
// Agent discovery endpoint (always JSON)
|
||||
// Agent discovery endpoint (always JSON, no auth)
|
||||
Route::get('.well-known/mcp-servers.json', [McpRegistryController::class, 'registry'])
|
||||
->name('registry');
|
||||
|
||||
// Landing page
|
||||
// ── Functional API (authenticated) ────────────────────────────
|
||||
Route::middleware(McpApiKeyAuth::class)->group(function () {
|
||||
Route::post('tools/call', [McpApiController::class, 'callTool'])->name('tools.call');
|
||||
Route::get('resources/{uri}', [McpApiController::class, 'resource'])->name('resources.read')
|
||||
->where('uri', '.+');
|
||||
Route::get('servers.json', [McpApiController::class, 'servers'])->name('servers.json');
|
||||
Route::get('servers/{id}.json', [McpApiController::class, 'server'])->name('servers.json.show')
|
||||
->where('id', '[a-z0-9-]+');
|
||||
Route::get('servers/{id}/tools', [McpApiController::class, 'tools'])->name('servers.tools')
|
||||
->where('id', '[a-z0-9-]+');
|
||||
});
|
||||
|
||||
// ── Human-readable portal (optional auth) ────────────────────
|
||||
Route::get('/', [McpRegistryController::class, 'landing'])
|
||||
->middleware(McpAuthenticate::class.':optional')
|
||||
->name('landing');
|
||||
|
||||
// Server list (HTML/JSON based on Accept header)
|
||||
Route::get('servers', [McpRegistryController::class, 'index'])
|
||||
->middleware(McpAuthenticate::class.':optional')
|
||||
->name('servers.index');
|
||||
|
||||
// Server detail (supports .json extension)
|
||||
Route::get('servers/{id}', [McpRegistryController::class, 'show'])
|
||||
->middleware(McpAuthenticate::class.':optional')
|
||||
->name('servers.show')
|
||||
->where('id', '[a-z0-9-]+(?:\.json)?');
|
||||
->where('id', '[a-z0-9-]+');
|
||||
|
||||
// Connection config page
|
||||
Route::get('connect', [McpRegistryController::class, 'connect'])
|
||||
->middleware(McpAuthenticate::class.':optional')
|
||||
->name('connect');
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
wire:model="baseUrl"
|
||||
class="rounded-md border-yellow-300 shadow-sm focus:border-yellow-500 focus:ring-yellow-500 text-sm"
|
||||
>
|
||||
<option value="https://api.host.uk.com">Production</option>
|
||||
<option value="https://api.staging.host.uk.com">Staging</option>
|
||||
<option value="https://mcp.lthn.ai">Production</option>
|
||||
<option value="https://mcp.lthn.sh">Homelab</option>
|
||||
<option value="http://localhost">Local</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -149,13 +149,14 @@
|
|||
<p class="text-zinc-600 dark:text-zinc-400 mb-4 text-sm">
|
||||
Call an MCP tool via HTTP POST:
|
||||
</p>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-3 overflow-x-auto text-xs"><code class="text-emerald-400">curl -X POST https://mcp.host.uk.com/api/v1/tools/call \
|
||||
@php $mcpUrl = request()->getSchemeAndHttpHost(); @endphp
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-3 overflow-x-auto text-xs"><code class="text-emerald-400">curl -X POST {{ $mcpUrl }}/tools/call \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"server": "commerce",
|
||||
"tool": "product_list",
|
||||
"arguments": {}
|
||||
"server": "openbrain",
|
||||
"tool": "brain_recall",
|
||||
"arguments": { "query": "recent decisions" }
|
||||
}'</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
<x-layouts.mcp>
|
||||
<x-slot:title>Setup Guide</x-slot:title>
|
||||
|
||||
@php
|
||||
$mcpUrl = request()->getSchemeAndHttpHost();
|
||||
@endphp
|
||||
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="mb-8">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 dark:text-white">Setup Guide</h1>
|
||||
<p class="mt-2 text-lg text-zinc-600 dark:text-zinc-400">
|
||||
Connect to MCP servers via HTTP API or stdio.
|
||||
Connect AI agents to MCP servers via HTTP.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -28,7 +32,7 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<!-- HTTP API (Primary) -->
|
||||
<!-- HTTP API -->
|
||||
<div class="bg-white dark:bg-zinc-800 rounded-xl border-2 border-cyan-500 p-6 mb-8">
|
||||
<div class="flex items-center space-x-3 mb-4">
|
||||
<div class="p-2 bg-cyan-100 dark:bg-cyan-900/30 rounded-lg">
|
||||
|
|
@ -37,143 +41,118 @@
|
|||
<div>
|
||||
<h2 class="text-xl font-semibold text-zinc-900 dark:text-white">HTTP API</h2>
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-cyan-100 text-cyan-800 dark:bg-cyan-900/30 dark:text-cyan-300">
|
||||
Recommended
|
||||
All platforms
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Call MCP tools from any language or platform using standard HTTP requests.
|
||||
Perfect for external integrations, webhooks, and remote agents.
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Call MCP tools from any language, platform, or AI agent using standard HTTP requests.
|
||||
Works with Claude Code, Cursor, custom agents, webhooks, and any HTTP client.
|
||||
</p>
|
||||
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">1. Get your API key</h3>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4 text-sm">
|
||||
Sign in to your account to create an API key from the admin dashboard.
|
||||
Create an API key from your admin dashboard. Keys use the <code class="px-1 py-0.5 bg-zinc-100 dark:bg-zinc-700 rounded text-xs">hk_</code> prefix.
|
||||
</p>
|
||||
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">2. Call a tool</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm mb-4"><code class="text-emerald-400">curl -X POST https://mcp.host.uk.com/api/v1/mcp/tools/call \
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">2. Discover available servers</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm mb-4"><code class="text-emerald-400">curl {{ $mcpUrl }}/servers.json \
|
||||
-H "Authorization: Bearer YOUR_API_KEY"</code></pre>
|
||||
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">3. Call a tool</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm mb-4"><code class="text-emerald-400">curl -X POST {{ $mcpUrl }}/tools/call \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"server": "commerce",
|
||||
"tool": "product_list",
|
||||
"arguments": { "category": "hosting" }
|
||||
"server": "openbrain",
|
||||
"tool": "brain_recall",
|
||||
"arguments": { "query": "authentication decisions" }
|
||||
}'</code></pre>
|
||||
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">3. List available tools</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-emerald-400">curl https://mcp.host.uk.com/api/v1/mcp/servers \
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">4. Read a resource</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-emerald-400">curl {{ $mcpUrl }}/resources/plans://all \
|
||||
-H "Authorization: Bearer YOUR_API_KEY"</code></pre>
|
||||
|
||||
<div class="mt-6 p-4 bg-zinc-50 dark:bg-zinc-900/50 rounded-lg">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h4 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300">API Endpoints</h4>
|
||||
<h4 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300">Endpoints</h4>
|
||||
<a href="{{ route('mcp.openapi.json') }}" target="_blank" class="text-xs text-cyan-600 hover:text-cyan-700 dark:text-cyan-400">
|
||||
View OpenAPI Spec →
|
||||
</a>
|
||||
</div>
|
||||
<div class="space-y-2 text-sm">
|
||||
<div class="flex items-center justify-between">
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /api/v1/mcp/servers</code>
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /.well-known/mcp-servers.json</code>
|
||||
<span class="text-zinc-500">Agent discovery</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /servers</code>
|
||||
<span class="text-zinc-500">List all servers</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /api/v1/mcp/servers/{id}</code>
|
||||
<span class="text-zinc-500">Server details</span>
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /servers/{id}</code>
|
||||
<span class="text-zinc-500">Server details + tools</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /api/v1/mcp/servers/{id}/tools</code>
|
||||
<span class="text-zinc-500">List tools</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<code class="text-zinc-600 dark:text-zinc-400">POST /api/v1/mcp/tools/call</code>
|
||||
<code class="text-zinc-600 dark:text-zinc-400">POST /tools/call</code>
|
||||
<span class="text-zinc-500">Execute a tool</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /api/v1/mcp/resources/{uri}</code>
|
||||
<code class="text-zinc-600 dark:text-zinc-400">GET /resources/{uri}</code>
|
||||
<span class="text-zinc-500">Read a resource</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stdio (Secondary) -->
|
||||
<!-- Code Examples -->
|
||||
<div class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-6 mb-8">
|
||||
<div class="flex items-center space-x-3 mb-4">
|
||||
<div class="p-2 bg-violet-100 dark:bg-violet-900/30 rounded-lg">
|
||||
<flux:icon.command-line class="w-6 h-6 text-violet-600 dark:text-violet-400" />
|
||||
<flux:icon.code-bracket class="w-6 h-6 text-violet-600 dark:text-violet-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-zinc-900 dark:text-white">Stdio (Local)</h2>
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-zinc-100 text-zinc-600 dark:bg-zinc-700 dark:text-zinc-400">
|
||||
For local development
|
||||
</span>
|
||||
<h2 class="text-xl font-semibold text-zinc-900 dark:text-white">Code Examples</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Direct stdio connection for Claude Code and other local AI agents.
|
||||
Ideal for OSS framework users running their own Host Hub instance.
|
||||
</p>
|
||||
<div class="space-y-6">
|
||||
<!-- Python -->
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">Python</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-emerald-400">import requests
|
||||
|
||||
<details class="group">
|
||||
<summary class="cursor-pointer text-sm font-medium text-cyan-600 dark:text-cyan-400 hover:text-cyan-700">
|
||||
Show stdio configuration
|
||||
</summary>
|
||||
|
||||
<div class="mt-4 space-y-6">
|
||||
<!-- Claude Code -->
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">Claude Code</h3>
|
||||
<p class="text-zinc-500 dark:text-zinc-400 text-sm mb-2">
|
||||
Add to <code class="px-1 py-0.5 bg-zinc-100 dark:bg-zinc-700 rounded">~/.claude/claude_code_config.json</code>:
|
||||
</p>
|
||||
<pre class="bg-zinc-100 dark:bg-zinc-900 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-zinc-800 dark:text-zinc-200">{
|
||||
"mcpServers": {
|
||||
@foreach($servers as $server)
|
||||
"{{ $server['id'] }}": {
|
||||
"command": "{{ $server['connection']['command'] ?? 'php' }}",
|
||||
"args": {!! json_encode($server['connection']['args'] ?? ['artisan', 'mcp:agent-server']) !!},
|
||||
"cwd": "{{ $server['connection']['cwd'] ?? '/path/to/host.uk.com' }}"
|
||||
}{{ !$loop->last ? ',' : '' }}
|
||||
@endforeach
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
|
||||
<!-- Cursor -->
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">Cursor</h3>
|
||||
<p class="text-zinc-500 dark:text-zinc-400 text-sm mb-2">
|
||||
Add to <code class="px-1 py-0.5 bg-zinc-100 dark:bg-zinc-700 rounded">.cursor/mcp.json</code>:
|
||||
</p>
|
||||
<pre class="bg-zinc-100 dark:bg-zinc-900 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-zinc-800 dark:text-zinc-200">{
|
||||
"mcpServers": {
|
||||
@foreach($servers as $server)
|
||||
"{{ $server['id'] }}": {
|
||||
"command": "{{ $server['connection']['command'] ?? 'php' }}",
|
||||
"args": {!! json_encode($server['connection']['args'] ?? ['artisan', 'mcp:agent-server']) !!}
|
||||
}{{ !$loop->last ? ',' : '' }}
|
||||
@endforeach
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
|
||||
<!-- Docker -->
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">Docker</h3>
|
||||
<pre class="bg-zinc-100 dark:bg-zinc-900 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-zinc-800 dark:text-zinc-200">{
|
||||
"mcpServers": {
|
||||
"hosthub-agent": {
|
||||
"command": "docker",
|
||||
"args": ["exec", "-i", "hosthub-app", "php", "artisan", "mcp:agent-server"]
|
||||
resp = requests.post(
|
||||
"{{ $mcpUrl }}/tools/call",
|
||||
headers={"Authorization": "Bearer hk_your_key"},
|
||||
json={
|
||||
"server": "openbrain",
|
||||
"tool": "brain_recall",
|
||||
"arguments": {"query": "recent decisions"}
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
)
|
||||
print(resp.json())</code></pre>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- JavaScript -->
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-zinc-700 dark:text-zinc-300 mb-2">JavaScript</h3>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-emerald-400">const resp = await fetch("{{ $mcpUrl }}/tools/call", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Authorization": "Bearer hk_your_key",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
server: "openbrain",
|
||||
tool: "brain_recall",
|
||||
arguments: { query: "recent decisions" },
|
||||
}),
|
||||
});
|
||||
const data = await resp.json();</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Authentication Methods -->
|
||||
|
|
@ -199,6 +178,28 @@
|
|||
check your key's server scopes in your admin dashboard.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 p-4 bg-cyan-50 dark:bg-cyan-900/20 rounded-lg border border-cyan-200 dark:border-cyan-800">
|
||||
<h4 class="text-sm font-semibold text-cyan-800 dark:text-cyan-300 mb-1">Rate limiting</h4>
|
||||
<p class="text-sm text-cyan-700 dark:text-cyan-400">
|
||||
Requests are rate limited to 120 per minute. Rate limit headers
|
||||
(<code class="text-xs">X-RateLimit-Limit</code>, <code class="text-xs">X-RateLimit-Remaining</code>)
|
||||
are included in all responses.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Discovery -->
|
||||
<div class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold text-zinc-900 dark:text-white mb-4">Discovery</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Agents discover available servers automatically via the well-known endpoint:
|
||||
</p>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm mb-4"><code class="text-emerald-400">curl {{ $mcpUrl }}/.well-known/mcp-servers.json</code></pre>
|
||||
<p class="text-sm text-zinc-500 dark:text-zinc-400">
|
||||
Returns the server registry with capabilities and connection details.
|
||||
No authentication required for discovery.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Help -->
|
||||
|
|
@ -208,8 +209,8 @@
|
|||
<flux:button href="{{ route('mcp.servers.index') }}" icon="server-stack">
|
||||
Browse Servers
|
||||
</flux:button>
|
||||
<flux:button href="https://host.uk.com/contact" variant="ghost">
|
||||
Contact Support
|
||||
<flux:button href="{{ route('mcp.openapi.json') }}" icon="code-bracket" variant="ghost" target="_blank">
|
||||
OpenAPI Spec
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
@case('supporthost')
|
||||
<flux:icon.chat-bubble-left-right class="w-6 h-6 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
@case('openbrain')
|
||||
<flux:icon.light-bulb class="w-6 h-6 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
@case('analyticshost')
|
||||
<flux:icon.chart-bar class="w-6 h-6 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@
|
|||
@case('supporthost')
|
||||
<flux:icon.chat-bubble-left-right class="w-6 h-6 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
@case('openbrain')
|
||||
<flux:icon.light-bulb class="w-6 h-6 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
@case('analyticshost')
|
||||
<flux:icon.chart-bar class="w-6 h-6 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
|
|
@ -180,18 +183,21 @@
|
|||
@endif
|
||||
|
||||
<!-- Quick Start -->
|
||||
@php
|
||||
$mcpUrl = request()->getSchemeAndHttpHost();
|
||||
@endphp
|
||||
<section class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-8">
|
||||
<h2 class="text-2xl font-semibold text-zinc-900 dark:text-white mb-4">Quick Start</h2>
|
||||
<p class="text-zinc-600 dark:text-zinc-400 mb-6">
|
||||
Call MCP tools via HTTP API with your API key:
|
||||
Call MCP tools via HTTP with your API key:
|
||||
</p>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm mb-6"><code class="text-emerald-400">curl -X POST https://mcp.host.uk.com/api/v1/mcp/tools/call \
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm mb-6"><code class="text-emerald-400">curl -X POST {{ $mcpUrl }}/tools/call \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"server": "commerce",
|
||||
"tool": "product_list",
|
||||
"arguments": {}
|
||||
"server": "openbrain",
|
||||
"tool": "brain_recall",
|
||||
"arguments": { "query": "recent decisions" }
|
||||
}'</code></pre>
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
<flux:button href="{{ route('mcp.connect') }}" icon="document-text" variant="primary">
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
@case('supporthost')
|
||||
<flux:icon.chat-bubble-left-right class="w-8 h-8 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
@case('openbrain')
|
||||
<flux:icon.light-bulb class="w-8 h-8 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
@case('analyticshost')
|
||||
<flux:icon.chart-bar class="w-8 h-8 text-cyan-600 dark:text-cyan-400" />
|
||||
@break
|
||||
|
|
@ -96,18 +99,28 @@
|
|||
</div>
|
||||
|
||||
<!-- Connection -->
|
||||
@if(!empty($server['connection']))
|
||||
<div class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-6 mb-8">
|
||||
<h2 class="text-lg font-semibold text-zinc-900 dark:text-white mb-4">Connection</h2>
|
||||
<pre class="bg-zinc-100 dark:bg-zinc-900 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-zinc-800 dark:text-zinc-200">{
|
||||
"{{ $server['id'] }}": {
|
||||
"command": "{{ $server['connection']['command'] ?? 'php' }}",
|
||||
"args": {!! json_encode($server['connection']['args'] ?? ['artisan', 'mcp:agent-server']) !!},
|
||||
"cwd": "{{ $server['connection']['cwd'] ?? '/path/to/project' }}"
|
||||
}
|
||||
}</code></pre>
|
||||
</div>
|
||||
@endif
|
||||
@php
|
||||
$mcpUrl = request()->getSchemeAndHttpHost();
|
||||
@endphp
|
||||
<div class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 p-6 mb-8">
|
||||
<h2 class="text-lg font-semibold text-zinc-900 dark:text-white mb-4">Connection</h2>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
|
||||
Call tools on this server via HTTP:
|
||||
</p>
|
||||
<pre class="bg-zinc-900 dark:bg-zinc-950 rounded-lg p-4 overflow-x-auto text-sm"><code class="text-emerald-400">curl -X POST {{ $mcpUrl }}/tools/call \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"server": "{{ $server['id'] }}",
|
||||
"tool": "{{ !empty($server['tools']) ? $server['tools'][0]['name'] : 'tool_name' }}",
|
||||
"arguments": {}
|
||||
}'</code></pre>
|
||||
<p class="mt-3 text-xs text-zinc-500 dark:text-zinc-400">
|
||||
<a href="{{ route('mcp.connect') }}" class="text-cyan-600 dark:text-cyan-400 hover:underline">
|
||||
Full setup guide →
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Tools -->
|
||||
@if(!empty($server['tools']))
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ class ApiExplorer extends Component
|
|||
|
||||
public function mount(): void
|
||||
{
|
||||
// Set base URL from config
|
||||
$this->baseUrl = config('api.base_url', config('app.url'));
|
||||
// Set base URL from current request (mcp domain)
|
||||
$this->baseUrl = request()->getSchemeAndHttpHost();
|
||||
|
||||
// Pre-select first endpoint
|
||||
if (! empty($this->endpoints)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue