# How the OpenSEO MCP Server Integrates with AI Agents like Claude Code

> Discover how the OpenSEO MCP server integrates with AI agents like Claude Code. Learn about authenticated JSON-RPC access, typed tool handlers, and structured research data.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-07-31

---

**The OpenSEO MCP server exposes SEO tools through a JSON-RPC gateway at `/mcp`, where AI agents authenticate via OAuth or first-party contexts before executing typed tool handlers that return structured research data.**

The Model Context Protocol (MCP) implementation in the `every-app/open-seo` repository enables AI agents such as Claude Code to perform SEO research without direct API integration. When an agent requires keyword metrics or backlink analysis, it sends a JSON-RPC request to the MCP endpoint, which validates the authentication context, dispatches the call to the appropriate tool implementation in [`src/server/mcp/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/server.ts), and returns Zod-validated results. This architecture decouples AI agents from specific SEO service implementations while maintaining strict security boundaries.

## Transport Layer and Request Handling

All MCP traffic enters through the `/mcp` endpoint defined in [`src/server/mcp/transport.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/transport.ts). The `createOpenSeoMcpServer` function initializes an `McpServer` instance from the `@modelcontextprotocol/sdk` and registers available SEO tools.

```typescript
import { createMcpHandler } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

function createOpenSeoMcpServer() {
  const server = new McpServer(
    { name: "OpenSEO MCP", title: "OpenSEO", version: "0.0.11" },
    { instructions: "OpenSEO research tools use credits..." },
  );
  registerOpenSeoMcpTools(server);
  return server;
}

```

The `createMcpHandler` utility from the `agents/mcp` package transforms this server into a Cloudflare Workers request handler. Incoming POST requests to `/mcp` trigger `handleOpenSeoMcpRequest`, which validates the JSON-RPC payload and routes to the appropriate tool handler.

When authentication props are present, the request executes within `runWithMcpToolAuthContext` to ensure the tool can access user identity information.

## Authentication Context Management

The server supports two authentication models for MCP clients, defined in [`src/server/mcp/context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/context.ts). The `McpToolAuthContext` carries user identity, organization membership, and credential metadata through `AsyncLocalStorage` (`mcpToolAuthContextStorage`), making it available to tool handlers without explicit parameter passing.

**OAuth Clients** validate incoming requests using `workersOAuthMcpPropsSchema`, checking for the required `MCP_SCOPE` in the token.

**First-Party/Self-Hosted** contexts, used by internal Claude agents, bypass OAuth and instead call `buildFirstPartyMcpAuthContext` with a `null` client ID and derived audience URL:

```typescript
const context = await resolveLocalNoAuthContext();
const props = createWorkersOAuthMcpProps(
  buildFirstPartyMcpAuthContext({
    userId: context.userId,
    userEmail: context.userEmail,
    organizationId: context.organizationId,
    baseUrl,
  })
);

```

Tools retrieve this context using `requireMcpToolAuthContext(extra)`, ensuring every execution runs within an authenticated boundary.

## Tool Registration and Execution

SEO capabilities are exposed as typed MCP tools in [`src/server/mcp/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/server.ts). The `registerOpenSeoMcpTools` function maps tool names to handlers, wrapping each with `instrumentMcpToolHandler` for PostHog telemetry and error handling.

```typescript
export function registerOpenSeoMcpTools(server: McpServer) {
  server.registerTool(
    whoamiTool.name,
    whoamiTool.config,
    instrumentMcpToolHandler(
      whoamiTool.name,
      whoamiTool.config.outputSchema,
      whoamiTool.handler
    ),
  );
  // Additional tools: listProjectsTool, getDomainOverviewTool, etc.
}

```

Each tool follows a consistent pattern: define input/output Zod schemas, implement the handler, and extract auth context via `requireMcpToolAuthContext`. For example, a custom tool implementation looks like:

```typescript
import { z } from "zod";
import { requireMcpToolAuthContext } from "@/server/mcp/context";

export const myCustomTool = {
  name: "myCustomTool",
  config: {
    inputSchema: z.object({ query: z.string() }),
    outputSchema: z.object({ answer: z.string() }),
  },
  async handler(input, extra) {
    const auth = requireMcpToolAuthContext(extra);
    const answer = `Hello ${auth.userEmail}, you asked: ${input.query}`;
    return { answer };
  },
};

```

## Claude-Specific Integration via Prompt Explorer

While Claude acts as an MCP client consuming OpenSEO tools, it also serves as a backend model for certain SEO features. The [`src/server/features/ai-search/services/promptExplorer.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/ai-search/services/promptExplorer.ts) file maps internal model identifiers to DataForSEO LLM endpoints, including Claude:

```typescript
const MODEL_NAMES: Record<PromptExplorerModel, string> = {
  chat_gpt: "gpt-5",
  claude: "claude-sonnet-4-5",
  gemini: "gemini-2.5-pro",
  perplexity: "sonar-reasoning-pro",
};

```

When Claude Code (as an MCP client) calls `getKeywordMetricsTool` or `searchLocalBusinessesTool`, the handler may route complex queries through DataForSEO's LLM endpoints, potentially using Claude's model (`claude-sonnet-4-5`) for natural language processing tasks. This creates a bidirectional relationship where Claude both consumes and powers OpenSEO's research capabilities.

## End-to-End Integration Flow

The complete interaction between Claude Code and the OpenSEO MCP server follows this sequence:

1. **Claude** sends a JSON-RPC POST request to `https://<instance>/mcp` with method name and authentication token.
2. **Transport layer** ([`transport.ts`](https://github.com/every-app/open-seo/blob/main/transport.ts)) validates the request and determines authentication type (OAuth or first-party).
3. **Context builder** creates an `McpToolAuthContext` and stores it in `AsyncLocalStorage`.
4. **Tool dispatcher** routes to the registered handler in [`server.ts`](https://github.com/every-app/open-seo/blob/main/server.ts), which executes within the authenticated context.
5. **Business logic** runs—potentially calling DataForSEO APIs or internal databases.
6. **Response serialization** returns structured data through the MCP JSON-RPC response to Claude.

This flow ensures that AI agents receive consistent, validated SEO data while the server maintains audit trails and credit accounting for every tool invocation.

## Summary

- The **MCP server** in OpenSEO functions as a JSON-RPC gateway on Cloudflare Workers, exposing SEO tools through a standardized protocol.
- **Authentication** supports both OAuth external clients and first-party self-hosted contexts, stored in `AsyncLocalStorage` for clean separation of concerns.
- **Tool registration** occurs centrally in `registerOpenSeoMcpTools`, with handlers wrapped for telemetry and error handling.
- **Claude Code** integrates bidirectionally: as an MCP client consuming tools and as a backend model (via DataForSEO) for AI-powered SEO analysis.
- All tool executions run within isolated authentication contexts, enabling secure multi-tenant access to sensitive SEO data.

## Frequently Asked Questions

### What endpoint do AI agents use to connect to the OpenSEO MCP server?

AI agents send JSON-RPC requests to the `/mcp` endpoint, defined as `MCP_ROUTE` in [`src/server/mcp/context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/context.ts). This single endpoint handles all tool discovery and execution requests through the `createMcpHandler` wrapper, which parses incoming payloads and routes them to the appropriate tool handlers registered in [`src/server/mcp/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/server.ts).

### How does authentication differ between OAuth and first-party MCP clients?

OAuth clients present tokens validated against `workersOAuthMcpPropsSchema` requiring the `MCP_SCOPE` permission, while first-party (self-hosted) clients use `buildFirstPartyMcpAuthContext` with a null `clientId` and derived audience URL. Both methods store the resulting `McpToolAuthContext` in `AsyncLocalStorage` via `runWithMcpToolAuthContext`, allowing tool handlers to access user identity through `requireMcpToolAuthContext` regardless of the authentication source.

### Can I register custom SEO tools for Claude Code to use?

Yes. Create a tool definition with Zod input/output schemas in `src/server/mcp/tools/`, implement the handler using `requireMcpToolAuthContext` to access user credentials, and add it to `registerOpenSeoMcpTools` in [`src/server/mcp/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/server.ts) using `server.registerTool` wrapped with `instrumentMcpToolHandler`. Once registered, Claude Code can discover and invoke the tool through standard MCP protocol methods.

### Why does the integration mention Claude both as a client and a backend model?

Claude Code functions as an MCP client when requesting SEO data from OpenSEO tools, but the OpenSEO platform also uses Claude's capabilities internally through the Prompt Explorer service. When handling complex queries, tools may route requests to DataForSEO's LLM endpoints using the `claude-sonnet-4-5` model slug, allowing Claude to process and analyze SEO data before returning structured results to the original MCP client.