客户端配置
逐个客户端的实配片段。用哪种凭证只取决于一件事:你的客户端能不能用一份托管的元数据文档自证身份(CIMD)。能,填一个地址就够;不能,用长期密钥。
我的客户端该用哪种凭证?
从上往下看,命中第一条就停。决定因素是客户端的能力,不是牌子 —— 任何会 CIMD 的客户端都走「只填地址」这条路,不管它在不在下面的表里。
- 它支持 CIMD → 把接入地址填进去就完事了(Cursor 多一行 —— 它的文档我们替你挂好了,见下)。浏览器只弹一次:登录 → 选工作区 → 同意。不用注册,也没有密钥要保管。
- 它会 DCR(首次使用时自己注册)→ 同样只填接入地址。n8n、Dify 走这条,把它们的「Use Dynamic Client Registration」开关保持打开即可。
- 两样都不会,但你能自定义请求头 → 在设置页签发一枚
popkit_it_…,放进Authorization。无人值守的场景也该用这条。 - 它会 OAuth,而且允许你手填
client_id→ 自己托管一份小小的元数据文档,拿它的 URL 当client_id。这样任何支持 OAuth 的客户端都能变成 CIMD 客户端 —— 做法见下一节。 - 以上都不是 → 它走不了 OAuth。实际上就是 Continue —— 它的 MCP 配置里根本没有 OAuth 字段。
| 客户端 | 用哪种凭证 | 为什么 |
|---|---|---|
| Claude Code · claude.ai | OAuth(不用注册) | 会 CIMD —— 用一个托管的元数据 URL 自证身份 |
| Cursor | OAuth(不用注册) | 它的元数据文档我们替你挂好了 —— 填一个网址,不用密钥。见下 |
| Cline · Continue | 请求头里放 popkit_it_… | Cline 能手填 client_id 但官方没文档;Continue 根本没有 OAuth 字段 |
| n8n · Dify | OAuth(客户端自己注册) | 它们的 OAuth 走 DCR,生产现已开放 —— 保持 DCR 开关打开,不要手填 |
| 自建脚本 | 请求头里放 popkit_it_… | 最省事的一条;也可以自托管一份元数据文档改走 OAuth |
| 其它任何客户端 | 跑下一节那个自测 | 要问的是它会不会 CIMD,而不是它是哪个产品 |
多数客户端共用同一份 JSON 形状 —— mcpServers 映射 + url + headers:
{
"mcpServers": {
"popkit": {
"url": "https://popkit.loxily.com/api/mcp",
"headers": {
"Authorization": "Bearer popkit_it_YOUR_TOKEN"
}
}
}
}会 CIMD 的客户端(Claude Code · claude.ai)
claude mcp add --transport http popkit https://popkit.loxily.com/api/mcp第一次使用时授权页自己会弹出来:登录 → 选工作区 → 同意 scope。没有 token 要粘,也没有东西要保管。claude.ai 那边把同一个地址加成自定义连接器即可。
scope 是在同意页上授予的,所以你在那里勾的就是这条连接的上限 —— 且永远不会超过你本人的角色。
Cursor
Cursor 不会自助注册,但它允许你手填 client_id —— 而这份我们替你挂好了,你既不用发布文档,也不用保管密钥。把下面这段放进 ~/.cursor/mcp.json:
{
"mcpServers": {
"popkit": {
"url": "https://popkit.loxily.com/api/mcp",
"auth": {
"CLIENT_ID": "https://popkit.loxily.com/.well-known/mcp-client/cursor"
}
}
}
}那个 CLIENT_ID 就是我们提供的一个网址:它是一份客户端元数据文档,写明了这是 Cursor、以及它那两个固定回调。点 Connect,浏览器弹一次 —— 登录、选工作区、同意,就好了。CLIENT_SECRET 整个不用写:这是公开客户端,靠 PKCE 保证安全。
更想用密钥?请求头里放 popkit_it_… 也行 —— 见上面的通用模板。
Cline · Continue
Cursor —— 放进 ~/.cursor/mcp.json(全局)或项目根的 .cursor/mcp.json(可提交、与团队共享;同名时项目级优先)。Cursor 会在 url 与 headers 里解析 ${env:NAME},所以 token 不必落在文件里:
{
"mcpServers": {
"popkit": {
"url": "https://popkit.loxily.com/api/mcp",
"headers": {
"Authorization": "Bearer ${env:POPKIT_MCP_TOKEN}"
}
}
}
}在 Cursor → Settings → MCP 里检查,服务器下应当列出 popkit 的工具。Cursor 确实支持 OAuth,但只走动态注册 —— 对生产走不通,所以用上面这个请求头。
Cline —— 从命令面板打开设置文件(Cline: Open MCP Settings),把通用模板合并进去。文件真实位置是 ~/.cline/data/settings/cline_mcp_settings.json(Cline 自己的文档里写的是一个已经失效的旧路径)。保存即热加载,不用重启。
Continue —— 是 YAML 不是 JSON,而且它的 OAuth 只对 sse 类型的 server 生效,所以这里只能用请求头。放进 ~/.continue/config.yaml,或作为块文件放在 .continue/mcpServers/ 下:
name: popkit-mcp
version: 0.0.1
schema: v1
mcpServers:
- name: popkit
type: streamable-http
url: https://popkit.loxily.com/api/mcp
requestOptions:
headers:
Authorization: Bearer ${{ secrets.POPKIT_MCP_TOKEN }}POPKIT_MCP_TOKEN=… 写进 ~/.continue/.env。另外 MCP 工具只在 agent 模式下可用。n8n · Dify
n8n —— 给 Agent 挂一个 MCP Client Tool 节点(单次调用则用普通的 MCP Client 节点),填三项:
- Server Transport:选
HTTP Streamable(较新版本的默认值;SSE 那项已废弃) - Endpoint:
https://popkit.loxily.com/api/mcp - Authentication:选
MCP OAuth2 API,新建凭据后保持「Use Dynamic Client Registration」打开,只填 Server URL 为接入地址,保存,再点 Connect。浏览器会弹一次:登录 → 选工作区 → 同意。没有什么要粘。 - 更想用密钥(无人值守、没有浏览器)?那就选
Bearer Auth,把popkit_it_…填进唯一的 Bearer Token 框。
Dify —— Integrations → Tools → MCP → Add MCP Server (HTTP)。Server URL 填端点,起个名字和服务器标识,然后在 Headers 里加一行:名字 Authorization,值 Bearer popkit_it_…。也可以改开 OAuth 授权、并保持「Use Dynamic Client Registration」打开 —— 这条现在通了,省掉管密钥的麻烦。填好点 Get tools 导入工具。
其它 MCP 客户端
上面那些不是白名单 —— popkit 从不看是哪个产品在调。你的客户端不在表里,就照下面判断它落在四条路的哪一条:
- 把接入地址填进去,看它怎么反应。 会 CIMD 的客户端会拿自己那份元数据文档的 URL 当
client_id发过来,浏览器随即弹出,你就完事了。很多客户端号称「支持 OAuth」其实指的是 DCR —— 特征是报错里提到注册。 - 翻它的文档看有没有
client_id。 只要允许你手填,就走下面第 3 条,不管它自己怎么描述注册方式。 - 再不行就找自定义请求头的设置。 只要能发
Authorization: Bearer …,长期密钥就能用。
第 3 条 —— 自己托管一份元数据文档。 CIMD 的意思是 client_id 本身就是一个 URL,popkit 会去抓这个 URL 来认识这个客户端。所以把下面这份 JSON 挂到任意公网 HTTPS 地址上,再把这个地址作为 client_id 交给你的客户端即可:
{
"client_id": "https://example.com/mcp-client.json",
"client_name": "My Agent",
"redirect_uris": ["http://127.0.0.1:8765/callback"],
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}要求很短:HTTPS 上以 JSON 提供、client_name 非空、redirect_uris 是非空的绝对 URI 数组、token_endpoint_auth_method 取 none(缺省)或 private_key_jwt。http://127.0.0.1:端口/callback 这类环回回调是允许的,所以命令行与桌面客户端同样走得通。
client_name 就是同意页上给授权人看的名字 —— 请按真正在连接的那个东西命名,不要写成 popkit。对方在同意页上授予的 scope 就是这条连接的上限,且永远不会超过他本人的角色。自建客户端
用官方 SDK —— 传输层负责组包,你只管把请求头带上:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(new URL("https://popkit.loxily.com/api/mcp"), {
requestInit: {
headers: { Authorization: `Bearer ${process.env.POPKIT_MCP_TOKEN}` },
},
});
const client = new Client({ name: "my-app", version: "1.0.0" }, { capabilities: {} });
await client.connect(transport);
const { tools } = await client.listTools();
const res = await client.callTool({ name: "get_workspace_context", arguments: {} });
console.log(res.structuredContent);不用 SDK 的话,每次调用就是一个 POST —— 请求头与信封的硬要求见 工具参考。动手前有四件事值得先弄对:必带的请求头、_meta 信封、同时能读 application/json 与 SSE 两种应答、以及把三层错误分开处理(见 错误与排查)。
Mcp-Session-Id,所以没有会话要保活、也没有东西要注销。GET 与 DELETE 按设计回 405 —— MCP 的官方 SDK 把它当正常情况处理。