get_message
Retrieve a Basecamp project message by ID and render its content in markdown, HTML, text, or raw JSON format for viewing or processing.
Instructions
Fetch a single message by ID; render body as markdown/html/text, or return raw JSON.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | ||
| message_id | Yes | ||
| render | No |
Implementation Reference
- src/tools/messages.ts:217-239 (handler)The handler fetches the message content from Basecamp API using project_id and message_id, renders the HTML body to the specified format (markdown, html, text, or json), and returns the formatted output.async ({ project_id, message_id, render }) => { const msg = await bcRequest<any>( "GET", `/buckets/${project_id}/messages/${message_id}.json` ); const subject = msg.subject ?? msg.title ?? "(no subject)"; const html = msg.content || msg.body || ""; const mode = render ?? "markdown"; if (mode === "json") { return { content: [{ type: "text", text: JSON.stringify(msg, null, 2) }], }; } const body = renderBody(html, mode as "markdown" | "html" | "text"); const output = mode === "markdown" ? `# ${subject}\n\n${body}` : `${subject}\n\n${body}`; return { content: [{ type: "text", text: output }] }; }
- src/tools/messages.ts:207-216 (schema)Input schema definition using Zod, including required project_id and message_id (numbers), and optional render format.{ title: "Get a message", description: "Fetch a single message by ID; render body as markdown/html/text, or return raw JSON.", inputSchema: { project_id: z.number().int(), message_id: z.number().int(), render: z.enum(["markdown", "html", "text", "json"]).optional(), // default markdown }, },
- src/tools/messages.ts:205-240 (registration)Direct registration of the 'get_message' tool on the MCP server, including name, schema, and handler.server.registerTool( "get_message", { title: "Get a message", description: "Fetch a single message by ID; render body as markdown/html/text, or return raw JSON.", inputSchema: { project_id: z.number().int(), message_id: z.number().int(), render: z.enum(["markdown", "html", "text", "json"]).optional(), // default markdown }, }, async ({ project_id, message_id, render }) => { const msg = await bcRequest<any>( "GET", `/buckets/${project_id}/messages/${message_id}.json` ); const subject = msg.subject ?? msg.title ?? "(no subject)"; const html = msg.content || msg.body || ""; const mode = render ?? "markdown"; if (mode === "json") { return { content: [{ type: "text", text: JSON.stringify(msg, null, 2) }], }; } const body = renderBody(html, mode as "markdown" | "html" | "text"); const output = mode === "markdown" ? `# ${subject}\n\n${body}` : `${subject}\n\n${body}`; return { content: [{ type: "text", text: output }] }; } );
- src/tools/messages.ts:17-33 (helper)Helper function to render message HTML body into markdown (default), HTML, or plain text. Used by the get_message handler.function renderBody( html: string, render: "markdown" | "html" | "text" = "markdown" ): string { const markdown = td.turndown(html || ""); if (render === "markdown") return markdown; if (render === "html") return html || ""; // crude Markdown → plain-text return markdown .replace(/```[\s\S]*?```/g, "") // drop code blocks .replace(/`([^`]+)`/g, "$1") // inline code .replace(/!\[([^\]]*)]\([^)]*\)/g, "$1") // images .replace(/\[([^\]]+)]\([^)]*\)/g, "$1") // links .replace(/^[#>\-\*\d\.\s]+/gm, "") // headings/quotes/lists .replace(/[*_~`]/g, "") // emphasis .trim(); }
- src/basecamp-mcp.ts:15-15 (registration)Top-level call to registerMessageTools, which includes registration of the 'get_message' tool.registerMessageTools(server);