@mctx-ai/mcp-server 0.3.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.
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Conversation Module - Prompt System
3
+ *
4
+ * Provides a clean builder API for constructing MCP prompt messages.
5
+ * Supports user and AI messages with text, images, and embedded resources.
6
+ *
7
+ * @module conversation
8
+ */
9
+
10
+ /**
11
+ * Creates a conversation using a builder function
12
+ *
13
+ * @param {Function} builderFn - Function that receives { user, ai } helpers
14
+ * @returns {Object} MCP prompt result: { messages: [...] }
15
+ *
16
+ * @example
17
+ * conversation(({ user, ai }) => [
18
+ * user.say("What's in this image?"),
19
+ * user.attach(base64data, "image/png"),
20
+ * user.embed("db://customers/schema"),
21
+ * ai.say("I see a customer schema with fields: id, name, email"),
22
+ * ])
23
+ * // Returns: { messages: [{ role: "user", content: {...} }, ...] }
24
+ */
25
+ export function conversation(builderFn) {
26
+ if (typeof builderFn !== "function") {
27
+ throw new Error("conversation() requires a builder function");
28
+ }
29
+
30
+ // Create helper objects
31
+ const user = createRoleHelper("user");
32
+ const ai = createRoleHelper("assistant");
33
+
34
+ // Execute builder function
35
+ const result = builderFn({ user, ai });
36
+
37
+ // Validate result is array
38
+ if (!Array.isArray(result)) {
39
+ throw new Error("Builder function must return an array of messages");
40
+ }
41
+
42
+ return { messages: result };
43
+ }
44
+
45
+ /**
46
+ * Creates a role-specific helper object with say/attach/embed methods
47
+ * @private
48
+ * @param {string} role - The role ("user" or "assistant")
49
+ * @returns {Object} Helper with say/attach/embed methods
50
+ */
51
+ function createRoleHelper(role) {
52
+ return {
53
+ /**
54
+ * Add a text message
55
+ * @param {string} text - The text content
56
+ * @returns {Object} MCP message object
57
+ */
58
+ say(text) {
59
+ if (typeof text !== "string") {
60
+ throw new Error(`${role}.say() requires a string argument`);
61
+ }
62
+
63
+ return {
64
+ role,
65
+ content: {
66
+ type: "text",
67
+ text,
68
+ },
69
+ };
70
+ },
71
+
72
+ /**
73
+ * Attach an image (base64 data)
74
+ * @param {string} data - Base64-encoded image data
75
+ * @param {string} mimeType - MIME type (REQUIRED: e.g., "image/png", "image/jpeg")
76
+ * @returns {Object} MCP message object
77
+ * @throws {Error} If mimeType is missing
78
+ */
79
+ attach(data, mimeType) {
80
+ if (typeof data !== "string") {
81
+ throw new Error(
82
+ `${role}.attach() requires base64 data as first argument`,
83
+ );
84
+ }
85
+
86
+ if (mimeType === undefined || mimeType === null) {
87
+ throw new Error(
88
+ `${role}.attach() requires mimeType as second argument (e.g., "image/png")`,
89
+ );
90
+ }
91
+
92
+ if (typeof mimeType !== "string") {
93
+ throw new Error(
94
+ `${role}.attach() requires mimeType as second argument (e.g., "image/png")`,
95
+ );
96
+ }
97
+
98
+ if (!/^[a-zA-Z]+\/[a-zA-Z0-9\-+.]+$/.test(mimeType)) {
99
+ throw new Error(
100
+ `Invalid MIME type: "${mimeType}". Expected format: type/subtype (e.g., "image/png")`,
101
+ );
102
+ }
103
+
104
+ return {
105
+ role,
106
+ content: {
107
+ type: "image",
108
+ data,
109
+ mimeType,
110
+ },
111
+ };
112
+ },
113
+
114
+ /**
115
+ * Embed a resource by URI
116
+ * @param {string} uri - The resource URI to embed
117
+ * @returns {Object} MCP message object
118
+ *
119
+ * Note: Actual resource resolution happens at server level.
120
+ * This creates a placeholder with [embedded] text.
121
+ */
122
+ embed(uri) {
123
+ if (typeof uri !== "string") {
124
+ throw new Error(`${role}.embed() requires a URI string`);
125
+ }
126
+
127
+ return {
128
+ role,
129
+ content: {
130
+ type: "resource",
131
+ resource: {
132
+ uri,
133
+ text: "[embedded]",
134
+ },
135
+ },
136
+ };
137
+ },
138
+ };
139
+ }