Prism Relay

repository·main·Indexed 41 days ago

https://github.com/prism-php/relay

A 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.

Tokens
6.6K
Snippets
22
Records
27
Agent score
100%

What's inside Prism Relay

  1. Install Prism Relay

    main

    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"
  2. Configure MCP servers in relay.php

    main

    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),
    ];
  3. How Relay maps MCP tools to Prism Tools

    main

    When you call tools(), Relay performs several transformations to make MCP tools compatible with the Prism ecosystem:

    1. Naming: Tools are prefixed with relay__{serverName}__ to prevent collisions (e.g., relay__my_server__get_weather).
    2. Parameter Mapping: MCP inputSchema properties are converted into Prism Schema objects (e.g., StringSchema, NumberSchema, EnumSchema, ObjectSchema, ArraySchema).
    3. Handler Generation: A specialized handler function is generated for each tool. These handlers automatically map arguments to the correct MCP tool parameters.
    4. Specialized Handlers: Relay detects common tool patterns to provide cleaner calling signatures:
      • URL-based: Tools requiring only a url parameter.
      • Selector-based: Tools requiring only a selector parameter.
      • Selector/Value-based: Tools requiring selector and value.
      • Name-based: Tools containing a name property in their schema.
  4. Use multiple MCP servers in one agent

    main

    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();
  5. Use MCP tools with a Prism agent

    main

    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;
  6. Pass Bearer tokens to HTTP MCP servers

    main

    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());
    }
  7. Configure the HttpTransport for MCP servers

    main

    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);
  8. Configure HttpSseTransport

    main

    When instantiating HttpSseTransport, provide a configuration array with the following keys:

    KeyTypeDescription
    urlstringRequired. The base SSE endpoint URL of the MCP server.
    api_keystringOptional. An API key used for Bearer token authentication.
    headersarray<string, string>Optional. An associative array of additional HTTP headers to include in both SSE and POST requests.
    timeoutintOptional. The timeout in seconds for connections and waiting for responses. Defaults to 30.
  9. Configure StdioTransport

    main

    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,
    ]);
  10. Configure HTTP Transport for MCP servers

    main

    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',
        ]
    ],
  11. Configure STDIO Transport for MCP servers

    main

    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',
        ],
    ],
  12. Handle Relay exceptions

    main

    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());
    }