Install Prism Relay
mainInstall the package via Composer and then publish the configuration file to your Laravel application to begin defining MCP server connections.
composer require prism-php/relay
php artisan vendor:publish --tag="relay-config"repository·main·Indexed 41 days ago
https://github.com/prism-php/relayA seamless integration between Prism and the Model Context Protocol (MCP), allowing AI applications to leverage external tools via MCP servers. It supports both Stdio and Http (including SSE) transports, provides a Laravel facade for easy configuration, and automatically maps MCP tool definitions to Prism Tool objects.
Install the package via Composer and then publish the configuration file to your Laravel application to begin defining MCP server connections.
composer require prism-php/relay
php artisan vendor:publish --tag="relay-config"Define your MCP server connections in config/relay.php. Each server requires a unique name and specific configuration based on its transport type (Stdio or Http).
Key configuration options:
command: (Stdio only) An array representing the command to execute.url: (Http only) The endpoint of the MCP server.api_key: (Http only) Static API key for authentication.timeout: Execution timeout in seconds.env: (Stdio only) Environment variables for the subprocess.transport: Use \Prism\Relay\Enums\Transport::Stdio or \Prism\Relay\Enums\Transport::Http.cache_duration: Tool cache duration in minutes (set to 0 to disable).return [
'servers' => [
'puppeteer' => [
'command' => ['npx', '-y', '@modelcontextprotocol/server-puppeteer'],
'timeout' => 30,
'env' => [],
'transport' => \Prism\Relay\Enums\Transport::Stdio,
],
'github' => [
'url' => env('RELAY_GITHUB_SERVER_URL', 'http://localhost:8001/api'),
'timeout' => 30,
'transport' => \Prism\Relay\Enums\Transport::Http,
],
],
'cache_duration' => env('RELAY_TOOLS_CACHE_DURATION', 60),
];When you call tools(), Relay performs several transformations to make MCP tools compatible with the Prism ecosystem:
relay__{serverName}__ to prevent collisions (e.g., relay__my_server__get_weather).inputSchema properties are converted into Prism Schema objects (e.g., StringSchema, NumberSchema, EnumSchema, ObjectSchema, ArraySchema).Relay detects common tool patterns to provide cleaner calling signatures:url parameter.selector parameter.selector and value.name property in their schema.You can combine tools from multiple different MCP servers by spreading the results of multiple Relay::tools() calls into a single array within withTools().
use Prism\Prism\Prism;
use Prism\Relay\Facades\Relay;
use Prism\Prism\Enums\Provider;
$response = Prism::text()
->using(Provider::Anthropic, 'claude-3-7-sonnet-latest')
->withTools([
...Relay::tools('github'),
...Relay::tools('puppeteer')
])
->withPrompt('Find and take screenshots of Laravel repositories')
->asText();Integrate MCP tools into a Prism request by calling Relay::tools('server_name') and passing the result to withTools(). This allows the AI agent to access external capabilities provided by the specified MCP server.
use Prism\Prism\Prism;
use Prism\Relay\Facades\Relay;
use Prism\Prism\Enums\Provider;
$response = Prism::text()
->using(Provider::Anthropic, 'claude-3-7-sonnet-latest')
->withPrompt('Find information about Laravel on the web')
->withTools(Relay::tools('puppeteer'))
->asText();
return $response->text;To use dynamic OAuth tokens with HTTP transport, use the withToken() method. The runtime token takes priority over any static api_key defined in the configuration.
If the server returns an HTTP 401, Relay throws an AuthorizationException, which you should catch to trigger your application's re-authorization flow.
use Prism\Relay\Facades\Relay;
use Prism\Relay\Exceptions\AuthorizationException;
use Prism\Relay\Exceptions\TransportException;
try {
// Via the Facade
$tools = Relay::withToken($request->user()->mcp_token)->tools('github');
// Or on a Relay instance
$relay = Relay::make('github');
$tools = $relay->withToken($request->user()->mcp_token)->tools();
} catch (AuthorizationException $e) {
// Token is missing, expired, or rejected (HTTP 401)
return redirect('/oauth/reconnect');
} catch (TransportException $e) {
// Other transport failure (non-401)
Log::error('MCP Transport error: ' . $e->getMessage());
}The HttpTransport class is used to communicate with Model Context Protocol (MCP) servers over HTTP. It supports standard JSON-RPC 2.0 requests and handles both standard JSON responses and Server-Sent Events (SSE) for streamable HTTP.
When initializing the transport, you can provide a configuration array with the following keys:
url (string): The base URL of the MCP server.access_token (string): An optional Bearer token for authentication. If provided, it takes precedence over api_key.api_key (string): An optional API key for authentication.headers (array): An associative array of additional HTTP headers to include in every request.timeout (int): The request timeout in seconds. Defaults to 30 if not specified.$config = [
'url' => 'https://mcp-server.example.com',
'access_token' => 'your-bearer-token',
'headers' => [
'X-Custom-Header' => 'value',
],
'timeout' => 60,
];
$transport = new \\Prism\\Relay\\Transport\\HttpTransport($config);When instantiating HttpSseTransport, provide a configuration array with the following keys:
| Key | Type | Description |
|---|---|---|
url | string | Required. The base SSE endpoint URL of the MCP server. |
api_key | string | Optional. An API key used for Bearer token authentication. |
headers | array<string, string> | Optional. An associative array of additional HTTP headers to include in both SSE and POST requests. |
timeout | int | Optional. The timeout in seconds for connections and waiting for responses. Defaults to 30. |
The StdioTransport class implements the Transport interface using Standard Input/Output to communicate with an MCP server process. To instantiate it, you must provide a configuration array containing the following required keys:
command: An array<string> representing the command and its arguments to execute.env: An array<string, string> representing the environment variables for the process.Optional configuration keys:
timeout: An int specifying the timeout in seconds for waiting for responses (defaults to 30).$transport = new StdioTransport([
'command' => ['path/to/mcp-server', '--arg1', 'val1'],
'env' => ['API_KEY' => 'secret'],
'timeout' => 60,
]);When using Transport::Http, you can provide a url, api_key, timeout, and custom headers.
Note on Authentication: Relay handles attaching Bearer tokens to requests, but your application is responsible for the full OAuth 2.1 flow (discovery, authorization code exchange, and token management).
'github' => [
'url' => env('RELAY_GITHUB_SERVER_URL', 'http://localhost:8000/api'),
'api_key' => env('RELAY_GITHUB_SERVER_API_KEY'),
'timeout' => 30,
'transport' => Transport::Http,
'headers' => [
'User-Agent' => 'prism-php-relay/1.0',
]
],The Transport::Stdio mechanism launches a subprocess and communicates via standard I/O. This is ideal for running tools directly on your application server.
Use the command key to define the executable and its arguments. Arguments that are arrays will be passed as JSON encoded strings. Use the env key to pass environment variables to the subprocess.
'puppeteer' => [
'command' => [
'npx',
'-y',
'@modelcontextprotocol/server-puppeteer',
'--options',
[
'debug' => env('MCP_PUPPETEER_DEBUG', false)
]
],
'timeout' => 30,
'transport' => Transport::Stdio,
'env' => [
'NODE_ENV' => 'production',
'MCP_SERVER_PORT' => '3001',
],
],Relay uses specific exception types to allow for granular error handling:
ServerConfigurationException: Configuration errors (e.g., missing server or invalid settings).ToolDefinitionException: Issues retrieving tool definitions from the MCP server.AuthorizationException: HTTP 401 errors (token missing, expired, or invalid).TransportException: Communication failures with the MCP server.ToolCallException: Errors occurring during the execution of a specific tool.RelayException: General MCP-related errors.use Prism\Relay\Exceptions\ServerConfigurationException;
use Prism\Relay\Exceptions\ToolDefinitionException;
use Prism\Relay\Exceptions\AuthorizationException;
use Prism\Relay\Exceptions\TransportException;
use Prism\Relay\Exceptions\ToolCallException;
use Prism\Relay\Exceptions\RelayException;
try {
$tools = Relay::tools('puppeteer');
} catch (ServerConfigurationException $e) {
Log::error('MCP Server configuration error: ' . $e->getMessage());
} catch (ToolDefinitionException $e) {
Log::error('MCP Tool definition error: ' . $e->getMessage());
} catch (AuthorizationException $e) {
return redirect('/oauth/reconnect');
} catch (TransportException $e) {
Log::error('MCP Transport error: ' . $e->getMessage());
} catch (ToolCallException $e) {
Log::error('MCP Tool call error: ' . $e->getMessage());
} catch (RelayException $e) {
Log::error('Relay general error: ' . $e->getMessage());
}