Skip to Content
Agents & CLIMCP Plugin

MCP Plugin

The Model Context Protocol (MCP) plugin exposes a subset of Payload operations to MCP-capable agent clients (Claude Code, Claude Desktop, etc.) on top of the same service layer the CLI and REST API use.

What’s enabled

// src/domains/cms/payload/plugins/plugin-mcp.ts mcpPlugin({ collections: { pages: { enabled: true }, tenants: { enabled: true }, }, })
  • pagescreate, update, delete via generic collection tools, plus custom tools page_list, page_get, page_get_block for read access. Generic find is intentionally disabled because full-page reads can blow MCP context.
  • tenants — fully enabled (find / create / update / delete).

Other collections will be added as their corresponding services land.

How agents connect

ShipMore’s MCP server runs in-process on the deployed box. Point your MCP client at:

https://<your-shipmore-box>/api/mcp

Authentication uses the same Payload API key as the CLI — pass it as a bearer token.

For Claude Desktop, add to your config:

{ "mcpServers": { "shipmore": { "url": "https://your-shipmore-box/api/mcp", "headers": { "Authorization": "Bearer YOUR_PAYLOAD_API_KEY" } } } }

Adapter rule

MCP tool handlers, REST handlers, CLI scripts, and webhook handlers are all adapters — they translate inputs, call a service method, and return the result. No business logic in handlers.

// ✅ correct — adapter calls service server.registerTool('add_block_to_page', schema, async (input) => PageService.addBlock({ pageId: input.page_id, block: input.block, position: input.position, tenantId: input.tenant_id, }) ) // ❌ wrong — logic in the adapter (will be duplicated in REST and CLI) server.registerTool('add_block_to_page', schema, async (input) => { const payload = await getPayload({ config }) const page = await payload.findByID({ collection: 'pages', id: input.page_id }) // ... 30 more lines of logic } )

Enabling more collections

To add a collection to the MCP plugin:

  1. Build the corresponding service in src/domains/.../services/. Tests first.
  2. Add custom MCP tools (or generic CRUD) in src/domains/cms/payload/plugins/plugin-mcp.ts that thinly call the service.
  3. Update SKILL.md so agents know the new operations exist.
  4. Run pnpm generate:types if you added fields.

When to add custom MCP tools vs. generic CRUD

Add a custom MCP tool when…Use generic CRUD when…
The operation has business logic (composition, multi-step orchestration, validation beyond field-level)Plain create/update/delete is enough and access control is sufficient
Generic find would return too much context (e.g. full pages with all blocks)Reads are small and well-bounded
There’s a CLI counterpart that already encapsulates the operationThe collection is simple and admin-managed

Reference

  • Plugin source: src/domains/cms/payload/plugins/plugin-mcp.ts
  • Plugin docs: refs/plugin-mcp/README.md (in the repo)
  • Patterns: Agents → Patterns