# How to Manage Projects Using MCP Tools in OpenSEO: A Complete Guide

> Learn to manage OpenSEO projects programmatically using MCP tools like list projects and create project via JSON-RPC POST requests to mcp. Automate your workflows today.

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

---

**Use the `list_projects`, `create_project`, and `project_context` MCP tools via JSON-RPC POST requests to `/mcp` to programmatically manage OpenSEO projects and their shared memory.**

Projects in OpenSEO serve as the core container for all SEO data, and the Model-Connect-Protocol (MCP) server exposes a unified interface for AI agents to manage them. According to the `every-app/open-seo` source code, these tools delegate to the same internal services used by the dashboard UI, ensuring consistent behavior across all clients.

## MCP Architecture for Project Management

The MCP implementation follows a layered architecture that separates transport concerns from business logic. Understanding these components helps diagnose issues and extend functionality.

### Transport and Authentication Layer

The **MCP Transport Layer** ([`src/server/mcp/transport.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/transport.ts)) handles request validation, CORS, and injects the authenticated user or organization scope into every request. This ensures that all subsequent tool executions respect the caller's permissions before reaching business logic.

### Core Services

All MCP tools delegate to two primary services:

- **Project Service** ([`src/server/features/projects/services/projects.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/projects/services/projects.ts)) — Handles creation, listing, and metadata updates. Both the React dashboard and MCP tools call `createProject()` through this service.
- **Project-Context Service** ([`src/server/features/project-context/services/ProjectContextService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/project-context/services/ProjectContextService.ts)) — Manages the "shared memory" accessible to both the UI (SAM) and AI agents. This service guarantees that tags, notes, and saved keywords remain synchronized across interfaces.

### Tool Registration

The **MCP Tool Registry** ([`src/server/mcp/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/server.ts)) exposes the available methods to clients. Each tool is stateless: it receives a JSON-RPC request, delegates to the appropriate service, and returns a structured response containing human-readable text, metadata URLs, and machine-readable content.

## Available MCP Tools for Project Operations

The OpenSEO MCP server exposes three primary tools for project management, each implemented in dedicated files under `src/server/mcp/tools/`.

### list_projects

**File:** [`src/server/mcp/tools/list-projects.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/list-projects.ts)

Returns every project visible to the caller, scoped by organization or user. This tool accepts no arguments (`{}`) and returns an array of project objects containing `id`, `name`, `domain`, `locationCode`, `languageCode`, and `url`. When called with a user-scoped token, the response includes projects from all organizations the user belongs to, annotated with `organization` and `organizationId` fields.

### create_project

**File:** [`src/server/mcp/tools/create-project.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/create-project.ts)

Creates a new project within the caller's organization. The tool validates input using `createProjectSchema`, requiring `name` and optionally accepting `domain`, `locationCode`, and `languageCode`. The implementation mirrors the UI's server function exactly, ensuring data quality through shared validation logic.

### project_context

**File:** [`src/server/mcp/tools/project-context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/project-context.ts)

Provides read/write access to per-project memory through two sub-operations:

- `get_project_context` — Retrieves current context for a specified `projectId`
- `update_project_context` — Applies structured updates using `projectContextUpdateSchema`, supporting operations like `upsert` on sections such as `tags`

Both operations route through `ProjectContextService`, maintaining consistency with the dashboard's state management.

## Practical Implementation

All MCP calls follow JSON-RPC 2.0 over HTTP POST to the `/mcp` endpoint at `https://app.openseo.so/mcp`.

### Request Format

Every request requires:

- `Authorization: Bearer <MCP-TOKEN>` header
- `Content-Type: application/json` header
- A JSON body with `jsonrpc: "2.0"`, a unique `id`, the `method` name, and a `params` object

The response always contains three keys:

- `text` — Human-readable summary suitable for displaying to end users
- `meta` — Optional UI links, including dashboard URLs
- `structuredContent` — Machine-parseable data for programmatic consumption

### Listing Accessible Projects

Use `list_projects` to retrieve available project IDs before performing operations:

```bash
curl -X POST https://app.openseo.so/mcp \
  -H "Authorization: Bearer <MCP-TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
        "jsonrpc":"2.0",
        "id":"list-001",
        "method":"list_projects",
        "params":{}
      }'

```

**Sample response:**

```json
{
  "jsonrpc":"2.0",
  "id":"list-001",
  "result":{
    "text":"Projects (2):\n- proj_123  Acme (acme.com)  market:2704/en",
    "meta":{"url":"https://app.openseo.so/"},
    "structuredContent":{
      "projects":[
        {
          "id":"proj_123",
          "name":"Acme",
          "domain":"acme.com",
          "locationCode":2704,
          "languageCode":"en",
          "url":"https://app.openseo.so/p/proj_123"
        }
      ]
    }
  }
}

```

### Creating a New Project

Invoke `create_project` with the required schema fields:

```bash
curl -X POST https://app.openseo.so/mcp \
  -H "Authorization: Bearer <MCP-TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
        "jsonrpc":"2.0",
        "id":"create-001",
        "method":"create_project",
        "params":{
          "name":"New Brand",
          "domain":"newbrand.com",
          "locationCode":2704,
          "languageCode":"en"
        }
      }'

```

The response includes the newly created project's ID and a direct dashboard URL in `meta.url`, allowing agents to immediately reference the project in the UI.

### Managing Project Context

Read the current context state:

```json
{
  "jsonrpc":"2.0",
  "id":"ctx-001",
  "method":"get_project_context",
  "params":{"projectId":"proj_123"}
}

```

Update the context by applying structured operations:

```json
{
  "jsonrpc":"2.0",
  "id":"ctx-002",
  "method":"update_project_context",
  "params":{
    "projectId":"proj_123",
    "updates":[
      {"section":"tags","operation":"upsert","payload":{"tag":"high-intent"}}
    ]
  }
}

```

Both calls guarantee consistency with the SAM (Search Agent Manager) interface and dashboard UI because they share the `ProjectContextService` implementation.

## Node.js Integration Example

The following snippet demonstrates production-ready patterns for managing projects using the MCP tools:

```javascript
import fetch from 'node-fetch';

const MCP_ENDPOINT = 'https://app.openseo.so/mcp';
const TOKEN = process.env.MCP_TOKEN;

async function mcpCall(method, params = {}) {
  const body = {
    jsonrpc: '2.0',
    id: `${method}-${Date.now()}`,
    method,
    params,
  };
  
  const res = await fetch(MCP_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${TOKEN}`,
    },
    body: JSON.stringify(body),
  });
  
  const json = await res.json();
  return json.result;
}

// List all accessible projects
const list = await mcpCall('list_projects');
console.log('Projects:', list.structuredContent.projects);

// Create a project if none exist
if (list.structuredContent.projects.length === 0) {
  const created = await mcpCall('create_project', {
    name: 'Demo Project',
    domain: 'demo.com',
    locationCode: 2704,
    languageCode: 'en',
  });
  console.log('Created:', created.structuredContent.project);
}

// Read project context
const ctx = await mcpCall('get_project_context', { projectId: 'proj_123' });
console.log('Context:', ctx.structuredContent);

```

This implementation references the same source files ([`src/server/mcp/tools/list-projects.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/list-projects.ts), [`src/server/mcp/tools/create-project.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/create-project.ts), and [`src/server/mcp/tools/project-context.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/project-context.ts)) that power the OpenSEO dashboard, ensuring that changes to server logic propagate immediately to MCP clients.

## Summary

- **MCP tools delegate to shared services** — `list_projects` and `create_project` use [`src/server/features/projects/services/projects.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/projects/services/projects.ts), while context operations use `ProjectContextService`, ensuring UI and API consistency.
- **JSON-RPC 2.0 over HTTP POST** — All interactions use the `/mcp` endpoint with standard JSON-RPC framing and Bearer token authentication.
- **Three core operations** — List existing projects, create new ones using `createProjectSchema` validation, and read/write project memory via `get_project_context` and `update_project_context`.
- **Structured responses** — Every tool returns `text` for humans, `meta` for UI links (built via [`src/server/mcp/urls.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/urls.ts)), and `structuredContent` for programmatic consumption.
- **Stateless architecture** — The transport layer ([`src/server/mcp/transport.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/transport.ts)) handles auth injection, while tools remain stateless and idempotent where possible.

## Frequently Asked Questions

### How does authentication work for MCP tools in OpenSEO?

The transport layer in [`src/server/mcp/transport.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/transport.ts) validates the Bearer token from the `Authorization` header and injects the authenticated user or organization scope into the request context. MCP tokens can be user-scoped (accessing projects across all organizations) or organization-scoped (restricted to a single organization), and this scope determines the visibility of projects in `list_projects` responses.

### What data can be stored in project context?

The `project_context` tool stores arbitrary structured data defined by `projectContextUpdateSchema`, commonly including tags, saved keywords, research notes, and campaign configurations. Since `ProjectContextService` backs both the MCP tools and the SAM dashboard interface, any data written by an AI agent is immediately visible to human users in the UI, and vice versa.

### Why do MCP tools return both text and structuredContent?

The dual-response format supports both human-in-the-loop workflows and fully automated pipelines. The `text` field provides a human-readable summary suitable for displaying in chat interfaces or logs, while `structuredContent` delivers machine-parseable JSON that clients can process without string parsing. The optional `meta` field contains dashboard URLs generated by [`src/server/mcp/urls.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/urls.ts), allowing agents to link users directly to relevant UI views.

### Can I use the same validation schemas as the OpenSEO UI?

Yes. The `create_project` tool explicitly uses `createProjectSchema` for input validation, ensuring that MCP-created projects meet the same data quality standards as those created through the dashboard. This shared validation layer prevents malformed entries and maintains database integrity across all entry points.