How the OpenSEO MCP Server Integrates with AI Agents like Claude Code
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, 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. The createOpenSeoMcpServer function initializes an McpServer instance from the @modelcontextprotocol/sdk and registers available SEO tools.
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. 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:
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. The registerOpenSeoMcpTools function maps tool names to handlers, wrapping each with instrumentMcpToolHandler for PostHog telemetry and error handling.
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:
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 file maps internal model identifiers to DataForSEO LLM endpoints, including Claude:
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:
- Claude sends a JSON-RPC POST request to
https://<instance>/mcpwith method name and authentication token. - Transport layer (
transport.ts) validates the request and determines authentication type (OAuth or first-party). - Context builder creates an
McpToolAuthContextand stores it inAsyncLocalStorage. - Tool dispatcher routes to the registered handler in
server.ts, which executes within the authenticated context. - Business logic runs—potentially calling DataForSEO APIs or internal databases.
- 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
AsyncLocalStoragefor 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. 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.
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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →