
Your agent needs to answer a marketing lead's Monday question: what did we spend across Meta, Google, and TikTok last week, and which campaigns pushed CPA up? Windsor.ai already normalizes that data from 350+ sources. It ships a hosted Model Context Protocol (MCP) server and a REST Connectors API over the same backend, and write actions on both run through the same endpoint. So Windsor.ai MCP vs Windsor.ai API looks like a cosmetic choice.
It is not. The two paths accept different credentials, expose different capabilities at the edges, and fail differently once your agent serves more than one customer. Here's how to pick.
Both paths sit on the same Windsor.ai account model: a team that owns connected data source accounts. What differs is the interface and the credential each one accepts.
Windsor.ai's MCP server is remote and maintained by Windsor.ai. It was introduced in 2025 and is listed in the Claude connector directory and as a ChatGPT app. It speaks Streamable HTTP and SSE, so there is nothing to run locally, and Windsor states it is included on every plan.
The surface is 18 tools. Reads follow a strict discovery chain: get_connectors, then get_options and get_fields, then get_data. Field IDs passed to get_data must come from get_fields, and the tool descriptions tell the model not to guess them. Writes go through list_actions and execute_action.
The canonical tool reference is Windsor.ai's official MCP server documentation, served from the MCP host itself.
The Connectors API is a REST interface over the same connectors. A read is a GET /{connector} request with a comma-separated fields list and optional date_preset, date_from, date_to, filter, and select_accounts. A separate /{connector}/actions endpoint lists and executes write actions, and account endpoints generate co-user authorization links and manage linked accounts.
Authentication is a Windsor.ai API key in the api_key query parameter. Windsor's changelog entry of September 11, 2026 made this explicit: X-Api-Key and Authorization: Bearer headers are not supported on these endpoints and return a not-authorized error. The full reference is Windsor.ai's official API documentation.
Four dimensions decide this for Windsor.ai: what each path can do, which credential it accepts, where tenant isolation actually lives, and what breaks in production.
The read and write cores are at parity because both paths hit the same backend. The gaps sit at the edges.
Most MCP vs API comparisons end with the API as a strict superset. Windsor.ai is different. The MCP server exposes scheduled destination exports and custom field creation that the public Connectors API documentation does not describe, so a conversational agent can set up a daily BigQuery export or define a CPA formula field without a dashboard detour.
The API keeps the pipeline-shaped features: _renderer=csv for bulk handoff, _max_rows for bounded responses, and refresh_since with refresh_interval to force re-fetches of the last three days. The refresh floor is plan-dependent: one hour on Standard and Plus, 15 minutes on Professional and Enterprise.
Windsor.ai's write-action catalog lists 137 actions across 19 connectors as of September 2026, spanning Google Ads, Meta Ads, LinkedIn Ads, TikTok Ads, Microsoft Ads, Amazon, Stripe, Google Business Profile, and WordPress. The count moves fast; Windsor's MCP reference and its catalog page already disagree on how many connectors support writes. Treat list_actions as the runtime source of truth and never hardcode action IDs in prompts.
Writes must be enabled in Windsor's Team management settings, and the actions endpoint that also backs MCP writes returns 403 until they are. The toggle is team-wide, so treat tool-level scoping in your agent as the real per-role control.
Defaults differ by action. Campaign, ad group, and ad creation on Google Ads and Meta Ads starts paused, and LinkedIn creatives start as drafts. Instagram posts and Google Business Profile updates publish immediately. Put the approval gate in your code, not in the platform defaults.
Recommended reading: Human-in-the-Loop Tool Calling: Approval Gates for AI Agents
The MCP server implements the MCP authorization flow through a FastMCP OAuth proxy in front of Windsor.ai's own authorize and token endpoints. Its discovery metadata advertises PKCE with S256 (RFC 7636), Dynamic Client Registration (DCR, RFC 7591), Client ID Metadata Documents (CIMD), the offline_access scope, and exactly two grant types: authorization_code and refresh_token (RFC 6749).
That last detail defines the headless story. There is no client_credentials grant. A scheduled agent runs unattended only after a user has consented once and a refresh token exists. The alternative is an API key sent as a bearer header, which Windsor's MCP server accepts, but that key represents a Windsor.ai account, not an end user.
The Connectors API accepts api_key only as a query parameter. For an agent, that is a structural problem, not a style preference. Every request URL carries a secret that reads every data source in the Windsor team. HTTP client instrumentation, reverse proxies, APM traces, and error trackers commonly record full URLs, so the key spreads to every system that observes your agent's traffic. Windsor's own guidance is to rotate the key periodically if URL exposure is a concern.
There is also no end-user identity on this path. When one key serves many of your users, every call looks identical to Windsor, and your audit trail cannot say which user triggered which query.
Windsor.ai's isolation boundary is the Windsor team. A token or API key reads every account connected to that team, and a query without an account filter returns all of them.
If each of your customers has their own Windsor.ai account, per-user OAuth on the MCP path maps cleanly: one connected account per user, one team per customer. In an agency model, clients connect ad accounts into your team through co-user links, so one credential reaches every client. Isolation then depends on the account filter your code passes, and the Connectors API documents that unknown account IDs are ignored without error when at least one ID matches. A stale mapping degrades silently.
Recommended reading: How Tool Calling Auth Changes When You Move from Single-Tenant to Multi-Tenant
Windsor maintains the server, the tool schemas, and the connector catalog behind them. You own token storage, refresh, and revocation per user, plus three Windsor-specific behaviors.
First, response size. get_data fails with a size-limit error on broad queries, so the agent must narrow the date range, fields, or accounts and retry. Second, tool definitions are heavy: the get_connectors description alone enumerates all 357 supported connector slugs, and every exposed tool loads into context on every run. Third, upstream limits surface as tool errors. Meta allows four budget changes per ad set per hour, and Instagram accounts connected before comment access shipped must reconnect before commenting works.
Everything above, plus request construction, URL-encoding of the JSON filter parameter, bounding responses with _max_rows, retries, and schema drift. Windsor evolves this API through a dated changelog rather than versioned paths, so behavior changes like the September 2026 auth clarification land without a version bump.
Rate limits are explicit: 600 requests per minute and 10,000 per day, with a 429 on breach. An LLM-driven agent that follows the discovery chain spends four calls per question: connectors, options, fields, then data. At that rate, 10,000 daily requests cover roughly 2,500 agent questions across every user sharing the key.
These are Windsor.ai workloads where the MCP path is the better fit.
These are Windsor.ai workloads where the REST path is the better fit.
Neither path gives you a vault, a refresh scheduler, or a revocation flow. The token type differs; the infrastructure you need does not.
A B2B reporting agent serving 60 customer teams, each with its own Windsor.ai account, holds at least 60 credentials: refresh tokens on the MCP path, API keys on the REST path. Each needs encryption at rest, isolation per tenant, proactive refresh, and a revocation path when a customer disconnects or an employee leaves.
The failure is quiet. A revoked refresh token does not crash a scheduled digest. It produces an auth error inside a tool result, which the model may summarize as "no spend data this week" unless your code checks connected account status before the run starts. This is exactly why secure token management for AI agents at scale matters far more than the choice of interface.
The Scalekit Windsor.ai MCP connector (windsoraimcp) runs the OAuth 2.1 flow with Dynamic Client Registration against Windsor's server, stores each user's tokens in an encrypted vault, and refreshes them. Credentials never touch the agent runtime or the model context.
Scalekit ships Windsor.ai as a vendor MCP connector; there is no separate Windsor REST connector in the AgentKit connector catalog. If your workload depends on REST-only features like co-user link management, that path runs on a team key you hold. Either way, the MCP vs API decision should not change your auth infrastructure.
The build below uses Python and LangChain. It covers the three shapes a Windsor.ai agent usually takes: an interactive analyst, a deterministic pipeline, and a multi-tool agent behind a Virtual MCP server.
Create a Windsor.ai MCP connection in the Scalekit dashboard under AgentKit > Connections. The connection_name in your code must match the connection name configured in the dashboard exactly; a mismatch is the most common integration error. Each user also needs at least one data source connected inside Windsor.ai itself.
get_or_create_connected_account is idempotent. The first call creates the per-user record, and later calls return it with its current status. The user signs in to Windsor.ai once; Scalekit refreshes the token from then on.
The agent does not load the Windsor.ai connector catalog. actions.langchain.get_tools wraps list_scoped_tools: it returns only the tools this user's connected account is authorized to call, narrowed further to the tool names you pass. A reporting agent gets five read tools, not 18. Write and export tools never enter context, so they leave the model's decision space and stop costing tokens on every run.
get_tools returns native LangChain StructuredTool objects, so they bind directly to the model. Write tools pass through an approval gate in run_tool_call. With the read-only list above the gate never fires, and the same loop serves an optimizer role once you add windsoraimcp_list_actions and windsoraimcp_execute_action. For a deeper look at how LangChain tool calling works and where it stops, the pattern here maps directly to production agent design.
A weekly spend digest does not need a model to pick tools. Call execute_tool directly with fields you validated once through windsoraimcp_get_fields. The guard matters: without an explicit accounts list, Windsor returns every account in the team, which in an agency setup means every client.
When the agent spans Windsor.ai and Slack, or serves many tenants from one definition, move the scoping into a Virtual MCP server. You create it once per agent role, choose the exact tools from each connection, and get a static mcp_server_url. There is no MCP server to deploy, host, or maintain. The digest role below can read Windsor.ai data and post one Slack message; it cannot touch a budget.
Recommended reading: What Is a Virtual MCP Server? Scoped Tools and Per-User Auth
Before each run, confirm every connection on the server is still active for this user, then mint a short-lived session token bound to that user's connected accounts. One server definition serves every tenant. The identity changes per run; the endpoint never does. There is no refresh call, so when a token expires you mint a new one.
langchain-mcp-adapters connects over Streamable HTTP with the session token as bearer auth. The loop has the same shape as the direct-tools version, now async.
Every Windsor.ai tool call that runs through Scalekit lands in the AgentKit tool call log with its timestamp, connection, tool name, user identifier, and latency. The error breakdown separates connector errors, where Windsor or the upstream ad platform rejected the call, from API errors rejected before the call left Scalekit, such as an expired token or invalid parameters.
Logs are queryable, retained for 90 days by default, and exportable to Datadog, Splunk, or any SIEM. When an agent can change ad spend, that per-user record is the evidence a customer's security review asks for first. Understanding whether your agent is actually working depends on exactly this kind of observability infrastructure.
Recommended reading: Agent Tool Observability: Is Your Agent Actually Working?
If your agent answers questions in chat, acts for users who each own a Windsor.ai account, or sets up exports and custom fields conversationally, build on Windsor.ai MCP. If you run a fixed-schema pipeline that wants CSV, bounded rows, or forced refreshes, or you manage client onboarding through co-user links, the Connectors API is the right tool, with its team key treated as a production secret.
Many teams will run both: MCP for the analyst, REST for the warehouse sync. The credential lifecycle and tenant isolation problems are identical either way, and that is the part that needs production-grade infrastructure. Teams working through the auth patterns and anti-patterns for tool-calling agents will recognize this as the same problem that surfaces across every third-party integration.
Building a Windsor.ai agent for multi-tenant customers and need help with scoping, write-action approvals, or per-user auth? Talk to us for immediate help from the Scalekit team.
Start from the Windsor.ai MCP connector docs and the Windsor.ai connector page, then adapt a GTM and RevOps agent template such as the revenue forecast commentary agent. Check AgentKit pricing when you are ready for production.