使用说明
Plain MCP
MCP server for Plain customer support. Gives AI agents full access to threads, customers, and knowledge — search, read, and take action.
Tools (16)
Threads
| Tool | Type | Description |
|---|---|---|
search_threads |
read | Keyword search across threads |
list_threads |
read | Browse with filters (status, priority, assignee) |
get_thread_by_ref |
read | Lookup by reference (e.g. T-41131) |
get_thread_details |
read | Full thread with messages and timeline |
get_related_threads |
read | Semantically similar threads |
reply_to_thread |
write | Reply via email/chat/Slack |
add_thread_note |
write | Internal note (team only) |
assign_thread |
write | Assign or unassign |
change_thread_status |
write | Done, todo, or snooze |
change_thread_priority |
write | 0=urgent to 3=low |
add_thread_labels |
write | Add labels by type ID |
create_thread_link |
write | Link to external URL |
Customers
| Tool | Type | Description |
|---|---|---|
search_customers |
read | Search by name, email, or external ID |
get_customer_details |
read | Full profile with company and groups |
Knowledge
| Tool | Type | Description |
|---|---|---|
search_knowledge |
read | Search docs and knowledge base |
thread_clusters |
read | Spot trends in similar threads |
Usage
Two transport modes: stdio for local MCP clients (Claude Desktop), HTTP for hosted deployments.
Claude Desktop (stdio)
Add to claude_desktop_config.json:
{
"mcpServers": {
"explain": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/src/index.ts", "--stdio"],
"env": {
"PLAIN_API_KEY": "<your_plain_api_key>"
}
}
}
}
Restart Claude Desktop — the tools icon should appear.
Claude Code / HTTP clients
npm install
npm start
Server starts at http://localhost:3000/mcp. Clients pass their Plain API key via the Authorization header:
{
"mcpServers": {
"explain": {
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer <your_plain_api_key>"
}
}
}
}
Each session gets its own isolated client. No credentials stored on the server.
Docker
docker build -t explain-mcp .
docker run -p 3000:3000 explain-mcp
Node 24 LTS Alpine. Multi-stage build — no dev dependencies in the final image.
Development
npm run dev # watch mode
npm test # 20 tests (vitest)
npm run codegen # regenerate types from schema.graphql
npm run build # compile TypeScript
Project Structure
src/
index.ts HTTP server, session management
plain-client.ts GraphQL query + mutation helpers
register-tools.ts auto-discovers tools from domain dirs
types.ts ToolDefinition interface
tools/
threads/ 12 tools + shared helpers
customers/ 2 tools
knowledge/ 2 tools
generated/
graphql-types.ts auto-generated from schema.graphql
Adding a Tool
Create a file in the appropriate domain directory:
// src/tools/threads/my-new-tool.ts
import { z } from 'zod/v4';
import type { ToolDefinition } from '../../types.js';
const schema = z.object({
threadId: z.string().describe('Thread ID'),
});
export default {
name: 'my_new_tool',
description: 'Does something useful.',
schema,
handler: async (input, client) => {
const data = await client.graphqlRequest<MyResponse>(QUERY, { ... });
return { ... };
},
} satisfies ToolDefinition;
Drop the file in — auto-registration picks it up. No wiring needed.
Endpoints
| Method | Path | Description |
|---|---|---|
POST |
/mcp |
MCP Streamable HTTP endpoint |
GET |
/health |
Health check ({ status, sessions }) |
Environment Variables
| Variable | Default | Description |
|---|---|---|
PLAIN_API_KEY |
— | Plain API key (required in stdio mode) |
PORT |
3000 |
Server port (HTTP mode only) |
PLAIN_API_URL |
https://core-api.uk.plain.com/graphql/v1 |
Plain API endpoint |