Blog
"Your SaaS is already an MCP server"
"Postiba ships a production-grade Model Context Protocol endpoint from day zero. OAuth-authenticated, subscription-aware, audited. Claude.app connects out of the box."
Blog
"Postiba ships a production-grade Model Context Protocol endpoint from day zero. OAuth-authenticated, subscription-aware, audited. Claude.app connects out of the box."
The Model Context Protocol problem we hear most often: "great spec, but how do I plug it into my SaaS without rewriting the auth?"
The answer for Postiba forks: you don't. The OAuth/OIDC server that
already powers your dashboard is the same server that authenticates
MCP calls. The same per-user role, the same multi-tenant isolation,
the same audit pipeline. Three weeks of integration work compressed
into a dotnet sln line.
The Postiba.Module.Mcp module exposes a Streamable-HTTP /mcp
endpoint on the API host. Four tools out of the box, gated by
subscription tier:
Each tool declares its required feature key with a
[RequiresFeature(...)] attribute. The dispatcher filters
tools/list before the client ever sees them. A Free-tier user
calling tools/list sees one tool. A Pro-tier user sees four. An
Enterprise SystemAdmin sees five.
The integration step on the client side is exactly one URL.
https://api.acme.com/mcp into Claude.app./.well-known/oauth-protected-resource (RFC 9728)
to discover which authorization server protects the resource.registration_endpoint (RFC 7591), and POSTs its name and
redirect URI.Postiba.Oauth login page./mcp, your
feature gate filters the tool list, Claude shows the tools to the
user.No copy-paste of client IDs, no out-of-band coordination, no custom registration flow. Production OAuth doing what production OAuth was always supposed to do.
Postiba.Module.Mcp is three csproj under src/modules/Mcp/. A fork
that does not want MCP removes:
<ProjectReference> lines in Postiba.Api.csproj and the
module-assembly entry in Program.cs,mcp.tool_invocations table.Six lines of diff. The dynamic client registration endpoint stays
in core because it is a generic OAuth feature, but the /mcp
transport and the tools disappear cleanly.
This is the same modular-monolith pattern we use for Stripe billing (see the earlier post on module-or-core). A vertical that not every fork wants belongs in a module.
A fork that needs any of these adds them in the module's own namespace without changing the core surface.
Clone the template. Copy .env.example. docker compose up.
Open npx @modelcontextprotocol/inspector, point it at
http://localhost:5181/mcp, log in with the seed admin account.
The inspector shows the tool list. Call whoami. You see your
identity.
That's the end of the demo. From here it is your tools, your workspace data, your feature gates. The plumbing is done.