UNPKG

substack-mcp

Version:

A Model Context Protocol (MCP) Server for Substack enabling LLM clients to interact with Substack's API for automations like creating posts, managing drafts, and more.

70 lines (62 loc) 1.87 kB
#!/usr/bin/env node import {Server} from "@modelcontextprotocol/sdk/server/index.js"; import {StdioServerTransport} from "@modelcontextprotocol/sdk/server/stdio.js"; import { ListToolsRequestSchema, CallToolRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import {z} from "zod"; import {zodToJsonSchema} from "zod-to-json-schema"; import {createDraftPostSchema, createDraftPostHandler} from "./tools/create_draft_post.js"; // Create an MCP server const server = new Server({ name: "Substack MCP", version: "1.0.0" }, { capabilities: { tools: {}, resources: {}, logging: {} }, }); // check envs if (!process.env.SUBSTACK_PUBLICATION_URL || !process.env.SUBSTACK_SESSION_TOKEN || !process.env.SUBSTACK_USER_ID) { throw new Error("SUBSTACK_PUBLICATION_URL, SUBSTACK_SESSION_TOKEN and SUBSTACK_USER_ID must be set"); } server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "create_draft_post", description: "create a draft post on your Substack account.", inputSchema: zodToJsonSchema(createDraftPostSchema), } ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const {name, arguments: args} = request.params; try { switch (name) { case "create_draft_post": { const result = await createDraftPostHandler(args); return { content: [{type: "text", text: JSON.stringify(result, null, 2)}], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { if (error instanceof z.ZodError) { throw new Error(`Invalid input: ${JSON.stringify(error.errors)}`); } throw error; } }); const transport = new StdioServerTransport(); server.connect(transport).catch(() => { process.exit(1); });