# How OpenSEO Server Functions Share the ToolContext Contract and Zod Validation

> Discover how OpenSEO server functions share the ToolContext contract and Zod validation for unified authentication and runtime type safety. Learn more about this powerful integration.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: internals
- Published: 2026-09-12

---

**OpenSEO leverages TanStack React-Start Server Functions to enforce a unified authentication contract through a shared `ToolContext` type and guarantees runtime type safety by attaching reusable Zod schemas via the `.validator()` method.**

Every server function in the OpenSEO codebase follows a standardized architectural pattern that eliminates boilerplate while ensuring complete type safety. By centralizing the **ToolContext** definition and **Zod validation** schemas in single source files, the codebase guarantees that all API handlers receive consistently shaped authentication data and validated inputs without duplicating logic.

## The ToolContext Contract in OpenSEO Server Functions

All OpenSEO server functions rely on a common **ToolContext** type that standardizes how authentication data flows through the application. This contract ensures that every handler receives the same structured information about the requesting user, their organization, and their permissions.

### Defining the Shared Type

The `ToolContext` type is exported from [`src/server/mcp/context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/context.ts) and serves as the single source of truth for authentication context across the entire API:

```typescript
// src/server/mcp/context.ts
export type ToolContext = {
  auth: {
    userId: string;
    userEmail: string;
    organizationId: string;
    role: string;
    orgScope: "pinned" | "user";
    scopes: string[];
    clientId: string | null;
    baseUrl: string;
  };
  turnId?: string;   // present only for in‑app agent turns
};

```

This type describes every field required for authorization decisions, including the user's `organizationId`, their `role` within that organization, and an array of `scopes` defining their permissions. The optional `turnId` field supports in-app agent interactions, allowing server functions to track conversation state when called by AI agents.

### Middleware Injection Pattern

Server functions do not manually construct this context. Instead, they import middleware such as `requireAuthenticatedContext` or `requireProjectContext` from [`src/serverFunctions/middleware.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/middleware.ts). These middleware functions extract authentication headers, validate session tokens, and inject a fully populated `ToolContext` into the handler's `context` argument.

Because the context type is shared, middleware guarantees that every protected endpoint receives identical authentication shaping, eliminating the risk of field mismatches between different API routes.

## Centralizing Zod Validation Across OpenSEO Server Functions

Runtime type safety is enforced through Zod schemas stored in `src/types/schemas/*.ts`. By centralizing validation logic, OpenSEO ensures that input constraints remain consistent across production code, tests, and any future API consumers.

### Schema Reuse Strategy

Rather than defining validation rules inline, developers import schemas from central files like [`src/types/schemas/projects.ts`](https://github.com/every-app/open-seo/blob/main/src/types/schemas/projects.ts):

```typescript
// src/types/schemas/projects.ts
import { z } from "zod";

export const createProjectSchema = z.object({
  name: z.string().min(1),
  website: z.string().url().optional(),
  // …other fields…
});

```

These schemas are reused across multiple server functions and test suites. When business rules change, updating the central schema automatically propagates validation changes to every function that consumes it.

### The Validation Chain

Server functions attach Zod schemas using the `.validator()` method provided by `createServerFn`. This method parses and validates incoming JSON payloads before the handler executes, ensuring that the `data` object inside the handler is fully typed and safe to use:

```typescript
// src/serverFunctions/projects.ts
import { createServerFn } from "@tanstack/react-start";
import { requireAuthenticatedContext } from "@/serverFunctions/middleware";
import { createProjectSchema } from "@/types/schemas/projects";

export const createProject = createServerFn({ method: "POST" })
  .middleware(requireAuthenticatedContext)         // injects ToolContext
  .validator(createProjectSchema)                 // Zod validation
  .handler(async ({ data, context }) => {
    // `context` is a ToolContext – auth info is guaranteed present
    // `data` conforms to `createProjectSchema`
    return ProjectService.createProject(context.auth.organizationId, data);
  });

```

In this implementation, the handler receives a `context` object typed as `ToolContext` and a `data` object validated against `createProjectSchema`. This pattern eliminates defensive coding inside handlers since type safety is guaranteed at the framework level.

## Testing Server Functions with Mock ToolContext

The shared contract simplifies unit testing by allowing developers to inject valid authentication contexts without spinning up full request lifecycle simulations. The `makeToolContext` utility in [`src/server/mcp/tools/tool-test-support.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/tool-test-support.ts) generates compliant mock contexts for test isolation:

```typescript
// src/server/mcp/tools/tool-test-support.ts
import type { ToolAuthContext, ToolContext } from "@/server/mcp/context";

export function makeToolContext(
  overrides?: Partial<ToolAuthContext>
): ToolContext {
  const defaultAuth: ToolAuthContext = {
    userId: "test‑user",
    userEmail: "user@example.com",
    organizationId: "org‑123",
    role: "owner",
    orgScope: "pinned",
    scopes: [],
    clientId: null,
    baseUrl: "https://example.com",
  };
  return { auth: { ...defaultAuth, ...overrides } };
}

```

This helper allows tests to override specific auth fields—such as testing admin-only endpoints by setting `role: "admin"`—while maintaining the full `ToolContext` structure required by the server function. Combined with the centralized Zod schemas, tests can validate both business logic and input constraints using the same definitions as production code.

## Summary

- **Unified Authentication**: The `ToolContext` type in [`src/server/mcp/context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/context.ts) defines a single contract for user identity, organization membership, and permissions that every protected server function receives through middleware like `requireAuthenticatedContext`.

- **Centralized Validation**: All Zod schemas reside in `src/types/schemas/*.ts` and are attached to server functions via `.validator()`, ensuring runtime type checking matches TypeScript definitions.

- **Type-Safe Handlers**: The combination of injected `ToolContext` and validated `data` objects eliminates manual type guarding inside business logic handlers.

- **Testable Architecture**: The `makeToolContext` utility provides a factory for creating valid authentication contexts, enabling isolated unit tests without mocking HTTP requests.

## Frequently Asked Questions

### What is the ToolContext contract in OpenSEO?

The **ToolContext** contract is a TypeScript type defined in [`src/server/mcp/context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/context.ts) that standardizes the shape of authentication data passed to every server function. It contains an `auth` object with fields like `userId`, `organizationId`, `role`, and `scopes`, plus an optional `turnId` for agent-based interactions. This contract ensures that all API handlers receive identically structured authentication information.

### Where are Zod validation schemas stored in the OpenSEO codebase?

Zod schemas are centralized in `src/types/schemas/*.ts`, with specific domains separated into files like [`projects.ts`](https://github.com/every-app/open-seo/blob/main/projects.ts) and [`search-performance.ts`](https://github.com/every-app/open-seo/blob/main/search-performance.ts). This location allows schemas to be imported by multiple server functions and test files, ensuring that validation rules remain consistent across the entire application.

### How does middleware inject ToolContext into server functions?

Middleware functions such as `requireAuthenticatedContext` (defined in [`src/serverFunctions/middleware.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/middleware.ts)) intercept incoming requests, validate session tokens, and construct a `ToolContext` object. They then attach this context to the request pipeline, making it available as the `context` argument in the server function handler. This injection happens before the Zod validator runs.

### Can OpenSEO server functions be tested without a full HTTP request?

Yes. The `makeToolContext` helper in [`src/server/mcp/tools/tool-test-support.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/tool-test-support.ts) generates mock `ToolContext` objects that satisfy the type requirements for any server function. Developers can override specific auth fields for test scenarios and pass these contexts directly to service layers or handler logic, bypassing the HTTP layer and middleware stack entirely.