tailprint 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -2
  3. package/dist/config/env.d.ts +77 -0
  4. package/dist/config/env.js +38 -0
  5. package/dist/config/env.js.map +1 -0
  6. package/dist/config/plans.d.ts +15 -0
  7. package/dist/config/plans.js +104 -0
  8. package/dist/config/plans.js.map +1 -0
  9. package/dist/config/templates.d.ts +10 -0
  10. package/dist/config/templates.js +746 -0
  11. package/dist/config/templates.js.map +1 -0
  12. package/dist/mcp/server.d.ts +10 -0
  13. package/dist/mcp/server.js +897 -0
  14. package/dist/mcp/server.js.map +1 -0
  15. package/dist/mcp/stdio.d.ts +2 -0
  16. package/dist/mcp/stdio.js +27 -0
  17. package/dist/mcp/stdio.js.map +1 -0
  18. package/dist/routes/dashboard.d.ts +2 -0
  19. package/dist/routes/dashboard.js +454 -0
  20. package/dist/routes/dashboard.js.map +1 -0
  21. package/dist/routes/mcp.d.ts +2 -0
  22. package/dist/routes/mcp.js +329 -0
  23. package/dist/routes/mcp.js.map +1 -0
  24. package/dist/routes/render.d.ts +2 -0
  25. package/dist/routes/render.js +444 -0
  26. package/dist/routes/render.js.map +1 -0
  27. package/dist/routes/scrape.d.ts +2 -0
  28. package/dist/routes/scrape.js +132 -0
  29. package/dist/routes/scrape.js.map +1 -0
  30. package/dist/routes/templates.d.ts +2 -0
  31. package/dist/routes/templates.js +2449 -0
  32. package/dist/routes/templates.js.map +1 -0
  33. package/dist/routes/usage.d.ts +31 -0
  34. package/dist/routes/usage.js +73 -0
  35. package/dist/routes/usage.js.map +1 -0
  36. package/dist/routes/webhooks.d.ts +2 -0
  37. package/dist/routes/webhooks.js +227 -0
  38. package/dist/routes/webhooks.js.map +1 -0
  39. package/dist/schemas/render.d.ts +422 -0
  40. package/dist/schemas/render.js +91 -0
  41. package/dist/schemas/render.js.map +1 -0
  42. package/dist/schemas/scrape.d.ts +65 -0
  43. package/dist/schemas/scrape.js +24 -0
  44. package/dist/schemas/scrape.js.map +1 -0
  45. package/dist/server.d.ts +2 -0
  46. package/dist/server.js +206 -0
  47. package/dist/server.js.map +1 -0
  48. package/dist/services/browser.d.ts +21 -0
  49. package/dist/services/browser.js +299 -0
  50. package/dist/services/browser.js.map +1 -0
  51. package/dist/services/carousel.d.ts +43 -0
  52. package/dist/services/carousel.js +300 -0
  53. package/dist/services/carousel.js.map +1 -0
  54. package/dist/services/chart.d.ts +29 -0
  55. package/dist/services/chart.js +129 -0
  56. package/dist/services/chart.js.map +1 -0
  57. package/dist/services/eInvoice.d.ts +62 -0
  58. package/dist/services/eInvoice.js +413 -0
  59. package/dist/services/eInvoice.js.map +1 -0
  60. package/dist/services/email.d.ts +24 -0
  61. package/dist/services/email.js +177 -0
  62. package/dist/services/email.js.map +1 -0
  63. package/dist/services/mockup.d.ts +14 -0
  64. package/dist/services/mockup.js +130 -0
  65. package/dist/services/mockup.js.map +1 -0
  66. package/dist/services/pdfStamper.d.ts +16 -0
  67. package/dist/services/pdfStamper.js +47 -0
  68. package/dist/services/pdfStamper.js.map +1 -0
  69. package/dist/services/qr.d.ts +20 -0
  70. package/dist/services/qr.js +44 -0
  71. package/dist/services/qr.js.map +1 -0
  72. package/dist/services/redis.d.ts +65 -0
  73. package/dist/services/redis.js +318 -0
  74. package/dist/services/redis.js.map +1 -0
  75. package/dist/services/scraper.d.ts +16 -0
  76. package/dist/services/scraper.js +138 -0
  77. package/dist/services/scraper.js.map +1 -0
  78. package/dist/services/storage.d.ts +38 -0
  79. package/dist/services/storage.js +123 -0
  80. package/dist/services/storage.js.map +1 -0
  81. package/dist/services/stripe.d.ts +32 -0
  82. package/dist/services/stripe.js +229 -0
  83. package/dist/services/stripe.js.map +1 -0
  84. package/dist/services/visualDiff.d.ts +33 -0
  85. package/dist/services/visualDiff.js +218 -0
  86. package/dist/services/visualDiff.js.map +1 -0
  87. package/package.json +74 -4
@@ -0,0 +1,329 @@
1
+ import { z } from 'zod';
2
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
3
+ import { createMcpServer } from '../mcp/server.js';
4
+ import { redisService } from '../services/redis.js';
5
+ import { env } from '../config/env.js';
6
+ export const mcpRoutes = async (fastify) => {
7
+ // Store active sessions by sessionId
8
+ const sessions = new Map();
9
+ // Helper to authenticate request
10
+ async function resolveApiKey(request) {
11
+ const authHeader = request.headers.authorization;
12
+ const queryKey = request.query?.api_key;
13
+ let token = null;
14
+ if (authHeader && authHeader.startsWith('Bearer ')) {
15
+ token = authHeader.replace(/^Bearer\s+/i, '').trim();
16
+ }
17
+ else if (typeof queryKey === 'string' && queryKey.trim()) {
18
+ token = queryKey.trim();
19
+ }
20
+ else if (env.NODE_ENV === 'development') {
21
+ token = env.DEV_DEFAULT_API_KEY || 'sec_live_dev_test_key_12345';
22
+ }
23
+ if (!token) {
24
+ return null;
25
+ }
26
+ const apiKey = await redisService.getApiKey(token);
27
+ if (!apiKey || apiKey.status !== 'active') {
28
+ return null;
29
+ }
30
+ return { token, monthlyLimit: apiKey.monthly_limit };
31
+ }
32
+ // GET /v1/mcp/sse - Establish Server-Sent Events MCP channel
33
+ const sseHandler = async (request, reply) => {
34
+ const auth = await resolveApiKey(request);
35
+ if (!auth) {
36
+ return reply.code(401).send({
37
+ statusCode: 401,
38
+ error: 'Unauthorized',
39
+ message: 'Valid API key required via "Authorization: Bearer <KEY>" or "?api_key=<KEY>".',
40
+ });
41
+ }
42
+ // Hijack Fastify reply to manage SSE connection directly via Node raw stream
43
+ reply.hijack();
44
+ // The messages endpoint that this SSE transport will direct clients to
45
+ const messagesEndpoint = request.url.startsWith('/v1') ? '/v1/mcp/messages' : '/mcp/messages';
46
+ const transport = new SSEServerTransport(messagesEndpoint, reply.raw);
47
+ const mcpServer = createMcpServer({
48
+ name: 'tailprint-mcp',
49
+ version: '1.0.0',
50
+ onUsage: async (_toolName) => {
51
+ // Enforce quota usage on every tool execution
52
+ const quota = await redisService.incrementAndCheckQuota(auth.token, auth.monthlyLimit);
53
+ if (!quota.allowed) {
54
+ throw new Error(`Monthly quota limit of ${quota.limit} renders exceeded. Please upgrade your plan.`);
55
+ }
56
+ },
57
+ });
58
+ const sessionId = transport.sessionId;
59
+ sessions.set(sessionId, {
60
+ transport,
61
+ token: auth.token,
62
+ monthlyLimit: auth.monthlyLimit,
63
+ });
64
+ transport.onclose = () => {
65
+ sessions.delete(sessionId);
66
+ };
67
+ await mcpServer.connect(transport);
68
+ };
69
+ // POST /v1/mcp/messages - Client message receiver
70
+ const messagesHandler = async (request, reply) => {
71
+ const sessionId = request.query?.sessionId;
72
+ if (!sessionId || !sessions.has(sessionId)) {
73
+ return reply.code(404).send({
74
+ statusCode: 404,
75
+ error: 'Not Found',
76
+ message: `MCP session "${sessionId}" not found or expired.`,
77
+ });
78
+ }
79
+ const session = sessions.get(sessionId);
80
+ reply.hijack();
81
+ await session.transport.handlePostMessage(request.raw, reply.raw, request.body);
82
+ };
83
+ // Tools Catalog schema for OpenAPI docs
84
+ const ToolCatalogItemSchema = z.object({
85
+ name: z.string().describe('Tool identifier for JSON-RPC MCP calls'),
86
+ category: z.string().describe('Functional category'),
87
+ description: z.string().describe('Detailed tool behavior and capabilities'),
88
+ outputType: z.string().describe('Type of response returned (inline image, hosted PDF link, text)'),
89
+ arguments: z.record(z.string()).describe('Accepted argument types and defaults'),
90
+ examplePrompt: z.string().describe('Real-world conversational prompt for Claude or Cursor'),
91
+ });
92
+ const MCP_TOOLS_CATALOG = [
93
+ {
94
+ name: 'render_pdf',
95
+ category: 'Document Generation',
96
+ description: 'Converts HTML with Tailwind CSS classes or a public web URL into a vector PDF. Automatically saves to CDN and returns both a clickable download link and base64.',
97
+ outputType: 'application/pdf (CDN hosted URL + base64)',
98
+ arguments: {
99
+ html: 'string (optional) - Raw HTML with Tailwind utility classes',
100
+ url: 'string (optional) - Public web URL to render directly',
101
+ format: '"A4" | "Letter" (default: "A4")',
102
+ landscape: 'boolean (default: false)',
103
+ print_background: 'boolean (default: true)',
104
+ header_html: 'string (optional) - Page header template',
105
+ footer_html: 'string (optional) - Page footer template',
106
+ password: 'string (optional) - AES-256 PDF encryption password',
107
+ delay_ms: 'number (optional) - Render delay in milliseconds',
108
+ },
109
+ examplePrompt: 'Read this financial data and generate an executive 1-page PDF summary with benchmark bars.',
110
+ },
111
+ {
112
+ name: 'render_image',
113
+ category: 'Graphics & Open Graph',
114
+ description: 'Generates an optimized PNG or JPEG social preview card / Open Graph banner from Tailwind CSS. Returns an inline MCP image block + hosted CDN link.',
115
+ outputType: 'image/png or image/jpeg (inline image + hosted URL)',
116
+ arguments: {
117
+ html: 'string (optional) - HTML with Tailwind CSS classes',
118
+ url: 'string (optional) - Public web URL to capture',
119
+ width: 'number (default: 1200) - Viewport width in px',
120
+ height: 'number (default: 630) - Viewport height in px',
121
+ type: '"png" | "jpeg" (default: "png")',
122
+ delay_ms: 'number (optional) - Delay before capture',
123
+ },
124
+ examplePrompt: 'Generate a modern dark 1200x630 Open Graph card for my new blog post.',
125
+ },
126
+ {
127
+ name: 'render_chart',
128
+ category: 'Data Visualization',
129
+ description: 'Compiles Chart.js options into a high-DPI image (bar, line, radar, doughnut, polarArea) in light or dark themes. Returns an inline MCP image block + hosted CDN link.',
130
+ outputType: 'image/png (inline image + hosted URL)',
131
+ arguments: {
132
+ type: '"bar" | "line" | "doughnut" | "pie" | "radar" | "polarArea"',
133
+ labels: 'string[] - Axis category labels',
134
+ datasets: 'array of { label, data, backgroundColor?, borderColor? }',
135
+ title: 'string (optional) - Chart headline',
136
+ theme: '"dark" | "light" (default: "dark")',
137
+ width: 'number (default: 1000)',
138
+ height: 'number (default: 600)',
139
+ },
140
+ examplePrompt: 'Plot our monthly MRR growth vs burn rate for the last 6 months as a dark dual bar chart.',
141
+ },
142
+ {
143
+ name: 'generate_qr',
144
+ category: 'Utilities & Identification',
145
+ description: 'Generates mathematically verified, scannable QR codes and barcodes with custom error correction (L/M/Q/H) in light or dark themes. Returns an inline MCP image block.',
146
+ outputType: 'image/png or image/svg+xml (inline image + hosted URL)',
147
+ arguments: {
148
+ text: 'string - Content or target URL to encode',
149
+ format: '"png" | "svg" (default: "png")',
150
+ width: 'number (default: 512)',
151
+ error_correction: '"L" | "M" | "Q" | "H" (default: "M")',
152
+ dark_color: 'string (default: "#090d16")',
153
+ light_color: 'string (default: "#ffffff")',
154
+ },
155
+ examplePrompt: 'Generate a scannable high-resolution QR code pointing to https://tailprint.com/dashboard with dark theme.',
156
+ },
157
+ {
158
+ name: 'render_device_mockup',
159
+ category: 'Marketing & Presentation',
160
+ description: 'Captures any public website URL across parallel viewports and wraps it into a photorealistic MacBook Pro + floating iPhone 16 studio mockup canvas.',
161
+ outputType: 'image/png (inline image + hosted URL)',
162
+ arguments: {
163
+ url: 'string - Public website URL to showcase',
164
+ title: 'string (optional) - Studio banner label',
165
+ delay_ms: 'number (default: 500)',
166
+ },
167
+ examplePrompt: 'Create a showcase device mockup of https://tailprint.com on a MacBook Pro and iPhone 16.',
168
+ },
169
+ {
170
+ name: 'stamp_pdf',
171
+ category: 'Compliance & Security',
172
+ description: 'Applies a diagonal semi-transparent watermark or compliance stamp (e.g. "CONFIDENTIAL", "DRAFT", "FORTROLIGT") across all pages of an existing vector PDF using pdf-lib.',
173
+ outputType: 'application/pdf (hosted URL + base64)',
174
+ arguments: {
175
+ pdf_base64: 'string - Base64 encoded PDF string',
176
+ watermark_text: 'string - Watermark text to stamp diagonally',
177
+ opacity: 'number (default: 0.15) - Opacity from 0.05 to 0.5',
178
+ color: '"red" | "gray" | "blue" (default: "red")',
179
+ font_size: 'number (default: 54)',
180
+ },
181
+ examplePrompt: 'Stamp this contract PDF with a diagonal semi-transparent "FORTROLIGT / CONFIDENTIAL" watermark.',
182
+ },
183
+ {
184
+ name: 'compare_snapshots',
185
+ category: 'Quality Assurance & CI/CD',
186
+ description: 'Performs pixel-by-pixel visual regression testing between two URLs, HTML versions, or screenshots with pixelmatch. Returns a 3-panel studio comparison canvas with a neon-pink diff heatmap.',
187
+ outputType: 'image/png (inline image + hosted URL)',
188
+ arguments: {
189
+ before_url: 'string (optional) - Baseline URL before changes',
190
+ after_url: 'string (optional) - Modified URL after changes',
191
+ before_html: 'string (optional) - Baseline HTML',
192
+ after_html: 'string (optional) - Modified HTML',
193
+ width: 'number (default: 1200)',
194
+ height: 'number (default: 800)',
195
+ threshold: 'number (default: 0.1)',
196
+ },
197
+ examplePrompt: 'Compare our staging homepage against production to verify no breaking CSS regressions or layout shifts.',
198
+ },
199
+ {
200
+ name: 'render_carousel',
201
+ category: 'Social Media & Marketing',
202
+ description: 'Generates high-converting multi-slide social media carousels (1080x1350 px, 4:5 portrait) for LinkedIn (multi-page PDF) and Instagram/Twitter (PNG). Accepts markdown or structured slides.',
203
+ outputType: 'application/pdf + image/png (hosted URLs + inline preview)',
204
+ arguments: {
205
+ title: 'string (optional) - Carousel title',
206
+ author_name: 'string (default: "Tailprint Insights")',
207
+ author_handle: 'string (default: "@tailprint")',
208
+ theme: '"dark" | "light" | "emerald" | "gradient" (default: "dark")',
209
+ markdown: 'string (optional) - Markdown with slides separated by "---"',
210
+ slides: 'array of { headline, content, tag?, takeaway? }',
211
+ },
212
+ examplePrompt: 'Turn my blog post into a 5-slide portrait carousel PDF for LinkedIn with dark theme and swipe arrows.',
213
+ },
214
+ {
215
+ name: 'scrape_markdown',
216
+ category: 'AI Data Ingestion',
217
+ description: 'Scrapes any public web URL, eliminates ads, popups, and cookie walls, and converts the core content into clean, structured Markdown for LLMs with 90%+ context savings.',
218
+ outputType: 'text/markdown',
219
+ arguments: {
220
+ url: 'string - Public web URL to scrape',
221
+ wait_for: 'string (optional) - CSS selector to wait for',
222
+ delay_ms: 'number (optional) - Delay before scraping in ms',
223
+ },
224
+ examplePrompt: 'Scrape this 15-page documentation page and give me clean markdown without navigation chrome.',
225
+ },
226
+ {
227
+ name: 'render_template',
228
+ category: 'Template Automation',
229
+ description: 'Renders pre-designed, battle-tested Tailwind CSS templates directly with optional data variable substitution (e.g. {{customer_name}}, {{total}}).',
230
+ outputType: 'application/pdf or image/png',
231
+ arguments: {
232
+ template_id: '"invoice" | "certificate" | "report" | "resume" | "og-card" | "shipping-label" | "ticket" | "receipt"',
233
+ variables: 'record of string/number values to substitute in template',
234
+ output_format: '"pdf" | "png" | "jpeg" (default: "pdf")',
235
+ landscape: 'boolean (optional)',
236
+ password: 'string (optional)',
237
+ },
238
+ examplePrompt: 'Generate a PDF invoice for Acme Corp with 15h engineering at $150/hr using template invoice.',
239
+ },
240
+ {
241
+ name: 'list_templates',
242
+ category: 'Template Automation',
243
+ description: 'Lists all available pre-designed templates in the Tailprint catalog with format, dimensions, and description.',
244
+ outputType: 'application/json',
245
+ arguments: {},
246
+ examplePrompt: 'What document templates are available?',
247
+ },
248
+ {
249
+ name: 'get_template_source',
250
+ category: 'Template Automation',
251
+ description: 'Retrieves the complete Tailwind CSS HTML source code of any template, allowing an LLM to inspect or modify the markup before rendering.',
252
+ outputType: 'text/html',
253
+ arguments: {
254
+ template_id: '"invoice" | "certificate" | "report" | "resume" | "og-card" | "shipping-label" | "ticket" | "receipt"',
255
+ },
256
+ examplePrompt: 'Give me the HTML source of the invoice template so I can customize the table headers.',
257
+ },
258
+ {
259
+ name: 'generate_einvoice',
260
+ category: 'Compliance & E-Invoicing',
261
+ description: 'Generates an EU-compliant hybrid electronic invoice (Factur-X / ZUGFeRD 2.2 / EN 16931). Produces a Tailwind A4 PDF with embedded CrossIndustryInvoice XML (/EmbeddedFiles) for direct automated ingestion by ERP & accounting platforms (DATEV, SAP, Chorus Pro, Dinero, Billy).',
262
+ outputType: 'application/pdf (hosted CDN URL + XML data)',
263
+ arguments: {
264
+ invoice_number: 'string - Unique invoice identifier (e.g. "INV-2026-0042")',
265
+ seller_name: 'string - Supplier company name',
266
+ seller_vat_id: 'string (optional) - Supplier VAT ID (e.g. "DK12345678")',
267
+ seller_country: 'string (default: "DK") - 2-letter ISO country code',
268
+ buyer_name: 'string - Customer company name',
269
+ buyer_vat_id: 'string (optional) - Buyer VAT ID',
270
+ buyer_country: 'string (default: "DE") - 2-letter ISO country code',
271
+ line_items: 'array of { name, quantity, unit_price, vat_rate? }',
272
+ currency: 'string (default: "EUR") - 3-letter currency code (e.g. EUR, DKK)',
273
+ due_date: 'string (optional) - Due date in YYYY-MM-DD',
274
+ payment_iban: 'string (optional) - Bank IBAN for wire transfer',
275
+ payment_bic: 'string (optional) - Bank SWIFT/BIC code',
276
+ profile: '"BASIC" | "EN16931" (default: "BASIC")',
277
+ },
278
+ examplePrompt: 'Issue an EU-compliant Factur-X e-invoice to BMW AG for 40 hours consulting at 150 EUR/hr with 25% VAT and my IBAN.',
279
+ },
280
+ ];
281
+ // GET /v1/mcp/tools - Comprehensive Tool Catalog & Documentation
282
+ fastify.get('/v1/mcp/tools', {
283
+ schema: {
284
+ tags: ['MCP'],
285
+ summary: 'List All 13 Model Context Protocol (MCP) Tools & Schemas',
286
+ description: 'Returns the full catalog of 13 native MCP tools supported by Tailprint, including argument definitions, output types, and real-world prompt examples for Claude Desktop, Cursor, and autonomous agents.',
287
+ response: {
288
+ 200: z.object({
289
+ totalTools: z.number().describe('Number of registered tools'),
290
+ protocolVersion: z.string().describe('MCP Specification version'),
291
+ transportSupport: z.array(z.string()).describe('Supported transport mechanisms'),
292
+ tools: z.array(ToolCatalogItemSchema),
293
+ }),
294
+ },
295
+ },
296
+ }, async (_request, reply) => {
297
+ return reply.code(200).send({
298
+ totalTools: MCP_TOOLS_CATALOG.length,
299
+ protocolVersion: '2024-11-05',
300
+ transportSupport: ['stdio (local CLI)', 'SSE (Remote Cloud via /v1/mcp/sse)'],
301
+ tools: MCP_TOOLS_CATALOG,
302
+ });
303
+ });
304
+ // Register Canonical Endpoints
305
+ fastify.get('/v1/mcp/sse', {
306
+ schema: {
307
+ tags: ['MCP'],
308
+ summary: 'Establish Remote MCP Server-Sent Events (SSE) Stream',
309
+ description: 'Connects AI clients (Claude Desktop, Cursor, ChatGPT Actions) directly via the Model Context Protocol over SSE.',
310
+ querystring: z.object({
311
+ api_key: z.string().optional().describe('Optional API key query parameter (alternative to Authorization Bearer header)'),
312
+ }),
313
+ },
314
+ }, sseHandler);
315
+ fastify.post('/v1/mcp/messages', {
316
+ schema: {
317
+ tags: ['MCP'],
318
+ summary: 'Send MCP Messages to Active SSE Session',
319
+ description: 'Receives JSON-RPC messages from connected MCP clients for an active session.',
320
+ querystring: z.object({
321
+ sessionId: z.string().describe('The session ID returned during the SSE initialization handshake'),
322
+ }),
323
+ },
324
+ }, messagesHandler);
325
+ // Short URL aliases
326
+ fastify.get('/mcp/sse', { schema: { hide: true } }, sseHandler);
327
+ fastify.post('/mcp/messages', { schema: { hide: true } }, messagesHandler);
328
+ };
329
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/routes/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { FastifyPluginAsyncZod } from 'fastify-type-provider-zod';
2
+ export declare const renderRoutes: FastifyPluginAsyncZod;