前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >适用于PHP的MCP模型上下文协议SDK

适用于PHP的MCP模型上下文协议SDK

作者头像
Tinywan
发布2025-03-27 15:24:30
发布2025-03-27 15:24:30
8200
代码可运行
举报
文章被收录于专栏:开源技术小栈开源技术小栈
运行总次数:0
代码可运行

背景

在 AI 大模型迅猛发展的当下,其影响力已广泛渗透至生活的方方面面。无论是智能客服的高效交互、内容创作的灵感激发,还是图像生成的创意呈现、数据分析的精准洞察,AI 大模型都展现出了令人瞩目的强大能力。然而,繁荣背后,AI 大模型正面临着一个棘手难题 —— 数据孤岛问题。这些模型如同被困孤岛的巨人,虽潜力无限,却因难以获取多元数据,致使应用严重受限。

以日常场景为例,当你向大模型询问明天的天气和个人日程安排时,它可能因无法获取实时天气数据与你的日程信息而无法作答。这是由于大模型与传统系统及信息流集成度低,难以突破数据瓶颈。每个新数据源都需定制化集成,这极大地阻碍了真正互联系统的扩展。在这个信息爆炸的时代,数据堪称 AI 大模型发展的 “石油”,是关键驱动力。但如今,数据孤岛却束缚了大模型,使其难以充分释放潜力。

那么,是否存在一种有效方法打破数据孤岛,让大模型自由获取所需数据,实现更强大功能呢?答案或许就在 MCP(Model Context Protocol,模型上下文协议)。MCP 的出现,宛如一座桥梁,有望连接大模型与外部数据源,开创全新的 AI 应用生态。接下来,让我们一同深入探究 MCP 的奥秘。

MCP 概述

MCP(Model Context Protocol,模型上下文协议),2024年11月底,由 Anthropic 推出的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源和工具之间的通信协议。MCP 的主要目的在于解决当前 AI 模型因数据孤岛限制而无法充分发挥潜力的难题,MCP 使得 AI 应用能够安全地访问和操作本地及远程数据,为 AI 应用提供了连接万物的接口。

开源技术小栈Function Calling是AI模型调用函数的机制,MCP是一个标准协议,使AI模型与API无缝交互,而AI Agent是一个自主运行的智能系统,利用Function Calling和MCP来分析和执行任务,实现特定目标。

MCP 架构图

MCP 架构图
MCP 架构图

开源技术小栈总共分为了下面五个部分:

  • MCP Hosts: Hosts 是指 LLM 启动连接的应用程序,像 Cursor, Claude Desktop、Cline这样的应用程序。
  • MCP Clients: 客户端是用来在 Hosts 应用程序内维护与 Server 之间 1:1 连接。
  • MCP Servers: 通过标准化的协议,为 Client 端提供上下文、工具和提示。
  • Local Data Sources: 本地的文件、数据库和 API。
  • Remote Services: 外部的文件、数据库和 API。

PHP SDK

此包提供了模型上下文协议的 PHP 实现,允许应用程序LLMs以标准化方式为其提供上下文。它将提供上下文的关注点与实际LLM交互分开。

概述

此 PHP SDK 实现了完整的 MCP 规范,因此可以轻松

  • 构建可连接到任何 MCP 服务器的 MCP 客户端
  • 创建公开资源、提示和工具的 MCP 服务器
  • 使用标准传输方式,如 stdio 和 SSE
  • 处理所有 MCP 协议消息和生命周期事件

基于官方的Python SDK的模型上下文协议。此 SDK 主要面向致力于前沿 AI 集成解决方案的开发人员。某些功能可能不完整,在生产使用之前,应由经验丰富的开发人员对实现进行全面测试和安全审查。

安装

代码语言:javascript
代码运行次数:0
运行
复制
composer require logiscape/mcp-sdk-php

基本用法

创建 MCP 服务器

以下是创建提供提示的 MCP 服务器的完整示例:example_server.php

代码语言:javascript
代码运行次数:0
运行
复制
<?php

// A basic example server with a list of prompts for testing

require'vendor/autoload.php';

useMcp\Server\Server;
useMcp\Server\ServerRunner;
useMcp\Types\Prompt;
useMcp\Types\PromptArgument;
useMcp\Types\PromptMessage;
useMcp\Types\ListPromptsResult;
useMcp\Types\TextContent;
useMcp\Types\Role;
useMcp\Types\GetPromptResult;
useMcp\Types\GetPromptRequestParams;

// Create a server instance
$server = new Server('example-server');

// Register prompt handlers
$server->registerHandler('prompts/list', function($params) {
    $prompt = new Prompt(
        name: 'example-prompt',
        description: 'An example prompt template',
        arguments: [
            new PromptArgument(
                name: 'arg1',
                description: 'Example argument',
                required: true
            )
        ]
    );
    returnnew ListPromptsResult([$prompt]);
});

$server->registerHandler('prompts/get', function(GetPromptRequestParams $params) {

    $name = $params->name;
    $arguments = $params->arguments;

    if ($name !== 'example-prompt') {
        thrownew \InvalidArgumentException("Unknown prompt: {$name}");
    }

    // Get argument value safely
    $argValue = $arguments ? $arguments->arg1 : 'none';

    $prompt = new Prompt(
        name: 'example-prompt',
        description: 'An example prompt template',
        arguments: [
            new PromptArgument(
                name: 'arg1',
                description: 'Example argument',
                required: true
            )
        ]
    );

    returnnew GetPromptResult(
        messages: [
            new PromptMessage(
                role: Role::USER,
                content: new TextContent(
                    text: "Example prompt text with argument: $argValue"
                )
            )
        ],
        description: 'Example prompt'
    );
});

// Create initialization options and run server
$initOptions = $server->createInitializationOptions();
$runner = new ServerRunner($server, $initOptions);
$runner->run();

创建 MCP 客户端

下面介绍如何创建连接到示例服务器的客户端:example_client.php

代码语言:javascript
代码运行次数:0
运行
复制
<?php

// A basic example client that connects to example_server.php and outputs the prompts

require 'vendor/autoload.php';

use Mcp\Client\Client;
use Mcp\Client\Transport\StdioServerParameters;
use Mcp\Types\TextContent;

// Create server parameters for stdio connection
$serverParams = new StdioServerParameters(
    command: 'php',  // Executable
    args: ['example_server.php'],  // File path to the server
    env: null  // Optional environment variables
);

// Create client instance
$client = new Client();

try {
    echo("Starting to connect\n");
    // Connect to the server using stdio transport
    $session = $client->connect(
        commandOrUrl: $serverParams->getCommand(),
        args: $serverParams->getArgs(),
        env: $serverParams->getEnv()
    );

    echo("Starting to get available prompts\n");
    // List available prompts
    $promptsResult = $session->listPrompts();

    // Output the list of prompts
    if (!empty($promptsResult->prompts)) {
        echo"Available prompts:\n";
        foreach ($promptsResult->prompts as $prompt) {
            echo"  - Name: " . $prompt->name . "\n";
            echo"    Description: " . $prompt->description . "\n";
            echo"    Arguments:\n";
            if (!empty($prompt->arguments)) {
                foreach ($prompt->arguments as $argument) {
                    echo"      - " . $argument->name . " (" . ($argument->required ? "required" : "optional") . "): " . $argument->description . "\n";
                }
            } else {
                echo"      (None)\n";
            }
        }
    } else {
        echo"No prompts available.\n";
    }

} catch (\Exception $e) {
    echo"Error: " . $e->getMessage() . "\n";
    exit(1);
} finally {
    // Close the server connection
    if (isset($client)) {
        $client->close();
    }
}

用于调试的高级日志记录

创建具有日志记录的 MCP 服务器

以下是前面启用了详细日志记录的 MCP 服务器示例:

代码语言:javascript
代码运行次数:0
运行
复制
<?php

// A version of the basic example server with extra logging

// Enable comprehensive error logging
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/php_errors.log'); // Logs errors to a file
error_reporting(E_ALL);

require'vendor/autoload.php';

useMcp\Server\Server;
useMcp\Server\ServerRunner;
useMcp\Types\Prompt;
useMcp\Types\PromptArgument;
useMcp\Types\PromptMessage;
useMcp\Types\ListPromptsResult;
useMcp\Types\TextContent;
useMcp\Types\Role;
useMcp\Types\GetPromptResult;
useMcp\Types\GetPromptRequestParams;

useMonolog\Logger;
useMonolog\Handler\StreamHandler;
useMonolog\Handler\RotatingFileHandler;
useMonolog\Formatter\LineFormatter;

// Create a logger
$logger = new Logger('mcp-server');

// Delete previous log
@unlink(__DIR__ . '/server_log.txt');

// Create a handler that writes to server_log.txt
$handler = new StreamHandler(__DIR__ . '/server_log.txt', Logger::DEBUG);

// Optional: Create a custom formatter to make logs more readable
$dateFormat = "Y-m-d H:i:s";
$output = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
$formatter = new LineFormatter($output, $dateFormat);
$handler->setFormatter($formatter);

// Add the handler to the logger
$logger->pushHandler($handler);

// Create a server instance
$server = new Server('example-server', $logger);

// Register prompt handlers
$server->registerHandler('prompts/list', function($params) {
    $prompt = new Prompt(
        name: 'example-prompt',
        description: 'An example prompt template',
        arguments: [
            new PromptArgument(
                name: 'arg1',
                description: 'Example argument',
                required: true
            )
        ]
    );
    returnnew ListPromptsResult([$prompt]);
});

$server->registerHandler('prompts/get', function(GetPromptRequestParams $params) {

    $name = $params->name;
    $arguments = $params->arguments;

    if ($name !== 'example-prompt') {
        thrownew \InvalidArgumentException("Unknown prompt: {$name}");
    }

    // Get argument value safely
    $argValue = $arguments ? $arguments->arg1 : 'none';

    $prompt = new Prompt(
        name: 'example-prompt',
        description: 'An example prompt template',
        arguments: [
            new PromptArgument(
                name: 'arg1',
                description: 'Example argument',
                required: true
            )
        ]
    );

    returnnew GetPromptResult(
        messages: [
            new PromptMessage(
                role: Role::USER,
                content: new TextContent(
                    text: "Example prompt text with argument: $argValue"
                )
            )
        ],
        description: 'Example prompt'
    );
});

// Create initialization options and run server
$initOptions = $server->createInitializationOptions();
$runner = new ServerRunner($server, $initOptions, $logger);

try {
    $runner->run();
} catch (\Throwable $e) {
    echo"An error occurred: " . $e->getMessage() . "\n";
    $logger->error("Server run failed", ['exception' => $e]);
}

创建具有日志记录的 MCP 客户端

以下是创建启用了详细日志记录的客户端的方法:

代码语言:javascript
代码运行次数:0
运行
复制
<?php

// A version of the basic example client with extra logging and output

// Enable comprehensive error reporting and logging
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/php_errors.log'); // Logs errors to a file
error_reporting(E_ALL);

require'vendor/autoload.php';

useMcp\Client\Client;
useMcp\Client\Transport\StdioServerParameters;
useMcp\Types\TextContent;

useMonolog\Logger;
useMonolog\Handler\StreamHandler;
useMonolog\Handler\RotatingFileHandler;
useMonolog\Formatter\LineFormatter;

// Create a logger
$logger = new Logger('mcp-client');

// Delete previous log
@unlink(__DIR__ . '/client_log.txt');

// Create a handler that writes to client_log.txt
$handler = new StreamHandler(__DIR__ . '/client_log.txt', Logger::DEBUG);

// Optional: Create a custom formatter to make logs more readable
$dateFormat = "Y-m-d H:i:s";
$output = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
$formatter = new LineFormatter($output, $dateFormat);
$handler->setFormatter($formatter);

// Add the handler to the logger
$logger->pushHandler($handler);

// Create server parameters for stdio connection
$serverParams = new StdioServerParameters(
    command: 'php',  // Executable
    args: ['debug_example_server.php'],  // File path to the server
    env: null// Optional environment variables
);

echo("Creating client\n");

// Create client instance
$client = new Client($logger);

try {
    echo("Starting to connect\n");
    // Connect to the server using stdio transport
    $session = $client->connect(
        commandOrUrl: $serverParams->getCommand(),
        args: $serverParams->getArgs(),
        env: $serverParams->getEnv()
    );

    echo("Starting to get available prompts\n");
    // List available prompts
    $promptsResult = $session->listPrompts();

    // Output the list of prompts
    if (!empty($promptsResult->prompts)) {
        echo"Available prompts:\n";
        foreach ($promptsResult->prompts as $prompt) {
            echo"  - Name: " . $prompt->name . "\n";
            echo"    Description: " . $prompt->description . "\n";
            echo"    Arguments:\n";
            if (!empty($prompt->arguments)) {
                foreach ($prompt->arguments as $argument) {
                    echo"      - " . $argument->name . " (" . ($argument->required ? "required" : "optional") . "): " . $argument->description . "\n";
                }
            } else {
                echo"      (None)\n";
            }
        }
    } else {
        echo"No prompts available.\n";
    }

} catch (\Exception $e) {
    echo"Error: " . $e->getMessage() . "\n";
    exit(1);
} finally {
    // Close the server connection
    if (isset($client)) {
        $client->close();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • MCP 概述
  • MCP 架构图
  • PHP SDK
    • 概述
    • 安装
  • 基本用法
    • 创建 MCP 服务器
    • 创建 MCP 客户端
  • 用于调试的高级日志记录
    • 创建具有日志记录的 MCP 服务器
    • 创建具有日志记录的 MCP 客户端
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档