Dotloop MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Dotloop MCP show me my recent loops"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Dotloop MCP
Read-first MCP server for Dotloop.
This initial implementation wraps dotloop==1.3.2 behind service adapters and
exposes safe read tools for account, profiles, loops, loop details, folders,
documents, participants, tasks, activity, and templates. State-changing tools
remain deferred by the planning docs under docs/planning/dotloop-mcp-buildout/.
MCP resources
dotloop://api-coverage-matrix: domain-level library and MCP exposure status.dotloop://library-method-coverage: method-leveldotloop==1.3.2coverage generated from the installed package surface.
The local docs/ tree is intentionally ignored by this repo. Runtime coverage
resources and make validate are self-contained for clean checkouts without
local planning docs.
Related MCP server: sources-mcp
Install
uv syncConfigure
Set a local Dotloop access token outside version control:
export DOTLOOP_ACCESS_TOKEN="..."The legacy DOTLOOP_API_KEY variable is also accepted because the underlying
dotloop package uses that name.
Use .env.example for the supported non-secret variable names. Keep real
values in your shell or a local ignored .env file. The server and live
readiness check load DOTLOOP_* values from .env in the current working
directory when those variables are not already exported. Set DOTLOOP_ENV_FILE
to point at a different local env file.
Run
uv run python -m dotloop_mcp.cli stdio
uv run python -m dotloop_mcp.cli streamable-http --host 127.0.0.1 --port 8000 --path /mcpAI Client Battle Testing
Battle testing uses deterministic fixture data and a JSONL tool-call recorder so Claude, ChatGPT, and local harnesses can be scored against the same scenario corpus without touching live Dotloop data.
export DOTLOOP_BATTLE_FIXTURE_MODE=1
export DOTLOOP_BATTLE_RECORD_PATH="tmp/ai-battle/<run-id>/<client>/mcp_calls.jsonl"Fixture mode is incompatible with DOTLOOP_RUN_LIVE_TESTS=1 and never builds a
real Dotloop API client. Use these targets for local validation and report
scoring:
make battle-smoke
make battle-test
DOTLOOP_BATTLE_CALL_LOG=tmp/ai-battle/<run-id>/<client>/mcp_calls.jsonl make battle-reportThe scenario corpus lives at
tests/battle/scenarios/dotloop_ai_battle_scenarios.json and covers 150
identity/navigation, loop/document, people/workflow, template, multi-turn, and
negative-safety prompts. ChatGPT hosted connector checks should use the staging
HTTPS MCP URL with fixture mode enabled before any live Dotloop credentials are
attached.
Authenticate the MCP URL
Streamable HTTP can be protected as an MCP OAuth resource server. The server
can validate tokens from an external OAuth/OIDC issuer and JWKS URL, then
clients must send Authorization: Bearer <token> on every MCP HTTP request.
Tokens in URL query strings are not supported.
export DOTLOOP_TRANSPORT=streamable-http
export DOTLOOP_MCP_AUTH_ENABLED=1
export DOTLOOP_MCP_AUTH_ISSUER_URL="https://auth.example.com"
export DOTLOOP_MCP_AUTH_RESOURCE_SERVER_URL="https://dotloop-mcp.example.com/mcp"
export DOTLOOP_MCP_AUTH_JWKS_URL="https://auth.example.com/.well-known/jwks.json"
export DOTLOOP_MCP_AUTH_REQUIRED_SCOPES="dotloop:read"DOTLOOP_MCP_AUTH_RESOURCE_SERVER_URL is the public MCP endpoint URL clients
authenticate for. It is also used for protected-resource metadata discovery.
Set DOTLOOP_MCP_AUTH_AUDIENCE only when the issuer uses a separate JWT
audience value. Stdio transport is unchanged and should continue to load local
credentials from the environment.
Hosted staging can also expose built-in OAuth issuer endpoints for MCP clients that expect URL-based browser authentication. Hosted live-read deployments should enable Dotloop app OAuth so the connector flow first authorizes the MCP URL and then, when needed, redirects through Dotloop's own OAuth app flow:
export DOTLOOP_MCP_HOSTED_OAUTH_ENABLED=1
export DOTLOOP_MCP_HOSTED_OAUTH_PUBLIC_CONSENT_ENABLED=0
export DOTLOOP_APP_OAUTH_ENABLED=1
export DOTLOOP_API_CLIENT_ID="..."
export DOTLOOP_API_SECRET="..."
export DOTLOOP_APP_OAUTH_REDIRECT_URL="https://tpgstats.com/agents/dotloop/callback"
export DOTLOOP_APP_OAUTH_TOKEN_SECRET_ARN="arn:aws:secretsmanager:..."That built-in issuer serves:
/.well-known/oauth-authorization-server
/.well-known/openid-configuration
/.well-known/jwks.json
/oauth/register
/oauth/authorize
/oauth/dotloop/callback
/oauth/tokenWhen DOTLOOP_APP_OAUTH_ENABLED=1, /oauth/authorize checks the hosted
Dotloop token store before issuing an MCP authorization code. If no valid
Dotloop API token is available, it redirects to Dotloop OAuth and resumes the
original MCP PKCE flow after /oauth/dotloop/callback stores refreshable token
state. The caller's MCP Bearer token is never passed through to Dotloop.
For the hosted Perry Group deployment, Dotloop app authorization uses the
registered https://tpgstats.com/agents/dotloop/callback redirect URI, and
that Django callback relays MCP-prefixed OAuth states back to
https://dotloop.theperry.group/oauth/dotloop/callback.
Hosted Staging Deployment
Dotloop staging is designed to run as a Docker image with the
dotloop-mcp-hosted entrypoint on ECS/Fargate behind
an HTTPS load balancer, with the public MCP endpoint expected at:
https://dotloop.theperry.group/mcpThe hosted entrypoint is streamable HTTP only and requires inbound MCP URL auth:
DOTLOOP_TRANSPORT=streamable-http
DOTLOOP_HOST=0.0.0.0
DOTLOOP_PORT=8000
DOTLOOP_STREAMABLE_HTTP_PATH=/mcp
DOTLOOP_MCP_AUTH_ENABLED=1
DOTLOOP_MCP_AUTH_ISSUER_URL=https://dotloop.theperry.group
DOTLOOP_MCP_AUTH_RESOURCE_SERVER_URL=https://dotloop.theperry.group/mcp
DOTLOOP_MCP_AUTH_JWKS_URL=https://dotloop.theperry.group/.well-known/jwks.json
DOTLOOP_MCP_HOSTED_OAUTH_ENABLED=1
DOTLOOP_MCP_HOSTED_OAUTH_PUBLIC_CONSENT_ENABLED=0
DOTLOOP_APP_OAUTH_ENABLED=1
DOTLOOP_APP_OAUTH_REDIRECT_URL=https://tpgstats.com/agents/dotloop/callback
DOTLOOP_APP_OAUTH_TOKEN_SECRET_ARN=arn:aws:secretsmanager:...Deployment assets live under deploy/ecs/. The staging GitHub Actions workflow
is .github/workflows/deploy-staging.yml; it validates the repo, builds and
pushes a multi-architecture ECR image, renders the ECS task definition, updates
the configured ECS service, and waits for stability. DNS should point
dotloop.theperry.group at the public load balancer before enabling client use.
Validate
make validateLive checks are disabled by default and require explicit opt-in:
make live-readiness-check
make live-read-checkAvailable Tools
33 toolsdotloop_download_documentC
Download a Dotloop document as base64 with a byte-size limit.
Inputs: loop_id (required), profile_id (required), document_id (required), folder_id, +1 more. Returns: result
dotloop_find_template_by_nameC
Find a Dotloop template by name.
Inputs: profile_id (required), template_name (required), exact_match. Returns: result
dotloop_get_accountB
Get the current Dotloop account.
Inputs: no named parameters. Returns: result
dotloop_get_activity_by_typeD
Get Dotloop loop activity filtered by type.
Inputs: loop_id (required), profile_id (required), activity_type (required), batch_size. Returns: result
dotloop_get_activity_by_userC
Get Dotloop loop activity filtered by user.
Inputs: loop_id (required), user_name (required), profile_id (required), batch_size. Returns: result
dotloop_get_activity_summaryC
Get Dotloop activity summary.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_all_tasks_in_loopC
Get all tasks in a Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_completed_tasksC
Get completed tasks in a Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_custom_templatesC
Get custom Dotloop templates.
Inputs: profile_id (required). Returns: result
dotloop_get_default_templatesD
Get default Dotloop templates.
Inputs: profile_id (required). Returns: result
dotloop_get_documentC
Get Dotloop document metadata.
Inputs: loop_id (required), profile_id (required), document_id (required), folder_id. Returns: result
dotloop_get_folderC
Get one Dotloop loop folder.
Inputs: loop_id (required), folder_id (required), profile_id (required), include_archived, +1 more. Returns: result
dotloop_get_loopC
Get one Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_loop_detailsC
Get details for one Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_loop_templateC
Get one Dotloop loop template.
Inputs: profile_id (required), template_id (required). Returns: result
dotloop_get_participantC
Get one Dotloop loop participant.
Inputs: loop_id (required), profile_id (required), participant_id (required). Returns: result
dotloop_get_pending_tasksC
Get pending tasks in a Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_profileC
Get one Dotloop profile by ID.
Inputs: profile_id (required). Returns: result
dotloop_get_recent_activityC
Get recent Dotloop loop activity.
Inputs: loop_id (required), profile_id (required), limit. Returns: result
dotloop_get_taskC
Get one Dotloop task.
Inputs: loop_id (required), task_id (required), profile_id (required), tasklist_id (required). Returns: result
dotloop_get_task_listC
Get one Dotloop task list.
Inputs: loop_id (required), profile_id (required), tasklist_id (required). Returns: result
dotloop_get_task_summaryC
Get task summary for a Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_get_templates_by_typeC
Get Dotloop templates by type.
Inputs: profile_id (required), template_type (required). Returns: result
dotloop_get_template_summaryC
Get Dotloop template summary for a profile.
Inputs: profile_id (required). Returns: result
dotloop_list_documentsC
List Dotloop loop documents.
Inputs: loop_id (required), profile_id (required), folder_id. Returns: result
dotloop_list_foldersC
List folders for a Dotloop loop.
Inputs: loop_id (required), profile_id (required), include_archived, include_documents. Returns: result
dotloop_list_loop_activityC
List Dotloop loop activity.
Inputs: loop_id (required), profile_id (required), batch_size, batch_number. Returns: result
dotloop_list_loopsC
List loops for a Dotloop profile.
Inputs: profile_id (required), sort, batch_size, batch_number, +1 more. Returns: result
dotloop_list_loop_templatesC
List Dotloop loop templates.
Inputs: profile_id (required). Returns: result
dotloop_list_participantsC
List Dotloop loop participants.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_list_profilesC
List Dotloop profiles.
Inputs: no named parameters. Returns: result
dotloop_list_task_listsC
List task lists for a Dotloop loop.
Inputs: loop_id (required), profile_id (required). Returns: result
dotloop_list_tasksC
List Dotloop tasks in a task list.
Inputs: loop_id (required), profile_id (required), tasklist_id (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 33 tools
Most tools have distinct purposes with clear verb_noun patterns, but pairs like get_loop and get_loop_details or multiple activity tools could confuse an agent without careful reading.
All tools consistently follow the dotloop_verb_noun pattern in snake_case, with verbs like get, list, find, download; no mixing of conventions.
With 33 tools, the set is slightly over-scoped for a single server, though many are read-only retrievals; borderline heavy but can be justified by the domain's complexity.
The tools are heavily focused on retrieval (get/list) with only a download and a find operation; missing essential write operations like create, update, or delete for loops, documents, and other resources, limiting agent capabilities.
Maintenance
Related MCP Connectors
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Read-only MCP server for interior design studios: projects, overviews, weekly activity. No writes.
Read-only CRE prospects, listings, campaigns, reporting, broker search, and resources.
Read-only MCP server for The Quiet Protocol's engines, benchmarks, proof, and business data.
Related MCP Servers
- AlicenseAqualityCmaintenanceRead-only MCP server for Akamai CDN that enables searching properties, browsing EdgeWorker code, querying DNS zones, inspecting network lists, and translating error codes via natural language.16334 PyPI1MIT
- FlicenseNot gradedqualityCmaintenanceRead-only MCP server exposing homelab data sources (files, mail, calls) to Cloudflare OS, enabling read-only access to documents, emails, and call records.-
- AlicenseNot gradedqualityBmaintenanceRead-only MCP server for ClickUp that enables querying workspace hierarchy, task trees, activity history, comments, and time entries without any write capabilities.1MIT
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server that enables access to Ultrahuman health data, including daily summaries, sleep, recovery, activity, glucose, and time-series metrics via the Partner API.8 npmMIT