Skip to content

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

Oct 2026
Published on GitHub (single commit, October 12)
6
Tools: 4 read and 2 write
18
Test cases across 3 test files
MIT
License

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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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

Published October 2026

Keep reading

More Case Studies

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.