Announcing CIMD support for MCP Client registration
Learn more

Should you use Loops MCP or Loops API for building AI Agents?

TL;DR

  • The Loops MCP server exposes 20 tools covering tasks, loops, the priority queue, and workflow guidance. The REST API covers nearly the same ground and adds five capability areas the tool list does not expose: project notes, workspace members, task comments, loop assignment, and explicit claim and release endpoints.
  • Two tools have no documented REST equivalent: get_queue_stats and get_workflow. The MCP path also ships slash-command prompts (/loops, /implement, /review-tasks) that the REST path cannot replicate.
  • Both paths terminate in the same credential. The remote MCP server runs a browser OAuth flow and then creates a workspace-scoped API token behind the scenes; the REST path uses that same token type directly. The blast radius is identical.
  • Atomic work claiming is the deciding factor for fleets. Loops documents ?claim=true on the REST next-work endpoint, which returns a 409 when another worker got there first. Without it, two agents pick up the same loop.
  • Neither path gives you a vault, rotation, or revocation. Scalekit's Loops MCP connector resolves the per-user credential at call time and logs every downstream tool call against the identity that authorized it.

Your agent needs to pull work from Loops. Loops ships a remote Model Context Protocol (MCP) server at one URL and a REST API at another, and unlike most tools in this series, the two surfaces are close to the same size. That makes the decision harder, not easier: there is no obvious "MCP is the small subset" heuristic to fall back on. The gap is narrow, specific, and lands exactly where autonomous workers break. Here is where it sits.

What Loops MCP and the Loops API actually are

Loops is a work queue for coding agents. Humans plan and prioritize; agents call for the top item, build it, and mark it shipped. Both integration paths expose that same object model of workspaces, loops, tasks, and a priority queue.

The Loops MCP server

The remote server lives at mcp.useloops.io and is added over HTTP transport in one command. Authorization runs in the browser: you log in to Loops, pick a workspace, and approve. Scalekit classifies the connector as OAuth 2.1 with Dynamic Client Registration (DCR).

A local server invoked through npx loops-mcp-server with a LOOPS_API_TOKEN environment variable appears in the configuration examples, but Loops marks the local setup as coming soon. Treat remote as the only shipping transport today.

Official reference: Loops MCP server setup.

The Loops REST API

The REST API is rooted at useloops.io/api/v1 and authenticates with Authorization: Bearer YOUR_API_TOKEN. Tokens are created in Loops under Settings, then API Tokens, and each one is scoped to exactly one workspace.

The surface covers identity discovery, workspace details, tasks, loops, the queue, project notes, members, and comments. There are no LLM-specific affordances: schemas, retries, and error mapping are yours.

Official reference: Loops API reference and the machine-readable API documentation, which lists several endpoints the main reference tab does not.

Why the two surfaces are unusually close

Most MCP servers in this category wrap a fraction of a large API. Loops is different. The product was built for agents first, so the MCP server is a near-complete projection of the REST surface rather than a curated slice of it.

That changes the shape of the decision. You are not choosing between coverage and convenience. You are choosing between a guided, prompt-driven surface and a slightly wider, fully explicit one.

Comparing them where it matters for agents

Four dimensions decide this for a production agent: what it can call, what credential it holds, what you own when something breaks, and whether more than one worker can run at a time.

What your agent can actually do

The MCP tool list and the REST endpoint list overlap heavily. The differences are concentrated in coordination and memory.

Capability
Loops MCP
Loops REST API
Read the priority queue
Yes, loopsmcp_get_loop_queue
Yes, GET /workspaces/{id}/queue
Pick up the next loop
Yes, loopsmcp_get_next_work
Yes, GET /workspaces/{id}/next-work
Atomically claim a loop
Verify the live tool schema
Yes, ?claim=true and POST /loops/{id}/claim
Create, update, delete tasks
Yes
Yes
Bulk update tasks
Yes, loopsmcp_bulk_update_tasks
Yes, POST /workspaces/{id}/tasks/bulk-update
Reorder and prioritize loops
Yes, loopsmcp_reorder_loops
Yes, POST /workspaces/{id}/queue/reorder
Close, reopen, ship a loop
Yes
Yes
Queue statistics
Yes, loopsmcp_get_queue_stats
Not in the published reference
Workflow guidance
Yes, loopsmcp_get_workflow
No
Read and write project notes
No
Yes, /workspaces/{id}/notes
Comment on a task
No
Yes, POST /workspaces/{id}/tasks/{taskId}/comments
List members and assign a loop
No
Yes, /members and PATCH /loops/{id}/assign

Where the gap actually bites

Project notes are the workspace's long-term memory. Loops documents five categories: note, decision, structure, change, and limitation. An agent that reads notes before working and writes a change note after shipping makes the next session smarter. That read-write cycle is REST-only.

Task comments and loop assignment are the escalation path. When an agent is blocked, the documented pattern is to comment on the task, put the loop on hold, and assign it to a human found through the members endpoint. All three calls sit outside the MCP tool list.

The state transition that trips agents up

Shipping is not a single action. The REST reference states that a loop must be on hold before it can be shipped, and that shipping is final and irreversible. So the sequence is close, then ship, on either path.

The MCP tool description for loopsmcp_ship_loop does not mention the precondition. The state machine is a property of the resource, not the transport, so an agent that calls ship directly fails the same way on both paths. Encode the two-step sequence in your prompt or your pipeline rather than hoping the model infers it.

The auth path each one puts you on

The remote MCP path runs browser OAuth with workspace selection at consent time. The REST path uses a static bearer token you generate yourself. Those look like different security postures. They are not.

Loops states plainly that the OAuth flow creates a scoped API token behind the scenes. The MCP server is a delivery mechanism for the same workspace-scoped credential the REST path uses directly.

One workspace, one token, one blast radius

Loops does not document a scope model on either path. Consent selects a workspace, not a permission set. A token that can read the queue can also delete a task, reorder priorities, and ship a loop irreversibly.

That has a direct consequence. Least privilege cannot come from the token, because the token has no scopes to narrow. It has to come from the tool layer: decide which of the 20 tools a given agent role is allowed to see, and enforce it before the model ever gets a tool list. This is a pattern explored in depth in access control for multi-tenant AI agents.

What you own in production

On the MCP path, Loops owns the tool schemas, the workspace resolution, and the prompt definitions. You own the connected account: storage, refresh where applicable, revocation, and knowing which workspace each account maps to.

On the REST path you own all of that plus the schema layer. You write the tool contracts, map the documented error codes (401 for an invalid token, 403 for permission, 404 for a missing resource, 409 for a claim conflict), and handle pagination and retries yourself.

The unknown you should plan around

Loops does not publish rate limits for either path. That is not a reason to avoid the API; it is a reason to instrument your own call volume and design for throttling rather than assuming headroom.

There is also no documented programmatic revoke endpoint. Token lifecycle is a dashboard action in Loops, which means offboarding has to be driven from your side of the boundary, not theirs.

The claim race that decides whether you can run a fleet

This is the single most consequential difference. Loops documents ?claim=true on the REST next-work endpoint: it assigns the loop and moves it to in progress in one atomic step, returning 409 if another worker claimed it first.

Loops describes the same behavior as get_next_work(claim=true) on the MCP path. Tool schemas published in any connector catalog are point-in-time snapshots, so call list_scoped_tools and read the live input schema before you build multi-worker coordination on it. If claim is not in the schema you actually receive, two cron workers will pick up the same loop and implement it twice.

When to use Loops MCP

The MCP path is the right default when a human is present and the prompts do real work for you.

  • You are running a coding agent interactively: Claude Code, Cursor, Windsurf, or Codex, where /implement and /review-tasks carry the workflow logic
  • You want Loops' own guidance surface (loopsmcp_get_workflow) instead of writing triage and organize prompts yourself
  • You are prototyping the queue-to-shipped cycle and want tool schemas without writing contracts
  • You are exposing Loops alongside other tools in one agent and want a single protocol across all of them

When to use the Loops REST API

The REST path is the right default when the agent runs without a human watching.

  • You are running unattended workers on a schedule and need ?claim=true so two workers never grab the same loop
  • Your agent needs to read and write project notes as long-term memory across sessions
  • Your agent must escalate: comment on a blocked task, assign the loop to a named human, and wait
  • You are driving Loops from a deterministic pipeline where explicit endpoints and explicit error codes beat model-mediated tool selection
  • You need task fields the tool list does not expose, such as estimated_minutes and assignee_id

The credential problem that exists on both paths

Both paths hand you a bearer token scoped to one Loops workspace. Neither hands you a vault, a rotation policy, or a revocation flow. That infrastructure is yours to build regardless of which path you picked. For a deeper look at why this matters at scale, see secure token management for AI agents.

The N-workspace problem

Loops tokens are workspace-scoped by design, and the MCP server auto-resolves the workspace from the token. One connected account equals one workspace. An agency running Loops across 12 client projects holds 12 credentials, each with full write access to its workspace.

Plan limits compound this. Loops allows one agent per workspace on the free tier, three on Maker, and unlimited on Agentic, so a growing fleet multiplies both credentials and billing surface at the same time.

Attribution collapses under a shared token

Loops models agents as first-class workspace members, with an is_agent flag distinguishing them from humans. Comments, status changes, and claimed loops are attributed to whoever the token represents.

Share one token across your fleet and that model collapses. Every comment, every shipped task, and every claim shows the same actor. When a task ships that should not have, the Loops audit trail tells you a token did it. It cannot tell you which agent run, triggered by which user, made the call. This is exactly the attribution gap covered in audit trails for agent auth in B2B SaaS.

Where Scalekit fits

Scalekit's Loops MCP connector stores each user's Loops credential in a per-tenant vault and resolves it at call time, so credentials never enter the agent runtime or the model context. The same connected-account model works whether you call tools through MCP or proxy the REST API, which means the path decision does not change your auth architecture.

Related reading: access control for multi-tenant AI agents and the token vault behind execute_tool.

Connecting an agent to Loops with Scalekit

The connector is loopsmcp, and its tools are prefixed accordingly: loopsmcp_get_next_work, loopsmcp_update_task, loopsmcp_ship_loop. Configure the connection once in the dashboard, then authorize each user against it.

Configure the connection and authorize a user

The connection_name string in your code must match the connection name configured in the Scalekit dashboard exactly. This is the most common integration error and it fails silently at authorization time.

pip install scalekit-sdk-python langchain-openai
import os from scalekit import ScalekitClient scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) actions = scalekit_client.actions CONNECTION = "loopsmcp" # must match the dashboard connection name IDENTIFIER = "user_123" # your app's stable identifier for this user account = actions.get_or_create_connected_account( connection_name=CONNECTION, identifier=IDENTIFIER, ) if account.connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name=CONNECTION, identifier=IDENTIFIER, ) print("Authorize Loops:", link.link) input("Press Enter after authorizing...")

Retrieve the tools this user is authorized to call

Before the agent sees a tool list, it is worth being precise about what that list is. The agent is not loading a flat catalog of every Loops tool in the connector. It is loading the tools this user's connected account is authorized to call, resolved against their Loops workspace. That distinction is what separates a per-user agent from a shared-credential agent.

from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, ToolMessage tools = actions.langchain.get_tools( identifier=IDENTIFIER, connection_names=[CONNECTION], page_size=100, # Loops exposes 20 tools; avoid truncation on the default page ) tool_map = {t.name: t for t in tools}

Run the agent loop in Python

The queue-to-shipped cycle is a fixed sequence, so the prompt states it rather than leaving the model to discover it.

llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [HumanMessage( "Get the next loop from my Loops queue. For each approved task, " "set its status to in_progress, summarise what needs building, " "then set it to shipped. Do not close or ship the loop itself." )] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: result = tool_map[tc["name"]].invoke(tc["args"]) messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

Run the same agent in TypeScript with the Claude SDK

The Node SDK returns tool definitions in Anthropic's native input_schema format, so no conversion step is needed. executeTool returns both the tool result and an execution ID you can correlate with your own traces.

npm install @scalekit-sdk/node @anthropic-ai/sdk
import { ScalekitClient } from '@scalekit-sdk/node'; import Anthropic from '@anthropic-ai/sdk'; const scalekit = new ScalekitClient( process.env.SCALEKIT_ENVIRONMENT_URL!, process.env.SCALEKIT_CLIENT_ID!, process.env.SCALEKIT_CLIENT_SECRET!, ); const anthropic = new Anthropic(); const CONNECTION = 'loopsmcp'; // must match the dashboard connection name const IDENTIFIER = 'user_123'; const { tools } = await scalekit.tools.listScopedTools(IDENTIFIER, { filter: { connectionNames: [CONNECTION] }, pageSize: 100, }); const llmTools = tools.map(t => ({ name: t.tool.definition.name, description: t.tool.definition.description, input_schema: t.tool.definition.input_schema, }));

Complete the tool-use loop

The loop checks stop_reason, executes each tool block through Scalekit, and appends the results before the next turn.

const messages: Anthropic.MessageParam[] = [ { role: 'user', content: 'Show me the Loops queue statistics, then read the top loop and list ' + 'its approved tasks with their agent prompts. Do not change any status.', }, ]; while (true) { const response = await anthropic.messages.create({ model: 'claude-sonnet-4-6', max_tokens: 1024, tools: llmTools, messages, }); if (response.stop_reason === 'end_turn') { const text = response.content.find(b => b.type === 'text'); if (text?.type === 'text') console.log(text.text); break; } const toolResults: Anthropic.ToolResultBlockParam[] = []; for (const block of response.content) { if (block.type === 'tool_use') { const result = await scalekit.actions.executeTool({ toolName: block.name, identifier: IDENTIFIER, toolInput: block.input as Record, }); console.log('execution:', result.executionId, block.name); toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: JSON.stringify(result.data), }); } } messages.push({ role: 'assistant', content: response.content }); messages.push({ role: 'user', content: toolResults }); }

Taking the REST path through a custom connector

Scalekit's catalog ships the Loops MCP connector. If your agent needs the REST-only surface — notes, comments, member lookup, loop assignment, and ?claim=true — register the REST API as a custom connector so it inherits the same vault and connected-account model.

{ "display_name": "Loops REST", "description": "Connect to the Loops REST API for tasks, loops, notes, and the work queue", "auth_patterns": [ { "type": "BEARER", "display_name": "Loops API Token", "description": "Authenticate with a workspace-scoped Loops API token", "fields": [ { "field_name": "token", "label": "Loops API Token", "input_type": "password", "hint": "Create one in Loops under Settings, then API Tokens", "required": true } ] } ], "proxy_url": "https://useloops.io/api/v1", "proxy_enabled": true }

Claim work atomically through the proxy

With the connector in place, actions.request proxies any Loops endpoint and injects the user's credential server-side. The 409 branch is not an edge case; it is the normal outcome when a second worker reaches the queue first.

def loops_claim_next_work(identifier: str, workspace_id: str): response = actions.request( connection_name="loops-rest", # must match the dashboard connection name identifier=identifier, method="GET", path=f"/workspaces/{workspace_id}/next-work", query_params={"claim": "true"}, ) if response.status_code == 409: return {"claimed": False, "reason": "another worker claimed this loop"} if response.status_code == 404: return {"claimed": False, "reason": "no work available"} response.raise_for_status() return {"claimed": True, "work": response.json()}

Virtual MCP servers for multi-tool, multi-tenant Loops agents

A Loops agent is rarely a Loops-only agent. It reads the queue, then reads the repository, then posts a summary. Virtual MCP Servers give you one endpoint per agent role across all of those connectors, scoped to exactly the tools that role needs.

Scoping the tool surface per agent role

An implementing agent needs loopsmcp_get_next_work, loopsmcp_update_task, and loopsmcp_get_loop. It does not need loopsmcp_delete_task, loopsmcp_reorder_loops, or loopsmcp_ship_loop. Since the Loops token carries no scopes, the tool mapping is where that boundary gets enforced.

The cost argument is secondary but real. Using the roughly 200 tokens per tool figure in Scalekit's Virtual MCP documentation, a full 20-tool Loops surface spends about 4,000 tokens of context before the agent does any work. This is the tradeoff discussed in MCP is up to 32× more expensive than CLI.

from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = scalekit_client.actions.mcp.create_config( name="loops-implementing-agent", description="Read-and-implement surface for coding agents", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="loopsmcp", tools=[ "loopsmcp_get_next_work", "loopsmcp_get_loop", "loopsmcp_get_task", "loopsmcp_update_task", ], ), McpConfigConnectionToolMapping( connection_name="github", tools=["github_pull_request_create"], ), ], ) config_id = vmcp.config.id mcp_server_url = vmcp.config.mcp_server_url

Session tokens instead of shared URLs

Create the server once per agent role, not once per user. At runtime, confirm the user's connections are active, then mint a short-lived token bound to that user. The default expiry is about an hour, and create_session_token is also the remint call; there is no refresh endpoint and a token cannot be extended in place.

from datetime import timedelta state = scalekit_client.actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier="user_123", include_auth_link=True, ) for account in state.connected_accounts: if account.connected_account_status != "ACTIVE": raise RuntimeError(f"{account.connection_name}: {account.authentication_link}") session = scalekit_client.actions.mcp.create_session_token( mcp_config_id=config_id, identifier="user_123", expiry=timedelta(minutes=30), ) mcp_server = { "url": mcp_server_url, "headers": {"Authorization": f"Bearer {session.token}"}, }

What the audit trail gives you

Every tool call through Scalekit returns an execution ID and is recorded against the connected account that authorized it. For a Loops agent that ships loops irreversibly, that is the difference between knowing a loop shipped and knowing which user's authorization shipped it.

That record is also what an enterprise security review asks for. More on the structure of those events in agent tool observability and audit trails for agent auth.

Where this pattern shows up

Loops sits upstream of the agents that do the work, so it composes naturally with delivery-side templates: the engineering standup agent, the DevOps assistant agent, and the auto release notes agent.

Which one to build against

If a developer is sitting in Claude Code or Cursor and the value is in the guided workflow, build against the MCP server. The prompts and loopsmcp_get_workflow do work you would otherwise write and maintain yourself.

If the agent runs unattended, needs project notes as memory, or has to escalate blocked work to a named human, build against the REST API. Atomic claiming in particular is not optional once you run more than one worker.

Most production setups end up using both, which is exactly why the credential layer should not care which one you picked. That is the part worth building on infrastructure rather than in your application.

Build Loops agents with Scalekit

Start with the Loops MCP connector documentation or the Loops MCP connector page.

Building agents on top of Loops and hitting the multi-worker or multi-workspace wall? Join the Scalekit Slack community, or talk to us for help wiring it up.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.