import { useEffect, useState } from 'react'; import { api } from './api'; type Connection = { id: string; name: string; scopes: string[]; expiresAt: string; revokedAt: string | null; clientId: string | null; }; type Operation = { id: string; tool: string; status: string; expiresAt: string; createdAt: string }; type Management = { mcpUrl: string; mode: string; grants: Connection[]; operations: Operation[]; calls: { id: string; tool: string; status: string; createdAt: string }[]; }; type Preview = { operationId: string; tool: string; status: string; description: string; impact: unknown; web?: string; sensitive: boolean; result?: unknown; }; type Consent = { id: string; name: string; scopes: string[]; redirectUri: string; resource: string; }; export function AgentConnections() { const [data, setData] = useState(null), [error, setError] = useState(''), [message, setMessage] = useState(''), [token, setToken] = useState(''), [preview, setPreview] = useState(null), [consent, setConsent] = useState(null), [busy, setBusy] = useState(false); const load = async () => setData(await api('/agent')); const act = async (work: () => Promise) => { if (busy) return; setBusy(true); setError(''); setMessage(''); try { await work(); await load(); } catch (e) { setError(e instanceof Error ? e.message : '操作失败'); } finally { setBusy(false); } }; const show = async (id: string) => setPreview(await api('/agent/operations/' + id)); useEffect(() => { void act(async () => { await load(); const params = new URLSearchParams(location.search); const authorization = params.get('agent_authorization'), operation = params.get('agent_operation'); if (authorization) setConsent(await api('/agent/authorizations/' + authorization)); if (operation) await show(operation); }); }, []); return (

连接 Agent

{error && (

{error}

)} {message &&

{message}

} {data && ( <>

远程 MCP 地址

{data.mcpUrl}

支持 Streamable HTTP。OAuth 客户端使用此地址发现授权信息,浏览器登录 WorthPath 后审核连接名称、回调地址和权限。访问令牌每小时过期,刷新令牌最多 30 天并在使用时轮换。个人令牌适用于支持 Bearer 头的客户端。

已验证客户端:官方 TypeScript SDK 1.31.0(OAuth / Bearer)。其他 Agent 尚未验证;不会保证任意客户端兼容。

官方 SDK 的已验证接入配置
{`new StreamableHTTPClientTransport(new URL(${JSON.stringify(data.mcpUrl)}), {\n  requestInit: { headers: { Authorization: 'Bearer ' + process.env.MCP_ACCESS_TOKEN } }\n});`}

先在终端设置 MCP_ACCESS_TOKEN,再运行复制的命令。完整 OAuth 示例及安全存储说明见 docs/mcp.md;此配置仅针对官方 SDK 1.31.0。

{ e.preventDefault(); const f = new FormData(e.currentTarget), form = e.currentTarget; void act(async () => { await api('/agent/policy', 'PUT', { mode: f.get('mode'), password: f.get('password'), }); form.reset(); setMessage('写入策略已保存'); }); }} >

写入策略

OAuth 授权与个人令牌

read 查询;draft 创建草稿;write 按写入策略执行普通写入;sensitive 发起敏感操作,仍须网页验证密码。令牌到期可新建并撤销旧令牌。

{ e.preventDefault(); const form = e.currentTarget, f = new FormData(form); void act(async () => { const v = await api<{ token: string }>('/agent/tokens', 'POST', { name: f.get('name'), days: Number(f.get('days')), password: f.get('password'), scopes: f.getAll('scope'), }); setToken(v.token); form.reset(); }); }} > {['read', 'draft', 'write', 'sensitive'].map((s) => ( ))}
{token && (

完整令牌仅显示这一次,请妥善保存。

{token}
)}

已授权连接(最近 100 条)

{data.grants.map((g) => (
{g.name} · {g.clientId ? 'OAuth' : '个人令牌'} · {g.scopes.join(', ')} ·{' '} {new Date(g.expiresAt).toLocaleString()} · {g.revokedAt ? '已撤销' : ''} {!g.revokedAt && ( )}
))}

待确认及最近操作(最近 100 条)

{data.operations.map((o) => (
{o.tool} ·{' '} {o.status === 'pending' && new Date(o.expiresAt) < new Date() ? 'expired' : o.status}{' '} · {new Date(o.createdAt).toLocaleString()}
))}

最近调用(不保存参数和敏感内容)

{data.calls.map((c) => (
{c.tool} · {c.status} · {new Date(c.createdAt).toLocaleString()}
))} )} {consent && (

审核 OAuth 连接

{consent.name}

权限:{consent.scopes.join(', ')}

资源:{consent.resource}

回调地址:{consent.redirectUri}

只批准你正在连接的客户端;请核对回调地址。

{[true, false].map((approve) => ( ))}
)} {preview && (

{preview.tool} · {preview.status}

{preview.description}

{JSON.stringify(preview.impact, null, 2)}
{preview.result !== undefined &&
{JSON.stringify(preview.result, null, 2)}
} {preview.status === 'pending' && (
{ e.preventDefault(); const f = new FormData(e.currentTarget), form = e.currentTarget; void act(async () => { await api('/agent/operations/' + preview.operationId, 'POST', { approve: true, ...(f.get('password') ? { password: f.get('password') } : {}), ...(f.get('username') ? { username: f.get('username') } : {}), ...(f.get('newPassword') ? { newPassword: f.get('newPassword') } : {}), ...(f.get('confirmation') ? { confirmation: f.get('confirmation') } : {}), }); form.reset(); await show(preview.operationId); setMessage('操作已提交,Agent 可以查询最终结果'); }); }} > {preview.web === 'clear' && ( <> 先下载当前账号备份

确认备份已保存后输入“确定清空”。

)} {preview.web === 'credentials' && ( <> )} {preview.sensitive && ( )}
)}
)}
); }