使用说明
WBMCP集成规范
本文档仅描述了此存储库中实现的ChatGPT<->OAuth<->MCP<->的SOAP集成设计。 它有意关注身份、协议、工具、权限和API流。
1) 整合参与者
- ChatGPT连接器运行时
- 此MCP服务器(
/mcp、OAuth元数据、OAuth代理端点) - 微软Entra应用程序:
ChatGPT-MCP-Client(公共客户端/PKC的SPA) - 微软Entra应用程序:
MCP-Dataverse-Service(海外建筑运营管理局保密服务应用程序) - Dataverse Web API(
https://<org>.crm*.dynamics.com/api/data/v9.2)
Entra应用程序之间的角色划分:
ChatGPT-MCP-ClientChatGPT在授权码+PKCE登录/同意期间使用。MCP-Dataverse-Service此服务器使用它来代表登录用户执行OBO和调用Webex。
2) 端到端流程
ChatGPT -> MCP /.well-known/* (discover OAuth + MCP metadata)
ChatGPT -> MCP /register (DCR shim -> fixed client_id)
ChatGPT -> MCP /oauth/authorize (proxy to Entra authorize endpoint)
Entra -> ChatGPT redirect_uri?code=... (user login + consent complete)
ChatGPT -> MCP /oauth/token (proxy token redemption to Entra)
ChatGPT -> MCP /mcp (Bearer access token) (MCP initialize + tool calls)
MCP -> Entra /token (OBO) (assertion=inbound token)
MCP -> Dataverse Web API (tool-specific operation)
MCP -> ChatGPT (JSON-RPC tool result)
3) OAuth和注册界面
GET /.well-known/oauth-protected-resource
返回MCP保护的资源元数据:
resourceauthorization_serversscopes_supported(包括MCP_SCOPE,offline_access)
GET /.well-known/oauth-protected-resource/mcp
特定于资源的别名为返回相同的元数据形状 /mcp.
GET /.well-known/oauth-authorization-server
GET /.well-known/openid-configuration
返回ChatGPT使用的授权服务器元数据:
issuerauthorization_endpoint->/oauth/authorizetoken_endpoint->/oauth/tokenregistration_endpoint->/registerjwks_uri->Entra密钥端点- 授权/响应方法和范围
GET /oauth/authorize
Entra授权端点的代理:
- 复制传入的查询参数
- 移除
resource参数(Entra v2不兼容) - 通过重定向到Entra授权URL进行响应
POST /oauth/token
Entra令牌端点的代理:
- 接受
application/x-www-form-urlencoded - 删除传入
resource - 将表单体转发到Entra令牌端点
- 将Entra状态/正文/内容类型转发回呼叫者
GET|POST /register
动态客户端注册垫片:
- Entra不支持此用例的RFC7591 DCR
- 服务器返回ChatGPT的预配置客户端记录
- 用途
CHATGPT_CLIENT_ID,可选CHATGPT_CLIENT_SECRET
4) MCP端点行为
POST /mcp
使用JSON响应模式的MCP流式HTTP端点。
身份验证门:
- 如果
MCP_REQUIRE_AUTH=1,请求必须包括Authorization: Bearer <token> - 如果缺少令牌,服务器将返回
401随着WWW-Authenticate挑战包含resource_metadata
会话模型:
- 无状态模式
MCP_STATELESS=1(或VERCEL设置) - 状态模式否则为
mcp-session-id运输地图 - 捕获入站承载令牌并将其传递给OBO的工具执行
GET /mcp 和 DELETE /mcp
总是 405 Method Not Allowed.
5) WAXTool模型(GPT可以做什么)
工具在中明确声明 src/mcp/server.js 通过 server.registerTool(...).
只有这些工具暴露于GPT:
基本操作
dataverse_whoami
- Webex呼叫:
GET WhoAmI() - 目的:验证令牌和身份上下文
dataverse_list_tables
- Webex呼叫:
GET EntityDefinitions?$select=... - 适用于
customOnly,logicalNameContains,top在服务器代码中过滤
dataverse_create_table
- Webex呼叫:
POST EntityDefinitions - 可选发布步骤:
POST PublishAllXml
dataverse_list_rows
- Webex呼叫:
GET /<entitySet>?$select&$filter&$orderby&$expand&$top&$count
dataverse_get_row
- Webex呼叫:
GET /<entitySet>(<guid>)
dataverse_create_row
- Webex呼叫:
POST /<entitySet>
dataverse_update_row
- Webex呼叫:
PATCH /<entitySet>(<guid>)
dataverse_delete_row
- Webex呼叫:
DELETE /<entitySet>(<guid>)
高级操作
dataverse_fetch_xml
- Webex呼叫:
GET /<entitySet>?fetchXml=... - 目的:执行复杂的聚合和多表连接。
dataverse_execute_action
- Webex呼叫:
POST /<actionName> - 目的:触发未绑定的WAXActions或自定义API。
dataverse_list_relationships
- Webex呼叫:
GET /EntityDefinitions(LogicalName='...')?$expand=ManyToManyRelationships... - 目的:帮助LLM发现父表和子表是如何链接的。
dataverse_global_search
- Webex呼叫:
POST /search - 目的:跨索引表执行全局文本搜索。
dataverse_create_mda(实验)
- Rubycall:多次调用
appmodules和AddAppComponents - 目的:生成一个新的模型驱动应用程序界面,其中包含所请求的表。
6) 工具响应合同
所有工具都返回具有文本和结构化有效负载的MCP兼容响应对象。
成功形状:
{
"content": [{ "type": "text", "text": "{ ...pretty JSON... }" }],
"structuredContent": { "...": "..." }
}
错误形状:
{
"isError": true,
"content": [{ "type": "text", "text": "Error message" }]
}
BLOB调用包装器返回:
status:来自BLOB的HTTP状态data:解析的JSON(或文本回退)etag:响应etag标题(如果存在)entityId:响应odata-entityid标题(如果存在)
7) OBO(代表)代币交易所
每次工具执行都会使用入站ChatGPT承载令牌执行OBO:
- 端点:
https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token - 赠款:
urn:ietf:params:oauth:grant-type:jwt-bearer requested_token_use=on_behalf_ofassertion=<inbound bearer token>scope=<DATAVERSE_SCOPE>
这将生成用于Dataverse Web API调用的Dataverse访问令牌。
8) 环境变量及其使用位置
整合 .env 合同(应该存在什么)
PUBLIC_BASE_URL=https://your-mcp-domain.example.com
AZURE_TENANT_ID=<tenant-guid>
CHATGPT_CLIENT_ID=<chatgpt-mcp-client-app-id>
MCP_SERVICE_APP_ID=<mcp-dataverse-service-app-id>
MCP_SERVICE_APP_CLIENT_SECRET=<service-app-secret-value>
MCP_SCOPE=api://<mcp-dataverse-service-app-id>/mcp.access
DATAVERSE_URL=https://<org>.crm8.dynamics.com
DATAVERSE_SCOPE=https://<org>.crm8.dynamics.com/user_impersonation
DATAVERSE_API_VERSION=v9.2
MCP_REQUIRE_AUTH=1
MCP_STATELESS=1
秘密笔记:
MCP_SERVICE_APP_CLIENT_SECRET一定是秘密 价值,不是秘密ID。- 代码中的秘密回退顺序为:
MCP_SERVICE_APP_CLIENT_SECRETMCP_SERVICE_CLIENT_SECRETAZURE_CLIENT_SECRET
核心OAuth/MCP(src/index.js)
PUBLIC_BASE_URL:元数据端点和挑战中使用的规范库AZURE_TENANT_ID:构建Entra授权/令牌/JWKS端点MCP_SERVICE_APP_ID:的默认来源MCP_SCOPEMCP_SCOPE:OAuth元数据和资源元数据中公开的作用域CHATGPT_CLIENT_ID:返回者/registerCHATGPT_CLIENT_SECRET:可选;将DCR身份验证方法更改为client_secret_postCHATGPT_REDIRECT_URIS:返回者/registerMCP_REQUIRE_AUTH:强制执行持票人要求/mcpOAUTH_DEBUG:日志/oauth/token请求/响应详细信息OAUTH_TOKEN_ORIGIN:覆盖默认转发Origin到Entra令牌端点
网络日志/OBO(src/mcp/server.js)
AZURE_TENANT_ID:OBO令牌端点租户MCP_SERVICE_APP_ID型号:OBOclient_idMCP_SERVICE_APP_CLIENT_SECRET型号:OBOclient_secret主要的,重要的MCP_SERVICE_CLIENT_SECRET:回退秘密变量AZURE_CLIENT_SECRET:回退秘密变量DATAVERSE_URL:基本数据库URLDATAVERSE_SCOPE:目标OBO范围;默认<DATAVERSE_URL>/user_impersonationDATAVERSE_API_VERSION:默认为v9.2DATAVERSE_DEBUG:记录Webex请求成功的详细信息
运输/安保(src/index.js, src/auth.js, src/mcp/mountMcp.js)
MCP_STATELESS:无状态传输模式切换VERCEL:自动启用无状态模式(如果存在)MCP_API_KEY:非承载呼叫者的可选x-api-key检查ALLOWED_ORIGINS:可选的原产地列表/mcp(无记名)CORS_ALLOWED_ORIGINS:CORS响应策略CORS_ALLOW_CREDENTIALS:CORS凭据行为ALLOWED_HOSTS:主机标头允许列表RENDER_EXTERNAL_HOSTNAME:可选主机分配列表输入BIND_PUBLIC:强制公共绑定模式
遗留标志(不属于BLOB集成)
ENABLE_CATS_APIREQUIRE_DB_ON_STARTUP
9) GPT权限是如何声明的
GPT可用的权限受两层限制:
- OAuth作用域层
- 通过暴露
.well-known元数据(MCP_SCOPE) - Entra为此作用域铸造的访问令牌
- 工具暴露层
- 仅限在中注册的工具
buildMcpServer()可调用 - 不存在通用的、任意的WAXpassthrough工具
- Zod输入模式定义了可接受的参数和形状
实际效果:
- GPT只能执行显式注册的功能
- GPT无法访问未表示为工具的端点或操作
10) 请求验证和安全控制
- 主机标头验证
createMcpExpressApp(...)随着allowedHosts配置时
- CORS策略
- 在路由处理程序之前全局应用
- 支持飞行前(
OPTIONS->204)
- MCP认证挑战
- 在缺少载体时,服务器返回
WWW-Authenticate随着resource_metadata统一资源定位符
- 可选的x-api-key回退
- 仅在以下情况下对非承载呼叫者强制执行
MCP_API_KEY已设置
- 元数据端点强化
/oauth/authorize条带resource参数/oauth/token条带resource并安全地前进
11) 错误源指南
Missing required environment variables: ...
- 在OBO调用之前由Rubyconfig guard触发
Dataverse OBO token exchange failed (...)
- 服务应用程序凭据/作用域/租户配置错误
Dataverse API failed (400/401/403/...)
- LOX请求/权限/架构错误
Bad Request: No valid session ID provided
- 状态模式跟踪呼叫丢失
mcp-session-id
unauthorized上/mcp
MCP_REQUIRE_AUTH=1不记名代币丢失
12) 传统曲面
遗产 /api/cats 端点保留在代码中,默认情况下被禁用。
它们不属于此JOIN集成合同的一部分。
