Accubid MCP服务器
用于Accubid Anywhere API和Trimble身份验证的MCP服务器。
特性
- Trimble身份 代表 auth:每个MCP HTTP请求都携带
Authorization: Bearer(例如,来自Agent Studio);服务器 交换 它在id.trimble.com/oauth/token(RFC 8693)因此Accubid Anywhere会收到一个令牌 你的CLIENT_ID - 域工具用于:
- 数据库 - 项目 - 估计 - 清仓 - 变更单 - 见解 - 上下文 - 工作流
- YAML中的工具元数据和服务器功能
- 具有重试/超时的共享API客户端
- 内置断路器和可选速率限制的弹性
- 通用Accubid工作流程的MCP资源和提示
- 用于分析和一次通话数据收集的见解和上下文工具
- 用于项目和评估准备情况的工作流包工具
- 用于多服务器环境的可选命名空间工具别名
- 具有稳定错误代码和请求ID的结构化响应信封
- 运行时丰富的工具发现元数据(
required_params,optional_params,别名信息)
身份验证(Trimble Agent Studio)
- 注册一个OAuth应用程序 在 Trimble开发人员控制台 和 代币交换(代表) 启用和 Accubid任何地方 订阅了该应用程序。
- 复制
.env.example到.env并设置CLIENT_ID,CLIENT_SECRET,以及ACCUBID_SCOPE(默认值openid accubid_agentic_ai--与您的邮递员授权保持一致scope=调试时)。 - 使用以下命令运行MCP 可流式传输HTTP (
python -m src.main --http或accubid-mcp-http). 工作室 没有每个请求的HTTP标头;如果没有参与者,工具就会失败。 - 连接来源 代理工作室 因此每个MCP请求包括
Authorization: Bearer <actor JWT>(代表演员)。服务器在以下位置交换该令牌POST {issuer}/oauth/token和grant_type=urn:ietf:params:oauth:grant-type:token-exchange并将返回的访问令牌用于Accubid API调用。
邮递员 授权码 代币直接发放到您的应用程序;MCP路径使用 代币兑换 相反。两者都应该针对 相同 CLIENT_ID 并且兼容 范围 Accubid接受出境持票人。
直接服务URL(POC/临时)
如果 cloud.api.trimble.com 回报 900909 因为 控制台代理 需要API产品订阅,并且 AI代理工作室 如果上下文无法满足此要求,Accubid可能会指示您致电 直接微服务 开发主机(例如。 https://anywhereservices.trimbleplatform.net/...)直到Identity/Console提供了一种支持的方式来代表令牌使用公共代理。
以...为背景 .env:
ACCUBID_USE_DIRECT_SERVICES=trueACCUBID_DIRECT_PLATFORM_HOST=https://anywhereservices.trimbleplatform.net(如果未设置,则默认)
MCP按区域建立服务根(databaseservice, projectservice, estimateservice\[/v2\], closeoutservice, changeorderservice).列出数据库映射 /databases → /Databases 以匹配直接的OpenAPI。可选的 **ACCUBID_DIRECT_*_SERVICE_URL** var覆盖单个碱基。
还原到代理URL (ACCUBID_USE_DIRECT_SERVICES=false)一旦Trimble权限得到解决,就可以进行与生产一致的行为。
设置
- 复制
.env.example到.env并设置CLIENT_ID,CLIENT_SECRET,ACCUBID_SCOPE. - 安装依赖项:
pip install -e .对于本地开发(测试、lint、打字):
pip install -e ".[dev]"授权码(邮递员)与代币兑换(MCP)
| 流程 | 发生了什么 |
|---|---|
| 授权代码 (邮递员) | 用户同意;Trimble发布访问令牌 直接 为您 client_id. |
| 代币兑换 (此MCP) | MCP发送 演员JWT 作为 subject_token;Trimble返回a 新 访问令牌 CLIENT_ID 范围从 ACCUBID_SCOPE. |
调试: 集 ACCUBID_DEBUG_LOG_OUTBOUND_TOKEN=true 简要地;比较出境JWT azp 到你的邮差令牌。在以下情况下,两者都应该是您订阅的应用程序 CLIENT_ID 比赛。
跑
- 工作室:
python -m src.main- HTTP:
python -m src.main --httpHTTP脚本入口点:
accubid-mcp-httpMCP资源
服务器公开只读资源:
accubid://databasesaccubid://databases/{database_token}/foldersaccubid://databases/{database_token}/folders/{parent_folder_id}accubid://databases/{database_token}/projectsaccubid://databases/{database_token}/projects/{project_id}accubid://databases/{database_token}/projects/{project_id}/estimatesaccubid://databases/{database_token}/estimates/{estimate_id}accubid://databases/{database_token}/projects/{project_id}/contractsaccubid://databases/{database_token}/contracts/{contract_id}/pcosaccubid://databases/{database_token}/contracts/{contract_id}/statusesaccubid://databases/{database_token}/estimates/{estimate_id}/bid-breakdown-viewsaccubid://databases/{database_token}/bid-summaries/{bid_summary_id}/final-priceaccubid://context/project/{database_token}/{project_id}accubid://insights/pipeline/{database_token}/{start_date}/{end_date}
这些资源对于轻量级的可缓存读取和上下文水合非常有用。
MCP提示
可重复使用的提示可用于指导工作流程:
bid_discoverycloseout_for_estimatechangeorder_flowpipeline_reportfull_closeout_reportchangeorder_summary_by_projectbid_risk_triagemargin_reviewpco_exposurecreate_estimate_from_csv
工作流程和分析
其他工具提供分析和上下文聚合,而不需要新的 Accubid端点:
- 洞察力:
- get_pipeline_summary - get_closeout_summary - get_changeorder_summary
- 背景:
- get_project_context - get_estimate_context
- 工作流程:
- get_project_health_packet - get_estimate_readiness_packet - create_estimate_from_csv_url
- 分析:
- analyze_bids_due_window - analyze_estimate_pricing - analyze_changeorder_exposure
推荐的工作流程链:
- 管道报告:
- list_databases -> get_pipeline_summary
- 收尾报告:
- get_estimate -> get_closeout_summary -> get_bid_breakdown (可选)
- 变更单摘要:
- list_contracts -> get_changeorder_summary
- 项目健康包:
- list_databases -> list_projects -> get_project_health_packet
- 估计准备就绪包:
- get_estimate -> get_estimate_readiness_packet
- 投标日分流:
- list_databases -> analyze_bids_due_window
- 定价异常检查:
- get_estimate -> analyze_estimate_pricing
- 变更单风险:
- list_contracts -> analyze_changeorder_exposure
- 估计进口行动:
- list_databases -> create_estimate_from_csv_url (dry_run=true,然后dry_run=false) - 可选安全旋钮: project_name_override, project_number_override,以及 on_project_create_failure="lookup_existing" - 演示的快速路径: allow_create_project=false 当项目已存在时
分析工作流演示提示
在Agent Studio中使用以下内容作为对话起点:
- “我正在为投标日做准备。看看我们在未来14天内到期的估计,告诉我哪些有风险,以及为什么——错过定价、错过细分,或者只是没有时间了。把它们排成红色/黄色/绿色,告诉我谁先打电话。”
- “提取项目\[名称\]的最新估算,并进行利润和成本组合审查。标记任何看起来有问题的地方——缺失的组件、劳动力组合异常值、可疑的总计——并给我一份300美分的执行摘要,我可以将其粘贴到状态电子邮件中。”
- “给我一个项目\[名称\]的变更单风险汇总:风险总金额、最古老的未结PCO、要追逐的最高合同,以及我本周应该采取的下一步行动。”
- 从此CSV URL创建新的估算。首先运行模拟预览,然后创建任何不重复的内容,并返回创建的项目和估算ID
CSV模板:
docs/samples/create_estimate_import_template.csv
演示前沙盒检查:
ACCUBID_ACTOR_TOKEN="" python scripts/sandbox_audit.py所有三个流程的定时排练:
ACCUBID_ACTOR_TOKEN="" python scripts/demo_rehearsal.py工具使用流程
对于大多数任务,按以下顺序调用工具:
list_databases->得到databaseTokenlist_projects->得到projectIDlist_estimates->得到estimateID- 使用带有先前步骤ID的收尾/变更单工具
数据库令牌和项目ID是稳定的,可以缓存。
许多列表样式工具支持可选的客户端分页:
page_index(基于0)page_size
列表回复包括 pagination 带有对象 page_index, page_size, total_count, total_pages,以及 has_next_page.
大容量列表工具现在还支持可选的查询整形:
search(文本搜索)sort_by(每个工具的字段别名)sort_direction(asc或desc)status(适用于相关的变更单列表工具)
示例:
list_projects(database_token="...", search="tower", sort_by="name", sort_direction="asc")
list_estimates(database_token="...", project_id="...", search="phase", sort_by="due_date", sort_direction="desc")
list_pcos(database_token="...", contract_id="...", status="Open", sort_by="number", sort_direction="asc")估算截止日期工作流的日期输入接受以下任一方式 yyyymmdd, YYYY-MM-DD,或 MM/DD/YYYY 并在内部进行标准化。
响应合同
所有工具都返回一个一致的信封:
{
"ok": true,
"request_id": "uuid",
"data": {}
}错误:
{
"ok": false,
"request_id": "uuid",
"error": {
"code": "validation_error",
"message": "..."
}
}常见错误代码包括 validation_error, auth_failed, api_error, dependency_unhealthy,以及 internal_error. 当API断路器打开时,错误代码 circuit_open 返回。
操作手册
- Accubid 401 / 900909 或“订阅无效”:以开头 解锁成功的Accubid呼叫 (路径A-C)。
- 验证基础运行状况:
- GET /health 在HTTP模式下。
- 验证依赖关系准备就绪:
- GET /ready 在HTTP模式下。
- 可选依赖元数据:
- 集 HEALTHCHECK_VERIFY_DEPENDENCIES=true 拥有 /health 包括结构化检查(env在导入时进行验证;实时Accubid调用仍然需要为每个请求提供一个actor Bearer)。
- 启动检查:
- 集 STARTUP_VALIDATE_DEPENDENCIES=true 在启动时运行依赖性检查。 - 集 STARTUP_VALIDATE_ACCUBID=true 请注意,Accubid API验证需要具有参与者令牌的可流化HTTP(请参阅检查有效负载)。
- JSON日志:
- 集 LOG_FORMAT=json.
- 重新调整:
- ACCUBID_CLIENT_RETRY_COUNT - ACCUBID_CLIENT_RETRY_BASE_SECONDS - ACCUBID_CLIENT_RETRY_MAX_SECONDS - ACCUBID_CLIENT_RETRYABLE_STATUS_CODES
- 断路器:
- ACCUBID_CIRCUIT_BREAKER_FAILURES - ACCUBID_CIRCUIT_BREAKER_COOLDOWN_SECONDS
- 可选API速率限制:
- ACCUBID_RATE_LIMIT_RPS (0禁用)
- 标准列表分页默认值:
- ACCUBID_LIST_DEFAULT_PAGE_SIZE - ACCUBID_LIST_MAX_PAGE_SIZE
- 用于发现终结点的可选短期缓存:
- ACCUBID_CACHE_ENABLED - ACCUBID_CACHE_TTL_SECONDS - ACCUBID_CACHE_STATE_FILE (可选持久缓存状态文件路径)
- 可选工具名称间距:
- 集 ACCUBID_TOOL_NAMESPACE=accubid 暴露别名,如 accubid/list_projects.
- 可选响应密钥规范化:
- 集 ACCUBID_RESPONSE_SNAKE_CASE=true 将工具响应密钥转换为snakecase。
- 请求相关性:
- 设置请求标头 X-Request-Id (或配置 REQUEST_ID_HEADER)因此日志和信封共享相关性ID。
- 韵律学:
- 集 ENABLE_METRICS=true 并刮擦 GET /metrics (或 METRICS_ROUTE).
- 域功能标志:
- ACCUBID_TOOLS_DISABLE_DATABASE - ACCUBID_TOOLS_DISABLE_PROJECT - ACCUBID_TOOLS_DISABLE_ESTIMATE - ACCUBID_TOOLS_DISABLE_CLOSEOUT - ACCUBID_TOOLS_DISABLE_CHANGEORDER
- 组合工具性能调优:
- ACCUBID_COMPOSED_TOOL_CONCURRENCY (默认值 4)
- 可选的持久化电路状态文件路径:
- ACCUBID_CIRCUIT_STATE_FILE
- Accubid Anywhere HTTP基础和每个模块路径:请求使用
ACCUBID_API_BASE_URL(默认值https://cloud.api.trimble.com/anywhere)加上/{area}/{version}以及记录的路径段——例如GET .../database/v1/databases,.../project/v2/Folders/{databaseToken},.../estimate/v1/Estimate/...,.../closeout/v1/BidBreakdownView/...(默认值ACCUBID_API_VERSION_*;如果Trimble更改了模块,则覆盖)。 - 安全生产:
- 集 ENV=production 强制HTTPS ACCUBID_API_BASE_URL.
Trimble 900909(“订阅未激活”)故障排除
Accubid Anywhere连接 401 /故障 900909 到 OAuth客户端 在 出境 访问令牌(JWT声明 azp),不仅仅是URL拼写错误。
清单
client_id平等 --邮递员client_id必须相等CLIENT_ID在.env.- 作用域(最常见的修复) --令牌交换发送
ACCUBID_SCOPE前往Trimble。如果outbound_scope_claim错误只是accubid_agentic_ai但邮递员的代币是有效的,你的邮递员 授权URL 几乎可以肯定包括额外的范围(例如。anywhere-database,anywhere-project, …).复制scope=从Postman查询值到ACCUBID_SCOPE(空格分开,与邮递员相同)。REST端点,例如GET .../database/v1/databases通常需要anywhere-database在访问令牌中,不仅accubid_agentic_ai. - 开发者控制台 --For
CLIENT_ID:启用相同 Accubid Anywhere API产品 /与Postman中的范围相同,以及 代币交换(代表)更换后重新启动MCPACCUBID_SCOPE(缓存键包括作用域)。 - 仍然失败? --联系方式 Trimble支架 与JWT合作
azp/scope工具错误详细信息。
如果 outbound_azp 已经等于你的 CLIENT_ID (代币兑换成功)但你仍然得到900909,这是 不 MCP接线错误-这是该客户与API路线的范围或产品订阅。
如果 outbound_scope_claim 已经包括 anywhere-database 你仍然会得到900909: MCP正在交换并请求正确的范围。邮递员使用 授权码;Agent Studio使用 代币兑换Trimble的Accubid网关可能适用 不同的订阅规则 对于这两种补助金类型。
不设置 ACCUBID_TOKEN_EXCHANGE_RESOURCE 或 ACCUBID_TOKEN_EXCHANGE_AUDIENCE. Trimble Identity为以下两种情况返回HTTP 400: resource / audience 此IDP明确拒绝的参数令牌交换请求可能仅包括 grant_type, subject_token, subject_token_type,以及 scope (加上您的客户端身份验证)。
如果Postman使用相同的工具 CLIENT_ID 但Agent Studio+MCP仍然可以 900909 和 anywhere-database 在出站令牌上打开 Trimble支架 case:问这个 Accubid Anywhere数据库API 权利适用于 RFC 8693令牌交换 访问OAuth应用程序的令牌,并从以下位置附加解码的JWT 授权码 (邮递员)vs token_exchange (aud, azp, scope)时间戳为900909。
MCP 交换 Agent Studio参与者令牌使用 CLIENT_ID / CLIENT_SECRETAccubid应该看到 azp =更换后的MCP应用程序。工具错误包括 actor_azp / actor_sub (入站JWT的未经验证的解码)用于诊断。
安全注意事项
- 永不承诺
.env,CLIENT_ID,或CLIENT_SECRET. - 更喜欢在生产中通过安全的秘密管理器注入秘密。
- 对于HTTP模式,部署在反向代理/负载均衡器后面,该均衡器终止TLS并强制执行访问控制和速率限制。
- 如果引入了面向浏览器的流量,请在反向代理/应用程序边缘配置CORS策略。
- 旋转
CLIENT_SECRET定期。
质量门
合并前运行:
python -m ruff check .
python -m mypy src
python -m pytest
python -m pip_audit可选的实时集成检查:
ACCUBID_INTEGRATION=1 pytest -m integration故障排除
auth_failed:验证CLIENT_ID,CLIENT_SECRET,ACCUBID_SCOPE,以及OPENID_CONFIGURATION_URL.api_error429/503:调整重试/断路器设置并检查上游API运行状况。api_error有效载荷主体缺少细节:为了安全起见,长上游有效载荷被故意截断。circuit_open:等待冷却或减少故障情况;检查API/网络状态。- 超时:增加
ACCUBID_REQUEST_TIMEOUT_SECONDS并验证网络可达性。 - ViewModel工具失败:确保
connection_id是有效的,并且来自现有的ViewModel会话(MCP不创建ViewModel会话)。
迁移说明
如果您从早期版本升级:
- 使用dev-extras重新安装以获取新的质量工具:
- pip install -e ".[dev]"
- 查看新的可选环境变量:
- ACCUBID_CACHE_STATE_FILE - ACCUBID_CIRCUIT_STATE_FILE - ACCUBID_COMPOSED_TOOL_CONCURRENCY
- 如果维护外部工具元数据快照,请刷新它们:
- list_available_tools 现在返回运行时丰富的元数据字段。
备注
- Accubid需要Accubid Anywhere Manager中的API数据访问权限。
- 基于ViewModel的扩展端点作为触发器工具公开,并需要有效的
connection_id.
