Files
zyt/server/app/mcp/controller/IndexController.php
T
2026-09-24 09:45:44 +08:00

64 lines
2.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\mcp\controller;
use app\BaseController;
use app\mcp\service\GrantService;
use app\mcp\service\Guard;
use app\mcp\service\McpConfig;
use app\mcp\service\McpException;
use app\mcp\service\Protocol;
use think\Response;
/**
* MCP 端点:POST /mcp(Streamable HTTP,无会话,只返回 JSON)。
* 每个请求都要带 Authorization: Bearer <AI 授权令牌>。
*/
class IndexController extends BaseController
{
public function index(): Response
{
if (!McpConfig::enabled()) {
return json(Protocol::error(null, -32000, 'AI 助手接口未启用'), 503);
}
if ($this->request->method(true) !== 'POST') {
return response('', 405)->header(['Allow' => 'POST']);
}
$guard = Guard::check($this->request);
if ($guard !== null) {
return json(Protocol::error(null, -32000, $guard[1]), $guard[0]);
}
$version = (string) $this->request->header('mcp-protocol-version', '');
if ($version !== '' && !in_array($version, McpConfig::PROTOCOL_VERSIONS, true)) {
return json(Protocol::error(null, Protocol::INVALID_REQUEST, 'Unsupported protocol version: ' . $version . '; supported: ' . implode(', ', McpConfig::PROTOCOL_VERSIONS)), 400);
}
try {
$identity = GrantService::authenticate($this->request);
} catch (McpException $e) {
return Guard::unauthorized($e);
}
$payload = json_decode((string) $this->request->getInput(), true);
if (!is_array($payload)) {
return json(Protocol::error(null, Protocol::PARSE_ERROR, 'Parse error'), 400);
}
$context = [
'task_id' => (string) $this->request->header('x-xingzhi-task-id', ''),
'ip' => $this->request->ip(),
];
$isBatch = $payload !== [] && array_keys($payload) === range(0, count($payload) - 1);
$messages = $isBatch ? $payload : [$payload];
$responses = [];
foreach ($messages as $message) {
$response = Protocol::handle($message, $identity, $context);
if ($response !== null) {
$responses[] = $response;
}
}
if ($responses === []) {
return response('', 202);
}
return json($isBatch ? $responses : $responses[0]);
}
}