
# Agent / MCP 接入手册

## 1. 连接方式

MCP 端点为：

```text
POST/GET/DELETE https://resources.example.com/mcp
```

它实现 MCP Streamable HTTP，而不是自定义 JSON RPC。初始化响应返回 `MCP-Session-Id`；后续 POST、GET SSE 和 DELETE 必须携带该 header。所有请求都要发送 bearer token。可给管理员 token 增加 `X-Tenant-Id`，把会话固定到单一租户；租户 token（`etk_`）必须带 `X-Tenant-Id`，会话天然限定在本租户内。

通用 Agent 配置示例（字段名以所用 Agent 客户端为准）：

```json
{
  "mcpServers": {
    "earth-resources": {
      "type": "streamable-http",
      "url": "https://resources.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${EARTH_RESOURCES_API_KEY}",
        "X-Tenant-Id": "acme"
      }
    }
  }
}
```

Node.js SDK 示例：

```js
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const client = new Client({ name: 'ops-agent', version: '1.0.0' });
const transport = new StreamableHTTPClientTransport(
  new URL('https://resources.example.com/mcp'),
  { requestInit: { headers: {
    Authorization: `Bearer ${process.env.EARTH_RESOURCES_API_KEY}`,
    'X-Tenant-Id': 'acme',
  } } },
);
await client.connect(transport);
console.log(await client.listTools());
```

## 2. 工具

| 工具 | 权限 | 作用 |
| --- | --- | --- |
| `list_resources` | 管理员、租户或本资源 | 列出资源与最新状态 |
| `get_resource` | 管理员、租户或本资源 | 获取资源快照和最近遥测 |
| `query_resource_events` | 管理员、租户或本资源 | 按可靠序号查询遥测与命令日志 |
| `get_fleet_summary` | 管理员、租户或本资源 | 汇总在线、离线、仅注册资源数 |
| `send_resource_command` | 管理员或租户 | 幂等地写入并下发资源命令 |

未使用 `X-Tenant-Id` 的全局管理员在每次工具调用中必须传 `tenantId`。租户 token 只能操作本租户，跨租户调用返回 `tenant_forbidden`。资源 token 只能读取自身；命令工具会返回权限错误。

调用示例：

```js
const response = await client.callTool({
  name: 'query_resource_events',
  arguments: { resourceId: 'sensor-01', afterSequence: 128, limit: 50 },
});

await client.callTool({
  name: 'send_resource_command',
  arguments: {
    resourceId: 'sensor-01',
    eventId: 'agent-plan-2026-09-10-step-3',
    command: { action: 'sample', intervalSeconds: 5 },
  },
});
```

写操作应由 Agent 生成稳定 `eventId`。工具调用超时后重试同一 ID，避免同一计划步骤生成多条命令。建议 Agent 在执行前调用 `get_resource`，检查资源状态和命令有效期；高风险物理动作应在 Agent 层加入人工确认。

## 3. 会话和安全

- MCP 会话绑定首次初始化时的 principal，不能换 token 接管。
- 客户端结束时发送 DELETE 关闭会话。
- 本服务使用静态 bearer token，不内置 OAuth 授权服务器。面向第三方用户时应在前置身份网关增加 OAuth 2.1，并把验证后的租户身份映射为受限 token/header。
- 不要把管理员或租户 token 写进 prompt、工具参数、日志或 URL。给 Agent 配租户 token 而不是管理员 token，可以把它的影响面限制在一个租户内。
- `send_resource_command` 的 MCP annotation 标记为非破坏、幂等写操作；具体命令是否危险仍由部署方的业务策略决定。

## 4. REST 备用路径

不支持 MCP 的 Agent 仍可读取 `/openapi.json` 并直接使用 REST API。两条路径共享认证、租户隔离、持久化和审计语义，因此不会形成第二套数据模型。
