How Instatic Integrates External AI Tools with MCP Connectors: A Complete Architecture Guide

Instatic integrates external AI tools with MCP connectors through a Model-Context-Protocol (MCP) stack that exposes an HTTP endpoint for JSON-RPC requests, persists connector credentials in TypeBox-schematized tables, and bridges tool invocations into the live Yjs editor via a persistent workspace stream.

Instatic, an open-source CMS, treats external AI services as first-class collaborators. To integrate external AI tools with MCP connectors, the platform implements a typed, secure protocol layer that translates AI driver requests directly into document mutations. This architecture separates transport concerns from business logic while maintaining real-time synchronization with the editor state.

The Three-Layer MCP Architecture

Instatic's integration consists of three tightly-coupled components that handle authentication, request routing, and editor synchronization.

1. MCP Server Endpoint

The entry point is a dedicated HTTP endpoint (/_instatic/mcp) registered in [server/router.ts](https://github.com/CoreBunch/Instatic/blob/main/server/router.ts). This route delegates to handleMcpHttp, which accepts JSON-RPC-style payloads from any external AI driver. The transport layer validates requests against TypeBox schemas defined in [src/core/ai/mcpConnectorSchemas.ts](https://github.com/CoreBunch/Instatic/blob/main/src/core/ai/mcpConnectorSchemas.ts) before forwarding them to the bridge.

2. Connector Store and Authentication Schemas

Persistent connector records live in database tables created by migrations in [server/db/migrations-pg.ts](https://github.com/CoreBunch/Instatic/blob/main/server/db/migrations-pg.ts) and [server/db/migrations-sqlite.ts](https://github.com/CoreBunch/Instatic/blob/main/server/db/migrations-sqlite.ts), specifically ai_mcp_connectors and ai_mcp_oauth_clients. The wire-level contracts are governed by [src/core/ai/mcpConnectorSchemas.ts](https://github.com/CoreBunch/Instatic/blob/main/src/core/ai/mcpConnectorSchemas.ts), which defines:

  • Bearer connectors: Created via POST /admin/api/ai/mcp/connections using CreateMcpAccessTokenBodySchema, returning a one-time token via CreateMcpAccessTokenResultSchema.
  • OAuth connectors: Provisioned through the OAuth flow at /admin/api/ai/mcp/oauth/authorization.

Security is enforced by storing hashed tokens (token_hash) in the database and never returning raw secrets after initial creation.

3. Workspace Bridge

The [server/ai/mcp/editorBridge.ts](https://github.com/CoreBunch/Instatic/blob/main/server/ai/mcp/editorBridge.ts) module opens a per-connector stream that forwards MCP tool calls into the editor's Yjs document. The admin UI consumes this bridge via the React hook [src/admin/ai/useMcpWorkspaceBridge.ts](https://github.com/CoreBunch/Instatic/blob/main/src/admin/ai/useMcpWorkspaceBridge.ts).

When initialized, the bridge registers the connector's scope (e.g., mcp offline_access) and attaches a Yjs mutation listener. Incoming requests are deserialized, routed to the appropriate tool implementation (such as insertHtml or readStyles), and results are streamed back. Errors and connection-loss events are logged with the consistent prefix [mcp-workspace-bridge:<scope>].

Authenticating External AI Drivers

Instatic supports two authentication patterns for MCP connectors, each suited to different deployment scenarios.

Creating Bearer Token Connectors

For server-to-server integrations, generate a bearer token through the admin API. The client-side implementation in [src/admin/ai/api.ts](https://github.com/CoreBunch/Instatic/blob/main/src/admin/ai/api.ts) uses the MCP_CONNECTIONS_BASE constant to route requests:

// POST /admin/api/ai/mcp/connections
import { apiRequest } from '@core/http';
import { CreateMcpAccessTokenBodySchema, CreateMcpAccessTokenResultSchema } from '@core/ai/mcpConnectorSchemas';

const body = {
  label: 'CLI tool',
  capabilities: ['site-read', 'site-write'],
  ttlDays: 30,
};

const result = await apiRequest('/admin/api/ai/mcp/connections', {
  method: 'POST',
  schema: CreateMcpAccessTokenResultSchema,
  json: body,
});

console.log('Access token (one‑time):', result.accessToken);

The API returns the raw token only once; subsequent storage uses the hashed value for validation.

OAuth 2.0 Connector Flow

For user-authorized integrations, implement the PKCE-enhanced OAuth flow using the MCP_OAUTH_AUTHORIZATION_PATH constant:

// 1. Request authorization URL
const authUrl = await apiRequest('/admin/api/ai/mcp/oauth/authorization', {
  method: 'POST',
  schema: McpOAuthAuthorizationViewSchema,
  json: {
    clientId: 'my-client',
    redirectUri: 'https://myapp.com/callback',
    codeChallenge: pkceChallenge,
    codeChallengeMethod: 'S256',
    scope: 'site-read',
    resource: 'http://localhost/_instatic/mcp',
  },
});

window.location.href = authUrl.authorizeUrl;

// 2. After redirect, exchange code for tokens
const tokenResult = await apiRequest('/admin/api/ai/mcp/oauth/tokens', {
  method: 'POST',
  schema: McpOAuthAuthorizationResultSchema,
  json: { code: returnedCode, codeVerifier: pkceVerifier },
});

This flow creates persistent OAuth credentials in the ai_mcp_oauth_clients table while adhering to the schemas defined in mcpConnectorSchemas.ts.

Bridging MCP Calls into the Live Editor

Once authenticated, AI drivers interact with the CMS through the workspace bridge. The React hook useMcpWorkspaceBridge manages the persistent connection:

import { useMcpWorkspaceBridge } from '@admin/ai/useMcpWorkspaceBridge';

function MyMcpComponent({ connectorId }: { connectorId: string }) {
  const { stream, send } = useMcpWorkspaceBridge(connectorId);

  // Example: ask the AI to insert a styled paragraph
  const insertParagraph = async () => {
    const resp = await send({
      tool: 'mcp__instatic__insertHtml',
      args: { html: '<p>Hello from AI</p>' },
    });
    console.log('Insert result:', resp);
  };

  return <button onClick={insertParagraph}>Insert via AI</button>;
}

Under the hood, [server/ai/mcp/transports/http.ts](https://github.com/CoreBunch/Instatic/blob/main/server/ai/mcp/transports/http.ts) validates the request format and forwards valid calls to editorBridge.ts, which then invokes the registered tool handlers.

Implementing Custom MCP Tools

Server-side tool implementations reside in src/core/ai/ and follow the ToolHandler interface. To modify the document tree, use the mutateActiveTree utility:

// src/core/ai/tools/insertHtml.ts
import { ToolHandler } from '@core/ai/toolSchemas';
import { mutateActiveTree } from '@core/page-tree/mutations';

export const insertHtml: ToolHandler = async (ctx, { html }) => {
  // Use the page‑tree mutation API to add a node
  await mutateActiveTree((tree) => {
    tree.insertNode({
      type: 'html',
      props: { content: html },
      parentId: ctx.currentNodeId,
    });
  });
  return { ok: true };
};

Register the handler in [src/core/ai/index.ts](https://github.com/CoreBunch/Instatic/blob/main/src/core/ai/index.ts) to make it available to the bridge. Each tool receives a context object (ctx) containing the current node ID and other editor state, ensuring mutations occur at the correct location in the document.

Data Flow and Security Model

The complete request lifecycle follows this path:

  1. External AI driver sends an HTTP POST to /_instatic/mcp with a JSON-RPC payload.
  2. server/router.ts delegates to handleMcpHttp, which authenticates the request against stored credentials.
  3. Valid requests enter editorBridge.ts, which deserializes the method call and routes it to the appropriate tool implementation in src/core/ai/.
  4. The tool executes Yjs operations via mutateActiveTree, modifying the live document.
  5. Results or errors stream back to the AI driver through the same HTTP connection.

Security boundaries are enforced at multiple layers: the HTTP transport validates request shapes against TypeBox schemas, the database stores only hashed tokens (token_hash), and the bridge logs all operations with scoped prefixes for auditability.

Summary

  • Instatic integrates external AI tools with MCP connectors via a three-layer architecture: an HTTP endpoint in server/router.ts, credential storage in ai_mcp_connectors tables, and a workspace bridge in editorBridge.ts.
  • Authentication supports both bearer tokens (for servers) and OAuth 2.0 with PKCE (for user-authorized apps), managed through schemas in mcpConnectorSchemas.ts.
  • Real-time editing is enabled by useMcpWorkspaceBridge, which streams tool calls into Yjs document mutations.
  • Custom tools implement the ToolHandler interface and register in src/core/ai/index.ts to access the page-tree mutation API.
  • Security relies on TypeBox schema validation, hashed token storage, and scoped logging prefixes.

Frequently Asked Questions

What is the MCP endpoint URL in Instatic?

The MCP server exposes JSON-RPC requests at the path /_instatic/mcp, defined by the MCP_ENDPOINT_PATH constant and registered in [server/router.ts](https://github.com/CoreBunch/Instatic/blob/main/server/router.ts). This endpoint accepts POST requests from external AI drivers after they authenticate via bearer token or OAuth credentials.

How does Instatic handle MCP authentication securely?

Instatic stores connector credentials in tables like ai_mcp_connectors and ai_mcp_oauth_clients, persisting only hashed tokens (token_hash) in the database. Raw access tokens are returned only once during the CreateMcpAccessTokenResultSchema response. All incoming requests are validated against TypeBox schemas in mcpConnectorSchemas.ts before reaching the tool implementation layer.

How do I create a custom tool for the Instatic MCP bridge?

Define a server-side handler in src/core/ai/tools/ that implements the ToolHandler interface, then register it in [src/core/ai/index.ts](https://github.com/CoreBunch/Instatic/blob/main/src/core/ai/index.ts). Use mutateActiveTree from @core/page-tree/mutations to perform document operations. The tool receives a context object with the current node ID, allowing precise insertion or modification of content within the Yjs-based editor.

What database tables support MCP connectors in Instatic?

The platform creates dedicated tables through migrations in [server/db/migrations-pg.ts](https://github.com/CoreBunch/Instatic/blob/main/server/db/migrations-pg.ts) and [server/db/migrations-sqlite.ts](https://github.com/CoreBunch/Instatic/blob/main/server/db/migrations-sqlite.ts), specifically ai_mcp_connectors for bearer token metadata and ai_mcp_oauth_clients for OAuth app registrations. These tables store connection labels, capability scopes, and hashed credential data.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →