AI integration / Open sourcesaas-mcp-connector: a safe MCP server for a SaaS API
An MCP server that lets Claude Desktop, Claude Code and other MCP clients use a SaaS product's API safely. Every call is scoped to one user's workspace, writes need explicit confirmation, and the HTTP transport is rate limited.
Our role: Open source, written by App369 founder Simon Dziak and released under the MIT license. It is a reference build that runs against an in-memory fake SaaS, not a client project and not a production deployment.
The problem
What saas-mcp-connector Needed to Solve
Customers are starting to ask whether a product works with their AI assistant. The easy way to build that is to expose the API as tools and hope the model behaves. The harder questions are the ones this build answers. Can a tool reach another customer's data? Can the model change something without asking? What happens when a client floods the server with requests, or when the upstream API fails with a message that should not reach the model?
The build
How We Built It
A TypeScript server on the official MCP SDK. Each token is resolved to an API client that is already bound to one workspace, and no tool takes a workspace argument, so cross-workspace access cannot be expressed. Write tools do nothing without confirm: true, and READ_ONLY=true blocks them completely. The same server runs over stdio for Claude Code and Claude Desktop, or over stateless Streamable HTTP with bearer-token auth and a per-token rate limit. The API client is an interface, so swapping the fake SaaS for a real REST API does not change the server.
Features
What the Product Does
Six tools
list_projects, list_tasks (with filters and cursor pagination), get_task and search are read tools. create_task and update_task_status are write tools.
Per-user scoping
The token chooses the workspace. Tests cover reads, search, listing and writes across workspaces.
Read-only mode
READ_ONLY=true makes every write tool return an error, even with confirm: true.
Explicit confirmation
A write without confirm: true does nothing and tells the model to ask the user first.
Rate limiting
A token bucket per token on the HTTP transport. Over the limit, the server returns 429 with Retry-After. Buckets are keyed by a hash of the token.
Safe errors
Known failures come back as MCP tool errors with a readable message. Unexpected exceptions are logged to stderr and returned as a generic message, with no stack traces or upstream details.
Architecture
The Stack, Layer by Layer
- Server
- Node 22 or newer, TypeScript, the official @modelcontextprotocol/sdk and zod for input validation. Read tools carry readOnlyHint so clients can treat them differently.
- API layer
- An ApiClient interface in src/api.ts, an in-memory multi-workspace fake in src/fake-saas.ts, and a client factory that maps a token to a client.
- Transports
- stdio, and Streamable HTTP built fresh per request from the caller's token, so no session state can leak between users.
- Tests
- vitest suites that run offline: server logic, the HTTP transport and a stdio smoke test.
By the numbers
Verifiable Facts
Counted from the public GitHub repository on October 13, 2026. This page makes no claims about stars, adoption or production use.
Lessons
What We Learned Shipping It
Make the unsafe call impossible to write
The server does not check that a tool is allowed to name a workspace. No tool has the argument at all. Removing the option is easier to test than policing it.
Gate writes twice
Confirmation protects against a model that acts too fast. Read-only mode protects against a deployment that should never write. They answer different questions, so both exist.
Stay stateless on HTTP
Building a fresh server per request from the caller's token means there is no session to leak, and the process can be restarted or scaled without a sticky session.
Keep the API as the authority
The README says your own API must still enforce authorization. This layer is defense in depth, not the only lock.
Say what is not built
OAuth sign-in is described in the README as an optional extension and is not implemented. A short list of what is missing is more useful to the next reader than a long list of claims.
Technologies Used
- TypeScript
- Node.js
- MCP
- zod
- vitest
- Claude
Timeline
Keep reading
More Case Studies
SaaS / Business software
Workspace369: a Flutter and Firebase SaaS for client work
An all-in-one workspace for freelancers and small service businesses: CRM, proposals, invoicing and payments, scheduling, a shared email/SMS/voice inbox, accounting and AI, in one Flutter app on iOS and the web.
Field service software / Contractor CRM
QuoteIQ: a contractor CRM in Flutter, Nuxt and Firebase
A CRM for home service contractors: quotes, scheduling, invoices and payments, customer messaging and AI automations, on iOS, Android and the web. On the App Store since September 2022, with 3,400+ ratings and a 4.7 average.
Consumer / Music
3693: a private music app in Flutter and Firebase
A private music app built with Flutter: search, a now-playing screen with lyrics, a queue, playlists, liked songs, a cloud library, listening stats and light and dark themes, on a typed Firebase backend.
Want something similar at a fixed price?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- Web App MVP Sprintfrom $6,000A scoped web app MVP in Vue/Nuxt or React, with a fixed quote after a $450 written scoping.
- App Fix Ticketfrom $450One reproducible bug in an existing mobile or web app, diagnosed and fixed.
- Monthly Dev Subscriptionfrom $1,495/monthOne development request at a time, most back in about 2 business days. Pause or cancel anytime.
Start here
Planning Something Similar?
We build Flutter and Firebase apps for startups and small businesses. Get a ballpark with our app cost calculator, see Flutter development, or tell us about your project.