mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-09-05 23:35:31 +08:00
feat(mcp): mcp 独立应用与 /mcp Streamable HTTP 端点(官方 SDK + PSR-7 桥接)
This commit is contained in:
31
extend/base/mcp/service/McpDispatchBase.php
Normal file
31
extend/base/mcp/service/McpDispatchBase.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\mcp\service;
|
||||
|
||||
/**
|
||||
* MCP 工具分发器(T8 实现真实分发).
|
||||
*
|
||||
* 职责(T8):以 McpService::verifyNode 还原编码工具名 -> 校验权限 ->
|
||||
* 内部 HTTP 调用对应节点 -> McpService::logCall 审计。
|
||||
*
|
||||
* T7 仅提供空壳占位,保证 tools/list 与 tools/call 链路可用:
|
||||
* call 返回固定错误文案,由 ToolResultFormatter 包装为 TextContent。
|
||||
*/
|
||||
class McpDispatchBase
|
||||
{
|
||||
/**
|
||||
* 分发一次 MCP 工具调用.
|
||||
*
|
||||
* @param array $auth McpService::authenticate() 的返回结构(key_row + creator)
|
||||
* @param string $toolName MCP 编码工具名(如 system-quick--index,需 verifyNode 还原)
|
||||
* @param array $arguments 客户端原始参数(已剔除 _session/_request 内部键)
|
||||
* @return string 工具执行结果(文本)
|
||||
*/
|
||||
public function call(array $auth, string $toolName, array $arguments): string
|
||||
{
|
||||
// T8 实现真实分发逻辑
|
||||
return '[ERROR] 分发器未就绪(T8 实现)';
|
||||
}
|
||||
}
|
||||
114
extend/base/mcp/service/Psr16ThinkCacheBase.php
Normal file
114
extend/base/mcp/service/Psr16ThinkCacheBase.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\mcp\service;
|
||||
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use think\cache\Driver;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* think Cache 驱动的 PSR-16 薄适配器.
|
||||
*
|
||||
* mcp/sdk 的 Psr16SessionStore 需要 Psr\SimpleCache\CacheInterface 实现,
|
||||
* think cache Driver 方法集与 PSR-16 同形(get/set/delete/clear/has/*Multiple),
|
||||
* 本类只做签名收紧与 TTL 归一(int|DateInterval|null → 秒),全部转发给
|
||||
* defaultStore() 指定的 think 缓存 store。
|
||||
*
|
||||
* 子类(app 壳)覆写 defaultStore() 返回 'mcp_session' 等具体 store 名。
|
||||
*/
|
||||
class Psr16ThinkCacheBase implements CacheInterface
|
||||
{
|
||||
protected Driver $driver;
|
||||
|
||||
public function __construct(?Driver $driver = null)
|
||||
{
|
||||
$this->driver = $driver ?? Cache::store($this->defaultStore());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认 think 缓存 store 名(子类覆写).
|
||||
*/
|
||||
protected function defaultStore(): string
|
||||
{
|
||||
return 'file';
|
||||
}
|
||||
|
||||
public function get(string $key, mixed $default = null): mixed
|
||||
{
|
||||
return $this->driver->get($key, $default);
|
||||
}
|
||||
|
||||
public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool
|
||||
{
|
||||
return (bool) $this->driver->set($key, $value, $this->normalizeTtl($ttl));
|
||||
}
|
||||
|
||||
public function delete(string $key): bool
|
||||
{
|
||||
return (bool) $this->driver->delete($key);
|
||||
}
|
||||
|
||||
public function clear(): bool
|
||||
{
|
||||
return (bool) $this->driver->clear();
|
||||
}
|
||||
|
||||
public function getMultiple(iterable $keys, mixed $default = null): iterable
|
||||
{
|
||||
$keys = is_array($keys) ? $keys : iterator_to_array($keys, false);
|
||||
|
||||
$result = [];
|
||||
foreach ($keys as $key) {
|
||||
$result[$key] = $this->driver->get($key, $default);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool
|
||||
{
|
||||
$ttl = $this->normalizeTtl($ttl);
|
||||
|
||||
$result = true;
|
||||
foreach ($values as $key => $value) {
|
||||
if (!$this->driver->set((string) $key, $value, $ttl)) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function deleteMultiple(iterable $keys): bool
|
||||
{
|
||||
$result = true;
|
||||
foreach ($keys as $key) {
|
||||
if (!$this->driver->delete($key)) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function has(string $key): bool
|
||||
{
|
||||
return (bool) $this->driver->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* PSR-16 TTL 归一为秒:DateInterval 折算秒数;null 视为 0(think 驱动默认有效期,0=永久).
|
||||
*/
|
||||
protected function normalizeTtl(null|int|\DateInterval $ttl): int
|
||||
{
|
||||
if ($ttl instanceof \DateInterval) {
|
||||
$now = new \DateTimeImmutable('@' . time());
|
||||
|
||||
return max(0, $now->add($ttl)->getTimestamp() - $now->getTimestamp());
|
||||
}
|
||||
|
||||
return max(0, (int) ($ttl ?? 0));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user