ProjectSight MCP Server
Provides access to the ProjectSight API for managing construction portfolios, projects, and records like ActionItems, RFIs, and Submittals. It features a modular architecture supporting CRUD operations, workflow state management, and OAuth2 authentication.
README
ProjectSight MCP Server
A scalable, maintainable MCP (Model Context Protocol) server that provides access to the ProjectSight API for managing portfolios, projects, and various record types like ActionItems, RFIs, Submittals, and more.
This server has been refactored into a modular, teachable structure that demonstrates best practices for building MCP servers. It's designed to be both production-ready and an excellent learning resource.
🎯 Features
- OAuth2 Authentication: Automatic token management with caching and refresh
- Modular Architecture: Clean separation of concerns, easy to extend
- Project Operations: Access project information
- Record Management: CRUD operations for:
- ActionItems
- RFIs (Request for Information)
- Submittals
- Workflow States: Get workflow states for record types
- Debug Tools: Test connection, debug tokens, test different scopes
📁 Project Structure
projectsight-mcp/
├── mcp/ # Main MCP server code
│ ├── main.py # Entry point - run this to start the server
│ ├── config.py # Configuration management
│ ├── auth.py # OAuth2 authentication
│ ├── client.py # API client for HTTP requests
│ ├── utils.py # Utility functions
│ └── tools/ # MCP tools organized by domain
│ ├── __init__.py # Tool registration
│ ├── debug.py # Debug/diagnostic tools
│ ├── projects.py # Project operations
│ ├── action_items.py # Action item CRUD
│ ├── rfis.py # RFI operations
│ ├── submittals.py # Submittal operations
│ └── workflow.py # Workflow state tools
├── README.md # This file
└── .env # Environment variables (create this)
🚀 Quick Start
1. Install Dependencies
pip install fastmcp python-dotenv aiohttp uvicorn
Or using a virtual environment:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install fastmcp python-dotenv aiohttp uvicorn
2. Configure Credentials
Create a .env file in the mcp/ directory (or project root) with your ProjectSight API credentials:
APPLICATION_NAME=your_app_name
CLIENT_ID=your_client_id
CLIENT_SECRET=your_client_secret
PORTFOLIO_ID=your_portfolio_id_or_guid
PROJECTSIGHT_API_URL=https://cloud.api.trimble.com/projectsight/us1/1.0
PROJECTSIGHT_SCOPE=ProjectSight_-_US1
Getting Credentials:
- Sign in to API Cloud with your Trimble account
- On the Discover API page, select ProjectSight or ProjectSight-EU
- Select Subscriptions and subscribe your application
- Select Get Key and copy:
- Application Name
- Consumer Key (CLIENT_ID)
- Consumer Secret (CLIENT_SECRET)
For more information, email ProjectSightAPISupport@trimble.com to request API access.
Note on Scope: The PROJECTSIGHT_SCOPE should match your API subscription region:
ProjectSight_-_US1for US regionProjectSight_-_EU1for EU regionProjectSight_-_US2for Azure US region
3. Run the Server
STDIO Mode (default for MCP clients):
cd mcp
python main.py
HTTP Streaming Mode:
cd mcp
python main.py --http
With custom host/port:
# Windows PowerShell
$env:MCP_HOST="0.0.0.0"
$env:MCP_PORT="8000"
python main.py --http
# Linux/Mac
export MCP_HOST=0.0.0.0
export MCP_PORT=8000
python main.py --http
🔧 MCP Client Configuration
STDIO Mode (Cursor, Claude Desktop, etc.)
{
"mcpServers": {
"projectsight": {
"command": "python",
"args": ["C:\\Users\\cforey\\Desktop\\projectsight-mcp\\mcp\\main.py"],
"env": {
"APPLICATION_NAME": "your_app_name",
"CLIENT_ID": "your_client_id",
"CLIENT_SECRET": "your_client_secret",
"PORTFOLIO_ID": "your-portfolio-guid-or-account-id"
}
}
}
}
Note: You can also use a .env file instead of setting environment variables in the config. The script will automatically load variables from a .env file in the mcp/ directory.
HTTP Mode
For MCP clients that support HTTP transport, configure the connection URL:
http://localhost:8000/mcp
📚 Available Tools
Connection & Debug Tools
- test_connection(): Test the connection to ProjectSight API and verify authentication
- debug_token(): Debug token acquisition and validation (without exposing the actual token)
- test_different_scopes(): Test different scope combinations to find what works
Project Operations
- get_projects(portfolio_guid): Get Projects for a specific Portfolio. If
portfolio_guidis not provided, usesPORTFOLIO_IDfrom.env.
ActionItem Operations
- get_action_item(portfolio_guid, project_id, action_item_id): Get an individual ActionItem
- list_action_items(portfolio_guid, project_id): List ActionItems for a project. If
portfolio_guidis not provided, usesPORTFOLIO_IDfrom.env. - create_or_update_action_item(portfolio_guid, project_id, action_item_data): Create or update an ActionItem
- delete_action_item(portfolio_guid, project_id, action_item_id): Delete an ActionItem
RFI Operations
- get_rfi(portfolio_guid, project_id, rfi_id): Get an individual RFI
- list_rfis(portfolio_guid, project_id, project_name): List RFIs for a project. Supports finding project by name if
project_idis not provided. Ifportfolio_guidis not provided, usesPORTFOLIO_IDfrom.env. - create_or_update_rfi(...): Create or update an RFI with flexible parameters:
- Required:
subject,question(ordetails), and eitherproject_idorproject_name - Optional:
date_due,importance,details,author_contact_id, etc. - Automatically handles date normalization, project name lookup, workflow state detection, and RFI number generation
- Required:
- delete_rfi(portfolio_guid, project_id, rfi_id): Delete an RFI
Submittal Operations
- get_submittal(portfolio_guid, project_id, submittal_id): Get an individual Submittal
- list_submittals(portfolio_guid, project_id): List Submittals for a project. If
portfolio_guidis not provided, usesPORTFOLIO_IDfrom.env.
Workflow Operations
- get_workflow_states(record_type, portfolio_guid, project_id): Get workflow states for a record type (e.g., "RFI", "ActionItem", "Submittal"). If
portfolio_guidis not provided, usesPORTFOLIO_IDfrom.env.
🏗️ Architecture & Best Practices
This MCP server has been refactored into a scalable, maintainable structure that demonstrates best practices:
- Modular Design: Each component in its own file with clear responsibilities
- Separation of Concerns: Configuration, authentication, API client, and tools are separated
- Organized Tools: Tools grouped by domain for easy discovery and extension
- Comprehensive Documentation: Architecture guide and extension examples included
🎓 Learning Resource
This structure is designed to be a teaching example - use it as a reference when building your own MCP servers! The code demonstrates:
- ✅ Single Responsibility Principle
- ✅ Separation of Concerns
- ✅ Dependency Injection
- ✅ DRY (Don't Repeat Yourself)
- ✅ Clear Naming Conventions
- ✅ Comprehensive Documentation
- ✅ Type Hints
- ✅ Error Handling Patterns
🔐 Authentication
The server uses OAuth2 client credentials flow with Trimble Identity:
- Tokens are automatically cached and refreshed
- Token cache is stored at
~/.cache/projectsight/token_cache.json - Tokens are refreshed automatically when expired
📝 Important Notes
-
Portfolio ID: The
PORTFOLIO_IDenvironment variable can be either:- An integer AccountID (e.g.,
1,2,3) - A Portfolio GUID in UUID format (e.g.,
b1123573-2dac-4499-81f4-7ec44b89152c)
- An integer AccountID (e.g.,
-
Project Lookup: Many tools support finding projects by name (case-insensitive, partial match) if you don't know the project ID.
-
RFI Creation: The
create_or_update_rfitool is highly flexible and will:- Auto-detect workflow states from existing RFIs
- Auto-generate RFI numbers
- Normalize dates from various formats ("today", "tomorrow", "2026-01-26", etc.)
- Map importance text ("high", "normal", "low") to importance IDs
- Use existing RFI settings as defaults when appropriate
🌐 Exposing via Public URL (Tunneling)
To make your local server accessible via a public URL, use a tunneling service:
Option 1: ngrok (Recommended)
-
Install ngrok on Windows:
winget install ngrok.ngrok -
Start your MCP server:
cd mcp python main.py --http -
Create a tunnel (in a separate terminal):
ngrok http 8000 -
Use the public URL: ngrok will provide a public URL like
https://abc123.ngrok-free.dev. The MCP endpoint is at/mcp:https://abc123.ngrok-free.dev/mcp
Option 2: Cloudflare Tunnel (cloudflared)
-
Install cloudflared: Download from developers.cloudflare.com
-
Start your MCP server:
cd mcp python main.py --http -
Create a tunnel (in a separate terminal):
cloudflared tunnel --url http://localhost:8000 -
Use the public URL: Cloudflare will provide a public URL like
https://random-subdomain.trycloudflare.com. Your MCP endpoint will be:https://random-subdomain.trycloudflare.com/mcp
🔒 Security Note
When exposing your server publicly, consider:
- Adding authentication/API keys if your MCP server handles sensitive data
- Using HTTPS (all tunneling services above provide HTTPS)
- Limiting access to specific IPs if possible
- Monitoring usage and rate limiting
📊 Rate Limits
Based on updated guidance from Trimble Cloud, you don't need to pass the x-API-key to the trimblepaas.com endpoints. If you do pass it, there is a limit of 50 requests per second.
📖 API Documentation
For detailed API documentation, refer to:
🔄 Migration from Old Structure
If you were using the old projectsight.py file directly:
- Update command: Use
python main.pyinstead ofpython projectsight.py - Configuration: Same
.envfile format (place inmcp/directory) - MCP Client Config: Update path to point to
mcp/main.py - Tools: All tools work the same, just organized better
The old projectsight.py file is still available for reference but the new modular structure is recommended.
🛠️ Extending the Server
See mcp/EXAMPLE_EXTENSION.md for detailed examples. Quick template:
# mcp/tools/my_new_tool.py
from fastmcp import FastMCP
from client import ProjectSightClient
_client: ProjectSightClient = None
def register(mcp: FastMCP):
@mcp.tool()
async def my_tool(param: str) -> Dict:
"""Tool description."""
result = await _client.get(f"/endpoint/{param}")
return {"result": result}
def set_client(client: ProjectSightClient):
global _client
_client = client
Then register it in mcp/tools/__init__.py.
📄 License
This project is provided as-is for use with the ProjectSight API.
Built with best practices in mind - Use this structure as a reference for building your own MCP servers! 🚀
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。