Claude Desktop
Settings → Connectors → Add custom connector. Paste the URL.
https://mcp.usetenon.com Tenon exposes 33 tools over the Model Context Protocol — 14 reads, 19 writes — covering projects, estimates, tasks, RFIs, schedule, timesheets, daily logs, and documents. Works with Claude Desktop, Claude Code, Cursor, ChatGPT, or any MCP-compatible client.
Any client that speaks the Model Context Protocol works. Tested with Claude Desktop, Claude Code, Cursor, and ChatGPT Custom GPT Actions. See the per-client recipes below.
Point your client at https://mcp.usetenon.com.
The server speaks Streamable HTTP and advertises its tool
catalog over tools/list on connect.
OAuth 2.1 with Google sign-in or email + password — the same auth as app.usetenon.com. The client redirects you through the consent screen on first connect.
Approve the scopes the client requests. Read-only is the default; write tools (clock-in, create-task, line-item mutations, etc.) need the matching write scope.
Settings → Connectors → Add custom connector. Paste the URL.
https://mcp.usetenon.com Run from any terminal:
claude mcp add tenon https://mcp.usetenon.com Settings → MCP Servers → Add. Paste the URL.
https://mcp.usetenon.com Use as a Custom GPT Action or via the Responses API tool.
https://mcp.usetenon.com
Some clients (notably the claude.ai connector flow) can't send
custom auth headers — for those, generate a long-lived MCP API
key and pass it as the api_key argument on
tool calls.
KEYS ARE SCOPED TO YOUR USER · KEY-LEVEL REVOCATION ONLY · WRITES OBEY YOUR RBAC ROLE
MCP tools respect the connected user's role. Admins get write tools; members get the read-only subset. Every tool call — read or write — is logged with the calling user, tool name, arguments, and outcome. Review activity under Settings → API Keys → Activity.
Every tool is tenant-scoped to the calling user's company and obeys their RBAC role. Writes are audit-logged. Most tools accept either a public UUID or a numeric internal id where an id is required.
Discover projects, drill into schedule, read live status. Project ids accept either the public UUID or numeric internal id.
| Tool | Kind | Description |
|---|---|---|
| list_projects | read | List the caller's projects, optionally filtered by status. Returns id, name, status, address, and last activity timestamp per row. |
| get_project | read | Fetch full details for a single project. Returns name, status, address, contract type, and timestamps. |
| get_project_schedule | read | Return tasks on a project's schedule, optionally filtered to a date range. |
Read tasks across the company or a single project. Create new tasks and mutate status, assignee, due date, or priority.
| Tool | Kind | Description |
|---|---|---|
| list_tasks | read | List tasks across the company. Cross-project when project_id is omitted. |
| create_task | write | Create a new task. Returns the created task id and a web URL. |
| update_task | write | Partial patch — status, assignee, due date, notes, priority. Audit-logged. |
Read the caller's active timer; start, stop, or log retroactive time. All writes are audit-logged.
| Tool | Kind | Description |
|---|---|---|
| get_active_timer | read | Return the caller's currently running tracker, if any. Includes project, started_at, paused state, and elapsed seconds. |
| clock_in | write | Start a timer. Stops any existing timer first when force=true. |
| clock_out | write | Stop the caller's active timer. Returns the resulting entry. |
| log_time | write | Log a manual (retroactive) entry against a project. Date defaults to today. |
List daily logs by project; create new ones and append narrative entries to existing logs.
| Tool | Kind | Description |
|---|---|---|
| list_daily_logs | read | List daily logs for a project, defaulting to the last 30 days. |
| create_daily_log | write | Create a daily log for a project. Defaults log_date to today. |
| add_log_entry | write | Append narrative to work_performed / issues / delays / notes. Concatenates — does not overwrite. |
List, create, and answer requests for information. Answering flips status to answered and records the responder.
| Tool | Kind | Description |
|---|---|---|
| list_rfis | read | List RFIs, optionally filtered by project or status. |
| create_rfi | write | Create an RFI on a project. |
| answer_rfi | write | Answer an existing RFI. Sets status=answered and records the responder. |
Surface open decisions and record a chosen option. Selections are audit-logged with full provenance.
| Tool | Kind | Description |
|---|---|---|
| get_decisions | read | List decisions for the company, optionally filtered by project or status. |
| make_selection | write | Mark a selection on a decision — chooses one of its options. Audit-logged. |
Full estimate surface — read versions, mutate line items, sections, and assemblies. Switch the Working version that proposals and invoices reference.
| Tool | Kind | Description |
|---|---|---|
| list_estimates | read | List estimates, optionally filtered by project or status. |
| get_estimate | read | Fetch a single estimate including header, totals, and line items. |
| get_estimate_versions | read | List all versions of an estimate. The is_working=true row is the one other docs reference. |
| export_estimate_csv | read | Return CSV of an estimate's line items. Columns: sort_order, cost_code, description, quantity, unit, unit_cost, markup_pct, builder_cost, total. |
| create_estimate | write | Create a new estimate. Returns id, public_id, and a web URL. |
| update_estimate | write | Partial patch of an estimate's header (title, status, notes, tax_rate). Audit-logged. |
| add_line_item | write | Append a line item. Defaults cost_type='material', quantity=1, unit='ea'. Audit-logged. |
| update_line_item | write | Patch a single line item. Audit-logged. |
| delete_line_item | write | Delete a single line item. Audit-logged. |
| reorder_line_items | write | Reorder by setting sort_order for each id in the array. Audit-logged. |
| add_section | write | Add a section header row. |
| add_assembly | write | Add an assembly parent row (children via add_line_item with parent_line_item_id). |
| set_working_version | write | Switch the Working version. The new version becomes the one proposals/invoices reference. |
Full-text search across every document type the company has filed.
| Tool | Kind | Description |
|---|---|---|
| search_documents | read | Full-text search across estimates, proposals, invoices, change orders, and bid requests. Returns relevance-ranked entity_type, id, title, and snippet. |
Read invoice state — billing flows are managed through the app UI rather than the MCP surface.
| Tool | Kind | Description |
|---|---|---|
| list_invoices | read | List invoices, optionally filtered by project or status. |
The MCP surface is a thin wrapper around the Tenon REST API. Anything an MCP tool can do, a Bearer-token HTTP call can do too — same RBAC, same audit log, same response shapes.
https://app.usetenon.com/api/v1 http://localhost:8080/api/v1 Authorization: Bearer <jwt> 1000 req/min per token | Group | Path prefix | Notes |
|---|---|---|
| Auth & Identity | /auth/*, /me/* | Email + password, Google OAuth, refresh, MFA, profile. |
| Projects | /projects | CRUD + status, schedule, members. |
| Tasks | /tasks | CRUD; cross-project filters via query params. |
| Estimates | /estimates | CRUD, line items, sections, assemblies, versions. |
| Proposals | /proposals | Generated from estimates; portal links + status. |
| Invoices | /invoices | Issue, send, mark paid; line items mirror estimate. |
| Change Orders | /change-orders | CRUD + portal acceptance. |
| Bid Requests | /bid-requests | Issue to subs, collect responses. |
| RFIs | /rfis | CRUD + answer flow. |
| Decisions | /decisions | CRUD + make_selection. |
| Daily Logs | /daily-logs | Per-project narratives, append-only entries. |
| Timesheets | /timesheets, /time-entries | Active timer + clock-in/out + retroactive log_time. |
| Documents | /documents/search | Full-text across estimates, proposals, invoices, COs, bids. |
| Handbook | /policies, /procedures | Org-wide policies + procedures library. |
| MCP API Keys | /mcp-api-keys | Self-serve generate + revoke; tied to the caller's user. |
| Audit | /audit | Read every write across the surfaces above. |
Download the live OpenAPI spec — generated from the running server, always in sync with deployed endpoints. Hook it into Postman, Insomnia, openapi-codegen, or any client SDK generator.
Download OpenAPI 3.0 specThe first 30 days are on us. Bring your existing projects, RFIs, and estimates — or start fresh and have your agent stub them out for you.