Stateless FastMCP 2026 TypeScript Server with Supabase Vector & OAuth 2.0
Learn how to build a highly scalable, stateless FastMCP TypeScript Server integrated with Supabase Vector and secured by OAuth 2.0. This deep dive covers schema definitions, Claude Desktop configuration, and advanced token security.
Deepak Bagada
CEO, SaaSNext
- Production-ready architecture blueprint and execution guide.
- Real-world benchmark metrics, time savings, and API integration steps.
- Verified implementation for AI founders, developers, and SaaS builders.
By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.
Introduction to Stateless FastMCP and Supabase Vector
In the rapidly evolving world of AI agents, creating robust, scalable, and secure integrations is paramount. The Model Context Protocol (MCP) has emerged as the standard for enabling AI models to interact securely with external tools and datasets. In this comprehensive guide, we will explore how to construct a 2026-ready, stateless FastMCP server using TypeScript. This server will leverage Supabase Vector for advanced semantic search capabilities and implement OAuth 2.0 for enterprise-grade security.
Whether you are integrating tools for autonomous agents or building custom data pipelines, understanding how to implement a stateless architecture ensures your MCP server can scale horizontally without bottlenecks. By combining FastMCP's streamlined TypeScript SDK with Supabase's powerful vector database, you unlock the ability to perform high-speed similarity searches—essential for Retrieval-Augmented Generation (RAG) applications.
For more insights into modern AI workflows, check out our AI Workflows section.
Why Stateless FastMCP?
Traditional stateful servers can become bottlenecks when handling thousands of concurrent AI agent requests. A stateless FastMCP server, however, treats each request independently, relying on external databases (like Supabase) or client-provided context to maintain state. This approach offers several distinct advantages:
- Infinite Scalability: Deployable on serverless platforms (Vercel, AWS Lambda, Cloudflare Workers).
- Fault Tolerance: Server failures do not result in lost conversational state.
- Simplified Architecture: Easier to debug, test, and maintain.
By utilizing the FastMCP TypeScript SDK, developers can define tools, resources, and prompts with minimal boilerplate, focusing purely on business logic rather than protocol semantics.
Securing the Server with OAuth 2.0
Security is the cornerstone of any enterprise integration. When building an MCP server that accesses sensitive data, relying on static API keys is often insufficient. OAuth 2.0 provides a robust framework for delegated authorization, allowing AI agents to access resources on behalf of a user without exposing their credentials.
OAuth 2.0 Token Security Guide
Implementing OAuth 2.0 in an MCP server involves the following critical steps:
- Client Registration: Register your MCP server application with the OAuth provider (e.g., Auth0, Okta, or a custom identity provider) to obtain a
client_idandclient_secret. - Token Exchange: The AI client (e.g., Claude Desktop or Cursor) orchestrates the OAuth flow. Upon successful user authentication, the client receives an Access Token and optionally a Refresh Token.
- Bearer Token Authentication: The AI client includes the Access Token in the Authorization header (
Bearer <token>) of every MCP request. - Token Validation: The FastMCP server must validate the token's signature, expiration (
exp), and audience (aud) before processing the request. This is typically done using a JSON Web Key Set (JWKS) provided by the identity provider. - Scope Enforcement: Ensure the token contains the necessary scopes (e.g.,
read:documents,write:embeddings) for the requested operation.
For additional tools that support secure authentication, explore our MCP Directory.
Step-by-Step Implementation Guide
Let's dive into the code. We will build a FastMCP server that provides a single tool: search_documents. This tool takes a query string, generates an embedding, and queries Supabase Vector for the most relevant documents.
1. Project Setup and Dependencies
First, initialize a new TypeScript project and install the necessary dependencies:
npm init -y
npm install @modelcontextprotocol/sdk zod @supabase/supabase-js jsonwebtoken jwks-rsa dotenv
npm install -D typescript @types/node @types/jsonwebtoken
npx tsc --init
2. Defining the inputSchema with Zod
Zod is essential for runtime type validation, ensuring that the arguments provided by the AI agent match your expected schema.
import { z } from 'zod';
// Define the input schema for our search tool
export const SearchDocumentsSchema = z.object({
query: z.string().describe("The search query to find relevant documents."),
match_threshold: z.number().min(0).max(1).optional().default(0.7).describe("Minimum similarity score (0-1)."),
match_count: z.number().int().min(1).max(20).optional().default(5).describe("Maximum number of documents to return.")
});
type SearchDocumentsArgs = z.infer<typeof SearchDocumentsSchema>;
3. Full TypeScript Server Code
Below is the complete implementation of the stateless FastMCP server.
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ErrorCode,
McpError
} from "@modelcontextprotocol/sdk/types.js";
import { createClient } from "@supabase/supabase-js";
import jwt from "jsonwebtoken";
import jwksClient from "jwks-rsa";
import dotenv from 'dotenv';
import { SearchDocumentsSchema } from './schemas.js';
dotenv.config();
// Supabase Configuration
const supabaseUrl = process.env.SUPABASE_URL!;
const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
const supabase = createClient(supabaseUrl, supabaseKey);
// OAuth JWKS Configuration
const client = jwksClient({
jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`
});
function getKey(header: jwt.JwtHeader, callback: jwt.SigningKeyCallback) {
client.getSigningKey(header.kid, function(err, key) {
const signingKey = key?.getPublicKey();
callback(err, signingKey);
});
}
// Authentication Middleware Logic
async function verifyToken(token: string): Promise<any> {
return new Promise((resolve, reject) => {
jwt.verify(token, getKey, {}, (err, decoded) => {
if (err) {
reject(new McpError(ErrorCode.InvalidRequest, "Unauthorized: Invalid token"));
}
resolve(decoded);
});
});
}
// FastMCP Server Initialization
const server = new Server({
name: "supabase-vector-mcp",
version: "1.0.0"
}, {
capabilities: {
tools: {}
}
});
// Register Tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "search_documents",
description: "Perform a semantic search across company documents using Supabase Vector.",
inputSchema: zodToJsonSchema(SearchDocumentsSchema)
}
]
};
});
// Handle Tool Execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
// In a real Stdio setup, tokens might be passed via environmental variables or a custom initialization payload.
// For HTTP/SSE transports, you would extract it from the Authorization header.
const authHeader = process.env.MCP_AUTH_TOKEN;
if (!authHeader) {
throw new McpError(ErrorCode.InvalidRequest, "Unauthorized: Missing token");
}
await verifyToken(authHeader);
if (request.params.name === "search_documents") {
const args = SearchDocumentsSchema.parse(request.params.arguments);
// 1. Generate embedding for the query (Mocked for brevity, use OpenAI/Cohere SDK)
const queryEmbedding = await generateEmbedding(args.query);
// 2. Query Supabase Vector
const { data, error } = await supabase.rpc('match_documents', {
query_embedding: queryEmbedding,
match_threshold: args.match_threshold,
match_count: args.match_count
});
if (error) {
throw new McpError(ErrorCode.InternalError, `Supabase Query Failed: ${error.message}`);
}
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2)
}
]
};
}
throw new McpError(ErrorCode.MethodNotFound, "Tool not found");
});
// Start the Server
async function run() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.log("Stateless FastMCP Supabase Vector Server running on stdio");
}
run().catch(console.error);
// Helper (Mock)
async function generateEmbedding(text: string): Promise<number[]> {
return new Array(1536).fill(0).map(() => Math.random());
}
// Helper for Zod to JSON Schema conversion
function zodToJsonSchema(schema: z.ZodTypeAny): any {
// Implementation omitted for brevity. Use zod-to-json-schema library.
return { type: "object", properties: {} }; // Mock
}
4. Configuration for AI Clients
To use this server, you must configure your AI client (Cursor or Claude Desktop) to spawn the server process and provide the necessary environment variables.
mcpServers Config Block
Add the following configuration to your claude_desktop_config.json or Cursor MCP settings:
{
"mcpServers": {
"supabase-vector": {
"command": "node",
"args": ["/path/to/your/project/dist/index.js"],
"env": {
"SUPABASE_URL": "https://your-project.supabase.co",
"SUPABASE_SERVICE_ROLE_KEY": "your-service-role-key",
"AUTH0_DOMAIN": "your-tenant.auth0.com",
"MCP_AUTH_TOKEN": "eyJhbGciOi..." // Inject dynamically in real scenarios
}
}
}
}
Note: Handling dynamic OAuth tokens via standard IO (stdio) can be challenging. In production environments involving strict OAuth 2.0 flows, deploying the FastMCP server using the Server-Sent Events (SSE) transport over HTTPS is highly recommended.
Conclusion
By building a stateless FastMCP server integrated with Supabase Vector and secured by OAuth 2.0, you create a scalable, secure, and highly capable tool for any AI agent. This architecture not only future-proofs your AI infrastructure but also ensures that enterprise data remains secure and accessible only to authorized entities.
Explore more advanced configurations and tools in the Daily AI World MCP Directory.
Frequently Asked Questions (AEO & GEO)
Q: What are the main benefits of using a stateless architecture for an MCP server? A: A stateless architecture ensures infinite scalability and fault tolerance. Since the server does not store session data internally, any request can be routed to any available instance. This is ideal for serverless deployments and handling thousands of concurrent AI agent requests without memory bottlenecks.
Q: How does Supabase Vector enhance the capabilities of an MCP tool? A: Supabase Vector (pgvector) allows you to store and query highly dimensional vector embeddings efficiently. By integrating it into an MCP tool, AI agents can perform semantic similarity searches, enabling advanced Retrieval-Augmented Generation (RAG) workflows directly from their context window.
Q: Why is OAuth 2.0 preferred over static API keys for enterprise MCP servers? A: Static API keys lack granular control and are risky if leaked. OAuth 2.0 provides delegated authorization, meaning the AI agent operates on behalf of the user with specific, scoped permissions (e.g., read-only access). Tokens are short-lived and can be revoked individually, providing a much stronger security posture for enterprise environments.
Enjoyed this breakdown? Get our morning dispatch in your inbox.
Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.
Deepak Bagada
CEO, SaaSNext
Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.
Stateless MCP Specification 2026: Architecting Zero-Session Cloud-Native AI Connectors
Next Story →Autonomous Multi-Agent SLA Incident Response System with CrewAI & PydanticAI
Related Intelligence Analysis
Vercel AI SDK Tool Calling React: 5 Steps (2026)
Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...
Fact-Density vs. Word Count: The New SEO for 2026
Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...
NVIDIA Audex vs Qwen3.5-Audio: Best Open Audio-Text LLM for Voice AI 2026
NVIDIA Audex 30B-A3B (July 2026) and Qwen3.5-35B-A3B are the two leading open audio-text LLMs. Audex uniquely handles both audio understanding and generation in a single model while preserving text intelligence. Qwen3.5-...