Plugins

MCP

Model Context Protocol server for AI agent integration.

MCP

Model Context Protocol (MCP) server plugin for integrating your Manic app with AI assistants and agents.

Provides an MCP endpoint (JSON-RPC over Streamable HTTP), built-in framework tools, auto-discovery endpoints, and browser-side WebMCP integration.

Installation

bun add @manicjs/mcp

Quick Start

// manic.config.ts
import {  } from 'manicjs/config';
import {  } from '@manicjs/mcp';

export default ({
  : [
    (),
  ],
});

That's it — the plugin registers a fully functional MCP server at /mcp with built-in tools and discovery endpoints.


Options

Prop

Type


Defining Custom Tools

Use defineTool with a Zod schema for type-safe tool definitions. The Zod schema is automatically converted to JSON Schema for the MCP protocol, and arguments are validated at call time.

// manic.config.ts
import {  } from 'manicjs/config';
declare function (?: <string, unknown>): unknown;
declare function (: string, : <string, unknown>): unknown;
const  = {
  : () => ({ : (: string) => ({}) }),
  : () => ({ : () => ({ : (: string) => ({}) }) }),
  : (: <string, unknown>) => ({} as any),
};
declare function (: string): <unknown>;
declare function (: string, : number): <unknown>;

export default ({
  : [
    mcp({
Type 'unknown' is not assignable to type 'ManicPlugin'.
: [ ('get_user', { : 'Get a user by ID', : .({ : .().('The user ID'), }), : async ({ }: { : string }) => { const = await (); return ; }, }), ('search_products', { : 'Search products by query', : .({ : .().('Search query'), : .().().('Max results'), }), : async ({ , }: { : string; ?: number }) => { return (, ?? 10); }, }), ], }), ], });

With McpTool Interface

For cases where you don't want a Zod dependency, you can pass raw McpTool objects with a JSON Schema inputSchema:

import {  } from 'manicjs/config';
import {  } from '@manicjs/mcp';
import type { McpTool } from '@manicjs/mcp';
declare function (: string, : string): <void>;

const : McpTool = {
  : 'send_notification',
  : 'Send a notification to a user',
  : {
    : 'object',
    : {
      : { : 'string', : 'Target user ID' },
      : { : 'string', : 'Notification body' },
    },
    : ['userId', 'message'],
  },
  : async ({ ,  }) => {
    await ((), ());
    return { : true };
  },
};

export default ({
  : [
    ({ : [] }),
  ],
});

McpTool Interface

interface McpTool {
  name: string;
  description: string;
  inputSchema: {
    type: 'object';
    properties?: Record<string, unknown>;
    required?: string[];
  };
  execute(args: Record<string, unknown>): Promise<unknown> | unknown;
}

Built-in Tools

The plugin automatically registers framework-aware tools alongside any custom tools you provide:

ToolDescription
get_routesReturns all page routes registered in the app (path + file path).
get_api_routesReturns all API routes registered under /api.
get_page_metaFetches a page and extracts its <title>, meta tags, and canonical link.
get_rendered_elementsFetches a page and returns a simplified element list (tag, id, class, text).
get_console_logsReturns captured browser console logs. Dev only.

get_page_meta

Accepts { url: string } — an absolute or relative URL. Returns { title, meta, canonical }.

get_rendered_elements

Accepts { url: string, selector?: string } — fetches the page and returns up to 100 elements with their tag, id, class, and text content. The optional selector parameter scopes the extraction (defaults to body).

get_console_logs

Dev-only tool. Accepts { level?: string, limit?: number }. Filter by log level (log, warn, error, info, debug) and limit the number of entries returned (default 50). Requires the console capture script, which is automatically injected in dev mode.


Discovery Endpoints

The plugin registers the following well-known endpoints for agent auto-discovery:

EndpointPurpose
/.well-known/mcp.jsonMCP discovery document (endpoint, tools, server info)
/.well-known/mcp/server-card.jsonMCP server card (transport, capabilities)
/.well-known/agent-skills/index.jsonAgent skills index (links to the skill document)
/.well-known/agent-skills/use-mcp/SKILL.mdMarkdown skill document with connection instructions and tool docs

These are served as routes in dev and emitted as static files in production builds. The plugin also adds RFC 8288 Link headers for discovery:

Link: </.well-known/mcp/server-card.json>; rel="mcp"; type="application/json"
Link: </.well-known/mcp.json>; rel="mcp-discovery"; type="application/json"
Link: </.well-known/agent-skills/index.json>; rel="agent-skills"; type="application/json"

WebMCP Browser Integration

The plugin serves a /webmcp.js script and automatically injects <script src="/webmcp.js"></script> into your HTML. This script registers all MCP tools with the browser's navigator.modelContext API (WebMCP), allowing browser-based AI agents to call your tools directly.

Each browser-side tool delegates execution to the MCP server endpoint via fetch, so tools are defined once and work in both server and browser contexts.


No built-in authentication — The MCP endpoint has no authentication by default. If you need to secure it, handle authentication at the infrastructure level (e.g., Vercel Edge Functions, Cloudflare Access, or a reverse proxy with auth).


Full Example

// manic.config.ts
import {  } from 'manicjs/config';
declare function (?: <string, unknown>): unknown;
declare function (: string, : <string, unknown>): unknown;
const  = {
  : () => ({ : (: string) => ({}) }),
  : () => ({ : () => ({ : (: string) => ({}) }) }),
  : (: <string, unknown>) => ({} as any),
};
declare function (: string, : number): <unknown[]>;
declare function (: string): <unknown>;

export default ({
  : [
    mcp({
Type 'unknown' is not assignable to type 'ManicPlugin'.
: 'my-app', : '2.0.0', : '/mcp', : [ ('query_posts', { : 'Search blog posts by keyword', : .({ : .().('Search keyword'), : .().().('Max results (default 10)'), }), : async ({ , }: { : string; ?: number }) => { const = await (, ?? 10); return { }; }, }), ('get_post', { : 'Get a single blog post by slug', : .({ : .().('Post URL slug'), }), : async ({ }: { : string }) => { return (); }, }), ], }), ], });

See Also

On this page