postproxy-mcp 0.1.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 (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +635 -0
  3. package/dist/api/client.d.ts +71 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +432 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/auth/credentials.d.ts +19 -0
  8. package/dist/auth/credentials.d.ts.map +1 -0
  9. package/dist/auth/credentials.js +40 -0
  10. package/dist/auth/credentials.js.map +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +44 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/server.d.ts +162 -0
  16. package/dist/server.d.ts.map +1 -0
  17. package/dist/server.js +220 -0
  18. package/dist/server.js.map +1 -0
  19. package/dist/setup-cli.d.ts +6 -0
  20. package/dist/setup-cli.d.ts.map +1 -0
  21. package/dist/setup-cli.js +10 -0
  22. package/dist/setup-cli.js.map +1 -0
  23. package/dist/setup.d.ts +8 -0
  24. package/dist/setup.d.ts.map +1 -0
  25. package/dist/setup.js +143 -0
  26. package/dist/setup.js.map +1 -0
  27. package/dist/tools/accounts.d.ts +11 -0
  28. package/dist/tools/accounts.d.ts.map +1 -0
  29. package/dist/tools/accounts.js +53 -0
  30. package/dist/tools/accounts.js.map +1 -0
  31. package/dist/tools/auth.d.ts +11 -0
  32. package/dist/tools/auth.d.ts.map +1 -0
  33. package/dist/tools/auth.js +35 -0
  34. package/dist/tools/auth.js.map +1 -0
  35. package/dist/tools/history.d.ts +13 -0
  36. package/dist/tools/history.d.ts.map +1 -0
  37. package/dist/tools/history.js +79 -0
  38. package/dist/tools/history.js.map +1 -0
  39. package/dist/tools/post.d.ts +44 -0
  40. package/dist/tools/post.d.ts.map +1 -0
  41. package/dist/tools/post.js +251 -0
  42. package/dist/tools/post.js.map +1 -0
  43. package/dist/tools/profiles.d.ts +11 -0
  44. package/dist/tools/profiles.d.ts.map +1 -0
  45. package/dist/tools/profiles.js +52 -0
  46. package/dist/tools/profiles.js.map +1 -0
  47. package/dist/types/index.d.ts +147 -0
  48. package/dist/types/index.d.ts.map +1 -0
  49. package/dist/types/index.js +5 -0
  50. package/dist/types/index.js.map +1 -0
  51. package/dist/utils/errors.d.ts +21 -0
  52. package/dist/utils/errors.d.ts.map +1 -0
  53. package/dist/utils/errors.js +33 -0
  54. package/dist/utils/errors.js.map +1 -0
  55. package/dist/utils/idempotency.d.ts +8 -0
  56. package/dist/utils/idempotency.d.ts.map +1 -0
  57. package/dist/utils/idempotency.js +23 -0
  58. package/dist/utils/idempotency.js.map +1 -0
  59. package/dist/utils/logger.d.ts +20 -0
  60. package/dist/utils/logger.d.ts.map +1 -0
  61. package/dist/utils/logger.js +68 -0
  62. package/dist/utils/logger.js.map +1 -0
  63. package/dist/utils/validation.d.ts +555 -0
  64. package/dist/utils/validation.d.ts.map +1 -0
  65. package/dist/utils/validation.js +145 -0
  66. package/dist/utils/validation.js.map +1 -0
  67. package/package.json +39 -0
  68. package/src/api/client.ts +497 -0
  69. package/src/auth/credentials.ts +43 -0
  70. package/src/index.ts +57 -0
  71. package/src/server.ts +235 -0
  72. package/src/setup-cli.ts +11 -0
  73. package/src/setup.ts +187 -0
  74. package/src/tools/auth.ts +45 -0
  75. package/src/tools/history.ts +89 -0
  76. package/src/tools/post.ts +338 -0
  77. package/src/tools/profiles.ts +69 -0
  78. package/src/types/index.ts +161 -0
  79. package/src/utils/errors.ts +38 -0
  80. package/src/utils/idempotency.ts +31 -0
  81. package/src/utils/logger.ts +75 -0
  82. package/src/utils/validation.ts +171 -0
  83. package/tsconfig.json +19 -0
  84. package/worker/index.ts +901 -0
  85. package/wrangler.toml +11 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Secure logging utilities that sanitize sensitive data
3
+ */
4
+
5
+ const DEBUG = process.env.POSTPROXY_MCP_DEBUG === "1";
6
+
7
+ /**
8
+ * Sanitize data for logging by removing sensitive fields
9
+ */
10
+ export function sanitizeForLog(data: any): any {
11
+ if (data === null || data === undefined) {
12
+ return data;
13
+ }
14
+
15
+ if (typeof data !== "object") {
16
+ return data;
17
+ }
18
+
19
+ if (Array.isArray(data)) {
20
+ return data.map(sanitizeForLog);
21
+ }
22
+
23
+ const sanitized: any = {};
24
+ const sensitiveKeys = [
25
+ "apiKey",
26
+ "api_key",
27
+ "api-key",
28
+ "authorization",
29
+ "token",
30
+ "password",
31
+ "secret",
32
+ "POSTPROXY_API_KEY",
33
+ ];
34
+
35
+ for (const [key, value] of Object.entries(data)) {
36
+ const lowerKey = key.toLowerCase();
37
+ if (sensitiveKeys.some((sk) => lowerKey.includes(sk.toLowerCase()))) {
38
+ sanitized[key] = "[REDACTED]";
39
+ } else if (typeof value === "object") {
40
+ sanitized[key] = sanitizeForLog(value);
41
+ } else {
42
+ sanitized[key] = value;
43
+ }
44
+ }
45
+
46
+ return sanitized;
47
+ }
48
+
49
+ /**
50
+ * Log a message to stderr
51
+ */
52
+ export function log(message: string, ...args: any[]): void {
53
+ const sanitizedArgs = args.map(sanitizeForLog);
54
+ console.error(`[postproxy-mcp] ${message}`, ...sanitizedArgs);
55
+ }
56
+
57
+ /**
58
+ * Log a tool call (without sensitive data)
59
+ */
60
+ export function logToolCall(toolName: string, params: any): void {
61
+ if (DEBUG) {
62
+ log(`Tool call: ${toolName}`, sanitizeForLog(params));
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Log an error
68
+ */
69
+ export function logError(error: Error, context?: string): void {
70
+ const contextMsg = context ? `[${context}] ` : "";
71
+ log(`Error ${contextMsg}${error.message}`, error);
72
+ if (DEBUG && error.stack) {
73
+ log("Stack trace:", error.stack);
74
+ }
75
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Validation schemas using Zod
3
+ */
4
+
5
+ import { z } from "zod";
6
+
7
+ /**
8
+ * Schema for ISO 8601 date strings
9
+ */
10
+ export const ISO8601DateSchema = z.string().refine(
11
+ (date) => {
12
+ const d = new Date(date);
13
+ return !isNaN(d.getTime()) && date.includes("T");
14
+ },
15
+ {
16
+ message: "Must be a valid ISO 8601 date string (e.g., 2024-01-01T12:00:00Z)",
17
+ }
18
+ );
19
+
20
+ /**
21
+ * Schema for URL strings
22
+ */
23
+ export const URLSchema = z.string().url({
24
+ message: "Must be a valid URL",
25
+ });
26
+
27
+ /**
28
+ * Check if a string looks like a file path
29
+ */
30
+ export function isFilePath(value: string): boolean {
31
+ // Absolute paths, relative paths, or home directory paths
32
+ return (
33
+ value.startsWith("/") ||
34
+ value.startsWith("./") ||
35
+ value.startsWith("../") ||
36
+ value.startsWith("~/") ||
37
+ // Windows absolute paths
38
+ /^[A-Za-z]:[\\/]/.test(value)
39
+ );
40
+ }
41
+
42
+ /**
43
+ * Schema for media items (URLs or file paths)
44
+ */
45
+ export const MediaItemSchema = z.string().refine(
46
+ (value) => {
47
+ // Allow file paths
48
+ if (isFilePath(value)) {
49
+ return true;
50
+ }
51
+ // Or valid URLs
52
+ try {
53
+ new URL(value);
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ },
59
+ {
60
+ message: "Must be a valid URL or file path",
61
+ }
62
+ );
63
+
64
+ /**
65
+ * Platform-specific validation schemas
66
+ */
67
+
68
+ // Instagram parameters validation
69
+ export const InstagramParamsSchema = z.object({
70
+ format: z.enum(["post", "reel", "story"], {
71
+ errorMap: () => ({ message: "Instagram format must be 'post', 'reel', or 'story'" }),
72
+ }).optional(),
73
+ collaborators: z.array(z.string()).max(10, {
74
+ message: "Instagram allows up to 10 collaborators for posts, 3 for reels",
75
+ }).optional(),
76
+ first_comment: z.string().optional(),
77
+ cover_url: URLSchema.optional(),
78
+ audio_name: z.string().optional(),
79
+ trial_strategy: z.enum(["MANUAL", "SS_PERFORMANCE"], {
80
+ errorMap: () => ({ message: "Instagram trial_strategy must be 'MANUAL' or 'SS_PERFORMANCE'" }),
81
+ }).optional(),
82
+ thumb_offset: z.string().optional(),
83
+ }).strict();
84
+
85
+ // YouTube parameters validation
86
+ export const YouTubeParamsSchema = z.object({
87
+ title: z.string().optional(),
88
+ privacy_status: z.enum(["public", "unlisted", "private"], {
89
+ errorMap: () => ({ message: "YouTube privacy_status must be 'public', 'unlisted', or 'private'" }),
90
+ }).optional(),
91
+ cover_url: URLSchema.optional(),
92
+ }).strict();
93
+
94
+ // TikTok parameters validation
95
+ export const TikTokParamsSchema = z.object({
96
+ privacy_status: z.enum([
97
+ "PUBLIC_TO_EVERYONE",
98
+ "MUTUAL_FOLLOW_FRIENDS",
99
+ "FOLLOWER_OF_CREATOR",
100
+ "SELF_ONLY"
101
+ ], {
102
+ errorMap: () => ({ message: "TikTok privacy_status must be one of: PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY" }),
103
+ }).optional(),
104
+ photo_cover_index: z.number().int().nonnegative({
105
+ message: "TikTok photo_cover_index must be a non-negative integer",
106
+ }).optional(),
107
+ auto_add_music: z.boolean().optional(),
108
+ made_with_ai: z.boolean().optional(),
109
+ disable_comment: z.boolean().optional(),
110
+ disable_duet: z.boolean().optional(),
111
+ disable_stitch: z.boolean().optional(),
112
+ brand_content_toggle: z.boolean().optional(),
113
+ brand_organic_toggle: z.boolean().optional(),
114
+ }).strict();
115
+
116
+ // Facebook parameters validation
117
+ export const FacebookParamsSchema = z.object({
118
+ format: z.enum(["post", "story"], {
119
+ errorMap: () => ({ message: "Facebook format must be 'post' or 'story'" }),
120
+ }).optional(),
121
+ first_comment: z.string().optional(),
122
+ page_id: z.string().optional(),
123
+ }).strict();
124
+
125
+ // LinkedIn parameters validation
126
+ export const LinkedInParamsSchema = z.object({
127
+ organization_id: z.string().optional(),
128
+ }).strict();
129
+
130
+ // Twitter/X and Threads don't have platform-specific parameters
131
+ export const TwitterParamsSchema = z.object({}).strict();
132
+ export const ThreadsParamsSchema = z.object({}).strict();
133
+
134
+ // Combined platform parameters schema
135
+ export const PlatformParamsSchema = z.object({
136
+ instagram: InstagramParamsSchema.optional(),
137
+ youtube: YouTubeParamsSchema.optional(),
138
+ tiktok: TikTokParamsSchema.optional(),
139
+ facebook: FacebookParamsSchema.optional(),
140
+ linkedin: LinkedInParamsSchema.optional(),
141
+ twitter: TwitterParamsSchema.optional(),
142
+ threads: ThreadsParamsSchema.optional(),
143
+ }).strict().optional();
144
+
145
+ /**
146
+ * Schema for post.publish parameters
147
+ */
148
+ export const PostPublishSchema = z.object({
149
+ content: z.string().min(1, "Content cannot be empty"),
150
+ targets: z.array(z.string()).min(1, "At least one target is required"),
151
+ schedule: ISO8601DateSchema.optional(),
152
+ media: z.array(MediaItemSchema).optional(),
153
+ idempotency_key: z.string().optional(),
154
+ require_confirmation: z.boolean().optional(),
155
+ draft: z.boolean().optional(),
156
+ platforms: PlatformParamsSchema,
157
+ });
158
+
159
+ /**
160
+ * Validate that a schedule date is in the future
161
+ */
162
+ export function validateScheduleInFuture(schedule: string): boolean {
163
+ const scheduleDate = new Date(schedule);
164
+ const now = new Date();
165
+ return scheduleDate > now;
166
+ }
167
+
168
+ /**
169
+ * Type inference helpers
170
+ */
171
+ export type PostPublishParams = z.infer<typeof PostPublishSchema>;
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }